1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Zbigniew Jędrzejewski-Szmek
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "sd-netlink.h"
28 #include "alloc-util.h"
29 #include "bus-error.h"
32 #include "gcrypt-util.h"
33 #include "in-addr-util.h"
34 #include "netlink-util.h"
36 #include "parse-util.h"
37 #include "resolved-def.h"
38 #include "resolved-dns-packet.h"
40 #include "terminal-util.h"
42 #define DNS_CALL_TIMEOUT_USEC (90*USEC_PER_SEC)
44 static int arg_family
= AF_UNSPEC
;
45 static int arg_ifindex
= 0;
46 static uint16_t arg_type
= 0;
47 static uint16_t arg_class
= 0;
48 static bool arg_legend
= true;
49 static uint64_t arg_flags
= 0;
50 static bool arg_no_pager
= false;
52 typedef enum ServiceFamily
{
56 _SERVICE_FAMILY_INVALID
= -1,
58 static ServiceFamily arg_service_family
= SERVICE_FAMILY_TCP
;
60 typedef enum RawType
{
65 static RawType arg_raw
= RAW_NONE
;
74 MODE_RESET_STATISTICS
,
76 MODE_RESET_SERVER_FEATURES
,
78 } arg_mode
= MODE_RESOLVE_HOST
;
80 static ServiceFamily
service_family_from_string(const char *s
) {
81 if (s
== NULL
|| streq(s
, "tcp"))
82 return SERVICE_FAMILY_TCP
;
84 return SERVICE_FAMILY_UDP
;
86 return SERVICE_FAMILY_SCTP
;
87 return _SERVICE_FAMILY_INVALID
;
90 static const char* service_family_to_string(ServiceFamily service
) {
92 case SERVICE_FAMILY_TCP
:
94 case SERVICE_FAMILY_UDP
:
96 case SERVICE_FAMILY_SCTP
:
99 assert_not_reached("invalid service");
103 static void print_source(uint64_t flags
, usec_t rtt
) {
104 char rtt_str
[FORMAT_TIMESTAMP_MAX
];
112 fputs("\n-- Information acquired via", stdout
);
115 printf(" protocol%s%s%s%s%s",
116 flags
& SD_RESOLVED_DNS
? " DNS" :"",
117 flags
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
118 flags
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
119 flags
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
120 flags
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
122 assert_se(format_timespan(rtt_str
, sizeof(rtt_str
), rtt
, 100));
124 printf(" in %s", rtt_str
);
129 printf("-- Data is authenticated: %s\n", yes_no(flags
& SD_RESOLVED_AUTHENTICATED
));
132 static int resolve_host(sd_bus
*bus
, const char *name
) {
134 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
135 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
136 const char *canonical
= NULL
;
137 char ifname
[IF_NAMESIZE
] = "";
145 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
146 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
148 log_debug("Resolving %s (family %s, interface %s).", name
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
150 r
= sd_bus_message_new_method_call(
153 "org.freedesktop.resolve1",
154 "/org/freedesktop/resolve1",
155 "org.freedesktop.resolve1.Manager",
158 return bus_log_create_error(r
);
160 r
= sd_bus_message_append(req
, "isit", arg_ifindex
, name
, arg_family
, arg_flags
);
162 return bus_log_create_error(r
);
164 ts
= now(CLOCK_MONOTONIC
);
166 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
168 return log_error_errno(r
, "%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
170 ts
= now(CLOCK_MONOTONIC
) - ts
;
172 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
174 return bus_log_parse_error(r
);
176 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
177 _cleanup_free_
char *pretty
= NULL
;
182 assert_cc(sizeof(int) == sizeof(int32_t));
184 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
186 return bus_log_parse_error(r
);
188 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
190 return bus_log_parse_error(r
);
192 r
= sd_bus_message_exit_container(reply
);
194 return bus_log_parse_error(r
);
196 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
197 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
201 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
202 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
207 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
208 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
210 r
= in_addr_ifindex_to_string(family
, a
, ifindex
, &pretty
);
212 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
214 printf("%*s%s %s%s%s\n",
215 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
217 isempty(ifname
) ? "" : "%", ifname
);
222 return bus_log_parse_error(r
);
224 r
= sd_bus_message_exit_container(reply
);
226 return bus_log_parse_error(r
);
228 r
= sd_bus_message_read(reply
, "st", &canonical
, &flags
);
230 return bus_log_parse_error(r
);
232 if (!streq(name
, canonical
))
233 printf("%*s%s (%s)\n",
234 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
238 log_error("%s: no addresses found", name
);
242 print_source(flags
, ts
);
247 static int resolve_address(sd_bus
*bus
, int family
, const union in_addr_union
*address
, int ifindex
) {
248 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
249 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
250 _cleanup_free_
char *pretty
= NULL
;
251 char ifname
[IF_NAMESIZE
] = "";
258 assert(IN_SET(family
, AF_INET
, AF_INET6
));
262 ifindex
= arg_ifindex
;
264 r
= in_addr_ifindex_to_string(family
, address
, ifindex
, &pretty
);
268 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
269 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
271 log_debug("Resolving %s%s%s.", pretty
, isempty(ifname
) ? "" : "%", ifname
);
273 r
= sd_bus_message_new_method_call(
276 "org.freedesktop.resolve1",
277 "/org/freedesktop/resolve1",
278 "org.freedesktop.resolve1.Manager",
281 return bus_log_create_error(r
);
283 r
= sd_bus_message_append(req
, "ii", ifindex
, family
);
285 return bus_log_create_error(r
);
287 r
= sd_bus_message_append_array(req
, 'y', address
, FAMILY_ADDRESS_SIZE(family
));
289 return bus_log_create_error(r
);
291 r
= sd_bus_message_append(req
, "t", arg_flags
);
293 return bus_log_create_error(r
);
295 ts
= now(CLOCK_MONOTONIC
);
297 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
299 log_error("%s: resolve call failed: %s", pretty
, bus_error_message(&error
, r
));
303 ts
= now(CLOCK_MONOTONIC
) - ts
;
305 r
= sd_bus_message_enter_container(reply
, 'a', "(is)");
307 return bus_log_create_error(r
);
309 while ((r
= sd_bus_message_enter_container(reply
, 'r', "is")) > 0) {
312 assert_cc(sizeof(int) == sizeof(int32_t));
314 r
= sd_bus_message_read(reply
, "is", &ifindex
, &n
);
318 r
= sd_bus_message_exit_container(reply
);
323 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
324 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
326 printf("%*s%*s%*s%s %s\n",
327 (int) strlen(pretty
), c
== 0 ? pretty
: "",
328 isempty(ifname
) ? 0 : 1, c
> 0 || isempty(ifname
) ? "" : "%",
329 (int) strlen(ifname
), c
== 0 ? ifname
: "",
336 return bus_log_parse_error(r
);
338 r
= sd_bus_message_exit_container(reply
);
340 return bus_log_parse_error(r
);
342 r
= sd_bus_message_read(reply
, "t", &flags
);
344 return bus_log_parse_error(r
);
347 log_error("%s: no names found", pretty
);
351 print_source(flags
, ts
);
356 static int output_rr_packet(const void *d
, size_t l
, int ifindex
) {
357 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
358 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
360 char ifname
[IF_NAMESIZE
] = "";
362 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0, DNS_PACKET_SIZE_MAX
);
366 p
->refuse_compression
= true;
368 r
= dns_packet_append_blob(p
, d
, l
, NULL
);
372 r
= dns_packet_read_rr(p
, &rr
, NULL
, NULL
);
374 return log_error_errno(r
, "Failed to parse RR: %m");
376 if (arg_raw
== RAW_PAYLOAD
) {
380 k
= dns_resource_record_payload(rr
, &data
);
382 return log_error_errno(k
, "Cannot dump RR: %m");
383 fwrite(data
, 1, k
, stdout
);
387 s
= dns_resource_record_to_string(rr
);
391 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
392 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
394 printf("%s%s%s\n", s
, isempty(ifname
) ? "" : " # interface ", ifname
);
400 static int resolve_record(sd_bus
*bus
, const char *name
, uint16_t class, uint16_t type
, bool warn_missing
) {
401 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
402 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
403 char ifname
[IF_NAMESIZE
] = "";
408 bool needs_authentication
= false;
412 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
413 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
415 log_debug("Resolving %s %s %s (interface %s).", name
, dns_class_to_string(class), dns_type_to_string(type
), isempty(ifname
) ? "*" : ifname
);
417 r
= sd_bus_message_new_method_call(
420 "org.freedesktop.resolve1",
421 "/org/freedesktop/resolve1",
422 "org.freedesktop.resolve1.Manager",
425 return bus_log_create_error(r
);
427 r
= sd_bus_message_append(req
, "isqqt", arg_ifindex
, name
, class, type
, arg_flags
);
429 return bus_log_create_error(r
);
431 ts
= now(CLOCK_MONOTONIC
);
433 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
435 if (warn_missing
|| r
!= -ENXIO
)
436 log_error("%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
440 ts
= now(CLOCK_MONOTONIC
) - ts
;
442 r
= sd_bus_message_enter_container(reply
, 'a', "(iqqay)");
444 return bus_log_parse_error(r
);
446 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iqqay")) > 0) {
452 assert_cc(sizeof(int) == sizeof(int32_t));
454 r
= sd_bus_message_read(reply
, "iqq", &ifindex
, &c
, &t
);
456 return bus_log_parse_error(r
);
458 r
= sd_bus_message_read_array(reply
, 'y', &d
, &l
);
460 return bus_log_parse_error(r
);
462 r
= sd_bus_message_exit_container(reply
);
464 return bus_log_parse_error(r
);
466 if (arg_raw
== RAW_PACKET
) {
467 uint64_t u64
= htole64(l
);
469 fwrite(&u64
, sizeof(u64
), 1, stdout
);
470 fwrite(d
, 1, l
, stdout
);
472 r
= output_rr_packet(d
, l
, ifindex
);
477 if (dns_type_needs_authentication(t
))
478 needs_authentication
= true;
483 return bus_log_parse_error(r
);
485 r
= sd_bus_message_exit_container(reply
);
487 return bus_log_parse_error(r
);
489 r
= sd_bus_message_read(reply
, "t", &flags
);
491 return bus_log_parse_error(r
);
495 log_error("%s: no records found", name
);
499 print_source(flags
, ts
);
501 if ((flags
& SD_RESOLVED_AUTHENTICATED
) == 0 && needs_authentication
) {
504 fprintf(stderr
, "\n%s"
505 "WARNING: The resources shown contain cryptographic key data which could not be\n"
506 " authenticated. It is not suitable to authenticate any communication.\n"
507 " This is usually indication that DNSSEC authentication was not enabled\n"
508 " or is not available for the selected protocol or DNS servers.%s\n",
509 ansi_highlight_red(),
516 static int resolve_rfc4501(sd_bus
*bus
, const char *name
) {
517 uint16_t type
= 0, class = 0;
518 const char *p
, *q
, *n
;
523 assert(startswith(name
, "dns:"));
525 /* Parse RFC 4501 dns: URIs */
535 e
= strchr(p
+ 2, '/');
540 log_warning("DNS authority specification not supported; ignoring specified authority.");
547 n
= strndupa(p
, q
- p
);
553 f
= startswith_no_case(q
, "class=");
555 _cleanup_free_
char *t
= NULL
;
559 log_error("DNS class specified twice.");
563 e
= strchrnul(f
, ';');
564 t
= strndup(f
, e
- f
);
568 r
= dns_class_from_string(t
);
570 log_error("Unknown DNS class %s.", t
);
584 f
= startswith_no_case(q
, "type=");
586 _cleanup_free_
char *t
= NULL
;
590 log_error("DNS type specified twice.");
594 e
= strchrnul(f
, ';');
595 t
= strndup(f
, e
- f
);
599 r
= dns_type_from_string(t
);
601 log_error("Unknown DNS type %s.", t
);
621 class = arg_class
?: DNS_CLASS_IN
;
623 type
= arg_type
?: DNS_TYPE_A
;
625 return resolve_record(bus
, n
, class, type
, true);
628 log_error("Invalid DNS URI: %s", name
);
632 static int resolve_service(sd_bus
*bus
, const char *name
, const char *type
, const char *domain
) {
633 const char *canonical_name
, *canonical_type
, *canonical_domain
;
634 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
635 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
636 char ifname
[IF_NAMESIZE
] = "";
647 name
= empty_to_null(name
);
648 type
= empty_to_null(type
);
650 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
651 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
654 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
);
656 log_debug("Resolving service type %s of %s (family %s, interface %s).", type
, domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
658 log_debug("Resolving service type %s (family %s, interface %s).", domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
660 r
= sd_bus_message_new_method_call(
663 "org.freedesktop.resolve1",
664 "/org/freedesktop/resolve1",
665 "org.freedesktop.resolve1.Manager",
668 return bus_log_create_error(r
);
670 r
= sd_bus_message_append(req
, "isssit", arg_ifindex
, name
, type
, domain
, arg_family
, arg_flags
);
672 return bus_log_create_error(r
);
674 ts
= now(CLOCK_MONOTONIC
);
676 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
678 return log_error_errno(r
, "Resolve call failed: %s", bus_error_message(&error
, r
));
680 ts
= now(CLOCK_MONOTONIC
) - ts
;
682 r
= sd_bus_message_enter_container(reply
, 'a', "(qqqsa(iiay)s)");
684 return bus_log_parse_error(r
);
687 (name
? strlen(name
) + 1 : 0) +
688 (type
? strlen(type
) + 1 : 0) +
692 while ((r
= sd_bus_message_enter_container(reply
, 'r', "qqqsa(iiay)s")) > 0) {
693 uint16_t priority
, weight
, port
;
694 const char *hostname
, *canonical
;
696 r
= sd_bus_message_read(reply
, "qqqs", &priority
, &weight
, &port
, &hostname
);
698 return bus_log_parse_error(r
);
701 printf("%*s%s", (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? "/" : " ");
703 printf("%*s%s", (int) strlen(type
), c
== 0 ? type
: "", c
== 0 ? "/" : " ");
705 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
706 (int) strlen(domain
), c
== 0 ? domain
: "",
711 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
713 return bus_log_parse_error(r
);
715 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
716 _cleanup_free_
char *pretty
= NULL
;
720 assert_cc(sizeof(int) == sizeof(int32_t));
722 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
724 return bus_log_parse_error(r
);
726 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
728 return bus_log_parse_error(r
);
730 r
= sd_bus_message_exit_container(reply
);
732 return bus_log_parse_error(r
);
734 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
735 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
739 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
740 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
745 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
746 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
748 r
= in_addr_to_string(family
, a
, &pretty
);
750 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
752 printf("%*s%s%s%s\n", (int) indent
, "", pretty
, isempty(ifname
) ? "" : "%s", ifname
);
755 return bus_log_parse_error(r
);
757 r
= sd_bus_message_exit_container(reply
);
759 return bus_log_parse_error(r
);
761 r
= sd_bus_message_read(reply
, "s", &canonical
);
763 return bus_log_parse_error(r
);
765 if (!streq(hostname
, canonical
))
766 printf("%*s(%s)\n", (int) indent
, "", canonical
);
768 r
= sd_bus_message_exit_container(reply
);
770 return bus_log_parse_error(r
);
775 return bus_log_parse_error(r
);
777 r
= sd_bus_message_exit_container(reply
);
779 return bus_log_parse_error(r
);
781 r
= sd_bus_message_enter_container(reply
, 'a', "ay");
783 return bus_log_parse_error(r
);
785 while ((r
= sd_bus_message_read_array(reply
, 'y', (const void**) &p
, &sz
)) > 0) {
786 _cleanup_free_
char *escaped
= NULL
;
788 escaped
= cescape_length(p
, sz
);
792 printf("%*s%s\n", (int) indent
, "", escaped
);
795 return bus_log_parse_error(r
);
797 r
= sd_bus_message_exit_container(reply
);
799 return bus_log_parse_error(r
);
801 r
= sd_bus_message_read(reply
, "ssst", &canonical_name
, &canonical_type
, &canonical_domain
, &flags
);
803 return bus_log_parse_error(r
);
805 canonical_name
= empty_to_null(canonical_name
);
806 canonical_type
= empty_to_null(canonical_type
);
808 if (!streq_ptr(name
, canonical_name
) ||
809 !streq_ptr(type
, canonical_type
) ||
810 !streq_ptr(domain
, canonical_domain
)) {
812 printf("%*s(", (int) indent
, "");
815 printf("%s/", canonical_name
);
817 printf("%s/", canonical_type
);
819 printf("%s)\n", canonical_domain
);
822 print_source(flags
, ts
);
827 static int resolve_openpgp(sd_bus
*bus
, const char *address
) {
828 const char *domain
, *full
;
830 _cleanup_free_
char *hashed
= NULL
;
835 domain
= strrchr(address
, '@');
837 log_error("Address does not contain '@': \"%s\"", address
);
839 } else if (domain
== address
|| domain
[1] == '\0') {
840 log_error("Address starts or ends with '@': \"%s\"", address
);
845 r
= string_hashsum_sha256(address
, domain
- 1 - address
, &hashed
);
847 return log_error_errno(r
, "Hashing failed: %m");
849 strshorten(hashed
, 56);
851 full
= strjoina(hashed
, "._openpgpkey.", domain
);
852 log_debug("Looking up \"%s\".", full
);
854 r
= resolve_record(bus
, full
,
855 arg_class
?: DNS_CLASS_IN
,
856 arg_type
?: DNS_TYPE_OPENPGPKEY
, false);
858 if (IN_SET(r
, -ENXIO
, -ESRCH
)) { /* NXDOMAIN or NODATA? */
860 r
= string_hashsum_sha224(address
, domain
- 1 - address
, &hashed
);
862 return log_error_errno(r
, "Hashing failed: %m");
864 full
= strjoina(hashed
, "._openpgpkey.", domain
);
865 log_debug("Looking up \"%s\".", full
);
867 return resolve_record(bus
, full
,
868 arg_class
?: DNS_CLASS_IN
,
869 arg_type
?: DNS_TYPE_OPENPGPKEY
, true);
875 static int resolve_tlsa(sd_bus
*bus
, const char *address
) {
877 uint16_t port_num
= 443;
878 _cleanup_free_
char *full
= NULL
;
884 port
= strrchr(address
, ':');
886 r
= parse_ip_port(port
+ 1, &port_num
);
888 return log_error_errno(r
, "Invalid port \"%s\".", port
+ 1);
890 address
= strndupa(address
, port
- address
);
893 r
= asprintf(&full
, "_%u.%s.%s",
895 service_family_to_string(arg_service_family
),
900 log_debug("Looking up \"%s\".", full
);
902 return resolve_record(bus
, full
,
903 arg_class
?: DNS_CLASS_IN
,
904 arg_type
?: DNS_TYPE_TLSA
, true);
907 static int show_statistics(sd_bus
*bus
) {
908 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
909 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
910 uint64_t n_current_transactions
, n_total_transactions
,
911 cache_size
, n_cache_hit
, n_cache_miss
,
912 n_dnssec_secure
, n_dnssec_insecure
, n_dnssec_bogus
, n_dnssec_indeterminate
;
913 int r
, dnssec_supported
;
917 r
= sd_bus_get_property_trivial(bus
,
918 "org.freedesktop.resolve1",
919 "/org/freedesktop/resolve1",
920 "org.freedesktop.resolve1.Manager",
926 return log_error_errno(r
, "Failed to get DNSSEC supported state: %s", bus_error_message(&error
, r
));
928 printf("DNSSEC supported by current servers: %s%s%s\n\n",
930 yes_no(dnssec_supported
),
933 r
= sd_bus_get_property(bus
,
934 "org.freedesktop.resolve1",
935 "/org/freedesktop/resolve1",
936 "org.freedesktop.resolve1.Manager",
937 "TransactionStatistics",
942 return log_error_errno(r
, "Failed to get transaction statistics: %s", bus_error_message(&error
, r
));
944 r
= sd_bus_message_read(reply
, "(tt)",
945 &n_current_transactions
,
946 &n_total_transactions
);
948 return bus_log_parse_error(r
);
950 printf("%sTransactions%s\n"
951 "Current Transactions: %" PRIu64
"\n"
952 " Total Transactions: %" PRIu64
"\n",
955 n_current_transactions
,
956 n_total_transactions
);
958 reply
= sd_bus_message_unref(reply
);
960 r
= sd_bus_get_property(bus
,
961 "org.freedesktop.resolve1",
962 "/org/freedesktop/resolve1",
963 "org.freedesktop.resolve1.Manager",
969 return log_error_errno(r
, "Failed to get cache statistics: %s", bus_error_message(&error
, r
));
971 r
= sd_bus_message_read(reply
, "(ttt)",
976 return bus_log_parse_error(r
);
978 printf("\n%sCache%s\n"
979 " Current Cache Size: %" PRIu64
"\n"
980 " Cache Hits: %" PRIu64
"\n"
981 " Cache Misses: %" PRIu64
"\n",
988 reply
= sd_bus_message_unref(reply
);
990 r
= sd_bus_get_property(bus
,
991 "org.freedesktop.resolve1",
992 "/org/freedesktop/resolve1",
993 "org.freedesktop.resolve1.Manager",
999 return log_error_errno(r
, "Failed to get DNSSEC statistics: %s", bus_error_message(&error
, r
));
1001 r
= sd_bus_message_read(reply
, "(tttt)",
1005 &n_dnssec_indeterminate
);
1007 return bus_log_parse_error(r
);
1009 printf("\n%sDNSSEC Verdicts%s\n"
1010 " Secure: %" PRIu64
"\n"
1011 " Insecure: %" PRIu64
"\n"
1012 " Bogus: %" PRIu64
"\n"
1013 " Indeterminate: %" PRIu64
"\n",
1019 n_dnssec_indeterminate
);
1024 static int reset_statistics(sd_bus
*bus
) {
1025 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1028 r
= sd_bus_call_method(bus
,
1029 "org.freedesktop.resolve1",
1030 "/org/freedesktop/resolve1",
1031 "org.freedesktop.resolve1.Manager",
1037 return log_error_errno(r
, "Failed to reset statistics: %s", bus_error_message(&error
, r
));
1042 static int flush_caches(sd_bus
*bus
) {
1043 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1046 r
= sd_bus_call_method(bus
,
1047 "org.freedesktop.resolve1",
1048 "/org/freedesktop/resolve1",
1049 "org.freedesktop.resolve1.Manager",
1055 return log_error_errno(r
, "Failed to flush caches: %s", bus_error_message(&error
, r
));
1060 static int reset_server_features(sd_bus
*bus
) {
1061 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1064 r
= sd_bus_call_method(bus
,
1065 "org.freedesktop.resolve1",
1066 "/org/freedesktop/resolve1",
1067 "org.freedesktop.resolve1.Manager",
1068 "ResetServerFeatures",
1073 return log_error_errno(r
, "Failed to reset server features: %s", bus_error_message(&error
, r
));
1078 static int map_link_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1079 char ***l
= userdata
;
1087 r
= sd_bus_message_enter_container(m
, 'a', "(iay)");
1097 r
= sd_bus_message_enter_container(m
, 'r', "iay");
1103 r
= sd_bus_message_read(m
, "i", &family
);
1107 r
= sd_bus_message_read_array(m
, 'y', &a
, &sz
);
1111 r
= sd_bus_message_exit_container(m
);
1115 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
1116 log_debug("Unexpected family, ignoring.");
1120 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
1121 log_debug("Address size mismatch, ignoring.");
1125 r
= in_addr_to_string(family
, a
, &pretty
);
1129 r
= strv_consume(l
, pretty
);
1134 r
= sd_bus_message_exit_container(m
);
1141 static int map_link_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1142 char ***l
= userdata
;
1150 r
= sd_bus_message_enter_container(m
, 'a', "(sb)");
1159 r
= sd_bus_message_read(m
, "(sb)", &domain
, &route_only
);
1166 pretty
= strappend("~", domain
);
1168 pretty
= strdup(domain
);
1172 r
= strv_consume(l
, pretty
);
1177 r
= sd_bus_message_exit_container(m
);
1184 static int status_ifindex(sd_bus
*bus
, int ifindex
, const char *name
, bool *empty_line
) {
1187 uint64_t scopes_mask
;
1194 int dnssec_supported
;
1197 static const struct bus_properties_map property_map
[] = {
1198 { "ScopesMask", "t", NULL
, offsetof(struct link_info
, scopes_mask
) },
1199 { "DNS", "a(iay)", map_link_dns_servers
, offsetof(struct link_info
, dns
) },
1200 { "Domains", "a(sb)", map_link_domains
, offsetof(struct link_info
, domains
) },
1201 { "LLMNR", "s", NULL
, offsetof(struct link_info
, llmnr
) },
1202 { "MulticastDNS", "s", NULL
, offsetof(struct link_info
, mdns
) },
1203 { "DNSSEC", "s", NULL
, offsetof(struct link_info
, dnssec
) },
1204 { "DNSSECNegativeTrustAnchors", "as", NULL
, offsetof(struct link_info
, ntas
) },
1205 { "DNSSECSupported", "b", NULL
, offsetof(struct link_info
, dnssec_supported
) },
1209 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1210 _cleanup_free_
char *ifi
= NULL
, *p
= NULL
;
1211 char ifname
[IF_NAMESIZE
] = "";
1216 assert(ifindex
> 0);
1220 if (!if_indextoname(ifindex
, ifname
))
1221 return log_error_errno(errno
, "Failed to resolve interface name for %i: %m", ifindex
);
1226 if (asprintf(&ifi
, "%i", ifindex
) < 0)
1229 r
= sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi
, &p
);
1233 r
= bus_map_all_properties(bus
,
1234 "org.freedesktop.resolve1",
1240 log_error_errno(r
, "Failed to get link data for %i: %s", ifindex
, bus_error_message(&error
, r
));
1244 pager_open(arg_no_pager
, false);
1247 fputc('\n', stdout
);
1249 printf("%sLink %i (%s)%s\n",
1250 ansi_highlight(), ifindex
, name
, ansi_normal());
1252 if (link_info
.scopes_mask
== 0)
1253 printf(" Current Scopes: none\n");
1255 printf(" Current Scopes:%s%s%s%s%s\n",
1256 link_info
.scopes_mask
& SD_RESOLVED_DNS
? " DNS" : "",
1257 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
1258 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
1259 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
1260 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
1262 printf(" LLMNR setting: %s\n"
1263 "MulticastDNS setting: %s\n"
1264 " DNSSEC setting: %s\n"
1265 " DNSSEC supported: %s\n",
1266 strna(link_info
.llmnr
),
1267 strna(link_info
.mdns
),
1268 strna(link_info
.dnssec
),
1269 yes_no(link_info
.dnssec_supported
));
1271 STRV_FOREACH(i
, link_info
.dns
) {
1273 i
== link_info
.dns
? "DNS Servers:" : " ",
1277 STRV_FOREACH(i
, link_info
.domains
) {
1279 i
== link_info
.domains
? "DNS Domain:" : " ",
1283 STRV_FOREACH(i
, link_info
.ntas
) {
1285 i
== link_info
.ntas
? "DNSSEC NTA:" : " ",
1294 strv_free(link_info
.dns
);
1295 strv_free(link_info
.domains
);
1296 free(link_info
.llmnr
);
1297 free(link_info
.mdns
);
1298 free(link_info
.dnssec
);
1299 strv_free(link_info
.ntas
);
1303 static int map_global_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1304 char ***l
= userdata
;
1312 r
= sd_bus_message_enter_container(m
, 'a', "(iiay)");
1319 int family
, ifindex
;
1322 r
= sd_bus_message_enter_container(m
, 'r', "iiay");
1328 r
= sd_bus_message_read(m
, "ii", &ifindex
, &family
);
1332 r
= sd_bus_message_read_array(m
, 'y', &a
, &sz
);
1336 r
= sd_bus_message_exit_container(m
);
1340 if (ifindex
!= 0) /* only show the global ones here */
1343 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
1344 log_debug("Unexpected family, ignoring.");
1348 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
1349 log_debug("Address size mismatch, ignoring.");
1353 r
= in_addr_to_string(family
, a
, &pretty
);
1357 r
= strv_consume(l
, pretty
);
1362 r
= sd_bus_message_exit_container(m
);
1369 static int map_global_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1370 char ***l
= userdata
;
1378 r
= sd_bus_message_enter_container(m
, 'a', "(isb)");
1384 int route_only
, ifindex
;
1387 r
= sd_bus_message_read(m
, "(isb)", &ifindex
, &domain
, &route_only
);
1393 if (ifindex
!= 0) /* only show the global ones here */
1397 pretty
= strappend("~", domain
);
1399 pretty
= strdup(domain
);
1403 r
= strv_consume(l
, pretty
);
1408 r
= sd_bus_message_exit_container(m
);
1415 static int status_global(sd_bus
*bus
, bool *empty_line
) {
1417 struct global_info
{
1423 static const struct bus_properties_map property_map
[] = {
1424 { "DNS", "a(iiay)", map_global_dns_servers
, offsetof(struct global_info
, dns
) },
1425 { "Domains", "a(isb)", map_global_domains
, offsetof(struct global_info
, domains
) },
1426 { "DNSSECNegativeTrustAnchors", "as", NULL
, offsetof(struct global_info
, ntas
) },
1430 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1437 r
= bus_map_all_properties(bus
,
1438 "org.freedesktop.resolve1",
1439 "/org/freedesktop/resolve1",
1444 log_error_errno(r
, "Failed to get global data: %s", bus_error_message(&error
, r
));
1448 if (strv_isempty(global_info
.dns
) && strv_isempty(global_info
.domains
) && strv_isempty(global_info
.ntas
)) {
1453 pager_open(arg_no_pager
, false);
1455 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1456 STRV_FOREACH(i
, global_info
.dns
) {
1458 i
== global_info
.dns
? "DNS Servers:" : " ",
1462 STRV_FOREACH(i
, global_info
.domains
) {
1464 i
== global_info
.domains
? "DNS Domain:" : " ",
1468 strv_sort(global_info
.ntas
);
1469 STRV_FOREACH(i
, global_info
.ntas
) {
1471 i
== global_info
.ntas
? "DNSSEC NTA:" : " ",
1480 strv_free(global_info
.dns
);
1481 strv_free(global_info
.domains
);
1482 strv_free(global_info
.ntas
);
1487 static int status_all(sd_bus
*bus
) {
1488 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
1489 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
1490 sd_netlink_message
*i
;
1491 bool empty_line
= false;
1496 r
= status_global(bus
, &empty_line
);
1500 r
= sd_netlink_open(&rtnl
);
1502 return log_error_errno(r
, "Failed to connect to netlink: %m");
1504 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_GETLINK
, 0);
1506 return rtnl_log_create_error(r
);
1508 r
= sd_netlink_message_request_dump(req
, true);
1510 return rtnl_log_create_error(r
);
1512 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
1514 return log_error_errno(r
, "Failed to enumerate links: %m");
1517 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
1522 q
= sd_netlink_message_get_type(i
, &type
);
1524 return rtnl_log_parse_error(q
);
1526 if (type
!= RTM_NEWLINK
)
1529 q
= sd_rtnl_message_link_get_ifindex(i
, &ifindex
);
1531 return rtnl_log_parse_error(q
);
1533 if (ifindex
== LOOPBACK_IFINDEX
)
1536 q
= sd_netlink_message_read_string(i
, IFLA_IFNAME
, &name
);
1538 return rtnl_log_parse_error(q
);
1540 q
= status_ifindex(bus
, ifindex
, name
, &empty_line
);
1541 if (q
< 0 && r
>= 0)
1548 static void help_protocol_types(void) {
1550 puts("Known protocol types:");
1551 puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6\nmdns\nmnds-ipv4\nmdns-ipv6");
1554 static void help_dns_types(void) {
1559 puts("Known DNS RR types:");
1560 for (i
= 0; i
< _DNS_TYPE_MAX
; i
++) {
1561 t
= dns_type_to_string(i
);
1567 static void help_dns_classes(void) {
1572 puts("Known DNS RR classes:");
1573 for (i
= 0; i
< _DNS_CLASS_MAX
; i
++) {
1574 t
= dns_class_to_string(i
);
1580 static void help(void) {
1581 printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
1582 "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
1583 "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
1584 "%1$s [OPTIONS...] --statistics\n"
1585 "%1$s [OPTIONS...] --reset-statistics\n"
1587 "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n"
1588 " -h --help Show this help\n"
1589 " --version Show package version\n"
1590 " --no-pager Do not pipe output into a pager\n"
1591 " -4 Resolve IPv4 addresses\n"
1592 " -6 Resolve IPv6 addresses\n"
1593 " -i --interface=INTERFACE Look on interface\n"
1594 " -p --protocol=PROTO|help Look via protocol\n"
1595 " -t --type=TYPE|help Query RR with DNS type\n"
1596 " -c --class=CLASS|help Query RR with DNS class\n"
1597 " --service Resolve service (SRV)\n"
1598 " --service-address=BOOL Resolve address for services (default: yes)\n"
1599 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
1600 " --openpgp Query OpenPGP public key\n"
1601 " --tlsa Query TLS public key\n"
1602 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
1603 " --search=BOOL Use search domains for single-label names\n"
1605 " --raw[=payload|packet] Dump the answer as binary data\n"
1606 " --legend=BOOL Print headers and additional info (default: yes)\n"
1607 " --statistics Show resolver statistics\n"
1608 " --reset-statistics Reset resolver statistics\n"
1609 " --status Show link and server status\n"
1610 " --flush-caches Flush all local DNS caches\n"
1611 " --reset-server-features\n"
1612 " Forget learnt DNS server feature levels\n"
1613 , program_invocation_short_name
);
1616 static int parse_argv(int argc
, char *argv
[]) {
1618 ARG_VERSION
= 0x100,
1622 ARG_SERVICE_ADDRESS
,
1629 ARG_RESET_STATISTICS
,
1632 ARG_RESET_SERVER_FEATURES
,
1636 static const struct option options
[] = {
1637 { "help", no_argument
, NULL
, 'h' },
1638 { "version", no_argument
, NULL
, ARG_VERSION
},
1639 { "type", required_argument
, NULL
, 't' },
1640 { "class", required_argument
, NULL
, 'c' },
1641 { "legend", required_argument
, NULL
, ARG_LEGEND
},
1642 { "interface", required_argument
, NULL
, 'i' },
1643 { "protocol", required_argument
, NULL
, 'p' },
1644 { "cname", required_argument
, NULL
, ARG_CNAME
},
1645 { "service", no_argument
, NULL
, ARG_SERVICE
},
1646 { "service-address", required_argument
, NULL
, ARG_SERVICE_ADDRESS
},
1647 { "service-txt", required_argument
, NULL
, ARG_SERVICE_TXT
},
1648 { "openpgp", no_argument
, NULL
, ARG_OPENPGP
},
1649 { "tlsa", optional_argument
, NULL
, ARG_TLSA
},
1650 { "raw", optional_argument
, NULL
, ARG_RAW
},
1651 { "search", required_argument
, NULL
, ARG_SEARCH
},
1652 { "statistics", no_argument
, NULL
, ARG_STATISTICS
, },
1653 { "reset-statistics", no_argument
, NULL
, ARG_RESET_STATISTICS
},
1654 { "status", no_argument
, NULL
, ARG_STATUS
},
1655 { "flush-caches", no_argument
, NULL
, ARG_FLUSH_CACHES
},
1656 { "reset-server-features", no_argument
, NULL
, ARG_RESET_SERVER_FEATURES
},
1657 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
1666 while ((c
= getopt_long(argc
, argv
, "h46i:t:c:p:", options
, NULL
)) >= 0)
1671 return 0; /* done */;
1677 arg_family
= AF_INET
;
1681 arg_family
= AF_INET6
;
1687 if (parse_ifindex(optarg
, &ifi
) >= 0)
1690 ifi
= if_nametoindex(optarg
);
1692 return log_error_errno(errno
, "Unknown interface %s: %m", optarg
);
1701 if (streq(optarg
, "help")) {
1706 r
= dns_type_from_string(optarg
);
1708 log_error("Failed to parse RR record type %s", optarg
);
1711 arg_type
= (uint16_t) r
;
1712 assert((int) arg_type
== r
);
1714 arg_mode
= MODE_RESOLVE_RECORD
;
1718 if (streq(optarg
, "help")) {
1723 r
= dns_class_from_string(optarg
);
1725 log_error("Failed to parse RR record class %s", optarg
);
1728 arg_class
= (uint16_t) r
;
1729 assert((int) arg_class
== r
);
1734 r
= parse_boolean(optarg
);
1736 return log_error_errno(r
, "Failed to parse --legend= argument");
1742 if (streq(optarg
, "help")) {
1743 help_protocol_types();
1745 } else if (streq(optarg
, "dns"))
1746 arg_flags
|= SD_RESOLVED_DNS
;
1747 else if (streq(optarg
, "llmnr"))
1748 arg_flags
|= SD_RESOLVED_LLMNR
;
1749 else if (streq(optarg
, "llmnr-ipv4"))
1750 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
1751 else if (streq(optarg
, "llmnr-ipv6"))
1752 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
1753 else if (streq(optarg
, "mdns"))
1754 arg_flags
|= SD_RESOLVED_MDNS
;
1755 else if (streq(optarg
, "mdns-ipv4"))
1756 arg_flags
|= SD_RESOLVED_MDNS_IPV4
;
1757 else if (streq(optarg
, "mdns-ipv6"))
1758 arg_flags
|= SD_RESOLVED_MDNS_IPV6
;
1760 log_error("Unknown protocol specifier: %s", optarg
);
1767 arg_mode
= MODE_RESOLVE_SERVICE
;
1771 arg_mode
= MODE_RESOLVE_OPENPGP
;
1775 arg_mode
= MODE_RESOLVE_TLSA
;
1776 arg_service_family
= service_family_from_string(optarg
);
1777 if (arg_service_family
< 0) {
1778 log_error("Unknown service family \"%s\".", optarg
);
1785 log_error("Refusing to write binary data to tty.");
1789 if (optarg
== NULL
|| streq(optarg
, "payload"))
1790 arg_raw
= RAW_PAYLOAD
;
1791 else if (streq(optarg
, "packet"))
1792 arg_raw
= RAW_PACKET
;
1794 log_error("Unknown --raw specifier \"%s\".", optarg
);
1802 r
= parse_boolean(optarg
);
1804 return log_error_errno(r
, "Failed to parse --cname= argument.");
1805 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CNAME
, r
== 0);
1808 case ARG_SERVICE_ADDRESS
:
1809 r
= parse_boolean(optarg
);
1811 return log_error_errno(r
, "Failed to parse --service-address= argument.");
1812 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ADDRESS
, r
== 0);
1815 case ARG_SERVICE_TXT
:
1816 r
= parse_boolean(optarg
);
1818 return log_error_errno(r
, "Failed to parse --service-txt= argument.");
1819 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TXT
, r
== 0);
1823 r
= parse_boolean(optarg
);
1825 return log_error_errno(r
, "Failed to parse --search argument.");
1826 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SEARCH
, r
== 0);
1829 case ARG_STATISTICS
:
1830 arg_mode
= MODE_STATISTICS
;
1833 case ARG_RESET_STATISTICS
:
1834 arg_mode
= MODE_RESET_STATISTICS
;
1837 case ARG_FLUSH_CACHES
:
1838 arg_mode
= MODE_FLUSH_CACHES
;
1841 case ARG_RESET_SERVER_FEATURES
:
1842 arg_mode
= MODE_RESET_SERVER_FEATURES
;
1846 arg_mode
= MODE_STATUS
;
1850 arg_no_pager
= true;
1857 assert_not_reached("Unhandled option");
1860 if (arg_type
== 0 && arg_class
!= 0) {
1861 log_error("--class= may only be used in conjunction with --type=.");
1865 if (arg_type
!= 0 && arg_mode
== MODE_RESOLVE_SERVICE
) {
1866 log_error("--service and --type= may not be combined.");
1870 if (arg_type
!= 0 && arg_class
== 0)
1871 arg_class
= DNS_CLASS_IN
;
1873 if (arg_class
!= 0 && arg_type
== 0)
1874 arg_type
= DNS_TYPE_A
;
1876 return 1 /* work to do */;
1879 int main(int argc
, char **argv
) {
1880 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1883 log_parse_environment();
1886 r
= parse_argv(argc
, argv
);
1890 r
= sd_bus_open_system(&bus
);
1892 log_error_errno(r
, "sd_bus_open_system: %m");
1898 case MODE_RESOLVE_HOST
:
1899 if (optind
>= argc
) {
1900 log_error("No arguments passed.");
1905 while (argv
[optind
]) {
1906 int family
, ifindex
, k
;
1907 union in_addr_union a
;
1909 if (startswith(argv
[optind
], "dns:"))
1910 k
= resolve_rfc4501(bus
, argv
[optind
]);
1912 k
= in_addr_ifindex_from_string_auto(argv
[optind
], &family
, &a
, &ifindex
);
1914 k
= resolve_address(bus
, family
, &a
, ifindex
);
1916 k
= resolve_host(bus
, argv
[optind
]);
1926 case MODE_RESOLVE_RECORD
:
1927 if (optind
>= argc
) {
1928 log_error("No arguments passed.");
1933 while (argv
[optind
]) {
1936 k
= resolve_record(bus
, argv
[optind
], arg_class
, arg_type
, true);
1944 case MODE_RESOLVE_SERVICE
:
1945 if (argc
< optind
+ 1) {
1946 log_error("Domain specification required.");
1950 } else if (argc
== optind
+ 1)
1951 r
= resolve_service(bus
, NULL
, NULL
, argv
[optind
]);
1952 else if (argc
== optind
+ 2)
1953 r
= resolve_service(bus
, NULL
, argv
[optind
], argv
[optind
+1]);
1954 else if (argc
== optind
+ 3)
1955 r
= resolve_service(bus
, argv
[optind
], argv
[optind
+1], argv
[optind
+2]);
1957 log_error("Too many arguments.");
1964 case MODE_RESOLVE_OPENPGP
:
1965 if (argc
< optind
+ 1) {
1966 log_error("E-mail address required.");
1973 while (optind
< argc
) {
1976 k
= resolve_openpgp(bus
, argv
[optind
++]);
1982 case MODE_RESOLVE_TLSA
:
1983 if (argc
< optind
+ 1) {
1984 log_error("Domain name required.");
1991 while (optind
< argc
) {
1994 k
= resolve_tlsa(bus
, argv
[optind
++]);
2000 case MODE_STATISTICS
:
2001 if (argc
> optind
) {
2002 log_error("Too many arguments.");
2007 r
= show_statistics(bus
);
2010 case MODE_RESET_STATISTICS
:
2011 if (argc
> optind
) {
2012 log_error("Too many arguments.");
2017 r
= reset_statistics(bus
);
2020 case MODE_FLUSH_CACHES
:
2021 if (argc
> optind
) {
2022 log_error("Too many arguments.");
2027 r
= flush_caches(bus
);
2030 case MODE_RESET_SERVER_FEATURES
:
2031 if (argc
> optind
) {
2032 log_error("Too many arguments.");
2037 r
= reset_server_features(bus
);
2042 if (argc
> optind
) {
2044 bool empty_line
= false;
2047 STRV_FOREACH(ifname
, argv
+ optind
) {
2050 q
= parse_ifindex(argv
[optind
], &ifindex
);
2052 ifindex
= if_nametoindex(argv
[optind
]);
2054 log_error_errno(errno
, "Failed to resolve interface name: %s", argv
[optind
]);
2059 q
= status_ifindex(bus
, ifindex
, NULL
, &empty_line
);
2060 if (q
< 0 && r
>= 0)
2064 r
= status_all(bus
);
2072 return r
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;