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
|| 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
;
1944 if (parse_ifindex(optarg
, &arg_ifindex
) < 0) {
1947 ifi
= if_nametoindex(optarg
);
1949 return log_error_errno(errno
, "Unknown interface %s: %m", optarg
);
1957 if (streq(optarg
, "help")) {
1962 r
= dns_type_from_string(optarg
);
1964 log_error("Failed to parse RR record type %s", optarg
);
1967 arg_type
= (uint16_t) r
;
1968 assert((int) arg_type
== r
);
1970 arg_mode
= MODE_RESOLVE_RECORD
;
1974 if (streq(optarg
, "help")) {
1979 r
= dns_class_from_string(optarg
);
1981 log_error("Failed to parse RR record class %s", optarg
);
1984 arg_class
= (uint16_t) r
;
1985 assert((int) arg_class
== r
);
1990 r
= parse_boolean(optarg
);
1992 return log_error_errno(r
, "Failed to parse --legend= argument");
1998 if (streq(optarg
, "help")) {
1999 help_protocol_types();
2001 } else if (streq(optarg
, "dns"))
2002 arg_flags
|= SD_RESOLVED_DNS
;
2003 else if (streq(optarg
, "llmnr"))
2004 arg_flags
|= SD_RESOLVED_LLMNR
;
2005 else if (streq(optarg
, "llmnr-ipv4"))
2006 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
2007 else if (streq(optarg
, "llmnr-ipv6"))
2008 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
2009 else if (streq(optarg
, "mdns"))
2010 arg_flags
|= SD_RESOLVED_MDNS
;
2011 else if (streq(optarg
, "mdns-ipv4"))
2012 arg_flags
|= SD_RESOLVED_MDNS_IPV4
;
2013 else if (streq(optarg
, "mdns-ipv6"))
2014 arg_flags
|= SD_RESOLVED_MDNS_IPV6
;
2016 log_error("Unknown protocol specifier: %s", optarg
);
2023 arg_mode
= MODE_RESOLVE_SERVICE
;
2027 arg_mode
= MODE_RESOLVE_OPENPGP
;
2031 arg_mode
= MODE_RESOLVE_TLSA
;
2032 arg_service_family
= service_family_from_string(optarg
);
2033 if (arg_service_family
< 0) {
2034 log_error("Unknown service family \"%s\".", optarg
);
2041 log_error("Refusing to write binary data to tty.");
2045 if (optarg
== NULL
|| streq(optarg
, "payload"))
2046 arg_raw
= RAW_PAYLOAD
;
2047 else if (streq(optarg
, "packet"))
2048 arg_raw
= RAW_PACKET
;
2050 log_error("Unknown --raw specifier \"%s\".", optarg
);
2058 r
= parse_boolean(optarg
);
2060 return log_error_errno(r
, "Failed to parse --cname= argument.");
2061 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CNAME
, r
== 0);
2064 case ARG_SERVICE_ADDRESS
:
2065 r
= parse_boolean(optarg
);
2067 return log_error_errno(r
, "Failed to parse --service-address= argument.");
2068 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ADDRESS
, r
== 0);
2071 case ARG_SERVICE_TXT
:
2072 r
= parse_boolean(optarg
);
2074 return log_error_errno(r
, "Failed to parse --service-txt= argument.");
2075 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TXT
, r
== 0);
2079 r
= parse_boolean(optarg
);
2081 return log_error_errno(r
, "Failed to parse --search argument.");
2082 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SEARCH
, r
== 0);
2085 case ARG_STATISTICS
:
2086 arg_mode
= MODE_STATISTICS
;
2089 case ARG_RESET_STATISTICS
:
2090 arg_mode
= MODE_RESET_STATISTICS
;
2093 case ARG_FLUSH_CACHES
:
2094 arg_mode
= MODE_FLUSH_CACHES
;
2097 case ARG_RESET_SERVER_FEATURES
:
2098 arg_mode
= MODE_RESET_SERVER_FEATURES
;
2102 arg_mode
= MODE_STATUS
;
2106 arg_no_pager
= true;
2110 struct in_addr_data data
, *n
;
2112 r
= in_addr_from_string_auto(optarg
, &data
.family
, &data
.address
);
2114 return log_error_errno(r
, "Failed to parse DNS server address: %s", optarg
);
2116 n
= realloc(arg_set_dns
, sizeof(struct in_addr_data
) * (arg_n_set_dns
+ 1));
2121 arg_set_dns
[arg_n_set_dns
++] = data
;
2122 arg_mode
= MODE_SET_LINK
;
2126 case ARG_SET_DOMAIN
: {
2129 p
= optarg
[0] == '~' ? optarg
+ 1 : optarg
;
2131 r
= dns_name_is_valid(p
);
2133 return log_error_errno(r
, "Failed to validate specified domain %s: %m", p
);
2135 log_error("Domain not valid: %s", p
);
2139 r
= strv_extend(&arg_set_domain
, optarg
);
2143 arg_mode
= MODE_SET_LINK
;
2148 r
= free_and_strdup(&arg_set_llmnr
, optarg
);
2152 arg_mode
= MODE_SET_LINK
;
2156 r
= free_and_strdup(&arg_set_mdns
, optarg
);
2160 arg_mode
= MODE_SET_LINK
;
2163 case ARG_SET_DNSSEC
:
2164 r
= free_and_strdup(&arg_set_dnssec
, optarg
);
2168 arg_mode
= MODE_SET_LINK
;
2172 r
= dns_name_is_valid(optarg
);
2174 return log_error_errno(r
, "Failed to validate specified domain %s: %m", optarg
);
2176 log_error("Domain not valid: %s", optarg
);
2180 r
= strv_extend(&arg_set_nta
, optarg
);
2184 arg_mode
= MODE_SET_LINK
;
2187 case ARG_REVERT_LINK
:
2188 arg_mode
= MODE_REVERT_LINK
;
2195 assert_not_reached("Unhandled option");
2198 if (arg_type
== 0 && arg_class
!= 0) {
2199 log_error("--class= may only be used in conjunction with --type=.");
2203 if (arg_type
!= 0 && arg_mode
== MODE_RESOLVE_SERVICE
) {
2204 log_error("--service and --type= may not be combined.");
2208 if (arg_type
!= 0 && arg_class
== 0)
2209 arg_class
= DNS_CLASS_IN
;
2211 if (arg_class
!= 0 && arg_type
== 0)
2212 arg_type
= DNS_TYPE_A
;
2214 if (IN_SET(arg_mode
, MODE_SET_LINK
, MODE_REVERT_LINK
)) {
2216 if (arg_ifindex
<= 0) {
2217 log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, --set-nta= and --revert require --interface=.");
2221 if (arg_ifindex
== LOOPBACK_IFINDEX
) {
2222 log_error("Interface can't be the loopback interface (lo). Sorry.");
2227 return 1 /* work to do */;
2230 int main(int argc
, char **argv
) {
2231 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2234 log_parse_environment();
2237 r
= parse_argv(argc
, argv
);
2241 r
= sd_bus_open_system(&bus
);
2243 log_error_errno(r
, "sd_bus_open_system: %m");
2249 case MODE_RESOLVE_HOST
:
2250 if (optind
>= argc
) {
2251 log_error("No arguments passed.");
2256 while (argv
[optind
]) {
2257 int family
, ifindex
, k
;
2258 union in_addr_union a
;
2260 if (startswith(argv
[optind
], "dns:"))
2261 k
= resolve_rfc4501(bus
, argv
[optind
]);
2263 k
= in_addr_ifindex_from_string_auto(argv
[optind
], &family
, &a
, &ifindex
);
2265 k
= resolve_address(bus
, family
, &a
, ifindex
);
2267 k
= resolve_host(bus
, argv
[optind
]);
2277 case MODE_RESOLVE_RECORD
:
2278 if (optind
>= argc
) {
2279 log_error("No arguments passed.");
2284 while (argv
[optind
]) {
2287 k
= resolve_record(bus
, argv
[optind
], arg_class
, arg_type
, true);
2295 case MODE_RESOLVE_SERVICE
:
2296 if (argc
< optind
+ 1) {
2297 log_error("Domain specification required.");
2301 } else if (argc
== optind
+ 1)
2302 r
= resolve_service(bus
, NULL
, NULL
, argv
[optind
]);
2303 else if (argc
== optind
+ 2)
2304 r
= resolve_service(bus
, NULL
, argv
[optind
], argv
[optind
+1]);
2305 else if (argc
== optind
+ 3)
2306 r
= resolve_service(bus
, argv
[optind
], argv
[optind
+1], argv
[optind
+2]);
2308 log_error("Too many arguments.");
2315 case MODE_RESOLVE_OPENPGP
:
2316 if (argc
< optind
+ 1) {
2317 log_error("E-mail address required.");
2324 while (optind
< argc
) {
2327 k
= resolve_openpgp(bus
, argv
[optind
++]);
2333 case MODE_RESOLVE_TLSA
:
2334 if (argc
< optind
+ 1) {
2335 log_error("Domain name required.");
2342 while (optind
< argc
) {
2345 k
= resolve_tlsa(bus
, argv
[optind
++]);
2351 case MODE_STATISTICS
:
2352 if (argc
> optind
) {
2353 log_error("Too many arguments.");
2358 r
= show_statistics(bus
);
2361 case MODE_RESET_STATISTICS
:
2362 if (argc
> optind
) {
2363 log_error("Too many arguments.");
2368 r
= reset_statistics(bus
);
2371 case MODE_FLUSH_CACHES
:
2372 if (argc
> optind
) {
2373 log_error("Too many arguments.");
2378 r
= flush_caches(bus
);
2381 case MODE_RESET_SERVER_FEATURES
:
2382 if (argc
> optind
) {
2383 log_error("Too many arguments.");
2388 r
= reset_server_features(bus
);
2393 if (argc
> optind
) {
2395 bool empty_line
= false;
2398 STRV_FOREACH(ifname
, argv
+ optind
) {
2401 q
= parse_ifindex(argv
[optind
], &ifindex
);
2403 ifindex
= if_nametoindex(argv
[optind
]);
2405 log_error_errno(errno
, "Failed to resolve interface name: %s", argv
[optind
]);
2410 q
= status_ifindex(bus
, ifindex
, NULL
, &empty_line
);
2411 if (q
< 0 && r
>= 0)
2415 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
;