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-common-errors.h"
30 #include "bus-error.h"
32 #include "dns-domain.h"
34 #include "gcrypt-util.h"
35 #include "in-addr-util.h"
36 #include "netlink-util.h"
38 #include "parse-util.h"
39 #include "resolved-def.h"
40 #include "resolved-dns-packet.h"
42 #include "terminal-util.h"
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
,
80 } arg_mode
= MODE_RESOLVE_HOST
;
82 static struct in_addr_data
*arg_set_dns
= NULL
;
83 static size_t arg_n_set_dns
= 0;
84 static char **arg_set_domain
= NULL
;
85 static char *arg_set_llmnr
= NULL
;
86 static char *arg_set_mdns
= NULL
;
87 static char *arg_set_dnssec
= NULL
;
88 static char **arg_set_nta
= NULL
;
90 static ServiceFamily
service_family_from_string(const char *s
) {
91 if (s
== NULL
|| streq(s
, "tcp"))
92 return SERVICE_FAMILY_TCP
;
94 return SERVICE_FAMILY_UDP
;
96 return SERVICE_FAMILY_SCTP
;
97 return _SERVICE_FAMILY_INVALID
;
100 static const char* service_family_to_string(ServiceFamily service
) {
102 case SERVICE_FAMILY_TCP
:
104 case SERVICE_FAMILY_UDP
:
106 case SERVICE_FAMILY_SCTP
:
109 assert_not_reached("invalid service");
113 static void print_source(uint64_t flags
, usec_t rtt
) {
114 char rtt_str
[FORMAT_TIMESTAMP_MAX
];
122 fputs("\n-- Information acquired via", stdout
);
125 printf(" protocol%s%s%s%s%s",
126 flags
& SD_RESOLVED_DNS
? " DNS" :"",
127 flags
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
128 flags
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
129 flags
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
130 flags
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
132 assert_se(format_timespan(rtt_str
, sizeof(rtt_str
), rtt
, 100));
134 printf(" in %s", rtt_str
);
139 printf("-- Data is authenticated: %s\n", yes_no(flags
& SD_RESOLVED_AUTHENTICATED
));
142 static int resolve_host(sd_bus
*bus
, const char *name
) {
144 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
145 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
146 const char *canonical
= NULL
;
147 char ifname
[IF_NAMESIZE
] = "";
155 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
156 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
158 log_debug("Resolving %s (family %s, interface %s).", name
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
160 r
= sd_bus_message_new_method_call(
163 "org.freedesktop.resolve1",
164 "/org/freedesktop/resolve1",
165 "org.freedesktop.resolve1.Manager",
168 return bus_log_create_error(r
);
170 r
= sd_bus_message_append(req
, "isit", arg_ifindex
, name
, arg_family
, arg_flags
);
172 return bus_log_create_error(r
);
174 ts
= now(CLOCK_MONOTONIC
);
176 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
178 return log_error_errno(r
, "%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
180 ts
= now(CLOCK_MONOTONIC
) - ts
;
182 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
184 return bus_log_parse_error(r
);
186 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
187 _cleanup_free_
char *pretty
= NULL
;
192 assert_cc(sizeof(int) == sizeof(int32_t));
194 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
196 return bus_log_parse_error(r
);
198 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
200 return bus_log_parse_error(r
);
202 r
= sd_bus_message_exit_container(reply
);
204 return bus_log_parse_error(r
);
206 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
207 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
211 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
212 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
217 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
218 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
220 r
= in_addr_ifindex_to_string(family
, a
, ifindex
, &pretty
);
222 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
224 printf("%*s%s %s%s%s\n",
225 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
227 isempty(ifname
) ? "" : "%", ifname
);
232 return bus_log_parse_error(r
);
234 r
= sd_bus_message_exit_container(reply
);
236 return bus_log_parse_error(r
);
238 r
= sd_bus_message_read(reply
, "st", &canonical
, &flags
);
240 return bus_log_parse_error(r
);
242 if (!streq(name
, canonical
))
243 printf("%*s%s (%s)\n",
244 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
248 log_error("%s: no addresses found", name
);
252 print_source(flags
, ts
);
257 static int resolve_address(sd_bus
*bus
, int family
, const union in_addr_union
*address
, int ifindex
) {
258 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
259 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
260 _cleanup_free_
char *pretty
= NULL
;
261 char ifname
[IF_NAMESIZE
] = "";
268 assert(IN_SET(family
, AF_INET
, AF_INET6
));
272 ifindex
= arg_ifindex
;
274 r
= in_addr_ifindex_to_string(family
, address
, ifindex
, &pretty
);
278 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
279 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
281 log_debug("Resolving %s%s%s.", pretty
, isempty(ifname
) ? "" : "%", ifname
);
283 r
= sd_bus_message_new_method_call(
286 "org.freedesktop.resolve1",
287 "/org/freedesktop/resolve1",
288 "org.freedesktop.resolve1.Manager",
291 return bus_log_create_error(r
);
293 r
= sd_bus_message_append(req
, "ii", ifindex
, family
);
295 return bus_log_create_error(r
);
297 r
= sd_bus_message_append_array(req
, 'y', address
, FAMILY_ADDRESS_SIZE(family
));
299 return bus_log_create_error(r
);
301 r
= sd_bus_message_append(req
, "t", arg_flags
);
303 return bus_log_create_error(r
);
305 ts
= now(CLOCK_MONOTONIC
);
307 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
309 log_error("%s: resolve call failed: %s", pretty
, bus_error_message(&error
, r
));
313 ts
= now(CLOCK_MONOTONIC
) - ts
;
315 r
= sd_bus_message_enter_container(reply
, 'a', "(is)");
317 return bus_log_create_error(r
);
319 while ((r
= sd_bus_message_enter_container(reply
, 'r', "is")) > 0) {
322 assert_cc(sizeof(int) == sizeof(int32_t));
324 r
= sd_bus_message_read(reply
, "is", &ifindex
, &n
);
328 r
= sd_bus_message_exit_container(reply
);
333 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
334 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
336 printf("%*s%*s%*s%s %s\n",
337 (int) strlen(pretty
), c
== 0 ? pretty
: "",
338 isempty(ifname
) ? 0 : 1, c
> 0 || isempty(ifname
) ? "" : "%",
339 (int) strlen(ifname
), c
== 0 ? ifname
: "",
346 return bus_log_parse_error(r
);
348 r
= sd_bus_message_exit_container(reply
);
350 return bus_log_parse_error(r
);
352 r
= sd_bus_message_read(reply
, "t", &flags
);
354 return bus_log_parse_error(r
);
357 log_error("%s: no names found", pretty
);
361 print_source(flags
, ts
);
366 static int output_rr_packet(const void *d
, size_t l
, int ifindex
) {
367 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
368 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
370 char ifname
[IF_NAMESIZE
] = "";
372 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0, DNS_PACKET_SIZE_MAX
);
376 p
->refuse_compression
= true;
378 r
= dns_packet_append_blob(p
, d
, l
, NULL
);
382 r
= dns_packet_read_rr(p
, &rr
, NULL
, NULL
);
384 return log_error_errno(r
, "Failed to parse RR: %m");
386 if (arg_raw
== RAW_PAYLOAD
) {
390 k
= dns_resource_record_payload(rr
, &data
);
392 return log_error_errno(k
, "Cannot dump RR: %m");
393 fwrite(data
, 1, k
, stdout
);
397 s
= dns_resource_record_to_string(rr
);
401 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
402 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
404 printf("%s%s%s\n", s
, isempty(ifname
) ? "" : " # interface ", ifname
);
410 static int resolve_record(sd_bus
*bus
, const char *name
, uint16_t class, uint16_t type
, bool warn_missing
) {
411 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
412 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
413 char ifname
[IF_NAMESIZE
] = "";
418 bool needs_authentication
= false;
422 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
423 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
425 log_debug("Resolving %s %s %s (interface %s).", name
, dns_class_to_string(class), dns_type_to_string(type
), isempty(ifname
) ? "*" : ifname
);
427 r
= sd_bus_message_new_method_call(
430 "org.freedesktop.resolve1",
431 "/org/freedesktop/resolve1",
432 "org.freedesktop.resolve1.Manager",
435 return bus_log_create_error(r
);
437 r
= sd_bus_message_append(req
, "isqqt", arg_ifindex
, name
, class, type
, arg_flags
);
439 return bus_log_create_error(r
);
441 ts
= now(CLOCK_MONOTONIC
);
443 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
445 if (warn_missing
|| r
!= -ENXIO
)
446 log_error("%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
450 ts
= now(CLOCK_MONOTONIC
) - ts
;
452 r
= sd_bus_message_enter_container(reply
, 'a', "(iqqay)");
454 return bus_log_parse_error(r
);
456 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iqqay")) > 0) {
462 assert_cc(sizeof(int) == sizeof(int32_t));
464 r
= sd_bus_message_read(reply
, "iqq", &ifindex
, &c
, &t
);
466 return bus_log_parse_error(r
);
468 r
= sd_bus_message_read_array(reply
, 'y', &d
, &l
);
470 return bus_log_parse_error(r
);
472 r
= sd_bus_message_exit_container(reply
);
474 return bus_log_parse_error(r
);
476 if (arg_raw
== RAW_PACKET
) {
477 uint64_t u64
= htole64(l
);
479 fwrite(&u64
, sizeof(u64
), 1, stdout
);
480 fwrite(d
, 1, l
, stdout
);
482 r
= output_rr_packet(d
, l
, ifindex
);
487 if (dns_type_needs_authentication(t
))
488 needs_authentication
= true;
493 return bus_log_parse_error(r
);
495 r
= sd_bus_message_exit_container(reply
);
497 return bus_log_parse_error(r
);
499 r
= sd_bus_message_read(reply
, "t", &flags
);
501 return bus_log_parse_error(r
);
505 log_error("%s: no records found", name
);
509 print_source(flags
, ts
);
511 if ((flags
& SD_RESOLVED_AUTHENTICATED
) == 0 && needs_authentication
) {
514 fprintf(stderr
, "\n%s"
515 "WARNING: The resources shown contain cryptographic key data which could not be\n"
516 " authenticated. It is not suitable to authenticate any communication.\n"
517 " This is usually indication that DNSSEC authentication was not enabled\n"
518 " or is not available for the selected protocol or DNS servers.%s\n",
519 ansi_highlight_red(),
526 static int resolve_rfc4501(sd_bus
*bus
, const char *name
) {
527 uint16_t type
= 0, class = 0;
528 const char *p
, *q
, *n
;
533 assert(startswith(name
, "dns:"));
535 /* Parse RFC 4501 dns: URIs */
545 e
= strchr(p
+ 2, '/');
550 log_warning("DNS authority specification not supported; ignoring specified authority.");
557 n
= strndupa(p
, q
- p
);
563 f
= startswith_no_case(q
, "class=");
565 _cleanup_free_
char *t
= NULL
;
569 log_error("DNS class specified twice.");
573 e
= strchrnul(f
, ';');
574 t
= strndup(f
, e
- f
);
578 r
= dns_class_from_string(t
);
580 log_error("Unknown DNS class %s.", t
);
594 f
= startswith_no_case(q
, "type=");
596 _cleanup_free_
char *t
= NULL
;
600 log_error("DNS type specified twice.");
604 e
= strchrnul(f
, ';');
605 t
= strndup(f
, e
- f
);
609 r
= dns_type_from_string(t
);
611 log_error("Unknown DNS type %s.", t
);
631 class = arg_class
?: DNS_CLASS_IN
;
633 type
= arg_type
?: DNS_TYPE_A
;
635 return resolve_record(bus
, n
, class, type
, true);
638 log_error("Invalid DNS URI: %s", name
);
642 static int resolve_service(sd_bus
*bus
, const char *name
, const char *type
, const char *domain
) {
643 const char *canonical_name
, *canonical_type
, *canonical_domain
;
644 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
645 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
646 char ifname
[IF_NAMESIZE
] = "";
657 name
= empty_to_null(name
);
658 type
= empty_to_null(type
);
660 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
661 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
664 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
);
666 log_debug("Resolving service type %s of %s (family %s, interface %s).", type
, domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
668 log_debug("Resolving service type %s (family %s, interface %s).", domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
670 r
= sd_bus_message_new_method_call(
673 "org.freedesktop.resolve1",
674 "/org/freedesktop/resolve1",
675 "org.freedesktop.resolve1.Manager",
678 return bus_log_create_error(r
);
680 r
= sd_bus_message_append(req
, "isssit", arg_ifindex
, name
, type
, domain
, arg_family
, arg_flags
);
682 return bus_log_create_error(r
);
684 ts
= now(CLOCK_MONOTONIC
);
686 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
688 return log_error_errno(r
, "Resolve call failed: %s", bus_error_message(&error
, r
));
690 ts
= now(CLOCK_MONOTONIC
) - ts
;
692 r
= sd_bus_message_enter_container(reply
, 'a', "(qqqsa(iiay)s)");
694 return bus_log_parse_error(r
);
697 (name
? strlen(name
) + 1 : 0) +
698 (type
? strlen(type
) + 1 : 0) +
702 while ((r
= sd_bus_message_enter_container(reply
, 'r', "qqqsa(iiay)s")) > 0) {
703 uint16_t priority
, weight
, port
;
704 const char *hostname
, *canonical
;
706 r
= sd_bus_message_read(reply
, "qqqs", &priority
, &weight
, &port
, &hostname
);
708 return bus_log_parse_error(r
);
711 printf("%*s%s", (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? "/" : " ");
713 printf("%*s%s", (int) strlen(type
), c
== 0 ? type
: "", c
== 0 ? "/" : " ");
715 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
716 (int) strlen(domain
), c
== 0 ? domain
: "",
721 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
723 return bus_log_parse_error(r
);
725 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
726 _cleanup_free_
char *pretty
= NULL
;
730 assert_cc(sizeof(int) == sizeof(int32_t));
732 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
734 return bus_log_parse_error(r
);
736 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
738 return bus_log_parse_error(r
);
740 r
= sd_bus_message_exit_container(reply
);
742 return bus_log_parse_error(r
);
744 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
745 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
749 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
750 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
755 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
756 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
758 r
= in_addr_to_string(family
, a
, &pretty
);
760 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
762 printf("%*s%s%s%s\n", (int) indent
, "", pretty
, isempty(ifname
) ? "" : "%s", ifname
);
765 return bus_log_parse_error(r
);
767 r
= sd_bus_message_exit_container(reply
);
769 return bus_log_parse_error(r
);
771 r
= sd_bus_message_read(reply
, "s", &canonical
);
773 return bus_log_parse_error(r
);
775 if (!streq(hostname
, canonical
))
776 printf("%*s(%s)\n", (int) indent
, "", canonical
);
778 r
= sd_bus_message_exit_container(reply
);
780 return bus_log_parse_error(r
);
785 return bus_log_parse_error(r
);
787 r
= sd_bus_message_exit_container(reply
);
789 return bus_log_parse_error(r
);
791 r
= sd_bus_message_enter_container(reply
, 'a', "ay");
793 return bus_log_parse_error(r
);
795 while ((r
= sd_bus_message_read_array(reply
, 'y', (const void**) &p
, &sz
)) > 0) {
796 _cleanup_free_
char *escaped
= NULL
;
798 escaped
= cescape_length(p
, sz
);
802 printf("%*s%s\n", (int) indent
, "", escaped
);
805 return bus_log_parse_error(r
);
807 r
= sd_bus_message_exit_container(reply
);
809 return bus_log_parse_error(r
);
811 r
= sd_bus_message_read(reply
, "ssst", &canonical_name
, &canonical_type
, &canonical_domain
, &flags
);
813 return bus_log_parse_error(r
);
815 canonical_name
= empty_to_null(canonical_name
);
816 canonical_type
= empty_to_null(canonical_type
);
818 if (!streq_ptr(name
, canonical_name
) ||
819 !streq_ptr(type
, canonical_type
) ||
820 !streq_ptr(domain
, canonical_domain
)) {
822 printf("%*s(", (int) indent
, "");
825 printf("%s/", canonical_name
);
827 printf("%s/", canonical_type
);
829 printf("%s)\n", canonical_domain
);
832 print_source(flags
, ts
);
837 static int resolve_openpgp(sd_bus
*bus
, const char *address
) {
838 const char *domain
, *full
;
840 _cleanup_free_
char *hashed
= NULL
;
845 domain
= strrchr(address
, '@');
847 log_error("Address does not contain '@': \"%s\"", address
);
849 } else if (domain
== address
|| domain
[1] == '\0') {
850 log_error("Address starts or ends with '@': \"%s\"", address
);
855 r
= string_hashsum_sha256(address
, domain
- 1 - address
, &hashed
);
857 return log_error_errno(r
, "Hashing failed: %m");
859 strshorten(hashed
, 56);
861 full
= strjoina(hashed
, "._openpgpkey.", domain
);
862 log_debug("Looking up \"%s\".", full
);
864 r
= resolve_record(bus
, full
,
865 arg_class
?: DNS_CLASS_IN
,
866 arg_type
?: DNS_TYPE_OPENPGPKEY
, false);
868 if (IN_SET(r
, -ENXIO
, -ESRCH
)) { /* NXDOMAIN or NODATA? */
870 r
= string_hashsum_sha224(address
, domain
- 1 - address
, &hashed
);
872 return log_error_errno(r
, "Hashing failed: %m");
874 full
= strjoina(hashed
, "._openpgpkey.", domain
);
875 log_debug("Looking up \"%s\".", full
);
877 return resolve_record(bus
, full
,
878 arg_class
?: DNS_CLASS_IN
,
879 arg_type
?: DNS_TYPE_OPENPGPKEY
, true);
885 static int resolve_tlsa(sd_bus
*bus
, const char *address
) {
887 uint16_t port_num
= 443;
888 _cleanup_free_
char *full
= NULL
;
894 port
= strrchr(address
, ':');
896 r
= parse_ip_port(port
+ 1, &port_num
);
898 return log_error_errno(r
, "Invalid port \"%s\".", port
+ 1);
900 address
= strndupa(address
, port
- address
);
903 r
= asprintf(&full
, "_%u.%s.%s",
905 service_family_to_string(arg_service_family
),
910 log_debug("Looking up \"%s\".", full
);
912 return resolve_record(bus
, full
,
913 arg_class
?: DNS_CLASS_IN
,
914 arg_type
?: DNS_TYPE_TLSA
, true);
917 static int show_statistics(sd_bus
*bus
) {
918 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
919 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
920 uint64_t n_current_transactions
, n_total_transactions
,
921 cache_size
, n_cache_hit
, n_cache_miss
,
922 n_dnssec_secure
, n_dnssec_insecure
, n_dnssec_bogus
, n_dnssec_indeterminate
;
923 int r
, dnssec_supported
;
927 r
= sd_bus_get_property_trivial(bus
,
928 "org.freedesktop.resolve1",
929 "/org/freedesktop/resolve1",
930 "org.freedesktop.resolve1.Manager",
936 return log_error_errno(r
, "Failed to get DNSSEC supported state: %s", bus_error_message(&error
, r
));
938 printf("DNSSEC supported by current servers: %s%s%s\n\n",
940 yes_no(dnssec_supported
),
943 r
= sd_bus_get_property(bus
,
944 "org.freedesktop.resolve1",
945 "/org/freedesktop/resolve1",
946 "org.freedesktop.resolve1.Manager",
947 "TransactionStatistics",
952 return log_error_errno(r
, "Failed to get transaction statistics: %s", bus_error_message(&error
, r
));
954 r
= sd_bus_message_read(reply
, "(tt)",
955 &n_current_transactions
,
956 &n_total_transactions
);
958 return bus_log_parse_error(r
);
960 printf("%sTransactions%s\n"
961 "Current Transactions: %" PRIu64
"\n"
962 " Total Transactions: %" PRIu64
"\n",
965 n_current_transactions
,
966 n_total_transactions
);
968 reply
= sd_bus_message_unref(reply
);
970 r
= sd_bus_get_property(bus
,
971 "org.freedesktop.resolve1",
972 "/org/freedesktop/resolve1",
973 "org.freedesktop.resolve1.Manager",
979 return log_error_errno(r
, "Failed to get cache statistics: %s", bus_error_message(&error
, r
));
981 r
= sd_bus_message_read(reply
, "(ttt)",
986 return bus_log_parse_error(r
);
988 printf("\n%sCache%s\n"
989 " Current Cache Size: %" PRIu64
"\n"
990 " Cache Hits: %" PRIu64
"\n"
991 " Cache Misses: %" PRIu64
"\n",
998 reply
= sd_bus_message_unref(reply
);
1000 r
= sd_bus_get_property(bus
,
1001 "org.freedesktop.resolve1",
1002 "/org/freedesktop/resolve1",
1003 "org.freedesktop.resolve1.Manager",
1009 return log_error_errno(r
, "Failed to get DNSSEC statistics: %s", bus_error_message(&error
, r
));
1011 r
= sd_bus_message_read(reply
, "(tttt)",
1015 &n_dnssec_indeterminate
);
1017 return bus_log_parse_error(r
);
1019 printf("\n%sDNSSEC Verdicts%s\n"
1020 " Secure: %" PRIu64
"\n"
1021 " Insecure: %" PRIu64
"\n"
1022 " Bogus: %" PRIu64
"\n"
1023 " Indeterminate: %" PRIu64
"\n",
1029 n_dnssec_indeterminate
);
1034 static int reset_statistics(sd_bus
*bus
) {
1035 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1038 r
= sd_bus_call_method(bus
,
1039 "org.freedesktop.resolve1",
1040 "/org/freedesktop/resolve1",
1041 "org.freedesktop.resolve1.Manager",
1047 return log_error_errno(r
, "Failed to reset statistics: %s", bus_error_message(&error
, r
));
1052 static int flush_caches(sd_bus
*bus
) {
1053 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1056 r
= sd_bus_call_method(bus
,
1057 "org.freedesktop.resolve1",
1058 "/org/freedesktop/resolve1",
1059 "org.freedesktop.resolve1.Manager",
1065 return log_error_errno(r
, "Failed to flush caches: %s", bus_error_message(&error
, r
));
1070 static int reset_server_features(sd_bus
*bus
) {
1071 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1074 r
= sd_bus_call_method(bus
,
1075 "org.freedesktop.resolve1",
1076 "/org/freedesktop/resolve1",
1077 "org.freedesktop.resolve1.Manager",
1078 "ResetServerFeatures",
1083 return log_error_errno(r
, "Failed to reset server features: %s", bus_error_message(&error
, r
));
1088 static int map_link_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1089 char ***l
= userdata
;
1097 r
= sd_bus_message_enter_container(m
, 'a', "(iay)");
1107 r
= sd_bus_message_enter_container(m
, 'r', "iay");
1113 r
= sd_bus_message_read(m
, "i", &family
);
1117 r
= sd_bus_message_read_array(m
, 'y', &a
, &sz
);
1121 r
= sd_bus_message_exit_container(m
);
1125 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
1126 log_debug("Unexpected family, ignoring.");
1130 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
1131 log_debug("Address size mismatch, ignoring.");
1135 r
= in_addr_to_string(family
, a
, &pretty
);
1139 r
= strv_consume(l
, pretty
);
1144 r
= sd_bus_message_exit_container(m
);
1151 static int map_link_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1152 char ***l
= userdata
;
1160 r
= sd_bus_message_enter_container(m
, 'a', "(sb)");
1169 r
= sd_bus_message_read(m
, "(sb)", &domain
, &route_only
);
1176 pretty
= strappend("~", domain
);
1178 pretty
= strdup(domain
);
1182 r
= strv_consume(l
, pretty
);
1187 r
= sd_bus_message_exit_container(m
);
1194 static int status_ifindex(sd_bus
*bus
, int ifindex
, const char *name
, bool *empty_line
) {
1197 uint64_t scopes_mask
;
1204 int dnssec_supported
;
1207 static const struct bus_properties_map property_map
[] = {
1208 { "ScopesMask", "t", NULL
, offsetof(struct link_info
, scopes_mask
) },
1209 { "DNS", "a(iay)", map_link_dns_servers
, offsetof(struct link_info
, dns
) },
1210 { "Domains", "a(sb)", map_link_domains
, offsetof(struct link_info
, domains
) },
1211 { "LLMNR", "s", NULL
, offsetof(struct link_info
, llmnr
) },
1212 { "MulticastDNS", "s", NULL
, offsetof(struct link_info
, mdns
) },
1213 { "DNSSEC", "s", NULL
, offsetof(struct link_info
, dnssec
) },
1214 { "DNSSECNegativeTrustAnchors", "as", NULL
, offsetof(struct link_info
, ntas
) },
1215 { "DNSSECSupported", "b", NULL
, offsetof(struct link_info
, dnssec_supported
) },
1219 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1220 _cleanup_free_
char *ifi
= NULL
, *p
= NULL
;
1221 char ifname
[IF_NAMESIZE
] = "";
1226 assert(ifindex
> 0);
1230 if (!if_indextoname(ifindex
, ifname
))
1231 return log_error_errno(errno
, "Failed to resolve interface name for %i: %m", ifindex
);
1236 if (asprintf(&ifi
, "%i", ifindex
) < 0)
1239 r
= sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi
, &p
);
1243 r
= bus_map_all_properties(bus
,
1244 "org.freedesktop.resolve1",
1250 log_error_errno(r
, "Failed to get link data for %i: %s", ifindex
, bus_error_message(&error
, r
));
1254 pager_open(arg_no_pager
, false);
1257 fputc('\n', stdout
);
1259 printf("%sLink %i (%s)%s\n",
1260 ansi_highlight(), ifindex
, name
, ansi_normal());
1262 if (link_info
.scopes_mask
== 0)
1263 printf(" Current Scopes: none\n");
1265 printf(" Current Scopes:%s%s%s%s%s\n",
1266 link_info
.scopes_mask
& SD_RESOLVED_DNS
? " DNS" : "",
1267 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
1268 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
1269 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
1270 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
1272 printf(" LLMNR setting: %s\n"
1273 "MulticastDNS setting: %s\n"
1274 " DNSSEC setting: %s\n"
1275 " DNSSEC supported: %s\n",
1276 strna(link_info
.llmnr
),
1277 strna(link_info
.mdns
),
1278 strna(link_info
.dnssec
),
1279 yes_no(link_info
.dnssec_supported
));
1281 STRV_FOREACH(i
, link_info
.dns
) {
1283 i
== link_info
.dns
? "DNS Servers:" : " ",
1287 STRV_FOREACH(i
, link_info
.domains
) {
1289 i
== link_info
.domains
? "DNS Domain:" : " ",
1293 STRV_FOREACH(i
, link_info
.ntas
) {
1295 i
== link_info
.ntas
? "DNSSEC NTA:" : " ",
1304 strv_free(link_info
.dns
);
1305 strv_free(link_info
.domains
);
1306 free(link_info
.llmnr
);
1307 free(link_info
.mdns
);
1308 free(link_info
.dnssec
);
1309 strv_free(link_info
.ntas
);
1313 static int map_global_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1314 char ***l
= userdata
;
1322 r
= sd_bus_message_enter_container(m
, 'a', "(iiay)");
1329 int family
, ifindex
;
1332 r
= sd_bus_message_enter_container(m
, 'r', "iiay");
1338 r
= sd_bus_message_read(m
, "ii", &ifindex
, &family
);
1342 r
= sd_bus_message_read_array(m
, 'y', &a
, &sz
);
1346 r
= sd_bus_message_exit_container(m
);
1350 if (ifindex
!= 0) /* only show the global ones here */
1353 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
1354 log_debug("Unexpected family, ignoring.");
1358 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
1359 log_debug("Address size mismatch, ignoring.");
1363 r
= in_addr_to_string(family
, a
, &pretty
);
1367 r
= strv_consume(l
, pretty
);
1372 r
= sd_bus_message_exit_container(m
);
1379 static int map_global_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1380 char ***l
= userdata
;
1388 r
= sd_bus_message_enter_container(m
, 'a', "(isb)");
1394 int route_only
, ifindex
;
1397 r
= sd_bus_message_read(m
, "(isb)", &ifindex
, &domain
, &route_only
);
1403 if (ifindex
!= 0) /* only show the global ones here */
1407 pretty
= strappend("~", domain
);
1409 pretty
= strdup(domain
);
1413 r
= strv_consume(l
, pretty
);
1418 r
= sd_bus_message_exit_container(m
);
1425 static int status_global(sd_bus
*bus
, bool *empty_line
) {
1427 struct global_info
{
1433 static const struct bus_properties_map property_map
[] = {
1434 { "DNS", "a(iiay)", map_global_dns_servers
, offsetof(struct global_info
, dns
) },
1435 { "Domains", "a(isb)", map_global_domains
, offsetof(struct global_info
, domains
) },
1436 { "DNSSECNegativeTrustAnchors", "as", NULL
, offsetof(struct global_info
, ntas
) },
1440 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1447 r
= bus_map_all_properties(bus
,
1448 "org.freedesktop.resolve1",
1449 "/org/freedesktop/resolve1",
1454 log_error_errno(r
, "Failed to get global data: %s", bus_error_message(&error
, r
));
1458 if (strv_isempty(global_info
.dns
) && strv_isempty(global_info
.domains
) && strv_isempty(global_info
.ntas
)) {
1463 pager_open(arg_no_pager
, false);
1465 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1466 STRV_FOREACH(i
, global_info
.dns
) {
1468 i
== global_info
.dns
? "DNS Servers:" : " ",
1472 STRV_FOREACH(i
, global_info
.domains
) {
1474 i
== global_info
.domains
? "DNS Domain:" : " ",
1478 strv_sort(global_info
.ntas
);
1479 STRV_FOREACH(i
, global_info
.ntas
) {
1481 i
== global_info
.ntas
? "DNSSEC NTA:" : " ",
1490 strv_free(global_info
.dns
);
1491 strv_free(global_info
.domains
);
1492 strv_free(global_info
.ntas
);
1497 static int status_all(sd_bus
*bus
) {
1498 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
1499 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
1500 sd_netlink_message
*i
;
1501 bool empty_line
= false;
1506 r
= status_global(bus
, &empty_line
);
1510 r
= sd_netlink_open(&rtnl
);
1512 return log_error_errno(r
, "Failed to connect to netlink: %m");
1514 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_GETLINK
, 0);
1516 return rtnl_log_create_error(r
);
1518 r
= sd_netlink_message_request_dump(req
, true);
1520 return rtnl_log_create_error(r
);
1522 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
1524 return log_error_errno(r
, "Failed to enumerate links: %m");
1527 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
1532 q
= sd_netlink_message_get_type(i
, &type
);
1534 return rtnl_log_parse_error(q
);
1536 if (type
!= RTM_NEWLINK
)
1539 q
= sd_rtnl_message_link_get_ifindex(i
, &ifindex
);
1541 return rtnl_log_parse_error(q
);
1543 if (ifindex
== LOOPBACK_IFINDEX
)
1546 q
= sd_netlink_message_read_string(i
, IFLA_IFNAME
, &name
);
1548 return rtnl_log_parse_error(q
);
1550 q
= status_ifindex(bus
, ifindex
, name
, &empty_line
);
1551 if (q
< 0 && r
>= 0)
1558 static int set_link(sd_bus
*bus
) {
1559 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1564 if (arg_n_set_dns
> 0) {
1565 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
1568 q
= sd_bus_message_new_method_call(
1571 "org.freedesktop.resolve1",
1572 "/org/freedesktop/resolve1",
1573 "org.freedesktop.resolve1.Manager",
1576 return bus_log_create_error(q
);
1578 q
= sd_bus_message_append(req
, "i", arg_ifindex
);
1580 return bus_log_create_error(q
);
1582 q
= sd_bus_message_open_container(req
, 'a', "(iay)");
1584 return bus_log_create_error(q
);
1586 for (i
= 0; i
< arg_n_set_dns
; i
++) {
1587 q
= sd_bus_message_open_container(req
, 'r', "iay");
1589 return bus_log_create_error(q
);
1591 q
= sd_bus_message_append(req
, "i", arg_set_dns
[i
].family
);
1593 return bus_log_create_error(q
);
1595 q
= sd_bus_message_append_array(req
, 'y', &arg_set_dns
[i
].address
, FAMILY_ADDRESS_SIZE(arg_set_dns
[i
].family
));
1597 return bus_log_create_error(q
);
1599 q
= sd_bus_message_close_container(req
);
1601 return bus_log_create_error(q
);
1604 q
= sd_bus_message_close_container(req
);
1606 return bus_log_create_error(q
);
1608 q
= sd_bus_call(bus
, req
, 0, &error
, NULL
);
1610 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1613 log_error_errno(q
, "Failed to set DNS configuration: %s", bus_error_message(&error
, q
));
1619 if (!strv_isempty(arg_set_domain
)) {
1620 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
1623 q
= sd_bus_message_new_method_call(
1626 "org.freedesktop.resolve1",
1627 "/org/freedesktop/resolve1",
1628 "org.freedesktop.resolve1.Manager",
1631 return bus_log_create_error(q
);
1633 q
= sd_bus_message_append(req
, "i", arg_ifindex
);
1635 return bus_log_create_error(q
);
1637 q
= sd_bus_message_open_container(req
, 'a', "(sb)");
1639 return bus_log_create_error(q
);
1641 STRV_FOREACH(p
, arg_set_domain
) {
1644 n
= **p
== '~' ? *p
+ 1 : *p
;
1645 q
= sd_bus_message_append(req
, "(sb)", n
, **p
== '~');
1647 return bus_log_create_error(q
);
1650 q
= sd_bus_message_close_container(req
);
1652 return bus_log_create_error(q
);
1654 q
= sd_bus_call(bus
, req
, 0, &error
, NULL
);
1656 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1659 log_error_errno(q
, "Failed to set domain configuration: %s", bus_error_message(&error
, q
));
1665 if (arg_set_llmnr
) {
1666 q
= sd_bus_call_method(bus
,
1667 "org.freedesktop.resolve1",
1668 "/org/freedesktop/resolve1",
1669 "org.freedesktop.resolve1.Manager",
1673 "is", arg_ifindex
, arg_set_llmnr
);
1675 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1678 log_error_errno(q
, "Failed to set LLMNR configuration: %s", bus_error_message(&error
, q
));
1685 q
= sd_bus_call_method(bus
,
1686 "org.freedesktop.resolve1",
1687 "/org/freedesktop/resolve1",
1688 "org.freedesktop.resolve1.Manager",
1689 "SetLinkMulticastDNS",
1692 "is", arg_ifindex
, arg_set_mdns
);
1694 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1697 log_error_errno(q
, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error
, q
));
1703 if (arg_set_dnssec
) {
1704 q
= sd_bus_call_method(bus
,
1705 "org.freedesktop.resolve1",
1706 "/org/freedesktop/resolve1",
1707 "org.freedesktop.resolve1.Manager",
1711 "is", arg_ifindex
, arg_set_dnssec
);
1713 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1716 log_error_errno(q
, "Failed to set DNSSEC configuration: %s", bus_error_message(&error
, q
));
1722 if (!strv_isempty(arg_set_nta
)) {
1723 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
1725 q
= sd_bus_message_new_method_call(
1728 "org.freedesktop.resolve1",
1729 "/org/freedesktop/resolve1",
1730 "org.freedesktop.resolve1.Manager",
1731 "SetLinkDNSSECNegativeTrustAnchors");
1733 return bus_log_create_error(q
);
1735 q
= sd_bus_message_append(req
, "i", arg_ifindex
);
1737 return bus_log_create_error(q
);
1739 q
= sd_bus_message_append_strv(req
, arg_set_nta
);
1741 return bus_log_create_error(q
);
1743 q
= sd_bus_call(bus
, req
, 0, &error
, NULL
);
1745 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1748 log_error_errno(q
, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error
, q
));
1758 char ifname
[IFNAMSIZ
];
1760 return log_error_errno(q
,
1761 "The specified interface %s is managed by systemd-networkd. Operation refused.\n"
1762 "Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.", strna(if_indextoname(arg_ifindex
, ifname
)));
1766 static int revert_link(sd_bus
*bus
) {
1767 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1772 r
= sd_bus_call_method(bus
,
1773 "org.freedesktop.resolve1",
1774 "/org/freedesktop/resolve1",
1775 "org.freedesktop.resolve1.Manager",
1781 return log_error_errno(r
, "Failed to revert interface configuration: %s", bus_error_message(&error
, r
));
1786 static void help_protocol_types(void) {
1788 puts("Known protocol types:");
1789 puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6\nmdns\nmdns-ipv4\nmdns-ipv6");
1792 static void help_dns_types(void) {
1797 puts("Known DNS RR types:");
1798 for (i
= 0; i
< _DNS_TYPE_MAX
; i
++) {
1799 t
= dns_type_to_string(i
);
1805 static void help_dns_classes(void) {
1810 puts("Known DNS RR classes:");
1811 for (i
= 0; i
< _DNS_CLASS_MAX
; i
++) {
1812 t
= dns_class_to_string(i
);
1818 static void help(void) {
1819 printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
1820 "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
1821 "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
1822 "%1$s [OPTIONS...] --statistics\n"
1823 "%1$s [OPTIONS...] --reset-statistics\n"
1825 "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n"
1826 " -h --help Show this help\n"
1827 " --version Show package version\n"
1828 " --no-pager Do not pipe output into a pager\n"
1829 " -4 Resolve IPv4 addresses\n"
1830 " -6 Resolve IPv6 addresses\n"
1831 " -i --interface=INTERFACE Look on interface\n"
1832 " -p --protocol=PROTO|help Look via protocol\n"
1833 " -t --type=TYPE|help Query RR with DNS type\n"
1834 " -c --class=CLASS|help Query RR with DNS class\n"
1835 " --service Resolve service (SRV)\n"
1836 " --service-address=BOOL Resolve address for services (default: yes)\n"
1837 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
1838 " --openpgp Query OpenPGP public key\n"
1839 " --tlsa Query TLS public key\n"
1840 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
1841 " --search=BOOL Use search domains for single-label names\n"
1843 " --raw[=payload|packet] Dump the answer as binary data\n"
1844 " --legend=BOOL Print headers and additional info (default: yes)\n"
1845 " --statistics Show resolver statistics\n"
1846 " --reset-statistics Reset resolver statistics\n"
1847 " --status Show link and server status\n"
1848 " --flush-caches Flush all local DNS caches\n"
1849 " --reset-server-features\n"
1850 " Forget learnt DNS server feature levels\n"
1851 " --set-dns=SERVER Set per-interface DNS server address\n"
1852 " --set-domain=DOMAIN Set per-interface search domain\n"
1853 " --set-llmnr=MODE Set per-interface LLMNR mode\n"
1854 " --set-mdns=MODE Set per-interface MulticastDNS mode\n"
1855 " --set-dnssec=MODE Set per-interface DNSSEC mode\n"
1856 " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
1857 " --revert Revert per-interface configuration\n"
1858 , program_invocation_short_name
);
1861 static int parse_argv(int argc
, char *argv
[]) {
1863 ARG_VERSION
= 0x100,
1867 ARG_SERVICE_ADDRESS
,
1874 ARG_RESET_STATISTICS
,
1877 ARG_RESET_SERVER_FEATURES
,
1888 static const struct option options
[] = {
1889 { "help", no_argument
, NULL
, 'h' },
1890 { "version", no_argument
, NULL
, ARG_VERSION
},
1891 { "type", required_argument
, NULL
, 't' },
1892 { "class", required_argument
, NULL
, 'c' },
1893 { "legend", required_argument
, NULL
, ARG_LEGEND
},
1894 { "interface", required_argument
, NULL
, 'i' },
1895 { "protocol", required_argument
, NULL
, 'p' },
1896 { "cname", required_argument
, NULL
, ARG_CNAME
},
1897 { "service", no_argument
, NULL
, ARG_SERVICE
},
1898 { "service-address", required_argument
, NULL
, ARG_SERVICE_ADDRESS
},
1899 { "service-txt", required_argument
, NULL
, ARG_SERVICE_TXT
},
1900 { "openpgp", no_argument
, NULL
, ARG_OPENPGP
},
1901 { "tlsa", optional_argument
, NULL
, ARG_TLSA
},
1902 { "raw", optional_argument
, NULL
, ARG_RAW
},
1903 { "search", required_argument
, NULL
, ARG_SEARCH
},
1904 { "statistics", no_argument
, NULL
, ARG_STATISTICS
, },
1905 { "reset-statistics", no_argument
, NULL
, ARG_RESET_STATISTICS
},
1906 { "status", no_argument
, NULL
, ARG_STATUS
},
1907 { "flush-caches", no_argument
, NULL
, ARG_FLUSH_CACHES
},
1908 { "reset-server-features", no_argument
, NULL
, ARG_RESET_SERVER_FEATURES
},
1909 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
1910 { "set-dns", required_argument
, NULL
, ARG_SET_DNS
},
1911 { "set-domain", required_argument
, NULL
, ARG_SET_DOMAIN
},
1912 { "set-llmnr", required_argument
, NULL
, ARG_SET_LLMNR
},
1913 { "set-mdns", required_argument
, NULL
, ARG_SET_MDNS
},
1914 { "set-dnssec", required_argument
, NULL
, ARG_SET_DNSSEC
},
1915 { "set-nta", required_argument
, NULL
, ARG_SET_NTA
},
1916 { "revert", no_argument
, NULL
, ARG_REVERT_LINK
},
1925 while ((c
= getopt_long(argc
, argv
, "h46i:t:c:p:", options
, NULL
)) >= 0)
1930 return 0; /* done */;
1936 arg_family
= AF_INET
;
1940 arg_family
= AF_INET6
;
1946 if (parse_ifindex(optarg
, &ifi
) >= 0)
1949 ifi
= if_nametoindex(optarg
);
1951 return log_error_errno(errno
, "Unknown interface %s: %m", optarg
);
1960 if (streq(optarg
, "help")) {
1965 r
= dns_type_from_string(optarg
);
1967 log_error("Failed to parse RR record type %s", optarg
);
1970 arg_type
= (uint16_t) r
;
1971 assert((int) arg_type
== r
);
1973 arg_mode
= MODE_RESOLVE_RECORD
;
1977 if (streq(optarg
, "help")) {
1982 r
= dns_class_from_string(optarg
);
1984 log_error("Failed to parse RR record class %s", optarg
);
1987 arg_class
= (uint16_t) r
;
1988 assert((int) arg_class
== r
);
1993 r
= parse_boolean(optarg
);
1995 return log_error_errno(r
, "Failed to parse --legend= argument");
2001 if (streq(optarg
, "help")) {
2002 help_protocol_types();
2004 } else if (streq(optarg
, "dns"))
2005 arg_flags
|= SD_RESOLVED_DNS
;
2006 else if (streq(optarg
, "llmnr"))
2007 arg_flags
|= SD_RESOLVED_LLMNR
;
2008 else if (streq(optarg
, "llmnr-ipv4"))
2009 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
2010 else if (streq(optarg
, "llmnr-ipv6"))
2011 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
2012 else if (streq(optarg
, "mdns"))
2013 arg_flags
|= SD_RESOLVED_MDNS
;
2014 else if (streq(optarg
, "mdns-ipv4"))
2015 arg_flags
|= SD_RESOLVED_MDNS_IPV4
;
2016 else if (streq(optarg
, "mdns-ipv6"))
2017 arg_flags
|= SD_RESOLVED_MDNS_IPV6
;
2019 log_error("Unknown protocol specifier: %s", optarg
);
2026 arg_mode
= MODE_RESOLVE_SERVICE
;
2030 arg_mode
= MODE_RESOLVE_OPENPGP
;
2034 arg_mode
= MODE_RESOLVE_TLSA
;
2035 arg_service_family
= service_family_from_string(optarg
);
2036 if (arg_service_family
< 0) {
2037 log_error("Unknown service family \"%s\".", optarg
);
2044 log_error("Refusing to write binary data to tty.");
2048 if (optarg
== NULL
|| streq(optarg
, "payload"))
2049 arg_raw
= RAW_PAYLOAD
;
2050 else if (streq(optarg
, "packet"))
2051 arg_raw
= RAW_PACKET
;
2053 log_error("Unknown --raw specifier \"%s\".", optarg
);
2061 r
= parse_boolean(optarg
);
2063 return log_error_errno(r
, "Failed to parse --cname= argument.");
2064 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CNAME
, r
== 0);
2067 case ARG_SERVICE_ADDRESS
:
2068 r
= parse_boolean(optarg
);
2070 return log_error_errno(r
, "Failed to parse --service-address= argument.");
2071 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ADDRESS
, r
== 0);
2074 case ARG_SERVICE_TXT
:
2075 r
= parse_boolean(optarg
);
2077 return log_error_errno(r
, "Failed to parse --service-txt= argument.");
2078 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TXT
, r
== 0);
2082 r
= parse_boolean(optarg
);
2084 return log_error_errno(r
, "Failed to parse --search argument.");
2085 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SEARCH
, r
== 0);
2088 case ARG_STATISTICS
:
2089 arg_mode
= MODE_STATISTICS
;
2092 case ARG_RESET_STATISTICS
:
2093 arg_mode
= MODE_RESET_STATISTICS
;
2096 case ARG_FLUSH_CACHES
:
2097 arg_mode
= MODE_FLUSH_CACHES
;
2100 case ARG_RESET_SERVER_FEATURES
:
2101 arg_mode
= MODE_RESET_SERVER_FEATURES
;
2105 arg_mode
= MODE_STATUS
;
2109 arg_no_pager
= true;
2113 struct in_addr_data data
, *n
;
2115 r
= in_addr_from_string_auto(optarg
, &data
.family
, &data
.address
);
2117 return log_error_errno(r
, "Failed to parse DNS server address: %s", optarg
);
2119 n
= reallocarray(arg_set_dns
, arg_n_set_dns
+ 1, sizeof(struct in_addr_data
));
2124 arg_set_dns
[arg_n_set_dns
++] = data
;
2125 arg_mode
= MODE_SET_LINK
;
2129 case ARG_SET_DOMAIN
: {
2132 p
= optarg
[0] == '~' ? optarg
+ 1 : optarg
;
2134 r
= dns_name_is_valid(p
);
2136 return log_error_errno(r
, "Failed to validate specified domain %s: %m", p
);
2138 return log_error_errno(r
, "Domain not valid: %s", p
);
2140 r
= strv_extend(&arg_set_domain
, optarg
);
2144 arg_mode
= MODE_SET_LINK
;
2149 r
= free_and_strdup(&arg_set_llmnr
, optarg
);
2153 arg_mode
= MODE_SET_LINK
;
2157 r
= free_and_strdup(&arg_set_mdns
, optarg
);
2161 arg_mode
= MODE_SET_LINK
;
2164 case ARG_SET_DNSSEC
:
2165 r
= free_and_strdup(&arg_set_dnssec
, optarg
);
2169 arg_mode
= MODE_SET_LINK
;
2173 r
= dns_name_is_valid(optarg
);
2175 return log_error_errno(r
, "Failed to validate specified domain %s: %m", optarg
);
2177 return log_error_errno(r
, "Domain not valid: %s", optarg
);
2179 r
= strv_extend(&arg_set_nta
, optarg
);
2183 arg_mode
= MODE_SET_LINK
;
2186 case ARG_REVERT_LINK
:
2187 arg_mode
= MODE_REVERT_LINK
;
2194 assert_not_reached("Unhandled option");
2197 if (arg_type
== 0 && arg_class
!= 0) {
2198 log_error("--class= may only be used in conjunction with --type=.");
2202 if (arg_type
!= 0 && arg_mode
== MODE_RESOLVE_SERVICE
) {
2203 log_error("--service and --type= may not be combined.");
2207 if (arg_type
!= 0 && arg_class
== 0)
2208 arg_class
= DNS_CLASS_IN
;
2210 if (arg_class
!= 0 && arg_type
== 0)
2211 arg_type
= DNS_TYPE_A
;
2213 if (IN_SET(arg_mode
, MODE_SET_LINK
, MODE_REVERT_LINK
)) {
2215 if (arg_ifindex
<= 0) {
2216 log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, --set-nta= and --revert require --interface=.");
2220 if (arg_ifindex
== LOOPBACK_IFINDEX
) {
2221 log_error("Interface can't be the loopback interface (lo). Sorry.");
2226 return 1 /* work to do */;
2229 int main(int argc
, char **argv
) {
2230 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2233 log_parse_environment();
2236 r
= parse_argv(argc
, argv
);
2240 r
= sd_bus_open_system(&bus
);
2242 log_error_errno(r
, "sd_bus_open_system: %m");
2248 case MODE_RESOLVE_HOST
:
2249 if (optind
>= argc
) {
2250 log_error("No arguments passed.");
2255 while (argv
[optind
]) {
2256 int family
, ifindex
, k
;
2257 union in_addr_union a
;
2259 if (startswith(argv
[optind
], "dns:"))
2260 k
= resolve_rfc4501(bus
, argv
[optind
]);
2262 k
= in_addr_ifindex_from_string_auto(argv
[optind
], &family
, &a
, &ifindex
);
2264 k
= resolve_address(bus
, family
, &a
, ifindex
);
2266 k
= resolve_host(bus
, argv
[optind
]);
2276 case MODE_RESOLVE_RECORD
:
2277 if (optind
>= argc
) {
2278 log_error("No arguments passed.");
2283 while (argv
[optind
]) {
2286 k
= resolve_record(bus
, argv
[optind
], arg_class
, arg_type
, true);
2294 case MODE_RESOLVE_SERVICE
:
2295 if (argc
< optind
+ 1) {
2296 log_error("Domain specification required.");
2300 } else if (argc
== optind
+ 1)
2301 r
= resolve_service(bus
, NULL
, NULL
, argv
[optind
]);
2302 else if (argc
== optind
+ 2)
2303 r
= resolve_service(bus
, NULL
, argv
[optind
], argv
[optind
+1]);
2304 else if (argc
== optind
+ 3)
2305 r
= resolve_service(bus
, argv
[optind
], argv
[optind
+1], argv
[optind
+2]);
2307 log_error("Too many arguments.");
2314 case MODE_RESOLVE_OPENPGP
:
2315 if (argc
< optind
+ 1) {
2316 log_error("E-mail address required.");
2323 while (optind
< argc
) {
2326 k
= resolve_openpgp(bus
, argv
[optind
++]);
2332 case MODE_RESOLVE_TLSA
:
2333 if (argc
< optind
+ 1) {
2334 log_error("Domain name required.");
2341 while (optind
< argc
) {
2344 k
= resolve_tlsa(bus
, argv
[optind
++]);
2350 case MODE_STATISTICS
:
2351 if (argc
> optind
) {
2352 log_error("Too many arguments.");
2357 r
= show_statistics(bus
);
2360 case MODE_RESET_STATISTICS
:
2361 if (argc
> optind
) {
2362 log_error("Too many arguments.");
2367 r
= reset_statistics(bus
);
2370 case MODE_FLUSH_CACHES
:
2371 if (argc
> optind
) {
2372 log_error("Too many arguments.");
2377 r
= flush_caches(bus
);
2380 case MODE_RESET_SERVER_FEATURES
:
2381 if (argc
> optind
) {
2382 log_error("Too many arguments.");
2387 r
= reset_server_features(bus
);
2392 if (argc
> optind
) {
2394 bool empty_line
= false;
2397 STRV_FOREACH(ifname
, argv
+ optind
) {
2400 q
= parse_ifindex(argv
[optind
], &ifindex
);
2402 ifindex
= if_nametoindex(argv
[optind
]);
2404 log_error_errno(errno
, "Failed to resolve interface name: %s", argv
[optind
]);
2409 q
= status_ifindex(bus
, ifindex
, NULL
, &empty_line
);
2410 if (q
< 0 && r
>= 0)
2414 r
= status_all(bus
);
2420 if (argc
> optind
) {
2421 log_error("Too many arguments.");
2429 case MODE_REVERT_LINK
:
2430 if (argc
> optind
) {
2431 log_error("Too many arguments.");
2436 r
= revert_link(bus
);
2444 strv_free(arg_set_domain
);
2445 free(arg_set_llmnr
);
2447 free(arg_set_dnssec
);
2448 strv_free(arg_set_nta
);
2450 return r
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;