1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Zbigniew Jędrzejewski-Szmek
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "alloc-util.h"
29 #include "bus-error.h"
32 #include "in-addr-util.h"
33 #include "parse-util.h"
34 #include "resolved-def.h"
35 #include "resolved-dns-packet.h"
37 #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
39 static int arg_family
= AF_UNSPEC
;
40 static int arg_ifindex
= 0;
41 static int arg_type
= 0;
42 static uint16_t arg_class
= 0;
43 static bool arg_legend
= true;
44 static uint64_t arg_flags
= 0;
45 static bool arg_resolve_service
= false;
47 static void print_source(uint64_t flags
, usec_t rtt
) {
48 char rtt_str
[FORMAT_TIMESTAMP_MAX
];
56 fputs("\n-- Information acquired via", stdout
);
59 printf(" protocol%s%s%s",
60 flags
& SD_RESOLVED_DNS
? " DNS" :"",
61 flags
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
62 flags
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "");
64 assert_se(format_timespan(rtt_str
, sizeof(rtt_str
), rtt
, 100));
66 printf(" in %s", rtt_str
);
72 static int resolve_host(sd_bus
*bus
, const char *name
) {
74 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
75 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
76 const char *canonical
= NULL
;
77 char ifname
[IF_NAMESIZE
] = "";
85 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
86 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
88 log_debug("Resolving %s (family %s, interface %s).", name
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
90 r
= sd_bus_message_new_method_call(
93 "org.freedesktop.resolve1",
94 "/org/freedesktop/resolve1",
95 "org.freedesktop.resolve1.Manager",
98 return bus_log_create_error(r
);
100 r
= sd_bus_message_append(req
, "isit", arg_ifindex
, name
, arg_family
, arg_flags
);
102 return bus_log_create_error(r
);
104 ts
= now(CLOCK_MONOTONIC
);
106 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
108 return log_error_errno(r
, "%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
110 ts
= now(CLOCK_MONOTONIC
) - ts
;
112 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
114 return bus_log_parse_error(r
);
116 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
117 _cleanup_free_
char *pretty
= NULL
;
122 assert_cc(sizeof(int) == sizeof(int32_t));
124 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
126 return bus_log_parse_error(r
);
128 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
130 return bus_log_parse_error(r
);
132 r
= sd_bus_message_exit_container(reply
);
134 return bus_log_parse_error(r
);
136 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
137 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
141 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
142 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
147 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
148 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
150 r
= in_addr_to_string(family
, a
, &pretty
);
152 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
154 printf("%*s%s %s%s%s\n",
155 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
157 isempty(ifname
) ? "" : "%", ifname
);
162 return bus_log_parse_error(r
);
164 r
= sd_bus_message_exit_container(reply
);
166 return bus_log_parse_error(r
);
168 r
= sd_bus_message_read(reply
, "st", &canonical
, &flags
);
170 return bus_log_parse_error(r
);
172 if (!streq(name
, canonical
))
173 printf("%*s%s (%s)\n",
174 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
178 log_error("%s: no addresses found", name
);
182 print_source(flags
, ts
);
187 static int resolve_address(sd_bus
*bus
, int family
, const union in_addr_union
*address
, int ifindex
) {
188 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
189 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
190 _cleanup_free_
char *pretty
= NULL
;
191 char ifname
[IF_NAMESIZE
] = "";
198 assert(IN_SET(family
, AF_INET
, AF_INET6
));
202 ifindex
= arg_ifindex
;
204 r
= in_addr_to_string(family
, address
, &pretty
);
208 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
209 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
211 log_debug("Resolving %s%s%s.", pretty
, isempty(ifname
) ? "" : "%", ifname
);
213 r
= sd_bus_message_new_method_call(
216 "org.freedesktop.resolve1",
217 "/org/freedesktop/resolve1",
218 "org.freedesktop.resolve1.Manager",
221 return bus_log_create_error(r
);
223 r
= sd_bus_message_append(req
, "ii", ifindex
, family
);
225 return bus_log_create_error(r
);
227 r
= sd_bus_message_append_array(req
, 'y', address
, FAMILY_ADDRESS_SIZE(family
));
229 return bus_log_create_error(r
);
231 r
= sd_bus_message_append(req
, "t", arg_flags
);
233 return bus_log_create_error(r
);
235 ts
= now(CLOCK_MONOTONIC
);
237 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
239 log_error("%s: resolve call failed: %s", pretty
, bus_error_message(&error
, r
));
243 ts
= now(CLOCK_MONOTONIC
) - ts
;
245 r
= sd_bus_message_enter_container(reply
, 'a', "(is)");
247 return bus_log_create_error(r
);
249 while ((r
= sd_bus_message_enter_container(reply
, 'r', "is")) > 0) {
252 assert_cc(sizeof(int) == sizeof(int32_t));
254 r
= sd_bus_message_read(reply
, "is", &ifindex
, &n
);
258 r
= sd_bus_message_exit_container(reply
);
263 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
264 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
266 printf("%*s%*s%*s%s %s\n",
267 (int) strlen(pretty
), c
== 0 ? pretty
: "",
268 isempty(ifname
) ? 0 : 1, c
> 0 || isempty(ifname
) ? "" : "%",
269 (int) strlen(ifname
), c
== 0 ? ifname
: "",
276 return bus_log_parse_error(r
);
278 r
= sd_bus_message_exit_container(reply
);
280 return bus_log_parse_error(r
);
282 r
= sd_bus_message_read(reply
, "t", &flags
);
284 return bus_log_parse_error(r
);
287 log_error("%s: no names found", pretty
);
291 print_source(flags
, ts
);
296 static int parse_address(const char *s
, int *family
, union in_addr_union
*address
, int *ifindex
) {
297 const char *percent
, *a
;
301 percent
= strchr(s
, '%');
303 if (parse_ifindex(percent
+1, &ifi
) < 0) {
304 ifi
= if_nametoindex(percent
+1);
309 a
= strndupa(s
, percent
- s
);
313 r
= in_addr_from_string_auto(a
, family
, address
);
321 static int resolve_record(sd_bus
*bus
, const char *name
) {
323 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
324 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
325 char ifname
[IF_NAMESIZE
] = "";
333 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
334 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
336 log_debug("Resolving %s %s %s (interface %s).", name
, dns_class_to_string(arg_class
), dns_type_to_string(arg_type
), isempty(ifname
) ? "*" : ifname
);
338 r
= sd_bus_message_new_method_call(
341 "org.freedesktop.resolve1",
342 "/org/freedesktop/resolve1",
343 "org.freedesktop.resolve1.Manager",
346 return bus_log_create_error(r
);
348 assert((uint16_t) arg_type
== arg_type
);
349 r
= sd_bus_message_append(req
, "isqqt", arg_ifindex
, name
, arg_class
, arg_type
, arg_flags
);
351 return bus_log_create_error(r
);
353 ts
= now(CLOCK_MONOTONIC
);
355 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
357 log_error("%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
361 ts
= now(CLOCK_MONOTONIC
) - ts
;
363 r
= sd_bus_message_enter_container(reply
, 'a', "(iqqay)");
365 return bus_log_parse_error(r
);
367 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iqqay")) > 0) {
368 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
369 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
370 _cleanup_free_
char *s
= NULL
;
376 assert_cc(sizeof(int) == sizeof(int32_t));
378 r
= sd_bus_message_read(reply
, "iqq", &ifindex
, &c
, &t
);
380 return bus_log_parse_error(r
);
382 r
= sd_bus_message_read_array(reply
, 'y', &d
, &l
);
384 return bus_log_parse_error(r
);
386 r
= sd_bus_message_exit_container(reply
);
388 return bus_log_parse_error(r
);
390 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0);
394 p
->refuse_compression
= true;
396 r
= dns_packet_append_blob(p
, d
, l
, NULL
);
400 r
= dns_packet_read_rr(p
, &rr
, NULL
);
402 log_error("Failed to parse RR.");
406 r
= dns_resource_record_to_string(rr
, &s
);
408 log_error("Failed to format RR.");
413 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
414 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
416 printf("%s%s%s\n", s
, isempty(ifname
) ? "" : " # interface ", ifname
);
420 return bus_log_parse_error(r
);
422 r
= sd_bus_message_exit_container(reply
);
424 return bus_log_parse_error(r
);
426 r
= sd_bus_message_read(reply
, "t", &flags
);
428 return bus_log_parse_error(r
);
431 log_error("%s: no records found", name
);
435 print_source(flags
, ts
);
440 static int resolve_service(sd_bus
*bus
, const char *name
, const char *type
, const char *domain
) {
441 const char *canonical_name
, *canonical_type
, *canonical_domain
;
442 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
443 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
444 char ifname
[IF_NAMESIZE
] = "";
460 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
461 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
464 log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name
, type
, domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
466 log_debug("Resolving service type %s of %s (family %s, interface %s).", type
, domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
468 log_debug("Resolving service type %s (family %s, interface %s).", domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
470 r
= sd_bus_message_new_method_call(
473 "org.freedesktop.resolve1",
474 "/org/freedesktop/resolve1",
475 "org.freedesktop.resolve1.Manager",
478 return bus_log_create_error(r
);
480 r
= sd_bus_message_append(req
, "isssit", arg_ifindex
, name
, type
, domain
, arg_family
, arg_flags
);
482 return bus_log_create_error(r
);
484 ts
= now(CLOCK_MONOTONIC
);
486 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
488 return log_error_errno(r
, "Resolve call failed: %s", bus_error_message(&error
, r
));
490 ts
= now(CLOCK_MONOTONIC
) - ts
;
492 r
= sd_bus_message_enter_container(reply
, 'a', "(qqqsa(iiay)s)");
494 return bus_log_parse_error(r
);
497 (name
? strlen(name
) + 1 : 0) +
498 (type
? strlen(type
) + 1 : 0) +
502 while ((r
= sd_bus_message_enter_container(reply
, 'r', "qqqsa(iiay)s")) > 0) {
503 uint16_t priority
, weight
, port
;
504 const char *hostname
, *canonical
;
506 r
= sd_bus_message_read(reply
, "qqqs", &priority
, &weight
, &port
, &hostname
);
508 return bus_log_parse_error(r
);
511 printf("%*s%s", (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? "/" : " ");
513 printf("%*s%s", (int) strlen(type
), c
== 0 ? type
: "", c
== 0 ? "/" : " ");
515 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
516 (int) strlen(domain
), c
== 0 ? domain
: "",
521 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
523 return bus_log_parse_error(r
);
525 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
526 _cleanup_free_
char *pretty
= NULL
;
530 assert_cc(sizeof(int) == sizeof(int32_t));
532 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
534 return bus_log_parse_error(r
);
536 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
538 return bus_log_parse_error(r
);
540 r
= sd_bus_message_exit_container(reply
);
542 return bus_log_parse_error(r
);
544 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
545 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
549 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
550 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
555 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
556 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
558 r
= in_addr_to_string(family
, a
, &pretty
);
560 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
562 printf("%*s%s%s%s\n", (int) indent
, "", pretty
, isempty(ifname
) ? "" : "%s", ifname
);
565 return bus_log_parse_error(r
);
567 r
= sd_bus_message_exit_container(reply
);
569 return bus_log_parse_error(r
);
571 r
= sd_bus_message_read(reply
, "s", &canonical
);
573 return bus_log_parse_error(r
);
575 if (!streq(hostname
, canonical
))
576 printf("%*s(%s)\n", (int) indent
, "", canonical
);
578 r
= sd_bus_message_exit_container(reply
);
580 return bus_log_parse_error(r
);
585 return bus_log_parse_error(r
);
587 r
= sd_bus_message_exit_container(reply
);
589 return bus_log_parse_error(r
);
591 r
= sd_bus_message_enter_container(reply
, 'a', "ay");
593 return bus_log_parse_error(r
);
596 while ((r
= sd_bus_message_read_array(reply
, 'y', (const void**) &p
, &sz
)) > 0) {
597 _cleanup_free_
char *escaped
= NULL
;
599 escaped
= cescape_length(p
, sz
);
603 printf("%*s%s\n", (int) indent
, "", escaped
);
607 return bus_log_parse_error(r
);
609 r
= sd_bus_message_exit_container(reply
);
611 return bus_log_parse_error(r
);
613 r
= sd_bus_message_read(reply
, "ssst", &canonical_name
, &canonical_type
, &canonical_domain
, &flags
);
615 return bus_log_parse_error(r
);
617 if (isempty(canonical_name
))
618 canonical_name
= NULL
;
619 if (isempty(canonical_type
))
620 canonical_type
= NULL
;
622 if (!streq_ptr(name
, canonical_name
) ||
623 !streq_ptr(type
, canonical_type
) ||
624 !streq_ptr(domain
, canonical_domain
)) {
626 printf("%*s(", (int) indent
, "");
629 printf("%s/", canonical_name
);
631 printf("%s/", canonical_type
);
633 printf("%s)\n", canonical_domain
);
636 print_source(flags
, ts
);
641 static void help_dns_types(void) {
646 puts("Known DNS RR types:");
647 for (i
= 0; i
< _DNS_TYPE_MAX
; i
++) {
648 t
= dns_type_to_string(i
);
654 static void help_dns_classes(void) {
659 puts("Known DNS RR classes:");
660 for (i
= 0; i
< _DNS_CLASS_MAX
; i
++) {
661 t
= dns_class_to_string(i
);
667 static void help(void) {
668 printf("%s [OPTIONS...] NAME...\n"
669 "%s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n\n"
670 "Resolve domain names, IPv4 or IPv6 addresses, resource records, and services.\n\n"
671 " -h --help Show this help\n"
672 " --version Show package version\n"
673 " -4 Resolve IPv4 addresses\n"
674 " -6 Resolve IPv6 addresses\n"
675 " -i INTERFACE Look on interface\n"
676 " -p --protocol=PROTOCOL Look via protocol\n"
677 " -t --type=TYPE Query RR with DNS type\n"
678 " -c --class=CLASS Query RR with DNS class\n"
679 " --service Resolve service (SRV)\n"
680 " --service-address=BOOL Do [not] resolve address for services\n"
681 " --service-txt=BOOL Do [not] resolve TXT records for services\n"
682 " --cname=BOOL Do [not] follow CNAME redirects\n"
683 " --search=BOOL Do [not] use search domains\n"
684 " --legend=BOOL Do [not] print column headers\n"
685 , program_invocation_short_name
, program_invocation_short_name
);
688 static int parse_argv(int argc
, char *argv
[]) {
699 static const struct option options
[] = {
700 { "help", no_argument
, NULL
, 'h' },
701 { "version", no_argument
, NULL
, ARG_VERSION
},
702 { "type", required_argument
, NULL
, 't' },
703 { "class", required_argument
, NULL
, 'c' },
704 { "legend", required_argument
, NULL
, ARG_LEGEND
},
705 { "protocol", required_argument
, NULL
, 'p' },
706 { "cname", required_argument
, NULL
, ARG_CNAME
},
707 { "service", no_argument
, NULL
, ARG_SERVICE
},
708 { "service-address", required_argument
, NULL
, ARG_SERVICE_ADDRESS
},
709 { "service-txt", required_argument
, NULL
, ARG_SERVICE_TXT
},
710 { "search", required_argument
, NULL
, ARG_SEARCH
},
719 while ((c
= getopt_long(argc
, argv
, "h46i:t:c:p:", options
, NULL
)) >= 0)
724 return 0; /* done */;
730 arg_family
= AF_INET
;
734 arg_family
= AF_INET6
;
740 if (parse_ifindex(optarg
, &ifi
) >= 0)
743 ifi
= if_nametoindex(optarg
);
745 return log_error_errno(errno
, "Unknown interface %s: %m", optarg
);
754 if (streq(optarg
, "help")) {
759 arg_type
= dns_type_from_string(optarg
);
761 log_error("Failed to parse RR record type %s", optarg
);
764 assert(arg_type
> 0 && (uint16_t) arg_type
== arg_type
);
769 if (streq(optarg
, "help")) {
774 r
= dns_class_from_string(optarg
, &arg_class
);
776 log_error("Failed to parse RR record class %s", optarg
);
783 r
= parse_boolean(optarg
);
785 return log_error_errno(r
, "Failed to parse --legend= argument");
791 if (streq(optarg
, "dns"))
792 arg_flags
|= SD_RESOLVED_DNS
;
793 else if (streq(optarg
, "llmnr"))
794 arg_flags
|= SD_RESOLVED_LLMNR
;
795 else if (streq(optarg
, "llmnr-ipv4"))
796 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
797 else if (streq(optarg
, "llmnr-ipv6"))
798 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
800 log_error("Unknown protocol specifier: %s", optarg
);
807 arg_resolve_service
= true;
811 r
= parse_boolean(optarg
);
813 return log_error_errno(r
, "Failed to parse --cname= argument.");
815 arg_flags
|= SD_RESOLVED_NO_CNAME
;
817 arg_flags
&= ~SD_RESOLVED_NO_CNAME
;
820 case ARG_SERVICE_ADDRESS
:
821 r
= parse_boolean(optarg
);
823 return log_error_errno(r
, "Failed to parse --service-address= argument.");
825 arg_flags
|= SD_RESOLVED_NO_ADDRESS
;
827 arg_flags
&= ~SD_RESOLVED_NO_ADDRESS
;
830 case ARG_SERVICE_TXT
:
831 r
= parse_boolean(optarg
);
833 return log_error_errno(r
, "Failed to parse --service-txt= argument.");
835 arg_flags
|= SD_RESOLVED_NO_TXT
;
837 arg_flags
&= ~SD_RESOLVED_NO_TXT
;
841 r
= parse_boolean(optarg
);
843 return log_error_errno(r
, "Failed to parse --search argument.");
845 arg_flags
|= SD_RESOLVED_NO_SEARCH
;
847 arg_flags
&= ~SD_RESOLVED_NO_SEARCH
;
854 assert_not_reached("Unhandled option");
857 if (arg_type
== 0 && arg_class
!= 0) {
858 log_error("--class= may only be used in conjunction with --type=.");
862 if (arg_type
!= 0 && arg_resolve_service
) {
863 log_error("--service and --type= may not be combined.");
867 if (arg_type
!= 0 && arg_class
== 0)
868 arg_class
= DNS_CLASS_IN
;
870 return 1 /* work to do */;
873 int main(int argc
, char **argv
) {
874 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
877 log_parse_environment();
880 r
= parse_argv(argc
, argv
);
884 if (optind
>= argc
) {
885 log_error("No arguments passed");
890 r
= sd_bus_open_system(&bus
);
892 log_error_errno(r
, "sd_bus_open_system: %m");
896 if (arg_resolve_service
) {
898 if (argc
< optind
+ 1) {
899 log_error("Domain specification required.");
903 } else if (argc
== optind
+ 1)
904 r
= resolve_service(bus
, NULL
, NULL
, argv
[optind
]);
905 else if (argc
== optind
+ 2)
906 r
= resolve_service(bus
, NULL
, argv
[optind
], argv
[optind
+1]);
907 else if (argc
== optind
+ 3)
908 r
= resolve_service(bus
, argv
[optind
], argv
[optind
+1], argv
[optind
+2]);
910 log_error("Too many arguments");
918 while (argv
[optind
]) {
919 int family
, ifindex
, k
;
920 union in_addr_union a
;
923 k
= resolve_record(bus
, argv
[optind
]);
925 k
= parse_address(argv
[optind
], &family
, &a
, &ifindex
);
927 k
= resolve_address(bus
, family
, &a
, ifindex
);
929 k
= resolve_host(bus
, argv
[optind
]);
939 return r
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;