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 #define DNS_CALL_TIMEOUT_USEC (90*USEC_PER_SEC)
46 static int arg_family
= AF_UNSPEC
;
47 static int arg_ifindex
= 0;
48 static uint16_t arg_type
= 0;
49 static uint16_t arg_class
= 0;
50 static bool arg_legend
= true;
51 static uint64_t arg_flags
= 0;
52 static bool arg_no_pager
= false;
54 typedef enum ServiceFamily
{
58 _SERVICE_FAMILY_INVALID
= -1,
60 static ServiceFamily arg_service_family
= SERVICE_FAMILY_TCP
;
62 typedef enum RawType
{
67 static RawType arg_raw
= RAW_NONE
;
76 MODE_RESET_STATISTICS
,
78 MODE_RESET_SERVER_FEATURES
,
82 } arg_mode
= MODE_RESOLVE_HOST
;
84 static struct in_addr_data
*arg_set_dns
= NULL
;
85 static size_t arg_n_set_dns
= 0;
86 static char **arg_set_domain
= NULL
;
87 static char *arg_set_llmnr
= NULL
;
88 static char *arg_set_mdns
= NULL
;
89 static char *arg_set_dnssec
= NULL
;
90 static char **arg_set_nta
= NULL
;
92 static ServiceFamily
service_family_from_string(const char *s
) {
93 if (s
== NULL
|| streq(s
, "tcp"))
94 return SERVICE_FAMILY_TCP
;
96 return SERVICE_FAMILY_UDP
;
98 return SERVICE_FAMILY_SCTP
;
99 return _SERVICE_FAMILY_INVALID
;
102 static const char* service_family_to_string(ServiceFamily service
) {
104 case SERVICE_FAMILY_TCP
:
106 case SERVICE_FAMILY_UDP
:
108 case SERVICE_FAMILY_SCTP
:
111 assert_not_reached("invalid service");
115 static void print_source(uint64_t flags
, usec_t rtt
) {
116 char rtt_str
[FORMAT_TIMESTAMP_MAX
];
124 fputs("\n-- Information acquired via", stdout
);
127 printf(" protocol%s%s%s%s%s",
128 flags
& SD_RESOLVED_DNS
? " DNS" :"",
129 flags
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
130 flags
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
131 flags
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
132 flags
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
134 assert_se(format_timespan(rtt_str
, sizeof(rtt_str
), rtt
, 100));
136 printf(" in %s", rtt_str
);
141 printf("-- Data is authenticated: %s\n", yes_no(flags
& SD_RESOLVED_AUTHENTICATED
));
144 static int resolve_host(sd_bus
*bus
, const char *name
) {
146 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
147 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
148 const char *canonical
= NULL
;
149 char ifname
[IF_NAMESIZE
] = "";
157 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
158 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
160 log_debug("Resolving %s (family %s, interface %s).", name
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
162 r
= sd_bus_message_new_method_call(
165 "org.freedesktop.resolve1",
166 "/org/freedesktop/resolve1",
167 "org.freedesktop.resolve1.Manager",
170 return bus_log_create_error(r
);
172 r
= sd_bus_message_append(req
, "isit", arg_ifindex
, name
, arg_family
, arg_flags
);
174 return bus_log_create_error(r
);
176 ts
= now(CLOCK_MONOTONIC
);
178 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
180 return log_error_errno(r
, "%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
182 ts
= now(CLOCK_MONOTONIC
) - ts
;
184 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
186 return bus_log_parse_error(r
);
188 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
189 _cleanup_free_
char *pretty
= NULL
;
194 assert_cc(sizeof(int) == sizeof(int32_t));
196 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
198 return bus_log_parse_error(r
);
200 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
202 return bus_log_parse_error(r
);
204 r
= sd_bus_message_exit_container(reply
);
206 return bus_log_parse_error(r
);
208 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
209 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
213 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
214 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
219 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
220 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
222 r
= in_addr_ifindex_to_string(family
, a
, ifindex
, &pretty
);
224 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
226 printf("%*s%s %s%s%s\n",
227 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
229 isempty(ifname
) ? "" : "%", ifname
);
234 return bus_log_parse_error(r
);
236 r
= sd_bus_message_exit_container(reply
);
238 return bus_log_parse_error(r
);
240 r
= sd_bus_message_read(reply
, "st", &canonical
, &flags
);
242 return bus_log_parse_error(r
);
244 if (!streq(name
, canonical
))
245 printf("%*s%s (%s)\n",
246 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
250 log_error("%s: no addresses found", name
);
254 print_source(flags
, ts
);
259 static int resolve_address(sd_bus
*bus
, int family
, const union in_addr_union
*address
, int ifindex
) {
260 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
261 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
262 _cleanup_free_
char *pretty
= NULL
;
263 char ifname
[IF_NAMESIZE
] = "";
270 assert(IN_SET(family
, AF_INET
, AF_INET6
));
274 ifindex
= arg_ifindex
;
276 r
= in_addr_ifindex_to_string(family
, address
, ifindex
, &pretty
);
280 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
281 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
283 log_debug("Resolving %s%s%s.", pretty
, isempty(ifname
) ? "" : "%", ifname
);
285 r
= sd_bus_message_new_method_call(
288 "org.freedesktop.resolve1",
289 "/org/freedesktop/resolve1",
290 "org.freedesktop.resolve1.Manager",
293 return bus_log_create_error(r
);
295 r
= sd_bus_message_append(req
, "ii", ifindex
, family
);
297 return bus_log_create_error(r
);
299 r
= sd_bus_message_append_array(req
, 'y', address
, FAMILY_ADDRESS_SIZE(family
));
301 return bus_log_create_error(r
);
303 r
= sd_bus_message_append(req
, "t", arg_flags
);
305 return bus_log_create_error(r
);
307 ts
= now(CLOCK_MONOTONIC
);
309 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
311 log_error("%s: resolve call failed: %s", pretty
, bus_error_message(&error
, r
));
315 ts
= now(CLOCK_MONOTONIC
) - ts
;
317 r
= sd_bus_message_enter_container(reply
, 'a', "(is)");
319 return bus_log_create_error(r
);
321 while ((r
= sd_bus_message_enter_container(reply
, 'r', "is")) > 0) {
324 assert_cc(sizeof(int) == sizeof(int32_t));
326 r
= sd_bus_message_read(reply
, "is", &ifindex
, &n
);
330 r
= sd_bus_message_exit_container(reply
);
335 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
336 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
338 printf("%*s%*s%*s%s %s\n",
339 (int) strlen(pretty
), c
== 0 ? pretty
: "",
340 isempty(ifname
) ? 0 : 1, c
> 0 || isempty(ifname
) ? "" : "%",
341 (int) strlen(ifname
), c
== 0 ? ifname
: "",
348 return bus_log_parse_error(r
);
350 r
= sd_bus_message_exit_container(reply
);
352 return bus_log_parse_error(r
);
354 r
= sd_bus_message_read(reply
, "t", &flags
);
356 return bus_log_parse_error(r
);
359 log_error("%s: no names found", pretty
);
363 print_source(flags
, ts
);
368 static int output_rr_packet(const void *d
, size_t l
, int ifindex
) {
369 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
370 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
372 char ifname
[IF_NAMESIZE
] = "";
374 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0, DNS_PACKET_SIZE_MAX
);
378 p
->refuse_compression
= true;
380 r
= dns_packet_append_blob(p
, d
, l
, NULL
);
384 r
= dns_packet_read_rr(p
, &rr
, NULL
, NULL
);
386 return log_error_errno(r
, "Failed to parse RR: %m");
388 if (arg_raw
== RAW_PAYLOAD
) {
392 k
= dns_resource_record_payload(rr
, &data
);
394 return log_error_errno(k
, "Cannot dump RR: %m");
395 fwrite(data
, 1, k
, stdout
);
399 s
= dns_resource_record_to_string(rr
);
403 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
404 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
406 printf("%s%s%s\n", s
, isempty(ifname
) ? "" : " # interface ", ifname
);
412 static int resolve_record(sd_bus
*bus
, const char *name
, uint16_t class, uint16_t type
, bool warn_missing
) {
413 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
414 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
415 char ifname
[IF_NAMESIZE
] = "";
420 bool needs_authentication
= false;
424 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
425 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
427 log_debug("Resolving %s %s %s (interface %s).", name
, dns_class_to_string(class), dns_type_to_string(type
), isempty(ifname
) ? "*" : ifname
);
429 r
= sd_bus_message_new_method_call(
432 "org.freedesktop.resolve1",
433 "/org/freedesktop/resolve1",
434 "org.freedesktop.resolve1.Manager",
437 return bus_log_create_error(r
);
439 r
= sd_bus_message_append(req
, "isqqt", arg_ifindex
, name
, class, type
, arg_flags
);
441 return bus_log_create_error(r
);
443 ts
= now(CLOCK_MONOTONIC
);
445 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
447 if (warn_missing
|| r
!= -ENXIO
)
448 log_error("%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
452 ts
= now(CLOCK_MONOTONIC
) - ts
;
454 r
= sd_bus_message_enter_container(reply
, 'a', "(iqqay)");
456 return bus_log_parse_error(r
);
458 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iqqay")) > 0) {
464 assert_cc(sizeof(int) == sizeof(int32_t));
466 r
= sd_bus_message_read(reply
, "iqq", &ifindex
, &c
, &t
);
468 return bus_log_parse_error(r
);
470 r
= sd_bus_message_read_array(reply
, 'y', &d
, &l
);
472 return bus_log_parse_error(r
);
474 r
= sd_bus_message_exit_container(reply
);
476 return bus_log_parse_error(r
);
478 if (arg_raw
== RAW_PACKET
) {
479 uint64_t u64
= htole64(l
);
481 fwrite(&u64
, sizeof(u64
), 1, stdout
);
482 fwrite(d
, 1, l
, stdout
);
484 r
= output_rr_packet(d
, l
, ifindex
);
489 if (dns_type_needs_authentication(t
))
490 needs_authentication
= true;
495 return bus_log_parse_error(r
);
497 r
= sd_bus_message_exit_container(reply
);
499 return bus_log_parse_error(r
);
501 r
= sd_bus_message_read(reply
, "t", &flags
);
503 return bus_log_parse_error(r
);
507 log_error("%s: no records found", name
);
511 print_source(flags
, ts
);
513 if ((flags
& SD_RESOLVED_AUTHENTICATED
) == 0 && needs_authentication
) {
516 fprintf(stderr
, "\n%s"
517 "WARNING: The resources shown contain cryptographic key data which could not be\n"
518 " authenticated. It is not suitable to authenticate any communication.\n"
519 " This is usually indication that DNSSEC authentication was not enabled\n"
520 " or is not available for the selected protocol or DNS servers.%s\n",
521 ansi_highlight_red(),
528 static int resolve_rfc4501(sd_bus
*bus
, const char *name
) {
529 uint16_t type
= 0, class = 0;
530 const char *p
, *q
, *n
;
535 assert(startswith(name
, "dns:"));
537 /* Parse RFC 4501 dns: URIs */
547 e
= strchr(p
+ 2, '/');
552 log_warning("DNS authority specification not supported; ignoring specified authority.");
559 n
= strndupa(p
, q
- p
);
565 f
= startswith_no_case(q
, "class=");
567 _cleanup_free_
char *t
= NULL
;
571 log_error("DNS class specified twice.");
575 e
= strchrnul(f
, ';');
576 t
= strndup(f
, e
- f
);
580 r
= dns_class_from_string(t
);
582 log_error("Unknown DNS class %s.", t
);
596 f
= startswith_no_case(q
, "type=");
598 _cleanup_free_
char *t
= NULL
;
602 log_error("DNS type specified twice.");
606 e
= strchrnul(f
, ';');
607 t
= strndup(f
, e
- f
);
611 r
= dns_type_from_string(t
);
613 log_error("Unknown DNS type %s.", t
);
633 class = arg_class
?: DNS_CLASS_IN
;
635 type
= arg_type
?: DNS_TYPE_A
;
637 return resolve_record(bus
, n
, class, type
, true);
640 log_error("Invalid DNS URI: %s", name
);
644 static int resolve_service(sd_bus
*bus
, const char *name
, const char *type
, const char *domain
) {
645 const char *canonical_name
, *canonical_type
, *canonical_domain
;
646 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
647 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
648 char ifname
[IF_NAMESIZE
] = "";
659 name
= empty_to_null(name
);
660 type
= empty_to_null(type
);
662 if (arg_ifindex
> 0 && !if_indextoname(arg_ifindex
, ifname
))
663 return log_error_errno(errno
, "Failed to resolve interface name for index %i: %m", arg_ifindex
);
666 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
);
668 log_debug("Resolving service type %s of %s (family %s, interface %s).", type
, domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
670 log_debug("Resolving service type %s (family %s, interface %s).", domain
, af_to_name(arg_family
) ?: "*", isempty(ifname
) ? "*" : ifname
);
672 r
= sd_bus_message_new_method_call(
675 "org.freedesktop.resolve1",
676 "/org/freedesktop/resolve1",
677 "org.freedesktop.resolve1.Manager",
680 return bus_log_create_error(r
);
682 r
= sd_bus_message_append(req
, "isssit", arg_ifindex
, name
, type
, domain
, arg_family
, arg_flags
);
684 return bus_log_create_error(r
);
686 ts
= now(CLOCK_MONOTONIC
);
688 r
= sd_bus_call(bus
, req
, DNS_CALL_TIMEOUT_USEC
, &error
, &reply
);
690 return log_error_errno(r
, "Resolve call failed: %s", bus_error_message(&error
, r
));
692 ts
= now(CLOCK_MONOTONIC
) - ts
;
694 r
= sd_bus_message_enter_container(reply
, 'a', "(qqqsa(iiay)s)");
696 return bus_log_parse_error(r
);
699 (name
? strlen(name
) + 1 : 0) +
700 (type
? strlen(type
) + 1 : 0) +
704 while ((r
= sd_bus_message_enter_container(reply
, 'r', "qqqsa(iiay)s")) > 0) {
705 uint16_t priority
, weight
, port
;
706 const char *hostname
, *canonical
;
708 r
= sd_bus_message_read(reply
, "qqqs", &priority
, &weight
, &port
, &hostname
);
710 return bus_log_parse_error(r
);
713 printf("%*s%s", (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? "/" : " ");
715 printf("%*s%s", (int) strlen(type
), c
== 0 ? type
: "", c
== 0 ? "/" : " ");
717 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
718 (int) strlen(domain
), c
== 0 ? domain
: "",
723 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
725 return bus_log_parse_error(r
);
727 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
728 _cleanup_free_
char *pretty
= NULL
;
732 assert_cc(sizeof(int) == sizeof(int32_t));
734 r
= sd_bus_message_read(reply
, "ii", &ifindex
, &family
);
736 return bus_log_parse_error(r
);
738 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
740 return bus_log_parse_error(r
);
742 r
= sd_bus_message_exit_container(reply
);
744 return bus_log_parse_error(r
);
746 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
747 log_debug("%s: skipping entry with family %d (%s)", name
, family
, af_to_name(family
) ?: "unknown");
751 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
752 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name
, sz
, af_to_name(family
) ?: "unknown");
757 if (ifindex
> 0 && !if_indextoname(ifindex
, ifname
))
758 log_warning_errno(errno
, "Failed to resolve interface name for index %i: %m", ifindex
);
760 r
= in_addr_to_string(family
, a
, &pretty
);
762 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
764 printf("%*s%s%s%s\n", (int) indent
, "", pretty
, isempty(ifname
) ? "" : "%s", ifname
);
767 return bus_log_parse_error(r
);
769 r
= sd_bus_message_exit_container(reply
);
771 return bus_log_parse_error(r
);
773 r
= sd_bus_message_read(reply
, "s", &canonical
);
775 return bus_log_parse_error(r
);
777 if (!streq(hostname
, canonical
))
778 printf("%*s(%s)\n", (int) indent
, "", canonical
);
780 r
= sd_bus_message_exit_container(reply
);
782 return bus_log_parse_error(r
);
787 return bus_log_parse_error(r
);
789 r
= sd_bus_message_exit_container(reply
);
791 return bus_log_parse_error(r
);
793 r
= sd_bus_message_enter_container(reply
, 'a', "ay");
795 return bus_log_parse_error(r
);
797 while ((r
= sd_bus_message_read_array(reply
, 'y', (const void**) &p
, &sz
)) > 0) {
798 _cleanup_free_
char *escaped
= NULL
;
800 escaped
= cescape_length(p
, sz
);
804 printf("%*s%s\n", (int) indent
, "", escaped
);
807 return bus_log_parse_error(r
);
809 r
= sd_bus_message_exit_container(reply
);
811 return bus_log_parse_error(r
);
813 r
= sd_bus_message_read(reply
, "ssst", &canonical_name
, &canonical_type
, &canonical_domain
, &flags
);
815 return bus_log_parse_error(r
);
817 canonical_name
= empty_to_null(canonical_name
);
818 canonical_type
= empty_to_null(canonical_type
);
820 if (!streq_ptr(name
, canonical_name
) ||
821 !streq_ptr(type
, canonical_type
) ||
822 !streq_ptr(domain
, canonical_domain
)) {
824 printf("%*s(", (int) indent
, "");
827 printf("%s/", canonical_name
);
829 printf("%s/", canonical_type
);
831 printf("%s)\n", canonical_domain
);
834 print_source(flags
, ts
);
839 static int resolve_openpgp(sd_bus
*bus
, const char *address
) {
840 const char *domain
, *full
;
842 _cleanup_free_
char *hashed
= NULL
;
847 domain
= strrchr(address
, '@');
849 log_error("Address does not contain '@': \"%s\"", address
);
851 } else if (domain
== address
|| domain
[1] == '\0') {
852 log_error("Address starts or ends with '@': \"%s\"", address
);
857 r
= string_hashsum_sha256(address
, domain
- 1 - address
, &hashed
);
859 return log_error_errno(r
, "Hashing failed: %m");
861 strshorten(hashed
, 56);
863 full
= strjoina(hashed
, "._openpgpkey.", domain
);
864 log_debug("Looking up \"%s\".", full
);
866 r
= resolve_record(bus
, full
,
867 arg_class
?: DNS_CLASS_IN
,
868 arg_type
?: DNS_TYPE_OPENPGPKEY
, false);
870 if (IN_SET(r
, -ENXIO
, -ESRCH
)) { /* NXDOMAIN or NODATA? */
872 r
= string_hashsum_sha224(address
, domain
- 1 - address
, &hashed
);
874 return log_error_errno(r
, "Hashing failed: %m");
876 full
= strjoina(hashed
, "._openpgpkey.", domain
);
877 log_debug("Looking up \"%s\".", full
);
879 return resolve_record(bus
, full
,
880 arg_class
?: DNS_CLASS_IN
,
881 arg_type
?: DNS_TYPE_OPENPGPKEY
, true);
887 static int resolve_tlsa(sd_bus
*bus
, const char *address
) {
889 uint16_t port_num
= 443;
890 _cleanup_free_
char *full
= NULL
;
896 port
= strrchr(address
, ':');
898 r
= parse_ip_port(port
+ 1, &port_num
);
900 return log_error_errno(r
, "Invalid port \"%s\".", port
+ 1);
902 address
= strndupa(address
, port
- address
);
905 r
= asprintf(&full
, "_%u.%s.%s",
907 service_family_to_string(arg_service_family
),
912 log_debug("Looking up \"%s\".", full
);
914 return resolve_record(bus
, full
,
915 arg_class
?: DNS_CLASS_IN
,
916 arg_type
?: DNS_TYPE_TLSA
, true);
919 static int show_statistics(sd_bus
*bus
) {
920 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
921 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
922 uint64_t n_current_transactions
, n_total_transactions
,
923 cache_size
, n_cache_hit
, n_cache_miss
,
924 n_dnssec_secure
, n_dnssec_insecure
, n_dnssec_bogus
, n_dnssec_indeterminate
;
925 int r
, dnssec_supported
;
929 r
= sd_bus_get_property_trivial(bus
,
930 "org.freedesktop.resolve1",
931 "/org/freedesktop/resolve1",
932 "org.freedesktop.resolve1.Manager",
938 return log_error_errno(r
, "Failed to get DNSSEC supported state: %s", bus_error_message(&error
, r
));
940 printf("DNSSEC supported by current servers: %s%s%s\n\n",
942 yes_no(dnssec_supported
),
945 r
= sd_bus_get_property(bus
,
946 "org.freedesktop.resolve1",
947 "/org/freedesktop/resolve1",
948 "org.freedesktop.resolve1.Manager",
949 "TransactionStatistics",
954 return log_error_errno(r
, "Failed to get transaction statistics: %s", bus_error_message(&error
, r
));
956 r
= sd_bus_message_read(reply
, "(tt)",
957 &n_current_transactions
,
958 &n_total_transactions
);
960 return bus_log_parse_error(r
);
962 printf("%sTransactions%s\n"
963 "Current Transactions: %" PRIu64
"\n"
964 " Total Transactions: %" PRIu64
"\n",
967 n_current_transactions
,
968 n_total_transactions
);
970 reply
= sd_bus_message_unref(reply
);
972 r
= sd_bus_get_property(bus
,
973 "org.freedesktop.resolve1",
974 "/org/freedesktop/resolve1",
975 "org.freedesktop.resolve1.Manager",
981 return log_error_errno(r
, "Failed to get cache statistics: %s", bus_error_message(&error
, r
));
983 r
= sd_bus_message_read(reply
, "(ttt)",
988 return bus_log_parse_error(r
);
990 printf("\n%sCache%s\n"
991 " Current Cache Size: %" PRIu64
"\n"
992 " Cache Hits: %" PRIu64
"\n"
993 " Cache Misses: %" PRIu64
"\n",
1000 reply
= sd_bus_message_unref(reply
);
1002 r
= sd_bus_get_property(bus
,
1003 "org.freedesktop.resolve1",
1004 "/org/freedesktop/resolve1",
1005 "org.freedesktop.resolve1.Manager",
1011 return log_error_errno(r
, "Failed to get DNSSEC statistics: %s", bus_error_message(&error
, r
));
1013 r
= sd_bus_message_read(reply
, "(tttt)",
1017 &n_dnssec_indeterminate
);
1019 return bus_log_parse_error(r
);
1021 printf("\n%sDNSSEC Verdicts%s\n"
1022 " Secure: %" PRIu64
"\n"
1023 " Insecure: %" PRIu64
"\n"
1024 " Bogus: %" PRIu64
"\n"
1025 " Indeterminate: %" PRIu64
"\n",
1031 n_dnssec_indeterminate
);
1036 static int reset_statistics(sd_bus
*bus
) {
1037 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1040 r
= sd_bus_call_method(bus
,
1041 "org.freedesktop.resolve1",
1042 "/org/freedesktop/resolve1",
1043 "org.freedesktop.resolve1.Manager",
1049 return log_error_errno(r
, "Failed to reset statistics: %s", bus_error_message(&error
, r
));
1054 static int flush_caches(sd_bus
*bus
) {
1055 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1058 r
= sd_bus_call_method(bus
,
1059 "org.freedesktop.resolve1",
1060 "/org/freedesktop/resolve1",
1061 "org.freedesktop.resolve1.Manager",
1067 return log_error_errno(r
, "Failed to flush caches: %s", bus_error_message(&error
, r
));
1072 static int reset_server_features(sd_bus
*bus
) {
1073 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1076 r
= sd_bus_call_method(bus
,
1077 "org.freedesktop.resolve1",
1078 "/org/freedesktop/resolve1",
1079 "org.freedesktop.resolve1.Manager",
1080 "ResetServerFeatures",
1085 return log_error_errno(r
, "Failed to reset server features: %s", bus_error_message(&error
, r
));
1090 static int map_link_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1091 char ***l
= userdata
;
1099 r
= sd_bus_message_enter_container(m
, 'a', "(iay)");
1109 r
= sd_bus_message_enter_container(m
, 'r', "iay");
1115 r
= sd_bus_message_read(m
, "i", &family
);
1119 r
= sd_bus_message_read_array(m
, 'y', &a
, &sz
);
1123 r
= sd_bus_message_exit_container(m
);
1127 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
1128 log_debug("Unexpected family, ignoring.");
1132 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
1133 log_debug("Address size mismatch, ignoring.");
1137 r
= in_addr_to_string(family
, a
, &pretty
);
1141 r
= strv_consume(l
, pretty
);
1146 r
= sd_bus_message_exit_container(m
);
1153 static int map_link_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1154 char ***l
= userdata
;
1162 r
= sd_bus_message_enter_container(m
, 'a', "(sb)");
1171 r
= sd_bus_message_read(m
, "(sb)", &domain
, &route_only
);
1178 pretty
= strappend("~", domain
);
1180 pretty
= strdup(domain
);
1184 r
= strv_consume(l
, pretty
);
1189 r
= sd_bus_message_exit_container(m
);
1196 static int status_ifindex(sd_bus
*bus
, int ifindex
, const char *name
, bool *empty_line
) {
1199 uint64_t scopes_mask
;
1206 int dnssec_supported
;
1209 static const struct bus_properties_map property_map
[] = {
1210 { "ScopesMask", "t", NULL
, offsetof(struct link_info
, scopes_mask
) },
1211 { "DNS", "a(iay)", map_link_dns_servers
, offsetof(struct link_info
, dns
) },
1212 { "Domains", "a(sb)", map_link_domains
, offsetof(struct link_info
, domains
) },
1213 { "LLMNR", "s", NULL
, offsetof(struct link_info
, llmnr
) },
1214 { "MulticastDNS", "s", NULL
, offsetof(struct link_info
, mdns
) },
1215 { "DNSSEC", "s", NULL
, offsetof(struct link_info
, dnssec
) },
1216 { "DNSSECNegativeTrustAnchors", "as", NULL
, offsetof(struct link_info
, ntas
) },
1217 { "DNSSECSupported", "b", NULL
, offsetof(struct link_info
, dnssec_supported
) },
1221 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1222 _cleanup_free_
char *ifi
= NULL
, *p
= NULL
;
1223 char ifname
[IF_NAMESIZE
] = "";
1228 assert(ifindex
> 0);
1232 if (!if_indextoname(ifindex
, ifname
))
1233 return log_error_errno(errno
, "Failed to resolve interface name for %i: %m", ifindex
);
1238 if (asprintf(&ifi
, "%i", ifindex
) < 0)
1241 r
= sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi
, &p
);
1245 r
= bus_map_all_properties(bus
,
1246 "org.freedesktop.resolve1",
1252 log_error_errno(r
, "Failed to get link data for %i: %s", ifindex
, bus_error_message(&error
, r
));
1256 pager_open(arg_no_pager
, false);
1259 fputc('\n', stdout
);
1261 printf("%sLink %i (%s)%s\n",
1262 ansi_highlight(), ifindex
, name
, ansi_normal());
1264 if (link_info
.scopes_mask
== 0)
1265 printf(" Current Scopes: none\n");
1267 printf(" Current Scopes:%s%s%s%s%s\n",
1268 link_info
.scopes_mask
& SD_RESOLVED_DNS
? " DNS" : "",
1269 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
1270 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
1271 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
1272 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
1274 printf(" LLMNR setting: %s\n"
1275 "MulticastDNS setting: %s\n"
1276 " DNSSEC setting: %s\n"
1277 " DNSSEC supported: %s\n",
1278 strna(link_info
.llmnr
),
1279 strna(link_info
.mdns
),
1280 strna(link_info
.dnssec
),
1281 yes_no(link_info
.dnssec_supported
));
1283 STRV_FOREACH(i
, link_info
.dns
) {
1285 i
== link_info
.dns
? "DNS Servers:" : " ",
1289 STRV_FOREACH(i
, link_info
.domains
) {
1291 i
== link_info
.domains
? "DNS Domain:" : " ",
1295 STRV_FOREACH(i
, link_info
.ntas
) {
1297 i
== link_info
.ntas
? "DNSSEC NTA:" : " ",
1306 strv_free(link_info
.dns
);
1307 strv_free(link_info
.domains
);
1308 free(link_info
.llmnr
);
1309 free(link_info
.mdns
);
1310 free(link_info
.dnssec
);
1311 strv_free(link_info
.ntas
);
1315 static int map_global_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1316 char ***l
= userdata
;
1324 r
= sd_bus_message_enter_container(m
, 'a', "(iiay)");
1331 int family
, ifindex
;
1334 r
= sd_bus_message_enter_container(m
, 'r', "iiay");
1340 r
= sd_bus_message_read(m
, "ii", &ifindex
, &family
);
1344 r
= sd_bus_message_read_array(m
, 'y', &a
, &sz
);
1348 r
= sd_bus_message_exit_container(m
);
1352 if (ifindex
!= 0) /* only show the global ones here */
1355 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
1356 log_debug("Unexpected family, ignoring.");
1360 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
1361 log_debug("Address size mismatch, ignoring.");
1365 r
= in_addr_to_string(family
, a
, &pretty
);
1369 r
= strv_consume(l
, pretty
);
1374 r
= sd_bus_message_exit_container(m
);
1381 static int map_global_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1382 char ***l
= userdata
;
1390 r
= sd_bus_message_enter_container(m
, 'a', "(isb)");
1396 int route_only
, ifindex
;
1399 r
= sd_bus_message_read(m
, "(isb)", &ifindex
, &domain
, &route_only
);
1405 if (ifindex
!= 0) /* only show the global ones here */
1409 pretty
= strappend("~", domain
);
1411 pretty
= strdup(domain
);
1415 r
= strv_consume(l
, pretty
);
1420 r
= sd_bus_message_exit_container(m
);
1427 static int status_global(sd_bus
*bus
, bool *empty_line
) {
1429 struct global_info
{
1435 static const struct bus_properties_map property_map
[] = {
1436 { "DNS", "a(iiay)", map_global_dns_servers
, offsetof(struct global_info
, dns
) },
1437 { "Domains", "a(isb)", map_global_domains
, offsetof(struct global_info
, domains
) },
1438 { "DNSSECNegativeTrustAnchors", "as", NULL
, offsetof(struct global_info
, ntas
) },
1442 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1449 r
= bus_map_all_properties(bus
,
1450 "org.freedesktop.resolve1",
1451 "/org/freedesktop/resolve1",
1456 log_error_errno(r
, "Failed to get global data: %s", bus_error_message(&error
, r
));
1460 if (strv_isempty(global_info
.dns
) && strv_isempty(global_info
.domains
) && strv_isempty(global_info
.ntas
)) {
1465 pager_open(arg_no_pager
, false);
1467 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1468 STRV_FOREACH(i
, global_info
.dns
) {
1470 i
== global_info
.dns
? "DNS Servers:" : " ",
1474 STRV_FOREACH(i
, global_info
.domains
) {
1476 i
== global_info
.domains
? "DNS Domain:" : " ",
1480 strv_sort(global_info
.ntas
);
1481 STRV_FOREACH(i
, global_info
.ntas
) {
1483 i
== global_info
.ntas
? "DNSSEC NTA:" : " ",
1492 strv_free(global_info
.dns
);
1493 strv_free(global_info
.domains
);
1494 strv_free(global_info
.ntas
);
1499 static int status_all(sd_bus
*bus
) {
1500 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
1501 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
1502 sd_netlink_message
*i
;
1503 bool empty_line
= false;
1508 r
= status_global(bus
, &empty_line
);
1512 r
= sd_netlink_open(&rtnl
);
1514 return log_error_errno(r
, "Failed to connect to netlink: %m");
1516 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_GETLINK
, 0);
1518 return rtnl_log_create_error(r
);
1520 r
= sd_netlink_message_request_dump(req
, true);
1522 return rtnl_log_create_error(r
);
1524 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
1526 return log_error_errno(r
, "Failed to enumerate links: %m");
1529 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
1534 q
= sd_netlink_message_get_type(i
, &type
);
1536 return rtnl_log_parse_error(q
);
1538 if (type
!= RTM_NEWLINK
)
1541 q
= sd_rtnl_message_link_get_ifindex(i
, &ifindex
);
1543 return rtnl_log_parse_error(q
);
1545 if (ifindex
== LOOPBACK_IFINDEX
)
1548 q
= sd_netlink_message_read_string(i
, IFLA_IFNAME
, &name
);
1550 return rtnl_log_parse_error(q
);
1552 q
= status_ifindex(bus
, ifindex
, name
, &empty_line
);
1553 if (q
< 0 && r
>= 0)
1560 static int set_link(sd_bus
*bus
) {
1561 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1566 if (arg_n_set_dns
> 0) {
1567 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
1570 q
= sd_bus_message_new_method_call(
1573 "org.freedesktop.resolve1",
1574 "/org/freedesktop/resolve1",
1575 "org.freedesktop.resolve1.Manager",
1578 return bus_log_create_error(q
);
1580 q
= sd_bus_message_append(req
, "i", arg_ifindex
);
1582 return bus_log_create_error(q
);
1584 q
= sd_bus_message_open_container(req
, 'a', "(iay)");
1586 return bus_log_create_error(q
);
1588 for (i
= 0; i
< arg_n_set_dns
; i
++) {
1589 q
= sd_bus_message_open_container(req
, 'r', "iay");
1591 return bus_log_create_error(q
);
1593 q
= sd_bus_message_append(req
, "i", arg_set_dns
[i
].family
);
1595 return bus_log_create_error(q
);
1597 q
= sd_bus_message_append_array(req
, 'y', &arg_set_dns
[i
].address
, FAMILY_ADDRESS_SIZE(arg_set_dns
[i
].family
));
1599 return bus_log_create_error(q
);
1601 q
= sd_bus_message_close_container(req
);
1603 return bus_log_create_error(q
);
1606 q
= sd_bus_message_close_container(req
);
1608 return bus_log_create_error(q
);
1610 q
= sd_bus_call(bus
, req
, 0, &error
, NULL
);
1612 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1615 log_error_errno(q
, "Failed to set DNS configuration: %s", bus_error_message(&error
, q
));
1621 if (!strv_isempty(arg_set_domain
)) {
1622 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
1625 q
= sd_bus_message_new_method_call(
1628 "org.freedesktop.resolve1",
1629 "/org/freedesktop/resolve1",
1630 "org.freedesktop.resolve1.Manager",
1633 return bus_log_create_error(q
);
1635 q
= sd_bus_message_append(req
, "i", arg_ifindex
);
1637 return bus_log_create_error(q
);
1639 q
= sd_bus_message_open_container(req
, 'a', "(sb)");
1641 return bus_log_create_error(q
);
1643 STRV_FOREACH(p
, arg_set_domain
) {
1646 n
= **p
== '~' ? *p
+ 1 : *p
;
1647 q
= sd_bus_message_append(req
, "(sb)", n
, **p
== '~');
1649 return bus_log_create_error(q
);
1652 q
= sd_bus_message_close_container(req
);
1654 return bus_log_create_error(q
);
1656 q
= sd_bus_call(bus
, req
, 0, &error
, NULL
);
1658 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1661 log_error_errno(q
, "Failed to set domain configuration: %s", bus_error_message(&error
, q
));
1667 if (arg_set_llmnr
) {
1668 q
= sd_bus_call_method(bus
,
1669 "org.freedesktop.resolve1",
1670 "/org/freedesktop/resolve1",
1671 "org.freedesktop.resolve1.Manager",
1675 "is", arg_ifindex
, arg_set_llmnr
);
1677 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1680 log_error_errno(q
, "Failed to set LLMNR configuration: %s", bus_error_message(&error
, q
));
1687 q
= sd_bus_call_method(bus
,
1688 "org.freedesktop.resolve1",
1689 "/org/freedesktop/resolve1",
1690 "org.freedesktop.resolve1.Manager",
1691 "SetLinkMulticastDNS",
1694 "is", arg_ifindex
, arg_set_mdns
);
1696 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1699 log_error_errno(q
, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error
, q
));
1705 if (arg_set_dnssec
) {
1706 q
= sd_bus_call_method(bus
,
1707 "org.freedesktop.resolve1",
1708 "/org/freedesktop/resolve1",
1709 "org.freedesktop.resolve1.Manager",
1713 "is", arg_ifindex
, arg_set_dnssec
);
1715 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1718 log_error_errno(q
, "Failed to set DNSSEC configuration: %s", bus_error_message(&error
, q
));
1724 if (!strv_isempty(arg_set_nta
)) {
1725 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
1727 q
= sd_bus_message_new_method_call(
1730 "org.freedesktop.resolve1",
1731 "/org/freedesktop/resolve1",
1732 "org.freedesktop.resolve1.Manager",
1733 "SetLinkDNSSECNegativeTrustAnchors");
1735 return bus_log_create_error(q
);
1737 q
= sd_bus_message_append(req
, "i", arg_ifindex
);
1739 return bus_log_create_error(q
);
1741 q
= sd_bus_message_append_strv(req
, arg_set_nta
);
1743 return bus_log_create_error(q
);
1745 q
= sd_bus_call(bus
, req
, 0, &error
, NULL
);
1747 if (sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
))
1750 log_error_errno(q
, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error
, q
));
1760 char ifname
[IFNAMSIZ
];
1762 return log_error_errno(q
,
1763 "The specified interface %s is managed by systemd-networkd. Operation refused.\n"
1764 "Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.", strna(if_indextoname(arg_ifindex
, ifname
)));
1768 static int revert_link(sd_bus
*bus
) {
1769 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1774 r
= sd_bus_call_method(bus
,
1775 "org.freedesktop.resolve1",
1776 "/org/freedesktop/resolve1",
1777 "org.freedesktop.resolve1.Manager",
1783 return log_error_errno(r
, "Failed to revert interface configuration: %s", bus_error_message(&error
, r
));
1788 static void help_protocol_types(void) {
1790 puts("Known protocol types:");
1791 puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6\nmdns\nmdns-ipv4\nmdns-ipv6");
1794 static void help_dns_types(void) {
1799 puts("Known DNS RR types:");
1800 for (i
= 0; i
< _DNS_TYPE_MAX
; i
++) {
1801 t
= dns_type_to_string(i
);
1807 static void help_dns_classes(void) {
1812 puts("Known DNS RR classes:");
1813 for (i
= 0; i
< _DNS_CLASS_MAX
; i
++) {
1814 t
= dns_class_to_string(i
);
1820 static void help(void) {
1821 printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
1822 "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
1823 "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
1824 "%1$s [OPTIONS...] --statistics\n"
1825 "%1$s [OPTIONS...] --reset-statistics\n"
1827 "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n"
1828 " -h --help Show this help\n"
1829 " --version Show package version\n"
1830 " --no-pager Do not pipe output into a pager\n"
1831 " -4 Resolve IPv4 addresses\n"
1832 " -6 Resolve IPv6 addresses\n"
1833 " -i --interface=INTERFACE Look on interface\n"
1834 " -p --protocol=PROTO|help Look via protocol\n"
1835 " -t --type=TYPE|help Query RR with DNS type\n"
1836 " -c --class=CLASS|help Query RR with DNS class\n"
1837 " --service Resolve service (SRV)\n"
1838 " --service-address=BOOL Resolve address for services (default: yes)\n"
1839 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
1840 " --openpgp Query OpenPGP public key\n"
1841 " --tlsa Query TLS public key\n"
1842 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
1843 " --search=BOOL Use search domains for single-label names\n"
1845 " --raw[=payload|packet] Dump the answer as binary data\n"
1846 " --legend=BOOL Print headers and additional info (default: yes)\n"
1847 " --statistics Show resolver statistics\n"
1848 " --reset-statistics Reset resolver statistics\n"
1849 " --status Show link and server status\n"
1850 " --flush-caches Flush all local DNS caches\n"
1851 " --reset-server-features\n"
1852 " Forget learnt DNS server feature levels\n"
1853 " --set-dns=SERVER Set per-interface DNS server address\n"
1854 " --set-domain=DOMAIN Set per-interface search domain\n"
1855 " --set-llmnr=MODE Set per-interface LLMNR mode\n"
1856 " --set-mdns=MODE Set per-interface MulticastDNS mode\n"
1857 " --set-dnssec=MODE Set per-interface DNSSEC mode\n"
1858 " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
1859 " --revert Revert per-interface configuration\n"
1860 , program_invocation_short_name
);
1863 static int parse_argv(int argc
, char *argv
[]) {
1865 ARG_VERSION
= 0x100,
1869 ARG_SERVICE_ADDRESS
,
1876 ARG_RESET_STATISTICS
,
1879 ARG_RESET_SERVER_FEATURES
,
1890 static const struct option options
[] = {
1891 { "help", no_argument
, NULL
, 'h' },
1892 { "version", no_argument
, NULL
, ARG_VERSION
},
1893 { "type", required_argument
, NULL
, 't' },
1894 { "class", required_argument
, NULL
, 'c' },
1895 { "legend", required_argument
, NULL
, ARG_LEGEND
},
1896 { "interface", required_argument
, NULL
, 'i' },
1897 { "protocol", required_argument
, NULL
, 'p' },
1898 { "cname", required_argument
, NULL
, ARG_CNAME
},
1899 { "service", no_argument
, NULL
, ARG_SERVICE
},
1900 { "service-address", required_argument
, NULL
, ARG_SERVICE_ADDRESS
},
1901 { "service-txt", required_argument
, NULL
, ARG_SERVICE_TXT
},
1902 { "openpgp", no_argument
, NULL
, ARG_OPENPGP
},
1903 { "tlsa", optional_argument
, NULL
, ARG_TLSA
},
1904 { "raw", optional_argument
, NULL
, ARG_RAW
},
1905 { "search", required_argument
, NULL
, ARG_SEARCH
},
1906 { "statistics", no_argument
, NULL
, ARG_STATISTICS
, },
1907 { "reset-statistics", no_argument
, NULL
, ARG_RESET_STATISTICS
},
1908 { "status", no_argument
, NULL
, ARG_STATUS
},
1909 { "flush-caches", no_argument
, NULL
, ARG_FLUSH_CACHES
},
1910 { "reset-server-features", no_argument
, NULL
, ARG_RESET_SERVER_FEATURES
},
1911 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
1912 { "set-dns", required_argument
, NULL
, ARG_SET_DNS
},
1913 { "set-domain", required_argument
, NULL
, ARG_SET_DOMAIN
},
1914 { "set-llmnr", required_argument
, NULL
, ARG_SET_LLMNR
},
1915 { "set-mdns", required_argument
, NULL
, ARG_SET_MDNS
},
1916 { "set-dnssec", required_argument
, NULL
, ARG_SET_DNSSEC
},
1917 { "set-nta", required_argument
, NULL
, ARG_SET_NTA
},
1918 { "revert", no_argument
, NULL
, ARG_REVERT_LINK
},
1927 while ((c
= getopt_long(argc
, argv
, "h46i:t:c:p:", options
, NULL
)) >= 0)
1932 return 0; /* done */;
1938 arg_family
= AF_INET
;
1942 arg_family
= AF_INET6
;
1948 if (parse_ifindex(optarg
, &ifi
) >= 0)
1951 ifi
= if_nametoindex(optarg
);
1953 return log_error_errno(errno
, "Unknown interface %s: %m", optarg
);
1962 if (streq(optarg
, "help")) {
1967 r
= dns_type_from_string(optarg
);
1969 log_error("Failed to parse RR record type %s", optarg
);
1972 arg_type
= (uint16_t) r
;
1973 assert((int) arg_type
== r
);
1975 arg_mode
= MODE_RESOLVE_RECORD
;
1979 if (streq(optarg
, "help")) {
1984 r
= dns_class_from_string(optarg
);
1986 log_error("Failed to parse RR record class %s", optarg
);
1989 arg_class
= (uint16_t) r
;
1990 assert((int) arg_class
== r
);
1995 r
= parse_boolean(optarg
);
1997 return log_error_errno(r
, "Failed to parse --legend= argument");
2003 if (streq(optarg
, "help")) {
2004 help_protocol_types();
2006 } else if (streq(optarg
, "dns"))
2007 arg_flags
|= SD_RESOLVED_DNS
;
2008 else if (streq(optarg
, "llmnr"))
2009 arg_flags
|= SD_RESOLVED_LLMNR
;
2010 else if (streq(optarg
, "llmnr-ipv4"))
2011 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
2012 else if (streq(optarg
, "llmnr-ipv6"))
2013 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
2014 else if (streq(optarg
, "mdns"))
2015 arg_flags
|= SD_RESOLVED_MDNS
;
2016 else if (streq(optarg
, "mdns-ipv4"))
2017 arg_flags
|= SD_RESOLVED_MDNS_IPV4
;
2018 else if (streq(optarg
, "mdns-ipv6"))
2019 arg_flags
|= SD_RESOLVED_MDNS_IPV6
;
2021 log_error("Unknown protocol specifier: %s", optarg
);
2028 arg_mode
= MODE_RESOLVE_SERVICE
;
2032 arg_mode
= MODE_RESOLVE_OPENPGP
;
2036 arg_mode
= MODE_RESOLVE_TLSA
;
2037 arg_service_family
= service_family_from_string(optarg
);
2038 if (arg_service_family
< 0) {
2039 log_error("Unknown service family \"%s\".", optarg
);
2046 log_error("Refusing to write binary data to tty.");
2050 if (optarg
== NULL
|| streq(optarg
, "payload"))
2051 arg_raw
= RAW_PAYLOAD
;
2052 else if (streq(optarg
, "packet"))
2053 arg_raw
= RAW_PACKET
;
2055 log_error("Unknown --raw specifier \"%s\".", optarg
);
2063 r
= parse_boolean(optarg
);
2065 return log_error_errno(r
, "Failed to parse --cname= argument.");
2066 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CNAME
, r
== 0);
2069 case ARG_SERVICE_ADDRESS
:
2070 r
= parse_boolean(optarg
);
2072 return log_error_errno(r
, "Failed to parse --service-address= argument.");
2073 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ADDRESS
, r
== 0);
2076 case ARG_SERVICE_TXT
:
2077 r
= parse_boolean(optarg
);
2079 return log_error_errno(r
, "Failed to parse --service-txt= argument.");
2080 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TXT
, r
== 0);
2084 r
= parse_boolean(optarg
);
2086 return log_error_errno(r
, "Failed to parse --search argument.");
2087 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SEARCH
, r
== 0);
2090 case ARG_STATISTICS
:
2091 arg_mode
= MODE_STATISTICS
;
2094 case ARG_RESET_STATISTICS
:
2095 arg_mode
= MODE_RESET_STATISTICS
;
2098 case ARG_FLUSH_CACHES
:
2099 arg_mode
= MODE_FLUSH_CACHES
;
2102 case ARG_RESET_SERVER_FEATURES
:
2103 arg_mode
= MODE_RESET_SERVER_FEATURES
;
2107 arg_mode
= MODE_STATUS
;
2111 arg_no_pager
= true;
2115 struct in_addr_data data
, *n
;
2117 r
= in_addr_from_string_auto(optarg
, &data
.family
, &data
.address
);
2119 return log_error_errno(r
, "Failed to parse DNS server address: %s", optarg
);
2121 n
= realloc(arg_set_dns
, sizeof(struct in_addr_data
) * (arg_n_set_dns
+ 1));
2126 arg_set_dns
[arg_n_set_dns
++] = data
;
2127 arg_mode
= MODE_SET_LINK
;
2131 case ARG_SET_DOMAIN
: {
2134 p
= optarg
[0] == '~' ? optarg
+ 1 : optarg
;
2136 r
= dns_name_is_valid(p
);
2138 return log_error_errno(r
, "Failed to validate specified domain %s: %m", p
);
2140 return log_error_errno(r
, "Domain not valid: %s", p
);
2142 r
= strv_extend(&arg_set_domain
, optarg
);
2146 arg_mode
= MODE_SET_LINK
;
2151 r
= free_and_strdup(&arg_set_llmnr
, optarg
);
2155 arg_mode
= MODE_SET_LINK
;
2159 r
= free_and_strdup(&arg_set_mdns
, optarg
);
2163 arg_mode
= MODE_SET_LINK
;
2166 case ARG_SET_DNSSEC
:
2167 r
= free_and_strdup(&arg_set_dnssec
, optarg
);
2171 arg_mode
= MODE_SET_LINK
;
2175 r
= dns_name_is_valid(optarg
);
2177 return log_error_errno(r
, "Failed to validate specified domain %s: %m", optarg
);
2179 return log_error_errno(r
, "Domain not valid: %s", optarg
);
2181 r
= strv_extend(&arg_set_nta
, optarg
);
2185 arg_mode
= MODE_SET_LINK
;
2188 case ARG_REVERT_LINK
:
2189 arg_mode
= MODE_REVERT_LINK
;
2196 assert_not_reached("Unhandled option");
2199 if (arg_type
== 0 && arg_class
!= 0) {
2200 log_error("--class= may only be used in conjunction with --type=.");
2204 if (arg_type
!= 0 && arg_mode
== MODE_RESOLVE_SERVICE
) {
2205 log_error("--service and --type= may not be combined.");
2209 if (arg_type
!= 0 && arg_class
== 0)
2210 arg_class
= DNS_CLASS_IN
;
2212 if (arg_class
!= 0 && arg_type
== 0)
2213 arg_type
= DNS_TYPE_A
;
2215 if (IN_SET(arg_mode
, MODE_SET_LINK
, MODE_REVERT_LINK
)) {
2217 if (arg_ifindex
<= 0) {
2218 log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, --set-nta= and --revert require --interface=.");
2222 if (arg_ifindex
== LOOPBACK_IFINDEX
) {
2223 log_error("Interface can't be the loopback interface (lo). Sorry.");
2228 return 1 /* work to do */;
2231 int main(int argc
, char **argv
) {
2232 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2235 log_parse_environment();
2238 r
= parse_argv(argc
, argv
);
2242 r
= sd_bus_open_system(&bus
);
2244 log_error_errno(r
, "sd_bus_open_system: %m");
2250 case MODE_RESOLVE_HOST
:
2251 if (optind
>= argc
) {
2252 log_error("No arguments passed.");
2257 while (argv
[optind
]) {
2258 int family
, ifindex
, k
;
2259 union in_addr_union a
;
2261 if (startswith(argv
[optind
], "dns:"))
2262 k
= resolve_rfc4501(bus
, argv
[optind
]);
2264 k
= in_addr_ifindex_from_string_auto(argv
[optind
], &family
, &a
, &ifindex
);
2266 k
= resolve_address(bus
, family
, &a
, ifindex
);
2268 k
= resolve_host(bus
, argv
[optind
]);
2278 case MODE_RESOLVE_RECORD
:
2279 if (optind
>= argc
) {
2280 log_error("No arguments passed.");
2285 while (argv
[optind
]) {
2288 k
= resolve_record(bus
, argv
[optind
], arg_class
, arg_type
, true);
2296 case MODE_RESOLVE_SERVICE
:
2297 if (argc
< optind
+ 1) {
2298 log_error("Domain specification required.");
2302 } else if (argc
== optind
+ 1)
2303 r
= resolve_service(bus
, NULL
, NULL
, argv
[optind
]);
2304 else if (argc
== optind
+ 2)
2305 r
= resolve_service(bus
, NULL
, argv
[optind
], argv
[optind
+1]);
2306 else if (argc
== optind
+ 3)
2307 r
= resolve_service(bus
, argv
[optind
], argv
[optind
+1], argv
[optind
+2]);
2309 log_error("Too many arguments.");
2316 case MODE_RESOLVE_OPENPGP
:
2317 if (argc
< optind
+ 1) {
2318 log_error("E-mail address required.");
2325 while (optind
< argc
) {
2328 k
= resolve_openpgp(bus
, argv
[optind
++]);
2334 case MODE_RESOLVE_TLSA
:
2335 if (argc
< optind
+ 1) {
2336 log_error("Domain name required.");
2343 while (optind
< argc
) {
2346 k
= resolve_tlsa(bus
, argv
[optind
++]);
2352 case MODE_STATISTICS
:
2353 if (argc
> optind
) {
2354 log_error("Too many arguments.");
2359 r
= show_statistics(bus
);
2362 case MODE_RESET_STATISTICS
:
2363 if (argc
> optind
) {
2364 log_error("Too many arguments.");
2369 r
= reset_statistics(bus
);
2372 case MODE_FLUSH_CACHES
:
2373 if (argc
> optind
) {
2374 log_error("Too many arguments.");
2379 r
= flush_caches(bus
);
2382 case MODE_RESET_SERVER_FEATURES
:
2383 if (argc
> optind
) {
2384 log_error("Too many arguments.");
2389 r
= reset_server_features(bus
);
2394 if (argc
> optind
) {
2396 bool empty_line
= false;
2399 STRV_FOREACH(ifname
, argv
+ optind
) {
2402 q
= parse_ifindex(argv
[optind
], &ifindex
);
2404 ifindex
= if_nametoindex(argv
[optind
]);
2406 log_error_errno(errno
, "Failed to resolve interface name: %s", argv
[optind
]);
2411 q
= status_ifindex(bus
, ifindex
, NULL
, &empty_line
);
2412 if (q
< 0 && r
>= 0)
2416 r
= status_all(bus
);
2422 if (argc
> optind
) {
2423 log_error("Too many arguments.");
2431 case MODE_REVERT_LINK
:
2432 if (argc
> optind
) {
2433 log_error("Too many arguments.");
2438 r
= revert_link(bus
);
2446 strv_free(arg_set_domain
);
2447 free(arg_set_llmnr
);
2449 free(arg_set_dnssec
);
2450 strv_free(arg_set_nta
);
2452 return r
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;