1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "sd-netlink.h"
11 #include "alloc-util.h"
12 #include "bus-common-errors.h"
13 #include "bus-error.h"
14 #include "bus-locator.h"
15 #include "bus-map-properties.h"
16 #include "bus-message-util.h"
17 #include "dns-domain.h"
18 #include "errno-list.h"
20 #include "format-table.h"
21 #include "format-util.h"
22 #include "gcrypt-util.h"
23 #include "hostname-util.h"
25 #include "main-func.h"
26 #include "missing_network.h"
27 #include "netlink-util.h"
28 #include "openssl-util.h"
30 #include "parse-argument.h"
31 #include "parse-util.h"
32 #include "pretty-print.h"
33 #include "process-util.h"
34 #include "resolvconf-compat.h"
35 #include "resolvectl.h"
36 #include "resolved-def.h"
37 #include "resolved-dns-packet.h"
38 #include "resolved-util.h"
39 #include "socket-netlink.h"
40 #include "sort-util.h"
41 #include "stdio-util.h"
42 #include "string-table.h"
44 #include "terminal-util.h"
47 #include "verb-log-control.h"
50 static int arg_family
= AF_UNSPEC
;
51 static int arg_ifindex
= 0;
52 static char *arg_ifname
= NULL
;
53 static uint16_t arg_type
= 0;
54 static uint16_t arg_class
= 0;
55 static bool arg_legend
= true;
56 static uint64_t arg_flags
= 0;
57 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
58 static PagerFlags arg_pager_flags
= 0;
59 bool arg_ifindex_permissive
= false; /* If true, don't generate an error if the specified interface index doesn't exist */
60 static const char *arg_service_family
= NULL
;
62 typedef enum RawType
{
67 static RawType arg_raw
= RAW_NONE
;
69 ExecutionMode arg_mode
= MODE_RESOLVE_HOST
;
71 char **arg_set_dns
= NULL
;
72 char **arg_set_domain
= NULL
;
73 static const char *arg_set_llmnr
= NULL
;
74 static const char *arg_set_mdns
= NULL
;
75 static const char *arg_set_dns_over_tls
= NULL
;
76 static const char *arg_set_dnssec
= NULL
;
77 static char **arg_set_nta
= NULL
;
79 STATIC_DESTRUCTOR_REGISTER(arg_ifname
, freep
);
80 STATIC_DESTRUCTOR_REGISTER(arg_set_dns
, strv_freep
);
81 STATIC_DESTRUCTOR_REGISTER(arg_set_domain
, strv_freep
);
82 STATIC_DESTRUCTOR_REGISTER(arg_set_nta
, strv_freep
);
84 typedef enum StatusMode
{
96 typedef struct InterfaceInfo
{
101 static int interface_info_compare(const InterfaceInfo
*a
, const InterfaceInfo
*b
) {
104 r
= CMP(a
->index
, b
->index
);
108 return strcmp_ptr(a
->name
, b
->name
);
111 int ifname_mangle_full(const char *s
, bool drop_protocol_specifier
) {
112 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
113 _cleanup_strv_free_
char **found
= NULL
;
118 if (drop_protocol_specifier
) {
119 _cleanup_free_
char *buf
= NULL
;
120 int ifindex_longest_name
= -ENODEV
;
122 /* When invoked as resolvconf, drop the protocol specifier(s) at the end. */
129 r
= rtnl_resolve_interface(&rtnl
, buf
);
131 if (ifindex_longest_name
<= 0)
132 ifindex_longest_name
= r
;
134 r
= strv_extend(&found
, buf
);
139 char *dot
= strrchr(buf
, '.');
146 unsigned n
= strv_length(found
);
148 _cleanup_free_
char *joined
= NULL
;
150 joined
= strv_join(found
, ", ");
151 log_warning("Found multiple interfaces (%s) matching with '%s'. Using '%s' (ifindex=%i).",
152 strna(joined
), s
, found
[0], ifindex_longest_name
);
157 proto
= ASSERT_PTR(startswith(s
, found
[0]));
159 log_info("Dropped protocol specifier '%s' from '%s'. Using '%s' (ifindex=%i).",
160 proto
, s
, found
[0], ifindex_longest_name
);
163 r
= ifindex_longest_name
;
165 r
= rtnl_resolve_interface(&rtnl
, s
);
167 if (ERRNO_IS_DEVICE_ABSENT(r
) && arg_ifindex_permissive
) {
168 log_debug_errno(r
, "Interface '%s' not found, but -f specified, ignoring: %m", s
);
171 return log_error_errno(r
, "Failed to resolve interface \"%s\": %m", s
);
174 if (arg_ifindex
> 0 && arg_ifindex
!= r
)
175 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Specified multiple different interfaces. Refusing.");
178 return free_and_strdup_warn(&arg_ifname
, found
? found
[0] : s
); /* found */
181 static void print_source(uint64_t flags
, usec_t rtt
) {
188 printf("\n%s-- Information acquired via", ansi_grey());
190 printf(" protocol%s%s%s%s%s",
191 flags
& SD_RESOLVED_DNS
? " DNS" :"",
192 flags
& SD_RESOLVED_LLMNR_IPV4
? " LLMNR/IPv4" : "",
193 flags
& SD_RESOLVED_LLMNR_IPV6
? " LLMNR/IPv6" : "",
194 flags
& SD_RESOLVED_MDNS_IPV4
? " mDNS/IPv4" : "",
195 flags
& SD_RESOLVED_MDNS_IPV6
? " mDNS/IPv6" : "");
198 "%s-- Data is authenticated: %s; Data was acquired via local or encrypted transport: %s%s\n",
199 FORMAT_TIMESPAN(rtt
, 100),
202 yes_no(flags
& SD_RESOLVED_AUTHENTICATED
),
203 yes_no(flags
& SD_RESOLVED_CONFIDENTIAL
),
206 if ((flags
& (SD_RESOLVED_FROM_MASK
|SD_RESOLVED_SYNTHETIC
)) != 0)
207 printf("%s-- Data from:%s%s%s%s%s%s\n",
209 FLAGS_SET(flags
, SD_RESOLVED_SYNTHETIC
) ? " synthetic" : "",
210 FLAGS_SET(flags
, SD_RESOLVED_FROM_CACHE
) ? " cache" : "",
211 FLAGS_SET(flags
, SD_RESOLVED_FROM_ZONE
) ? " zone" : "",
212 FLAGS_SET(flags
, SD_RESOLVED_FROM_TRUST_ANCHOR
) ? " trust-anchor" : "",
213 FLAGS_SET(flags
, SD_RESOLVED_FROM_NETWORK
) ? " network" : "",
217 static void print_ifindex_comment(int printed_so_far
, int ifindex
) {
218 char ifname
[IF_NAMESIZE
];
224 r
= format_ifname(ifindex
, ifname
);
226 return (void) log_warning_errno(r
, "Failed to resolve interface name for index %i, ignoring: %m", ifindex
);
228 printf("%*s%s-- link: %s%s",
229 60 > printed_so_far
? 60 - printed_so_far
: 0, " ", /* Align comment to the 60th column */
230 ansi_grey(), ifname
, ansi_normal());
233 static int resolve_host_error(const char *name
, int r
, const sd_bus_error
*error
) {
234 if (sd_bus_error_has_name(error
, BUS_ERROR_DNS_NXDOMAIN
))
235 return log_error_errno(r
, "%s: %s", name
, bus_error_message(error
, r
));
237 return log_error_errno(r
, "%s: resolve call failed: %s", name
, bus_error_message(error
, r
));
240 static int resolve_host(sd_bus
*bus
, const char *name
) {
241 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
242 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
243 const char *canonical
= NULL
;
251 log_debug("Resolving %s (family %s, interface %s).", name
, af_to_name(arg_family
) ?: "*", isempty(arg_ifname
) ? "*" : arg_ifname
);
253 r
= bus_message_new_method_call(bus
, &req
, bus_resolve_mgr
, "ResolveHostname");
255 return bus_log_create_error(r
);
257 r
= sd_bus_message_append(req
, "isit", arg_ifindex
, name
, arg_family
, arg_flags
);
259 return bus_log_create_error(r
);
261 ts
= now(CLOCK_MONOTONIC
);
263 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
265 return resolve_host_error(name
, r
, &error
);
267 ts
= now(CLOCK_MONOTONIC
) - ts
;
269 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
271 return bus_log_parse_error(r
);
273 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
274 _cleanup_free_
char *pretty
= NULL
;
275 int ifindex
, family
, k
;
276 union in_addr_union a
;
278 assert_cc(sizeof(int) == sizeof(int32_t));
280 r
= sd_bus_message_read(reply
, "i", &ifindex
);
282 return bus_log_parse_error(r
);
284 sd_bus_error_free(&error
);
285 r
= bus_message_read_in_addr_auto(reply
, &error
, &family
, &a
);
286 if (r
< 0 && !sd_bus_error_has_name(&error
, SD_BUS_ERROR_INVALID_ARGS
))
287 return log_error_errno(r
, "%s: systemd-resolved returned invalid result: %s", name
, bus_error_message(&error
, r
));
289 r
= sd_bus_message_exit_container(reply
);
291 return bus_log_parse_error(r
);
293 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_INVALID_ARGS
)) {
294 log_debug_errno(r
, "%s: systemd-resolved returned invalid result, ignoring: %s", name
, bus_error_message(&error
, r
));
298 r
= in_addr_ifindex_to_string(family
, &a
, ifindex
, &pretty
);
300 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
302 k
= printf("%*s%s %s%s%s",
303 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
304 ansi_highlight(), pretty
, ansi_normal());
306 print_ifindex_comment(k
, ifindex
);
312 return bus_log_parse_error(r
);
314 r
= sd_bus_message_exit_container(reply
);
316 return bus_log_parse_error(r
);
318 r
= sd_bus_message_read(reply
, "st", &canonical
, &flags
);
320 return bus_log_parse_error(r
);
322 if (!streq(name
, canonical
))
323 printf("%*s%s (%s)\n",
324 (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? ":" : " ",
328 return log_error_errno(SYNTHETIC_ERRNO(ESRCH
),
329 "%s: no addresses found", name
);
331 print_source(flags
, ts
);
336 static int resolve_address(sd_bus
*bus
, int family
, const union in_addr_union
*address
, int ifindex
) {
337 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
338 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
339 _cleanup_free_
char *pretty
= NULL
;
346 assert(IN_SET(family
, AF_INET
, AF_INET6
));
350 ifindex
= arg_ifindex
;
352 r
= in_addr_ifindex_to_string(family
, address
, ifindex
, &pretty
);
356 log_debug("Resolving %s.", pretty
);
358 r
= bus_message_new_method_call(bus
, &req
, bus_resolve_mgr
, "ResolveAddress");
360 return bus_log_create_error(r
);
362 r
= sd_bus_message_append(req
, "ii", ifindex
, family
);
364 return bus_log_create_error(r
);
366 r
= sd_bus_message_append_array(req
, 'y', address
, FAMILY_ADDRESS_SIZE(family
));
368 return bus_log_create_error(r
);
370 r
= sd_bus_message_append(req
, "t", arg_flags
);
372 return bus_log_create_error(r
);
374 ts
= now(CLOCK_MONOTONIC
);
376 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
378 return log_error_errno(r
, "%s: resolve call failed: %s", pretty
, bus_error_message(&error
, r
));
380 ts
= now(CLOCK_MONOTONIC
) - ts
;
382 r
= sd_bus_message_enter_container(reply
, 'a', "(is)");
384 return bus_log_create_error(r
);
386 while ((r
= sd_bus_message_enter_container(reply
, 'r', "is")) > 0) {
390 assert_cc(sizeof(int) == sizeof(int32_t));
392 r
= sd_bus_message_read(reply
, "is", &ifindex
, &n
);
396 r
= sd_bus_message_exit_container(reply
);
400 k
= printf("%*s%s %s%s%s",
401 (int) strlen(pretty
), c
== 0 ? pretty
: "",
403 ansi_highlight(), n
, ansi_normal());
405 print_ifindex_comment(k
, ifindex
);
411 return bus_log_parse_error(r
);
413 r
= sd_bus_message_exit_container(reply
);
415 return bus_log_parse_error(r
);
417 r
= sd_bus_message_read(reply
, "t", &flags
);
419 return bus_log_parse_error(r
);
422 return log_error_errno(SYNTHETIC_ERRNO(ESRCH
),
423 "%s: no names found", pretty
);
425 print_source(flags
, ts
);
430 static int output_rr_packet(const void *d
, size_t l
, int ifindex
) {
431 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
434 r
= dns_resource_record_new_from_raw(&rr
, d
, l
);
436 return log_error_errno(r
, "Failed to parse RR: %m");
438 if (arg_raw
== RAW_PAYLOAD
) {
442 k
= dns_resource_record_payload(rr
, &data
);
444 return log_error_errno(k
, "Cannot dump RR: %m");
445 fwrite(data
, 1, k
, stdout
);
450 s
= dns_resource_record_to_string(rr
);
455 print_ifindex_comment(k
, ifindex
);
462 static int idna_candidate(const char *name
, char **ret
) {
463 _cleanup_free_
char *idnafied
= NULL
;
469 r
= dns_name_apply_idna(name
, &idnafied
);
471 return log_error_errno(r
, "Failed to apply IDNA to name '%s': %m", name
);
472 if (r
> 0 && !streq(name
, idnafied
)) {
473 *ret
= TAKE_PTR(idnafied
);
481 static bool single_label_nonsynthetic(const char *name
) {
482 _cleanup_free_
char *first_label
= NULL
;
485 if (!dns_name_is_single_label(name
))
488 if (is_localhost(name
) || is_gateway_hostname(name
))
491 r
= resolve_system_hostname(NULL
, &first_label
);
493 log_warning_errno(r
, "Failed to determine the hostname: %m");
497 return !streq(name
, first_label
);
500 static int resolve_record(sd_bus
*bus
, const char *name
, uint16_t class, uint16_t type
, bool warn_missing
) {
501 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
502 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
503 _cleanup_free_
char *idnafied
= NULL
;
504 bool needs_authentication
= false;
512 log_debug("Resolving %s %s %s (interface %s).", name
, dns_class_to_string(class), dns_type_to_string(type
), isempty(arg_ifname
) ? "*" : arg_ifname
);
514 if (dns_name_dot_suffixed(name
) == 0 && single_label_nonsynthetic(name
))
515 log_notice("(Note that search domains are not appended when --type= is specified. "
516 "Please specify fully qualified domain names, or remove --type= switch from invocation in order to request regular hostname resolution.)");
518 r
= idna_candidate(name
, &idnafied
);
522 log_notice("(Note that IDNA translation is not applied when --type= is specified. "
523 "Please specify translated domain names — i.e. '%s' — when resolving raw records, or remove --type= switch from invocation in order to request regular hostname resolution.",
526 r
= bus_message_new_method_call(bus
, &req
, bus_resolve_mgr
, "ResolveRecord");
528 return bus_log_create_error(r
);
530 r
= sd_bus_message_append(req
, "isqqt", arg_ifindex
, name
, class, type
, arg_flags
);
532 return bus_log_create_error(r
);
534 ts
= now(CLOCK_MONOTONIC
);
536 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
538 if (warn_missing
|| r
!= -ENXIO
)
539 log_error("%s: resolve call failed: %s", name
, bus_error_message(&error
, r
));
543 ts
= now(CLOCK_MONOTONIC
) - ts
;
545 r
= sd_bus_message_enter_container(reply
, 'a', "(iqqay)");
547 return bus_log_parse_error(r
);
549 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iqqay")) > 0) {
555 assert_cc(sizeof(int) == sizeof(int32_t));
557 r
= sd_bus_message_read(reply
, "iqq", &ifindex
, &c
, &t
);
559 return bus_log_parse_error(r
);
561 r
= sd_bus_message_read_array(reply
, 'y', &d
, &l
);
563 return bus_log_parse_error(r
);
565 r
= sd_bus_message_exit_container(reply
);
567 return bus_log_parse_error(r
);
569 if (arg_raw
== RAW_PACKET
) {
570 uint64_t u64
= htole64(l
);
572 fwrite(&u64
, sizeof(u64
), 1, stdout
);
573 fwrite(d
, 1, l
, stdout
);
575 r
= output_rr_packet(d
, l
, ifindex
);
580 if (dns_type_needs_authentication(t
))
581 needs_authentication
= true;
586 return bus_log_parse_error(r
);
588 r
= sd_bus_message_exit_container(reply
);
590 return bus_log_parse_error(r
);
592 r
= sd_bus_message_read(reply
, "t", &flags
);
594 return bus_log_parse_error(r
);
598 log_error("%s: no records found", name
);
602 print_source(flags
, ts
);
604 if ((flags
& SD_RESOLVED_AUTHENTICATED
) == 0 && needs_authentication
) {
607 fprintf(stderr
, "\n%s"
608 "WARNING: The resources shown contain cryptographic key data which could not be\n"
609 " authenticated. It is not suitable to authenticate any communication.\n"
610 " This is usually indication that DNSSEC authentication was not enabled\n"
611 " or is not available for the selected protocol or DNS servers.%s\n",
612 ansi_highlight_red(),
619 static int resolve_rfc4501(sd_bus
*bus
, const char *name
) {
620 uint16_t type
= 0, class = 0;
621 const char *p
, *q
, *n
;
626 assert(startswith(name
, "dns:"));
628 /* Parse RFC 4501 dns: URIs */
638 e
= strchr(p
+ 2, '/');
643 log_warning("DNS authority specification not supported; ignoring specified authority.");
650 n
= strndupa_safe(p
, q
- p
);
656 f
= startswith_no_case(q
, "class=");
658 _cleanup_free_
char *t
= NULL
;
662 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
663 "DNS class specified twice.");
665 e
= strchrnul(f
, ';');
666 t
= strndup(f
, e
- f
);
670 r
= dns_class_from_string(t
);
672 return log_error_errno(r
, "Unknown DNS class %s.", t
);
684 f
= startswith_no_case(q
, "type=");
686 _cleanup_free_
char *t
= NULL
;
690 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
691 "DNS type specified twice.");
693 e
= strchrnul(f
, ';');
694 t
= strndup(f
, e
- f
);
698 r
= dns_type_from_string(t
);
700 return log_error_errno(r
, "Unknown DNS type %s: %m", t
);
718 class = arg_class
?: DNS_CLASS_IN
;
720 type
= arg_type
?: DNS_TYPE_A
;
722 return resolve_record(bus
, n
, class, type
, true);
725 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
726 "Invalid DNS URI: %s", name
);
729 static int verb_query(int argc
, char **argv
, void *userdata
) {
730 sd_bus
*bus
= userdata
;
734 STRV_FOREACH(p
, argv
+ 1) {
735 q
= resolve_record(bus
, *p
, arg_class
, arg_type
, true);
741 STRV_FOREACH(p
, argv
+ 1) {
742 if (startswith(*p
, "dns:"))
743 q
= resolve_rfc4501(bus
, *p
);
746 union in_addr_union a
;
748 q
= in_addr_ifindex_from_string_auto(*p
, &family
, &a
, &ifindex
);
750 q
= resolve_address(bus
, family
, &a
, ifindex
);
752 q
= resolve_host(bus
, *p
);
761 static int resolve_service(sd_bus
*bus
, const char *name
, const char *type
, const char *domain
) {
762 const char *canonical_name
, *canonical_type
, *canonical_domain
;
763 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
, *reply
= NULL
;
764 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
775 name
= empty_to_null(name
);
776 type
= empty_to_null(type
);
779 log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name
, type
, domain
, af_to_name(arg_family
) ?: "*", isempty(arg_ifname
) ? "*" : arg_ifname
);
781 log_debug("Resolving service type %s of %s (family %s, interface %s).", type
, domain
, af_to_name(arg_family
) ?: "*", isempty(arg_ifname
) ? "*" : arg_ifname
);
783 log_debug("Resolving service type %s (family %s, interface %s).", domain
, af_to_name(arg_family
) ?: "*", isempty(arg_ifname
) ? "*" : arg_ifname
);
785 r
= bus_message_new_method_call(bus
, &req
, bus_resolve_mgr
, "ResolveService");
787 return bus_log_create_error(r
);
789 r
= sd_bus_message_append(req
, "isssit", arg_ifindex
, name
, type
, domain
, arg_family
, arg_flags
);
791 return bus_log_create_error(r
);
793 ts
= now(CLOCK_MONOTONIC
);
795 r
= sd_bus_call(bus
, req
, SD_RESOLVED_QUERY_TIMEOUT_USEC
, &error
, &reply
);
797 return log_error_errno(r
, "Resolve call failed: %s", bus_error_message(&error
, r
));
799 ts
= now(CLOCK_MONOTONIC
) - ts
;
801 r
= sd_bus_message_enter_container(reply
, 'a', "(qqqsa(iiay)s)");
803 return bus_log_parse_error(r
);
806 (name
? strlen(name
) + 1 : 0) +
807 (type
? strlen(type
) + 1 : 0) +
811 while ((r
= sd_bus_message_enter_container(reply
, 'r', "qqqsa(iiay)s")) > 0) {
812 uint16_t priority
, weight
, port
;
813 const char *hostname
, *canonical
;
815 r
= sd_bus_message_read(reply
, "qqqs", &priority
, &weight
, &port
, &hostname
);
817 return bus_log_parse_error(r
);
820 printf("%*s%s", (int) strlen(name
), c
== 0 ? name
: "", c
== 0 ? "/" : " ");
822 printf("%*s%s", (int) strlen(type
), c
== 0 ? type
: "", c
== 0 ? "/" : " ");
824 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
825 (int) strlen(domain
), c
== 0 ? domain
: "",
830 r
= sd_bus_message_enter_container(reply
, 'a', "(iiay)");
832 return bus_log_parse_error(r
);
834 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iiay")) > 0) {
835 _cleanup_free_
char *pretty
= NULL
;
836 int ifindex
, family
, k
;
837 union in_addr_union a
;
839 assert_cc(sizeof(int) == sizeof(int32_t));
841 r
= sd_bus_message_read(reply
, "i", &ifindex
);
843 return bus_log_parse_error(r
);
845 sd_bus_error_free(&error
);
846 r
= bus_message_read_in_addr_auto(reply
, &error
, &family
, &a
);
847 if (r
< 0 && !sd_bus_error_has_name(&error
, SD_BUS_ERROR_INVALID_ARGS
))
848 return log_error_errno(r
, "%s: systemd-resolved returned invalid result: %s", name
, bus_error_message(&error
, r
));
850 r
= sd_bus_message_exit_container(reply
);
852 return bus_log_parse_error(r
);
854 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_INVALID_ARGS
)) {
855 log_debug_errno(r
, "%s: systemd-resolved returned invalid result, ignoring: %s", name
, bus_error_message(&error
, r
));
859 r
= in_addr_ifindex_to_string(family
, &a
, ifindex
, &pretty
);
861 return log_error_errno(r
, "Failed to print address for %s: %m", name
);
863 k
= printf("%*s%s", (int) indent
, "", pretty
);
864 print_ifindex_comment(k
, ifindex
);
868 return bus_log_parse_error(r
);
870 r
= sd_bus_message_exit_container(reply
);
872 return bus_log_parse_error(r
);
874 r
= sd_bus_message_read(reply
, "s", &canonical
);
876 return bus_log_parse_error(r
);
878 if (!streq(hostname
, canonical
))
879 printf("%*s(%s)\n", (int) indent
, "", canonical
);
881 r
= sd_bus_message_exit_container(reply
);
883 return bus_log_parse_error(r
);
888 return bus_log_parse_error(r
);
890 r
= sd_bus_message_exit_container(reply
);
892 return bus_log_parse_error(r
);
894 r
= sd_bus_message_enter_container(reply
, 'a', "ay");
896 return bus_log_parse_error(r
);
898 while ((r
= sd_bus_message_read_array(reply
, 'y', (const void**) &p
, &sz
)) > 0) {
899 _cleanup_free_
char *escaped
= NULL
;
901 escaped
= cescape_length(p
, sz
);
905 printf("%*s%s\n", (int) indent
, "", escaped
);
908 return bus_log_parse_error(r
);
910 r
= sd_bus_message_exit_container(reply
);
912 return bus_log_parse_error(r
);
914 r
= sd_bus_message_read(reply
, "ssst", &canonical_name
, &canonical_type
, &canonical_domain
, &flags
);
916 return bus_log_parse_error(r
);
918 canonical_name
= empty_to_null(canonical_name
);
919 canonical_type
= empty_to_null(canonical_type
);
921 if (!streq_ptr(name
, canonical_name
) ||
922 !streq_ptr(type
, canonical_type
) ||
923 !streq_ptr(domain
, canonical_domain
)) {
925 printf("%*s(", (int) indent
, "");
928 printf("%s/", canonical_name
);
930 printf("%s/", canonical_type
);
932 printf("%s)\n", canonical_domain
);
935 print_source(flags
, ts
);
940 static int verb_service(int argc
, char **argv
, void *userdata
) {
941 sd_bus
*bus
= userdata
;
944 return resolve_service(bus
, NULL
, NULL
, argv
[1]);
946 return resolve_service(bus
, NULL
, argv
[1], argv
[2]);
948 return resolve_service(bus
, argv
[1], argv
[2], argv
[3]);
951 static int resolve_openpgp(sd_bus
*bus
, const char *address
) {
952 const char *domain
, *full
;
954 _cleanup_free_
char *hashed
= NULL
;
959 domain
= strrchr(address
, '@');
961 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
962 "Address does not contain '@': \"%s\"", address
);
963 if (domain
== address
|| domain
[1] == '\0')
964 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
965 "Address starts or ends with '@': \"%s\"", address
);
968 r
= string_hashsum_sha256(address
, domain
- 1 - address
, &hashed
);
970 return log_error_errno(r
, "Hashing failed: %m");
972 strshorten(hashed
, 56);
974 full
= strjoina(hashed
, "._openpgpkey.", domain
);
975 log_debug("Looking up \"%s\".", full
);
977 r
= resolve_record(bus
, full
,
978 arg_class
?: DNS_CLASS_IN
,
979 arg_type
?: DNS_TYPE_OPENPGPKEY
, false);
981 if (IN_SET(r
, -ENXIO
, -ESRCH
)) { /* NXDOMAIN or NODATA? */
982 hashed
= mfree(hashed
);
983 r
= string_hashsum_sha224(address
, domain
- 1 - address
, &hashed
);
985 return log_error_errno(r
, "Hashing failed: %m");
987 full
= strjoina(hashed
, "._openpgpkey.", domain
);
988 log_debug("Looking up \"%s\".", full
);
990 return resolve_record(bus
, full
,
991 arg_class
?: DNS_CLASS_IN
,
992 arg_type
?: DNS_TYPE_OPENPGPKEY
, true);
998 static int verb_openpgp(int argc
, char **argv
, void *userdata
) {
999 sd_bus
*bus
= userdata
;
1002 STRV_FOREACH(p
, argv
+ 1) {
1003 q
= resolve_openpgp(bus
, *p
);
1011 static int resolve_tlsa(sd_bus
*bus
, const char *family
, const char *address
) {
1013 uint16_t port_num
= 443;
1014 _cleanup_free_
char *full
= NULL
;
1020 port
= strrchr(address
, ':');
1022 r
= parse_ip_port(port
+ 1, &port_num
);
1024 return log_error_errno(r
, "Invalid port \"%s\".", port
+ 1);
1026 address
= strndupa_safe(address
, port
- address
);
1029 r
= asprintf(&full
, "_%u._%s.%s",
1036 log_debug("Looking up \"%s\".", full
);
1038 return resolve_record(bus
, full
,
1039 arg_class
?: DNS_CLASS_IN
,
1040 arg_type
?: DNS_TYPE_TLSA
, true);
1043 static bool service_family_is_valid(const char *s
) {
1044 return STR_IN_SET(s
, "tcp", "udp", "sctp");
1047 static int verb_tlsa(int argc
, char **argv
, void *userdata
) {
1048 sd_bus
*bus
= userdata
;
1049 char **args
= argv
+ 1;
1050 const char *family
= "tcp";
1053 if (service_family_is_valid(argv
[1])) {
1058 STRV_FOREACH(p
, args
) {
1059 q
= resolve_tlsa(bus
, family
, *p
);
1067 static int show_statistics(int argc
, char **argv
, void *userdata
) {
1068 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1069 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1070 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1071 sd_bus
*bus
= ASSERT_PTR(userdata
);
1072 uint64_t n_current_transactions
, n_total_transactions
,
1073 cache_size
, n_cache_hit
, n_cache_miss
,
1074 n_dnssec_secure
, n_dnssec_insecure
, n_dnssec_bogus
, n_dnssec_indeterminate
;
1075 int r
, dnssec_supported
;
1077 r
= bus_get_property_trivial(bus
, bus_resolve_mgr
, "DNSSECSupported", &error
, 'b', &dnssec_supported
);
1079 return log_error_errno(r
, "Failed to get DNSSEC supported state: %s", bus_error_message(&error
, r
));
1081 printf("DNSSEC supported by current servers: %s%s%s\n\n",
1083 yes_no(dnssec_supported
),
1086 r
= bus_get_property(bus
, bus_resolve_mgr
, "TransactionStatistics", &error
, &reply
, "(tt)");
1088 return log_error_errno(r
, "Failed to get transaction statistics: %s", bus_error_message(&error
, r
));
1090 r
= sd_bus_message_read(reply
, "(tt)",
1091 &n_current_transactions
,
1092 &n_total_transactions
);
1094 return bus_log_parse_error(r
);
1096 reply
= sd_bus_message_unref(reply
);
1098 r
= bus_get_property(bus
, bus_resolve_mgr
, "CacheStatistics", &error
, &reply
, "(ttt)");
1100 return log_error_errno(r
, "Failed to get cache statistics: %s", bus_error_message(&error
, r
));
1102 r
= sd_bus_message_read(reply
, "(ttt)",
1107 return bus_log_parse_error(r
);
1109 reply
= sd_bus_message_unref(reply
);
1111 r
= bus_get_property(bus
, bus_resolve_mgr
, "DNSSECStatistics", &error
, &reply
, "(tttt)");
1113 return log_error_errno(r
, "Failed to get DNSSEC statistics: %s", bus_error_message(&error
, r
));
1115 r
= sd_bus_message_read(reply
, "(tttt)",
1119 &n_dnssec_indeterminate
);
1121 return bus_log_parse_error(r
);
1123 table
= table_new("key", "value");
1127 table_set_header(table
, false);
1129 r
= table_add_many(table
,
1130 TABLE_STRING
, "Transactions",
1131 TABLE_SET_COLOR
, ansi_highlight(),
1133 TABLE_STRING
, "Current Transactions:",
1134 TABLE_SET_ALIGN_PERCENT
, 100,
1135 TABLE_UINT64
, n_current_transactions
,
1136 TABLE_STRING
, "Total Transactions:",
1137 TABLE_UINT64
, n_total_transactions
,
1138 TABLE_EMPTY
, TABLE_EMPTY
,
1139 TABLE_STRING
, "Cache",
1140 TABLE_SET_COLOR
, ansi_highlight(),
1141 TABLE_SET_ALIGN_PERCENT
, 0,
1143 TABLE_STRING
, "Current Cache Size:",
1144 TABLE_SET_ALIGN_PERCENT
, 100,
1145 TABLE_UINT64
, cache_size
,
1146 TABLE_STRING
, "Cache Hits:",
1147 TABLE_UINT64
, n_cache_hit
,
1148 TABLE_STRING
, "Cache Misses:",
1149 TABLE_UINT64
, n_cache_miss
,
1150 TABLE_EMPTY
, TABLE_EMPTY
,
1151 TABLE_STRING
, "DNSSEC Verdicts",
1152 TABLE_SET_COLOR
, ansi_highlight(),
1153 TABLE_SET_ALIGN_PERCENT
, 0,
1155 TABLE_STRING
, "Secure:",
1156 TABLE_SET_ALIGN_PERCENT
, 100,
1157 TABLE_UINT64
, n_dnssec_secure
,
1158 TABLE_STRING
, "Insecure:",
1159 TABLE_UINT64
, n_dnssec_insecure
,
1160 TABLE_STRING
, "Bogus:",
1161 TABLE_UINT64
, n_dnssec_bogus
,
1162 TABLE_STRING
, "Indeterminate:",
1163 TABLE_UINT64
, n_dnssec_indeterminate
);
1165 table_log_add_error(r
);
1167 r
= table_print(table
, NULL
);
1169 return table_log_print_error(r
);
1174 static int reset_statistics(int argc
, char **argv
, void *userdata
) {
1175 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1176 sd_bus
*bus
= userdata
;
1179 r
= bus_call_method(bus
, bus_resolve_mgr
, "ResetStatistics", &error
, NULL
, NULL
);
1181 return log_error_errno(r
, "Failed to reset statistics: %s", bus_error_message(&error
, r
));
1186 static int flush_caches(int argc
, char **argv
, void *userdata
) {
1187 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1188 sd_bus
*bus
= userdata
;
1191 r
= bus_call_method(bus
, bus_resolve_mgr
, "FlushCaches", &error
, NULL
, NULL
);
1193 return log_error_errno(r
, "Failed to flush caches: %s", bus_error_message(&error
, r
));
1198 static int reset_server_features(int argc
, char **argv
, void *userdata
) {
1199 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1200 sd_bus
*bus
= userdata
;
1203 r
= bus_call_method(bus
, bus_resolve_mgr
, "ResetServerFeatures", &error
, NULL
, NULL
);
1205 return log_error_errno(r
, "Failed to reset server features: %s", bus_error_message(&error
, r
));
1210 static int read_dns_server_one(
1212 bool with_ifindex
, /* read "ifindex" reply that also carries an interface index */
1213 bool extended
, /* read "extended" reply, i.e. with port number and server name */
1214 bool only_global
, /* suppress entries with an (non-loopback) ifindex set (i.e. which are specific to some interface) */
1217 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1218 _cleanup_free_
char *pretty
= NULL
;
1219 union in_addr_union a
;
1220 const char *name
= NULL
;
1221 int32_t ifindex
= 0;
1228 r
= sd_bus_message_enter_container(m
, 'r', with_ifindex
? (extended
? "iiayqs" : "iiay") : (extended
? "iayqs" : "iay"));
1233 r
= sd_bus_message_read(m
, "i", &ifindex
);
1238 k
= bus_message_read_in_addr_auto(m
, &error
, &family
, &a
);
1239 if (k
< 0 && !sd_bus_error_has_name(&error
, SD_BUS_ERROR_INVALID_ARGS
))
1243 r
= sd_bus_message_read(m
, "q", &port
);
1247 r
= sd_bus_message_read(m
, "s", &name
);
1252 r
= sd_bus_message_exit_container(m
);
1257 log_debug("Invalid DNS server, ignoring: %s", bus_error_message(&error
, k
));
1262 if (only_global
&& ifindex
> 0 && ifindex
!= LOOPBACK_IFINDEX
) {
1263 /* This one has an (non-loopback) ifindex set, and we were told to suppress those. Hence do so. */
1268 r
= in_addr_port_ifindex_name_to_string(family
, &a
, port
, ifindex
, name
, &pretty
);
1272 *ret
= TAKE_PTR(pretty
);
1277 static int map_link_dns_servers_internal(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
, bool extended
) {
1278 char ***l
= ASSERT_PTR(userdata
);
1285 r
= sd_bus_message_enter_container(m
, 'a', extended
? "(iayqs)" : "(iay)");
1290 _cleanup_free_
char *pretty
= NULL
;
1292 r
= read_dns_server_one(m
, /* with_ifindex= */ false, extended
, /* only_global= */ false, &pretty
);
1298 if (isempty(pretty
))
1301 r
= strv_consume(l
, TAKE_PTR(pretty
));
1306 r
= sd_bus_message_exit_container(m
);
1313 static int map_link_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1314 return map_link_dns_servers_internal(bus
, member
, m
, error
, userdata
, false);
1317 static int map_link_dns_servers_ex(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1318 return map_link_dns_servers_internal(bus
, member
, m
, error
, userdata
, true);
1321 static int map_link_current_dns_server(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1325 return read_dns_server_one(m
, /* with_ifindex= */ false, /* extended= */ false, /* only_global= */ false, userdata
);
1328 static int map_link_current_dns_server_ex(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1332 return read_dns_server_one(m
, /* with_ifindex= */ false, /* extended= */ true, /* only_global= */ false, userdata
);
1335 static int read_domain_one(sd_bus_message
*m
, bool with_ifindex
, char **ret
) {
1336 _cleanup_free_
char *str
= NULL
;
1337 int ifindex
, route_only
, r
;
1344 r
= sd_bus_message_read(m
, "(isb)", &ifindex
, &domain
, &route_only
);
1346 r
= sd_bus_message_read(m
, "(sb)", &domain
, &route_only
);
1350 if (with_ifindex
&& ifindex
!= 0) {
1351 /* only show the global ones here */
1357 str
= strjoin("~", domain
);
1359 str
= strdup(domain
);
1363 *ret
= TAKE_PTR(str
);
1368 static int map_link_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1369 char ***l
= ASSERT_PTR(userdata
);
1376 r
= sd_bus_message_enter_container(m
, 'a', "(sb)");
1381 _cleanup_free_
char *pretty
= NULL
;
1383 r
= read_domain_one(m
, false, &pretty
);
1389 if (isempty(pretty
))
1392 r
= strv_consume(l
, TAKE_PTR(pretty
));
1397 r
= sd_bus_message_exit_container(m
);
1406 static int status_print_strv_ifindex(int ifindex
, const char *ifname
, char **p
) {
1407 const unsigned indent
= strlen("Global: "); /* Use the same indentation everywhere to make things nice */
1411 printf("%s%nLink %i (%s)%n%s:", ansi_highlight(), &pos1
, ifindex
, ifname
, &pos2
, ansi_normal());
1413 printf("%s%nGlobal%n%s:", ansi_highlight(), &pos1
, &pos2
, ansi_normal());
1415 size_t cols
= columns(), position
= pos2
- pos1
+ 2;
1417 STRV_FOREACH(i
, p
) {
1418 size_t our_len
= utf8_console_width(*i
); /* This returns -1 on invalid utf-8 (which shouldn't happen).
1419 * If that happens, we'll just print one item per line. */
1421 if (position
<= indent
|| size_add(size_add(position
, 1), our_len
) < cols
) {
1423 position
= size_add(size_add(position
, 1), our_len
);
1425 printf("\n%*s%s", (int) indent
, "", *i
);
1426 position
= size_add(our_len
, indent
);
1435 static int status_print_strv_global(char **p
) {
1436 return status_print_strv_ifindex(0, NULL
, p
);
1439 typedef struct LinkInfo
{
1440 uint64_t scopes_mask
;
1443 const char *dns_over_tls
;
1446 char *current_dns_ex
;
1451 bool dnssec_supported
;
1455 typedef struct GlobalInfo
{
1457 char *current_dns_ex
;
1460 char **fallback_dns
;
1461 char **fallback_dns_ex
;
1466 const char *dns_over_tls
;
1468 const char *resolv_conf_mode
;
1469 bool dnssec_supported
;
1472 static void link_info_clear(LinkInfo
*p
) {
1473 free(p
->current_dns
);
1474 free(p
->current_dns_ex
);
1476 strv_free(p
->dns_ex
);
1477 strv_free(p
->domains
);
1481 static void global_info_clear(GlobalInfo
*p
) {
1482 free(p
->current_dns
);
1483 free(p
->current_dns_ex
);
1485 strv_free(p
->dns_ex
);
1486 strv_free(p
->fallback_dns
);
1487 strv_free(p
->fallback_dns_ex
);
1488 strv_free(p
->domains
);
1492 static int dump_list(Table
*table
, const char *prefix
, char * const *l
) {
1495 if (strv_isempty(l
))
1498 r
= table_add_many(table
,
1499 TABLE_STRING
, prefix
,
1500 TABLE_STRV_WRAPPED
, l
);
1502 return table_log_add_error(r
);
1507 static int strv_extend_extended_bool(char ***strv
, const char *name
, const char *value
) {
1511 r
= parse_boolean(value
);
1513 return strv_extendf(strv
, "%s%s", plus_minus(r
), name
);
1516 return strv_extendf(strv
, "%s=%s", name
, value
?: "???");
1519 static char** link_protocol_status(const LinkInfo
*info
) {
1520 _cleanup_strv_free_
char **s
= NULL
;
1522 if (strv_extendf(&s
, "%sDefaultRoute", plus_minus(info
->default_route
)) < 0)
1525 if (strv_extend_extended_bool(&s
, "LLMNR", info
->llmnr
) < 0)
1528 if (strv_extend_extended_bool(&s
, "mDNS", info
->mdns
) < 0)
1531 if (strv_extend_extended_bool(&s
, "DNSOverTLS", info
->dns_over_tls
) < 0)
1534 if (strv_extendf(&s
, "DNSSEC=%s/%s",
1535 info
->dnssec
?: "???",
1536 info
->dnssec_supported
? "supported" : "unsupported") < 0)
1542 static char** global_protocol_status(const GlobalInfo
*info
) {
1543 _cleanup_strv_free_
char **s
= NULL
;
1545 if (strv_extend_extended_bool(&s
, "LLMNR", info
->llmnr
) < 0)
1548 if (strv_extend_extended_bool(&s
, "mDNS", info
->mdns
) < 0)
1551 if (strv_extend_extended_bool(&s
, "DNSOverTLS", info
->dns_over_tls
) < 0)
1554 if (strv_extendf(&s
, "DNSSEC=%s/%s",
1555 info
->dnssec
?: "???",
1556 info
->dnssec_supported
? "supported" : "unsupported") < 0)
1562 static int status_ifindex(sd_bus
*bus
, int ifindex
, const char *name
, StatusMode mode
, bool *empty_line
) {
1563 static const struct bus_properties_map property_map
[] = {
1564 { "ScopesMask", "t", NULL
, offsetof(LinkInfo
, scopes_mask
) },
1565 { "DNS", "a(iay)", map_link_dns_servers
, offsetof(LinkInfo
, dns
) },
1566 { "DNSEx", "a(iayqs)", map_link_dns_servers_ex
, offsetof(LinkInfo
, dns_ex
) },
1567 { "CurrentDNSServer", "(iay)", map_link_current_dns_server
, offsetof(LinkInfo
, current_dns
) },
1568 { "CurrentDNSServerEx", "(iayqs)", map_link_current_dns_server_ex
, offsetof(LinkInfo
, current_dns_ex
) },
1569 { "Domains", "a(sb)", map_link_domains
, offsetof(LinkInfo
, domains
) },
1570 { "DefaultRoute", "b", NULL
, offsetof(LinkInfo
, default_route
) },
1571 { "LLMNR", "s", NULL
, offsetof(LinkInfo
, llmnr
) },
1572 { "MulticastDNS", "s", NULL
, offsetof(LinkInfo
, mdns
) },
1573 { "DNSOverTLS", "s", NULL
, offsetof(LinkInfo
, dns_over_tls
) },
1574 { "DNSSEC", "s", NULL
, offsetof(LinkInfo
, dnssec
) },
1575 { "DNSSECNegativeTrustAnchors", "as", bus_map_strv_sort
, offsetof(LinkInfo
, ntas
) },
1576 { "DNSSECSupported", "b", NULL
, offsetof(LinkInfo
, dnssec_supported
) },
1579 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1580 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1581 _cleanup_(link_info_clear
) LinkInfo link_info
= {};
1582 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1583 _cleanup_free_
char *p
= NULL
;
1584 char ifi
[DECIMAL_STR_MAX(int)], ifname
[IF_NAMESIZE
];
1588 assert(ifindex
> 0);
1591 r
= format_ifname(ifindex
, ifname
);
1593 return log_error_errno(r
, "Failed to resolve interface name for %i: %m", ifindex
);
1598 xsprintf(ifi
, "%i", ifindex
);
1599 r
= sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi
, &p
);
1603 r
= bus_map_all_properties(bus
,
1604 "org.freedesktop.resolve1",
1607 BUS_MAP_BOOLEAN_AS_BOOL
,
1612 return log_error_errno(r
, "Failed to get link data for %i: %s", ifindex
, bus_error_message(&error
, r
));
1614 pager_open(arg_pager_flags
);
1616 if (mode
== STATUS_DNS
)
1617 return status_print_strv_ifindex(ifindex
, name
, link_info
.dns_ex
?: link_info
.dns
);
1619 if (mode
== STATUS_DOMAIN
)
1620 return status_print_strv_ifindex(ifindex
, name
, link_info
.domains
);
1622 if (mode
== STATUS_NTA
)
1623 return status_print_strv_ifindex(ifindex
, name
, link_info
.ntas
);
1625 if (mode
== STATUS_DEFAULT_ROUTE
) {
1626 printf("%sLink %i (%s)%s: %s\n",
1627 ansi_highlight(), ifindex
, name
, ansi_normal(),
1628 yes_no(link_info
.default_route
));
1633 if (mode
== STATUS_LLMNR
) {
1634 printf("%sLink %i (%s)%s: %s\n",
1635 ansi_highlight(), ifindex
, name
, ansi_normal(),
1636 strna(link_info
.llmnr
));
1641 if (mode
== STATUS_MDNS
) {
1642 printf("%sLink %i (%s)%s: %s\n",
1643 ansi_highlight(), ifindex
, name
, ansi_normal(),
1644 strna(link_info
.mdns
));
1649 if (mode
== STATUS_PRIVATE
) {
1650 printf("%sLink %i (%s)%s: %s\n",
1651 ansi_highlight(), ifindex
, name
, ansi_normal(),
1652 strna(link_info
.dns_over_tls
));
1657 if (mode
== STATUS_DNSSEC
) {
1658 printf("%sLink %i (%s)%s: %s\n",
1659 ansi_highlight(), ifindex
, name
, ansi_normal(),
1660 strna(link_info
.dnssec
));
1665 if (empty_line
&& *empty_line
)
1666 fputc('\n', stdout
);
1668 printf("%sLink %i (%s)%s\n",
1669 ansi_highlight(), ifindex
, name
, ansi_normal());
1671 table
= table_new("key", "value");
1675 table_set_header(table
, false);
1677 r
= table_add_many(table
,
1678 TABLE_STRING
, "Current Scopes:",
1679 TABLE_SET_ALIGN_PERCENT
, 100);
1681 return table_log_add_error(r
);
1683 if (link_info
.scopes_mask
== 0)
1684 r
= table_add_cell(table
, NULL
, TABLE_STRING
, "none");
1686 _cleanup_free_
char *buf
= NULL
;
1689 if (asprintf(&buf
, "%s%s%s%s%s",
1690 link_info
.scopes_mask
& SD_RESOLVED_DNS
? "DNS " : "",
1691 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV4
? "LLMNR/IPv4 " : "",
1692 link_info
.scopes_mask
& SD_RESOLVED_LLMNR_IPV6
? "LLMNR/IPv6 " : "",
1693 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV4
? "mDNS/IPv4 " : "",
1694 link_info
.scopes_mask
& SD_RESOLVED_MDNS_IPV6
? "mDNS/IPv6 " : "") < 0)
1699 buf
[len
- 1] = '\0';
1701 r
= table_add_cell(table
, NULL
, TABLE_STRING
, buf
);
1704 return table_log_add_error(r
);
1706 _cleanup_strv_free_
char **pstatus
= link_protocol_status(&link_info
);
1710 r
= table_add_many(table
,
1711 TABLE_STRING
, "Protocols:",
1712 TABLE_STRV_WRAPPED
, pstatus
);
1714 return table_log_add_error(r
);
1716 if (link_info
.current_dns
) {
1717 r
= table_add_many(table
,
1718 TABLE_STRING
, "Current DNS Server:",
1719 TABLE_STRING
, link_info
.current_dns_ex
?: link_info
.current_dns
);
1721 return table_log_add_error(r
);
1724 r
= dump_list(table
, "DNS Servers:", link_info
.dns_ex
?: link_info
.dns
);
1728 r
= dump_list(table
, "DNS Domain:", link_info
.domains
);
1732 r
= table_print(table
, NULL
);
1734 return table_log_print_error(r
);
1742 static int map_global_dns_servers_internal(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
, bool extended
) {
1743 char ***l
= ASSERT_PTR(userdata
);
1750 r
= sd_bus_message_enter_container(m
, 'a', extended
? "(iiayqs)" : "(iiay)");
1755 _cleanup_free_
char *pretty
= NULL
;
1757 r
= read_dns_server_one(m
, /* with_ifindex= */ true, extended
, /* only_global= */ true, &pretty
);
1763 if (isempty(pretty
))
1766 r
= strv_consume(l
, TAKE_PTR(pretty
));
1771 r
= sd_bus_message_exit_container(m
);
1778 static int map_global_dns_servers(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1779 return map_global_dns_servers_internal(bus
, member
, m
, error
, userdata
, false);
1782 static int map_global_dns_servers_ex(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1783 return map_global_dns_servers_internal(bus
, member
, m
, error
, userdata
, true);
1786 static int map_global_current_dns_server(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1787 return read_dns_server_one(m
, /* with_ifindex= */ true, /* extended= */ false, /* only_global= */ true, userdata
);
1790 static int map_global_current_dns_server_ex(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1791 return read_dns_server_one(m
, /* with_ifindex= */ true, /* extended= */ true, /* only_global= */ true, userdata
);
1794 static int map_global_domains(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1795 char ***l
= ASSERT_PTR(userdata
);
1802 r
= sd_bus_message_enter_container(m
, 'a', "(isb)");
1807 _cleanup_free_
char *pretty
= NULL
;
1809 r
= read_domain_one(m
, true, &pretty
);
1815 if (isempty(pretty
))
1818 r
= strv_consume(l
, TAKE_PTR(pretty
));
1823 r
= sd_bus_message_exit_container(m
);
1832 static int status_global(sd_bus
*bus
, StatusMode mode
, bool *empty_line
) {
1833 static const struct bus_properties_map property_map
[] = {
1834 { "DNS", "a(iiay)", map_global_dns_servers
, offsetof(GlobalInfo
, dns
) },
1835 { "DNSEx", "a(iiayqs)", map_global_dns_servers_ex
, offsetof(GlobalInfo
, dns_ex
) },
1836 { "FallbackDNS", "a(iiay)", map_global_dns_servers
, offsetof(GlobalInfo
, fallback_dns
) },
1837 { "FallbackDNSEx", "a(iiayqs)", map_global_dns_servers_ex
, offsetof(GlobalInfo
, fallback_dns_ex
) },
1838 { "CurrentDNSServer", "(iiay)", map_global_current_dns_server
, offsetof(GlobalInfo
, current_dns
) },
1839 { "CurrentDNSServerEx", "(iiayqs)", map_global_current_dns_server_ex
, offsetof(GlobalInfo
, current_dns_ex
) },
1840 { "Domains", "a(isb)", map_global_domains
, offsetof(GlobalInfo
, domains
) },
1841 { "DNSSECNegativeTrustAnchors", "as", bus_map_strv_sort
, offsetof(GlobalInfo
, ntas
) },
1842 { "LLMNR", "s", NULL
, offsetof(GlobalInfo
, llmnr
) },
1843 { "MulticastDNS", "s", NULL
, offsetof(GlobalInfo
, mdns
) },
1844 { "DNSOverTLS", "s", NULL
, offsetof(GlobalInfo
, dns_over_tls
) },
1845 { "DNSSEC", "s", NULL
, offsetof(GlobalInfo
, dnssec
) },
1846 { "DNSSECSupported", "b", NULL
, offsetof(GlobalInfo
, dnssec_supported
) },
1847 { "ResolvConfMode", "s", NULL
, offsetof(GlobalInfo
, resolv_conf_mode
) },
1850 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1851 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1852 _cleanup_(global_info_clear
) GlobalInfo global_info
= {};
1853 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1859 r
= bus_map_all_properties(bus
,
1860 "org.freedesktop.resolve1",
1861 "/org/freedesktop/resolve1",
1863 BUS_MAP_BOOLEAN_AS_BOOL
,
1868 return log_error_errno(r
, "Failed to get global data: %s", bus_error_message(&error
, r
));
1870 pager_open(arg_pager_flags
);
1872 if (mode
== STATUS_DNS
)
1873 return status_print_strv_global(global_info
.dns_ex
?: global_info
.dns
);
1875 if (mode
== STATUS_DOMAIN
)
1876 return status_print_strv_global(global_info
.domains
);
1878 if (mode
== STATUS_NTA
)
1879 return status_print_strv_global(global_info
.ntas
);
1881 if (mode
== STATUS_LLMNR
) {
1882 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1883 strna(global_info
.llmnr
));
1888 if (mode
== STATUS_MDNS
) {
1889 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1890 strna(global_info
.mdns
));
1895 if (mode
== STATUS_PRIVATE
) {
1896 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1897 strna(global_info
.dns_over_tls
));
1902 if (mode
== STATUS_DNSSEC
) {
1903 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1904 strna(global_info
.dnssec
));
1909 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1911 table
= table_new("key", "value");
1915 table_set_header(table
, false);
1917 _cleanup_strv_free_
char **pstatus
= global_protocol_status(&global_info
);
1921 r
= table_add_many(table
,
1922 TABLE_STRING
, "Protocols:",
1923 TABLE_SET_ALIGN_PERCENT
, 100,
1924 TABLE_STRV_WRAPPED
, pstatus
);
1926 return table_log_add_error(r
);
1928 if (global_info
.resolv_conf_mode
) {
1929 r
= table_add_many(table
,
1930 TABLE_STRING
, "resolv.conf mode:",
1931 TABLE_STRING
, global_info
.resolv_conf_mode
);
1933 return table_log_add_error(r
);
1936 if (global_info
.current_dns
) {
1937 r
= table_add_many(table
,
1938 TABLE_STRING
, "Current DNS Server:",
1939 TABLE_STRING
, global_info
.current_dns_ex
?: global_info
.current_dns
);
1941 return table_log_add_error(r
);
1944 r
= dump_list(table
, "DNS Servers", global_info
.dns_ex
?: global_info
.dns
);
1948 r
= dump_list(table
, "Fallback DNS Servers", global_info
.fallback_dns_ex
?: global_info
.fallback_dns
);
1952 r
= dump_list(table
, "DNS Domain", global_info
.domains
);
1956 r
= table_print(table
, NULL
);
1958 return table_log_print_error(r
);
1965 static int status_all(sd_bus
*bus
, StatusMode mode
) {
1966 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
1967 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
1968 bool empty_line
= false;
1973 r
= status_global(bus
, mode
, &empty_line
);
1977 r
= sd_netlink_open(&rtnl
);
1979 return log_error_errno(r
, "Failed to connect to netlink: %m");
1981 r
= sd_rtnl_message_new_link(rtnl
, &req
, RTM_GETLINK
, 0);
1983 return rtnl_log_create_error(r
);
1985 r
= sd_netlink_message_set_request_dump(req
, true);
1987 return rtnl_log_create_error(r
);
1989 r
= sd_netlink_call(rtnl
, req
, 0, &reply
);
1991 return log_error_errno(r
, "Failed to enumerate links: %m");
1993 _cleanup_free_ InterfaceInfo
*infos
= NULL
;
1996 for (sd_netlink_message
*i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
2001 r
= sd_netlink_message_get_type(i
, &type
);
2003 return rtnl_log_parse_error(r
);
2005 if (type
!= RTM_NEWLINK
)
2008 r
= sd_rtnl_message_link_get_ifindex(i
, &ifindex
);
2010 return rtnl_log_parse_error(r
);
2012 if (ifindex
== LOOPBACK_IFINDEX
)
2015 r
= sd_netlink_message_read_string(i
, IFLA_IFNAME
, &name
);
2017 return rtnl_log_parse_error(r
);
2019 if (!GREEDY_REALLOC(infos
, n_infos
+ 1))
2022 infos
[n_infos
++] = (InterfaceInfo
) { ifindex
, name
};
2025 typesafe_qsort(infos
, n_infos
, interface_info_compare
);
2028 for (size_t i
= 0; i
< n_infos
; i
++) {
2029 int q
= status_ifindex(bus
, infos
[i
].index
, infos
[i
].name
, mode
, &empty_line
);
2030 if (q
< 0 && r
>= 0)
2037 static int verb_status(int argc
, char **argv
, void *userdata
) {
2038 sd_bus
*bus
= userdata
;
2039 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
2043 bool empty_line
= false;
2045 STRV_FOREACH(ifname
, argv
+ 1) {
2048 ifindex
= rtnl_resolve_interface(&rtnl
, *ifname
);
2050 log_warning_errno(ifindex
, "Failed to resolve interface \"%s\", ignoring: %m", *ifname
);
2054 q
= status_ifindex(bus
, ifindex
, NULL
, STATUS_ALL
, &empty_line
);
2059 r
= status_all(bus
, STATUS_ALL
);
2064 static int call_dns(sd_bus
*bus
, char **dns
, const BusLocator
*locator
, sd_bus_error
*error
, bool extended
) {
2065 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
2068 r
= bus_message_new_method_call(bus
, &req
, locator
, extended
? "SetLinkDNSEx" : "SetLinkDNS");
2070 return bus_log_create_error(r
);
2072 r
= sd_bus_message_append(req
, "i", arg_ifindex
);
2074 return bus_log_create_error(r
);
2076 r
= sd_bus_message_open_container(req
, 'a', extended
? "(iayqs)" : "(iay)");
2078 return bus_log_create_error(r
);
2080 /* If only argument is the empty string, then call SetLinkDNS() with an
2081 * empty list, which will clear the list of domains for an interface. */
2082 if (!strv_equal(dns
, STRV_MAKE("")))
2083 STRV_FOREACH(p
, dns
) {
2084 _cleanup_free_
char *name
= NULL
;
2085 struct in_addr_data data
;
2089 r
= in_addr_port_ifindex_name_from_string_auto(*p
, &data
.family
, &data
.address
, &port
, &ifindex
, &name
);
2091 return log_error_errno(r
, "Failed to parse DNS server address: %s", *p
);
2093 if (ifindex
!= 0 && ifindex
!= arg_ifindex
)
2094 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid ifindex: %i", ifindex
);
2096 r
= sd_bus_message_open_container(req
, 'r', extended
? "iayqs" : "iay");
2098 return bus_log_create_error(r
);
2100 r
= sd_bus_message_append(req
, "i", data
.family
);
2102 return bus_log_create_error(r
);
2104 r
= sd_bus_message_append_array(req
, 'y', &data
.address
, FAMILY_ADDRESS_SIZE(data
.family
));
2106 return bus_log_create_error(r
);
2109 r
= sd_bus_message_append(req
, "q", port
);
2111 return bus_log_create_error(r
);
2113 r
= sd_bus_message_append(req
, "s", name
);
2115 return bus_log_create_error(r
);
2118 r
= sd_bus_message_close_container(req
);
2120 return bus_log_create_error(r
);
2123 r
= sd_bus_message_close_container(req
);
2125 return bus_log_create_error(r
);
2127 r
= sd_bus_call(bus
, req
, 0, error
, NULL
);
2128 if (r
< 0 && extended
&& sd_bus_error_has_name(error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
2129 sd_bus_error_free(error
);
2130 return call_dns(bus
, dns
, locator
, error
, false);
2135 static int verb_dns(int argc
, char **argv
, void *userdata
) {
2136 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2137 sd_bus
*bus
= ASSERT_PTR(userdata
);
2141 r
= ifname_mangle(argv
[1]);
2146 if (arg_ifindex
<= 0)
2147 return status_all(bus
, STATUS_DNS
);
2150 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_DNS
, NULL
);
2152 r
= call_dns(bus
, argv
+ 2, bus_resolve_mgr
, &error
, true);
2153 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2154 sd_bus_error_free(&error
);
2156 r
= call_dns(bus
, argv
+ 2, bus_network_mgr
, &error
, true);
2159 if (arg_ifindex_permissive
&&
2160 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2163 return log_error_errno(r
, "Failed to set DNS configuration: %s", bus_error_message(&error
, r
));
2169 static int call_domain(sd_bus
*bus
, char **domain
, const BusLocator
*locator
, sd_bus_error
*error
) {
2170 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
2173 r
= bus_message_new_method_call(bus
, &req
, locator
, "SetLinkDomains");
2175 return bus_log_create_error(r
);
2177 r
= sd_bus_message_append(req
, "i", arg_ifindex
);
2179 return bus_log_create_error(r
);
2181 r
= sd_bus_message_open_container(req
, 'a', "(sb)");
2183 return bus_log_create_error(r
);
2185 /* If only argument is the empty string, then call SetLinkDomains() with an
2186 * empty list, which will clear the list of domains for an interface. */
2187 if (!strv_equal(domain
, STRV_MAKE("")))
2188 STRV_FOREACH(p
, domain
) {
2191 n
= **p
== '~' ? *p
+ 1 : *p
;
2193 r
= dns_name_is_valid(n
);
2195 return log_error_errno(r
, "Failed to validate specified domain %s: %m", n
);
2197 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2198 "Domain not valid: %s",
2201 r
= sd_bus_message_append(req
, "(sb)", n
, **p
== '~');
2203 return bus_log_create_error(r
);
2206 r
= sd_bus_message_close_container(req
);
2208 return bus_log_create_error(r
);
2210 return sd_bus_call(bus
, req
, 0, error
, NULL
);
2213 static int verb_domain(int argc
, char **argv
, void *userdata
) {
2214 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2215 sd_bus
*bus
= ASSERT_PTR(userdata
);
2219 r
= ifname_mangle(argv
[1]);
2224 if (arg_ifindex
<= 0)
2225 return status_all(bus
, STATUS_DOMAIN
);
2228 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_DOMAIN
, NULL
);
2230 r
= call_domain(bus
, argv
+ 2, bus_resolve_mgr
, &error
);
2231 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2232 sd_bus_error_free(&error
);
2234 r
= call_domain(bus
, argv
+ 2, bus_network_mgr
, &error
);
2237 if (arg_ifindex_permissive
&&
2238 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2241 return log_error_errno(r
, "Failed to set domain configuration: %s", bus_error_message(&error
, r
));
2247 static int verb_default_route(int argc
, char **argv
, void *userdata
) {
2248 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2249 sd_bus
*bus
= ASSERT_PTR(userdata
);
2253 r
= ifname_mangle(argv
[1]);
2258 if (arg_ifindex
<= 0)
2259 return status_all(bus
, STATUS_DEFAULT_ROUTE
);
2262 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_DEFAULT_ROUTE
, NULL
);
2264 b
= parse_boolean(argv
[2]);
2266 return log_error_errno(b
, "Failed to parse boolean argument: %s", argv
[2]);
2268 r
= bus_call_method(bus
, bus_resolve_mgr
, "SetLinkDefaultRoute", &error
, NULL
, "ib", arg_ifindex
, b
);
2269 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2270 sd_bus_error_free(&error
);
2272 r
= bus_call_method(bus
, bus_network_mgr
, "SetLinkDefaultRoute", &error
, NULL
, "ib", arg_ifindex
, b
);
2275 if (arg_ifindex_permissive
&&
2276 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2279 return log_error_errno(r
, "Failed to set default route configuration: %s", bus_error_message(&error
, r
));
2285 static int verb_llmnr(int argc
, char **argv
, void *userdata
) {
2286 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2287 sd_bus
*bus
= ASSERT_PTR(userdata
);
2291 r
= ifname_mangle(argv
[1]);
2296 if (arg_ifindex
<= 0)
2297 return status_all(bus
, STATUS_LLMNR
);
2300 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_LLMNR
, NULL
);
2302 r
= bus_call_method(bus
, bus_resolve_mgr
, "SetLinkLLMNR", &error
, NULL
, "is", arg_ifindex
, argv
[2]);
2303 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2304 sd_bus_error_free(&error
);
2306 r
= bus_call_method(bus
, bus_network_mgr
, "SetLinkLLMNR", &error
, NULL
, "is", arg_ifindex
, argv
[2]);
2309 if (arg_ifindex_permissive
&&
2310 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2313 return log_error_errno(r
, "Failed to set LLMNR configuration: %s", bus_error_message(&error
, r
));
2319 static int verb_mdns(int argc
, char **argv
, void *userdata
) {
2320 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2321 sd_bus
*bus
= ASSERT_PTR(userdata
);
2325 r
= ifname_mangle(argv
[1]);
2330 if (arg_ifindex
<= 0)
2331 return status_all(bus
, STATUS_MDNS
);
2334 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_MDNS
, NULL
);
2336 r
= bus_call_method(bus
, bus_resolve_mgr
, "SetLinkMulticastDNS", &error
, NULL
, "is", arg_ifindex
, argv
[2]);
2337 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2338 sd_bus_error_free(&error
);
2340 r
= bus_call_method(
2343 "SetLinkMulticastDNS",
2346 "is", arg_ifindex
, argv
[2]);
2349 if (arg_ifindex_permissive
&&
2350 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2353 return log_error_errno(r
, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error
, r
));
2359 static int verb_dns_over_tls(int argc
, char **argv
, void *userdata
) {
2360 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2361 sd_bus
*bus
= ASSERT_PTR(userdata
);
2365 r
= ifname_mangle(argv
[1]);
2370 if (arg_ifindex
<= 0)
2371 return status_all(bus
, STATUS_PRIVATE
);
2374 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_PRIVATE
, NULL
);
2376 r
= bus_call_method(bus
, bus_resolve_mgr
, "SetLinkDNSOverTLS", &error
, NULL
, "is", arg_ifindex
, argv
[2]);
2377 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2378 sd_bus_error_free(&error
);
2380 r
= bus_call_method(
2383 "SetLinkDNSOverTLS",
2386 "is", arg_ifindex
, argv
[2]);
2389 if (arg_ifindex_permissive
&&
2390 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2393 return log_error_errno(r
, "Failed to set DNSOverTLS configuration: %s", bus_error_message(&error
, r
));
2399 static int verb_dnssec(int argc
, char **argv
, void *userdata
) {
2400 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2401 sd_bus
*bus
= ASSERT_PTR(userdata
);
2405 r
= ifname_mangle(argv
[1]);
2410 if (arg_ifindex
<= 0)
2411 return status_all(bus
, STATUS_DNSSEC
);
2414 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_DNSSEC
, NULL
);
2416 r
= bus_call_method(bus
, bus_resolve_mgr
, "SetLinkDNSSEC", &error
, NULL
, "is", arg_ifindex
, argv
[2]);
2417 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2418 sd_bus_error_free(&error
);
2420 r
= bus_call_method(bus
, bus_network_mgr
, "SetLinkDNSSEC", &error
, NULL
, "is", arg_ifindex
, argv
[2]);
2423 if (arg_ifindex_permissive
&&
2424 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2427 return log_error_errno(r
, "Failed to set DNSSEC configuration: %s", bus_error_message(&error
, r
));
2433 static int call_nta(sd_bus
*bus
, char **nta
, const BusLocator
*locator
, sd_bus_error
*error
) {
2434 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
2437 r
= bus_message_new_method_call(bus
, &req
, locator
, "SetLinkDNSSECNegativeTrustAnchors");
2439 return bus_log_create_error(r
);
2441 r
= sd_bus_message_append(req
, "i", arg_ifindex
);
2443 return bus_log_create_error(r
);
2445 r
= sd_bus_message_append_strv(req
, nta
);
2447 return bus_log_create_error(r
);
2449 return sd_bus_call(bus
, req
, 0, error
, NULL
);
2452 static int verb_nta(int argc
, char **argv
, void *userdata
) {
2453 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2454 sd_bus
*bus
= ASSERT_PTR(userdata
);
2459 r
= ifname_mangle(argv
[1]);
2464 if (arg_ifindex
<= 0)
2465 return status_all(bus
, STATUS_NTA
);
2468 return status_ifindex(bus
, arg_ifindex
, NULL
, STATUS_NTA
, NULL
);
2470 /* If only argument is the empty string, then call SetLinkDNSSECNegativeTrustAnchors()
2471 * with an empty list, which will clear the list of domains for an interface. */
2472 clear
= strv_equal(argv
+ 2, STRV_MAKE(""));
2475 STRV_FOREACH(p
, argv
+ 2) {
2476 r
= dns_name_is_valid(*p
);
2478 return log_error_errno(r
, "Failed to validate specified domain %s: %m", *p
);
2480 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2481 "Domain not valid: %s",
2485 r
= call_nta(bus
, clear
? NULL
: argv
+ 2, bus_resolve_mgr
, &error
);
2486 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2487 sd_bus_error_free(&error
);
2489 r
= call_nta(bus
, clear
? NULL
: argv
+ 2, bus_network_mgr
, &error
);
2492 if (arg_ifindex_permissive
&&
2493 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2496 return log_error_errno(r
, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error
, r
));
2502 static int verb_revert_link(int argc
, char **argv
, void *userdata
) {
2503 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2504 sd_bus
*bus
= ASSERT_PTR(userdata
);
2508 r
= ifname_mangle(argv
[1]);
2513 if (arg_ifindex
<= 0)
2514 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Interface argument required.");
2516 r
= bus_call_method(bus
, bus_resolve_mgr
, "RevertLink", &error
, NULL
, "i", arg_ifindex
);
2517 if (r
< 0 && sd_bus_error_has_name(&error
, BUS_ERROR_LINK_BUSY
)) {
2518 sd_bus_error_free(&error
);
2520 r
= bus_call_method(bus
, bus_network_mgr
, "RevertLinkDNS", &error
, NULL
, "i", arg_ifindex
);
2523 if (arg_ifindex_permissive
&&
2524 sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_LINK
))
2527 return log_error_errno(r
, "Failed to revert interface configuration: %s", bus_error_message(&error
, r
));
2533 static int verb_log_level(int argc
, char *argv
[], void *userdata
) {
2534 sd_bus
*bus
= ASSERT_PTR(userdata
);
2536 assert(IN_SET(argc
, 1, 2));
2538 return verb_log_control_common(bus
, "org.freedesktop.resolve1", argv
[0], argc
== 2 ? argv
[1] : NULL
);
2541 static int monitor_rkey_from_json(JsonVariant
*v
, DnsResourceKey
**ret_key
) {
2542 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
2543 uint16_t type
= 0, class = 0;
2544 const char *name
= NULL
;
2547 JsonDispatch dispatch_table
[] = {
2548 { "class", JSON_VARIANT_INTEGER
, json_dispatch_uint16
, PTR_TO_SIZE(&class), JSON_MANDATORY
},
2549 { "type", JSON_VARIANT_INTEGER
, json_dispatch_uint16
, PTR_TO_SIZE(&type
), JSON_MANDATORY
},
2550 { "name", JSON_VARIANT_STRING
, json_dispatch_const_string
, PTR_TO_SIZE(&name
), JSON_MANDATORY
},
2557 r
= json_dispatch(v
, dispatch_table
, NULL
, 0, NULL
);
2561 key
= dns_resource_key_new(class, type
, name
);
2565 *ret_key
= TAKE_PTR(key
);
2569 static int print_question(char prefix
, const char *color
, JsonVariant
*question
) {
2570 JsonVariant
*q
= NULL
;
2575 JSON_VARIANT_ARRAY_FOREACH(q
, question
) {
2576 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
2577 char buf
[DNS_RESOURCE_KEY_STRING_MAX
];
2579 r
= monitor_rkey_from_json(q
, &key
);
2581 log_warning_errno(r
, "Received monitor message with invalid question key, ignoring: %m");
2585 printf("%s%s %c%s: %s\n",
2587 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
),
2590 dns_resource_key_to_string(key
, buf
, sizeof(buf
)));
2596 static int print_answer(JsonVariant
*answer
) {
2600 JSON_VARIANT_ARRAY_FOREACH(a
, answer
) {
2601 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
2602 _cleanup_free_
void *d
= NULL
;
2607 jraw
= json_variant_by_key(a
, "raw");
2609 log_warning("Received monitor answer lacking valid raw data, ignoring.");
2613 r
= json_variant_unbase64(jraw
, &d
, &l
);
2615 log_warning_errno(r
, "Failed to undo base64 encoding of monitor answer raw data, ignoring.");
2619 r
= dns_resource_record_new_from_raw(&rr
, d
, l
);
2621 log_warning_errno(r
, "Failed to parse monitor answer RR, ignoring: %m");
2625 s
= dns_resource_record_to_string(rr
);
2629 printf("%s%s A%s: %s\n",
2630 ansi_highlight_yellow(),
2631 special_glyph(SPECIAL_GLYPH_ARROW_LEFT
),
2639 static void monitor_query_dump(JsonVariant
*v
) {
2640 _cleanup_(json_variant_unrefp
) JsonVariant
*question
= NULL
, *answer
= NULL
, *collected_questions
= NULL
;
2641 int rcode
= -1, error
= 0, r
;
2642 const char *state
= NULL
;
2646 JsonDispatch dispatch_table
[] = {
2647 { "question", JSON_VARIANT_ARRAY
, json_dispatch_variant
, PTR_TO_SIZE(&question
), JSON_MANDATORY
},
2648 { "answer", JSON_VARIANT_ARRAY
, json_dispatch_variant
, PTR_TO_SIZE(&answer
), 0 },
2649 { "collectedQuestions", JSON_VARIANT_ARRAY
, json_dispatch_variant
, PTR_TO_SIZE(&collected_questions
), 0 },
2650 { "state", JSON_VARIANT_STRING
, json_dispatch_const_string
, PTR_TO_SIZE(&state
), JSON_MANDATORY
},
2651 { "rcode", JSON_VARIANT_INTEGER
, json_dispatch_int
, PTR_TO_SIZE(&rcode
), 0 },
2652 { "errno", JSON_VARIANT_INTEGER
, json_dispatch_int
, PTR_TO_SIZE(&error
), 0 },
2656 r
= json_dispatch(v
, dispatch_table
, NULL
, 0, NULL
);
2658 return (void) log_warning("Received malformed monitor message, ignoring.");
2660 /* First show the current question */
2661 print_question('Q', ansi_highlight_cyan(), question
);
2663 /* And then show the questions that led to this one in case this was a CNAME chain */
2664 print_question('C', ansi_highlight_grey(), collected_questions
);
2666 printf("%s%s S%s: %s\n",
2667 streq_ptr(state
, "success") ? ansi_highlight_green() : ansi_highlight_red(),
2668 special_glyph(SPECIAL_GLYPH_ARROW_LEFT
),
2670 strna(streq_ptr(state
, "errno") ? errno_to_name(error
) :
2671 streq_ptr(state
, "rcode-failure") ? dns_rcode_to_string(rcode
) :
2674 print_answer(answer
);
2677 static int monitor_reply(
2679 JsonVariant
*parameters
,
2680 const char *error_id
,
2681 VarlinkReplyFlags flags
,
2689 disconnect
= streq(error_id
, VARLINK_ERROR_DISCONNECTED
);
2691 log_info("Disconnected.");
2693 log_error("Varlink error: %s", error_id
);
2695 (void) sd_event_exit(ASSERT_PTR(varlink_get_event(link
)), disconnect
? EXIT_SUCCESS
: EXIT_FAILURE
);
2699 if (json_variant_by_key(parameters
, "ready")) {
2700 /* The first message coming in will just indicate that we are now subscribed. We let our
2701 * caller know if they asked for it. Once the caller sees this they should know that we are
2702 * not going to miss any queries anymore. */
2703 (void) sd_notify(/* unset_environment=false */ false, "READY=1");
2707 if (arg_json_format_flags
& JSON_FORMAT_OFF
) {
2708 monitor_query_dump(parameters
);
2711 json_variant_dump(parameters
, arg_json_format_flags
, NULL
, NULL
);
2718 static int verb_monitor(int argc
, char *argv
[], void *userdata
) {
2719 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
2720 _cleanup_(varlink_unrefp
) Varlink
*vl
= NULL
;
2723 r
= sd_event_default(&event
);
2725 return log_error_errno(r
, "Failed to get event loop: %m");
2727 r
= sd_event_set_signal_exit(event
, true);
2729 return log_error_errno(r
, "Failed to enable exit on SIGINT/SIGTERM: %m");
2731 r
= varlink_connect_address(&vl
, "/run/systemd/resolve/io.systemd.Resolve.Monitor");
2733 return log_error_errno(r
, "Failed to connect to query monitoring service /run/systemd/resolve/io.systemd.Resolve.Monitor: %m");
2735 r
= varlink_set_relative_timeout(vl
, USEC_INFINITY
); /* We want the monitor to run basically forever */
2737 return log_error_errno(r
, "Failed to set varlink time-out: %m");
2739 r
= varlink_attach_event(vl
, event
, SD_EVENT_PRIORITY_NORMAL
);
2741 return log_error_errno(r
, "Failed to attach varlink connection to event loop: %m");
2743 r
= varlink_bind_reply(vl
, monitor_reply
);
2745 return log_error_errno(r
, "Failed to bind reply callback to varlink connection: %m");
2747 r
= varlink_observe(vl
, "io.systemd.Resolve.Monitor.SubscribeQueryResults", NULL
);
2749 return log_error_errno(r
, "Failed to issue SubscribeQueryResults() varlink call: %m");
2751 r
= sd_event_loop(event
);
2753 return log_error_errno(r
, "Failed to run event loop: %m");
2755 r
= sd_event_get_exit_code(event
, &c
);
2757 return log_error_errno(r
, "Failed to get exit code: %m");
2762 static void help_protocol_types(void) {
2764 puts("Known protocol types:");
2774 static void help_dns_types(void) {
2776 puts("Known DNS RR types:");
2778 DUMP_STRING_TABLE(dns_type
, int, _DNS_TYPE_MAX
);
2781 static void help_dns_classes(void) {
2783 puts("Known DNS RR classes:");
2785 DUMP_STRING_TABLE(dns_class
, int, _DNS_CLASS_MAX
);
2788 static int compat_help(void) {
2789 _cleanup_free_
char *link
= NULL
;
2792 r
= terminal_urlify_man("resolvectl", "1", &link
);
2796 printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
2797 "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
2798 "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
2799 "%1$s [OPTIONS...] --statistics\n"
2800 "%1$s [OPTIONS...] --reset-statistics\n"
2802 "%2$sResolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%3$s\n\n"
2803 " -h --help Show this help\n"
2804 " --version Show package version\n"
2805 " --no-pager Do not pipe output into a pager\n"
2806 " -4 Resolve IPv4 addresses\n"
2807 " -6 Resolve IPv6 addresses\n"
2808 " -i --interface=INTERFACE Look on interface\n"
2809 " -p --protocol=PROTO|help Look via protocol\n"
2810 " -t --type=TYPE|help Query RR with DNS type\n"
2811 " -c --class=CLASS|help Query RR with DNS class\n"
2812 " --service Resolve service (SRV)\n"
2813 " --service-address=BOOL Resolve address for services (default: yes)\n"
2814 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
2815 " --openpgp Query OpenPGP public key\n"
2816 " --tlsa Query TLS public key\n"
2817 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
2818 " --search=BOOL Use search domains for single-label names\n"
2820 " --raw[=payload|packet] Dump the answer as binary data\n"
2821 " --legend=BOOL Print headers and additional info (default: yes)\n"
2822 " --statistics Show resolver statistics\n"
2823 " --reset-statistics Reset resolver statistics\n"
2824 " --status Show link and server status\n"
2825 " --flush-caches Flush all local DNS caches\n"
2826 " --reset-server-features\n"
2827 " Forget learnt DNS server feature levels\n"
2828 " --set-dns=SERVER Set per-interface DNS server address\n"
2829 " --set-domain=DOMAIN Set per-interface search domain\n"
2830 " --set-llmnr=MODE Set per-interface LLMNR mode\n"
2831 " --set-mdns=MODE Set per-interface MulticastDNS mode\n"
2832 " --set-dnsovertls=MODE Set per-interface DNS-over-TLS mode\n"
2833 " --set-dnssec=MODE Set per-interface DNSSEC mode\n"
2834 " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
2835 " --revert Revert per-interface configuration\n"
2836 "\nSee the %4$s for details.\n",
2837 program_invocation_short_name
,
2845 static int native_help(void) {
2846 _cleanup_free_
char *link
= NULL
;
2849 r
= terminal_urlify_man("resolvectl", "1", &link
);
2853 printf("%s [OPTIONS...] COMMAND ...\n"
2855 "%sSend control commands to the network name resolution manager, or%s\n"
2856 "%sresolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%s\n"
2858 " query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses\n"
2859 " service [[NAME] TYPE] DOMAIN Resolve service (SRV)\n"
2860 " openpgp EMAIL@DOMAIN... Query OpenPGP public key\n"
2861 " tlsa DOMAIN[:PORT]... Query TLS public key\n"
2862 " status [LINK...] Show link and server status\n"
2863 " statistics Show resolver statistics\n"
2864 " reset-statistics Reset resolver statistics\n"
2865 " flush-caches Flush all local DNS caches\n"
2866 " reset-server-features Forget learnt DNS server feature levels\n"
2867 " monitor Monitor DNS queries\n"
2868 " dns [LINK [SERVER...]] Get/set per-interface DNS server address\n"
2869 " domain [LINK [DOMAIN...]] Get/set per-interface search domain\n"
2870 " default-route [LINK [BOOL]] Get/set per-interface default route flag\n"
2871 " llmnr [LINK [MODE]] Get/set per-interface LLMNR mode\n"
2872 " mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode\n"
2873 " dnsovertls [LINK [MODE]] Get/set per-interface DNS-over-TLS mode\n"
2874 " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n"
2875 " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n"
2876 " revert LINK Revert per-interface configuration\n"
2877 " log-level [LEVEL] Get/set logging threshold for systemd-resolved\n"
2879 " -h --help Show this help\n"
2880 " --version Show package version\n"
2881 " --no-pager Do not pipe output into a pager\n"
2882 " -4 Resolve IPv4 addresses\n"
2883 " -6 Resolve IPv6 addresses\n"
2884 " -i --interface=INTERFACE Look on interface\n"
2885 " -p --protocol=PROTO|help Look via protocol\n"
2886 " -t --type=TYPE|help Query RR with DNS type\n"
2887 " -c --class=CLASS|help Query RR with DNS class\n"
2888 " --service-address=BOOL Resolve address for services (default: yes)\n"
2889 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
2890 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
2891 " --validate=BOOL Allow DNSSEC validation (default: yes)\n"
2892 " --synthesize=BOOL Allow synthetic response (default: yes)\n"
2893 " --cache=BOOL Allow response from cache (default: yes)\n"
2894 " --zone=BOOL Allow response from locally registered mDNS/LLMNR\n"
2895 " records (default: yes)\n"
2896 " --trust-anchor=BOOL Allow response from local trust anchor (default:\n"
2898 " --network=BOOL Allow response from network (default: yes)\n"
2899 " --search=BOOL Use search domains for single-label names (default:\n"
2901 " --raw[=payload|packet] Dump the answer as binary data\n"
2902 " --legend=BOOL Print headers and additional info (default: yes)\n"
2903 " --json=MODE Output as JSON\n"
2904 " -j Same as --json=pretty on tty, --json=short\n"
2906 "\nSee the %s for details.\n",
2907 program_invocation_short_name
,
2917 static int verb_help(int argc
, char **argv
, void *userdata
) {
2918 return native_help();
2921 static int compat_parse_argv(int argc
, char *argv
[]) {
2923 ARG_VERSION
= 0x100,
2927 ARG_SERVICE_ADDRESS
,
2934 ARG_RESET_STATISTICS
,
2937 ARG_RESET_SERVER_FEATURES
,
2949 static const struct option options
[] = {
2950 { "help", no_argument
, NULL
, 'h' },
2951 { "version", no_argument
, NULL
, ARG_VERSION
},
2952 { "type", required_argument
, NULL
, 't' },
2953 { "class", required_argument
, NULL
, 'c' },
2954 { "legend", required_argument
, NULL
, ARG_LEGEND
},
2955 { "interface", required_argument
, NULL
, 'i' },
2956 { "protocol", required_argument
, NULL
, 'p' },
2957 { "cname", required_argument
, NULL
, ARG_CNAME
},
2958 { "service", no_argument
, NULL
, ARG_SERVICE
},
2959 { "service-address", required_argument
, NULL
, ARG_SERVICE_ADDRESS
},
2960 { "service-txt", required_argument
, NULL
, ARG_SERVICE_TXT
},
2961 { "openpgp", no_argument
, NULL
, ARG_OPENPGP
},
2962 { "tlsa", optional_argument
, NULL
, ARG_TLSA
},
2963 { "raw", optional_argument
, NULL
, ARG_RAW
},
2964 { "search", required_argument
, NULL
, ARG_SEARCH
},
2965 { "statistics", no_argument
, NULL
, ARG_STATISTICS
, },
2966 { "reset-statistics", no_argument
, NULL
, ARG_RESET_STATISTICS
},
2967 { "status", no_argument
, NULL
, ARG_STATUS
},
2968 { "flush-caches", no_argument
, NULL
, ARG_FLUSH_CACHES
},
2969 { "reset-server-features", no_argument
, NULL
, ARG_RESET_SERVER_FEATURES
},
2970 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
2971 { "set-dns", required_argument
, NULL
, ARG_SET_DNS
},
2972 { "set-domain", required_argument
, NULL
, ARG_SET_DOMAIN
},
2973 { "set-llmnr", required_argument
, NULL
, ARG_SET_LLMNR
},
2974 { "set-mdns", required_argument
, NULL
, ARG_SET_MDNS
},
2975 { "set-dnsovertls", required_argument
, NULL
, ARG_SET_PRIVATE
},
2976 { "set-dnssec", required_argument
, NULL
, ARG_SET_DNSSEC
},
2977 { "set-nta", required_argument
, NULL
, ARG_SET_NTA
},
2978 { "revert", no_argument
, NULL
, ARG_REVERT_LINK
},
2987 while ((c
= getopt_long(argc
, argv
, "h46i:t:c:p:", options
, NULL
)) >= 0)
2991 return compat_help();
2997 arg_family
= AF_INET
;
3001 arg_family
= AF_INET6
;
3005 r
= ifname_mangle(optarg
);
3011 if (streq(optarg
, "help")) {
3016 r
= dns_type_from_string(optarg
);
3018 return log_error_errno(r
, "Failed to parse RR record type %s: %m", optarg
);
3020 arg_type
= (uint16_t) r
;
3021 assert((int) arg_type
== r
);
3023 arg_mode
= MODE_RESOLVE_RECORD
;
3027 if (streq(optarg
, "help")) {
3032 r
= dns_class_from_string(optarg
);
3034 return log_error_errno(r
, "Failed to parse RR record class %s: %m", optarg
);
3036 arg_class
= (uint16_t) r
;
3037 assert((int) arg_class
== r
);
3042 r
= parse_boolean_argument("--legend=", optarg
, &arg_legend
);
3048 if (streq(optarg
, "help")) {
3049 help_protocol_types();
3051 } else if (streq(optarg
, "dns"))
3052 arg_flags
|= SD_RESOLVED_DNS
;
3053 else if (streq(optarg
, "llmnr"))
3054 arg_flags
|= SD_RESOLVED_LLMNR
;
3055 else if (streq(optarg
, "llmnr-ipv4"))
3056 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
3057 else if (streq(optarg
, "llmnr-ipv6"))
3058 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
3059 else if (streq(optarg
, "mdns"))
3060 arg_flags
|= SD_RESOLVED_MDNS
;
3061 else if (streq(optarg
, "mdns-ipv4"))
3062 arg_flags
|= SD_RESOLVED_MDNS_IPV4
;
3063 else if (streq(optarg
, "mdns-ipv6"))
3064 arg_flags
|= SD_RESOLVED_MDNS_IPV6
;
3066 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3067 "Unknown protocol specifier: %s", optarg
);
3072 arg_mode
= MODE_RESOLVE_SERVICE
;
3076 arg_mode
= MODE_RESOLVE_OPENPGP
;
3080 arg_mode
= MODE_RESOLVE_TLSA
;
3081 if (!optarg
|| service_family_is_valid(optarg
))
3082 arg_service_family
= optarg
;
3084 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3085 "Unknown service family \"%s\".", optarg
);
3090 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY
),
3091 "Refusing to write binary data to tty.");
3093 if (optarg
== NULL
|| streq(optarg
, "payload"))
3094 arg_raw
= RAW_PAYLOAD
;
3095 else if (streq(optarg
, "packet"))
3096 arg_raw
= RAW_PACKET
;
3098 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3099 "Unknown --raw specifier \"%s\".",
3106 r
= parse_boolean_argument("--cname=", optarg
, NULL
);
3109 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CNAME
, r
== 0);
3112 case ARG_SERVICE_ADDRESS
:
3113 r
= parse_boolean_argument("--service-address=", optarg
, NULL
);
3116 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ADDRESS
, r
== 0);
3119 case ARG_SERVICE_TXT
:
3120 r
= parse_boolean_argument("--service-txt=", optarg
, NULL
);
3123 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TXT
, r
== 0);
3127 r
= parse_boolean_argument("--search=", optarg
, NULL
);
3130 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SEARCH
, r
== 0);
3133 case ARG_STATISTICS
:
3134 arg_mode
= MODE_STATISTICS
;
3137 case ARG_RESET_STATISTICS
:
3138 arg_mode
= MODE_RESET_STATISTICS
;
3141 case ARG_FLUSH_CACHES
:
3142 arg_mode
= MODE_FLUSH_CACHES
;
3145 case ARG_RESET_SERVER_FEATURES
:
3146 arg_mode
= MODE_RESET_SERVER_FEATURES
;
3150 arg_mode
= MODE_STATUS
;
3154 arg_pager_flags
|= PAGER_DISABLE
;
3158 r
= strv_extend(&arg_set_dns
, optarg
);
3162 arg_mode
= MODE_SET_LINK
;
3165 case ARG_SET_DOMAIN
:
3166 r
= strv_extend(&arg_set_domain
, optarg
);
3170 arg_mode
= MODE_SET_LINK
;
3174 arg_set_llmnr
= optarg
;
3175 arg_mode
= MODE_SET_LINK
;
3179 arg_set_mdns
= optarg
;
3180 arg_mode
= MODE_SET_LINK
;
3183 case ARG_SET_PRIVATE
:
3184 arg_set_dns_over_tls
= optarg
;
3185 arg_mode
= MODE_SET_LINK
;
3188 case ARG_SET_DNSSEC
:
3189 arg_set_dnssec
= optarg
;
3190 arg_mode
= MODE_SET_LINK
;
3194 r
= strv_extend(&arg_set_nta
, optarg
);
3198 arg_mode
= MODE_SET_LINK
;
3201 case ARG_REVERT_LINK
:
3202 arg_mode
= MODE_REVERT_LINK
;
3209 assert_not_reached();
3212 if (arg_type
== 0 && arg_class
!= 0)
3213 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3214 "--class= may only be used in conjunction with --type=.");
3216 if (arg_type
!= 0 && arg_mode
== MODE_RESOLVE_SERVICE
)
3217 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3218 "--service and --type= may not be combined.");
3220 if (arg_type
!= 0 && arg_class
== 0)
3221 arg_class
= DNS_CLASS_IN
;
3223 if (arg_class
!= 0 && arg_type
== 0)
3224 arg_type
= DNS_TYPE_A
;
3226 if (IN_SET(arg_mode
, MODE_SET_LINK
, MODE_REVERT_LINK
)) {
3228 if (arg_ifindex
<= 0)
3229 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3230 "--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=.");
3233 return 1 /* work to do */;
3236 static int native_parse_argv(int argc
, char *argv
[]) {
3238 ARG_VERSION
= 0x100,
3247 ARG_SERVICE_ADDRESS
,
3255 static const struct option options
[] = {
3256 { "help", no_argument
, NULL
, 'h' },
3257 { "version", no_argument
, NULL
, ARG_VERSION
},
3258 { "type", required_argument
, NULL
, 't' },
3259 { "class", required_argument
, NULL
, 'c' },
3260 { "legend", required_argument
, NULL
, ARG_LEGEND
},
3261 { "interface", required_argument
, NULL
, 'i' },
3262 { "protocol", required_argument
, NULL
, 'p' },
3263 { "cname", required_argument
, NULL
, ARG_CNAME
},
3264 { "validate", required_argument
, NULL
, ARG_VALIDATE
},
3265 { "synthesize", required_argument
, NULL
, ARG_SYNTHESIZE
},
3266 { "cache", required_argument
, NULL
, ARG_CACHE
},
3267 { "zone", required_argument
, NULL
, ARG_ZONE
},
3268 { "trust-anchor", required_argument
, NULL
, ARG_TRUST_ANCHOR
},
3269 { "network", required_argument
, NULL
, ARG_NETWORK
},
3270 { "service-address", required_argument
, NULL
, ARG_SERVICE_ADDRESS
},
3271 { "service-txt", required_argument
, NULL
, ARG_SERVICE_TXT
},
3272 { "raw", optional_argument
, NULL
, ARG_RAW
},
3273 { "search", required_argument
, NULL
, ARG_SEARCH
},
3274 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
3275 { "json", required_argument
, NULL
, ARG_JSON
},
3284 while ((c
= getopt_long(argc
, argv
, "h46i:t:c:p:j", options
, NULL
)) >= 0)
3288 return native_help();
3294 arg_family
= AF_INET
;
3298 arg_family
= AF_INET6
;
3302 r
= ifname_mangle(optarg
);
3308 if (streq(optarg
, "help")) {
3313 r
= dns_type_from_string(optarg
);
3315 return log_error_errno(r
, "Failed to parse RR record type %s: %m", optarg
);
3317 arg_type
= (uint16_t) r
;
3318 assert((int) arg_type
== r
);
3323 if (streq(optarg
, "help")) {
3328 r
= dns_class_from_string(optarg
);
3330 return log_error_errno(r
, "Failed to parse RR record class %s: %m", optarg
);
3332 arg_class
= (uint16_t) r
;
3333 assert((int) arg_class
== r
);
3338 r
= parse_boolean_argument("--legend=", optarg
, &arg_legend
);
3344 if (streq(optarg
, "help")) {
3345 help_protocol_types();
3347 } else if (streq(optarg
, "dns"))
3348 arg_flags
|= SD_RESOLVED_DNS
;
3349 else if (streq(optarg
, "llmnr"))
3350 arg_flags
|= SD_RESOLVED_LLMNR
;
3351 else if (streq(optarg
, "llmnr-ipv4"))
3352 arg_flags
|= SD_RESOLVED_LLMNR_IPV4
;
3353 else if (streq(optarg
, "llmnr-ipv6"))
3354 arg_flags
|= SD_RESOLVED_LLMNR_IPV6
;
3355 else if (streq(optarg
, "mdns"))
3356 arg_flags
|= SD_RESOLVED_MDNS
;
3357 else if (streq(optarg
, "mdns-ipv4"))
3358 arg_flags
|= SD_RESOLVED_MDNS_IPV4
;
3359 else if (streq(optarg
, "mdns-ipv6"))
3360 arg_flags
|= SD_RESOLVED_MDNS_IPV6
;
3362 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3363 "Unknown protocol specifier: %s",
3370 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY
),
3371 "Refusing to write binary data to tty.");
3373 if (optarg
== NULL
|| streq(optarg
, "payload"))
3374 arg_raw
= RAW_PAYLOAD
;
3375 else if (streq(optarg
, "packet"))
3376 arg_raw
= RAW_PACKET
;
3378 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3379 "Unknown --raw specifier \"%s\".",
3386 r
= parse_boolean_argument("--cname=", optarg
, NULL
);
3389 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CNAME
, r
== 0);
3393 r
= parse_boolean_argument("--validate=", optarg
, NULL
);
3396 SET_FLAG(arg_flags
, SD_RESOLVED_NO_VALIDATE
, r
== 0);
3399 case ARG_SYNTHESIZE
:
3400 r
= parse_boolean_argument("--synthesize=", optarg
, NULL
);
3403 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SYNTHESIZE
, r
== 0);
3407 r
= parse_boolean_argument("--cache=", optarg
, NULL
);
3410 SET_FLAG(arg_flags
, SD_RESOLVED_NO_CACHE
, r
== 0);
3414 r
= parse_boolean_argument("--zone=", optarg
, NULL
);
3417 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ZONE
, r
== 0);
3420 case ARG_TRUST_ANCHOR
:
3421 r
= parse_boolean_argument("--trust-anchor=", optarg
, NULL
);
3424 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TRUST_ANCHOR
, r
== 0);
3428 r
= parse_boolean_argument("--network=", optarg
, NULL
);
3431 SET_FLAG(arg_flags
, SD_RESOLVED_NO_NETWORK
, r
== 0);
3434 case ARG_SERVICE_ADDRESS
:
3435 r
= parse_boolean_argument("--service-address=", optarg
, NULL
);
3438 SET_FLAG(arg_flags
, SD_RESOLVED_NO_ADDRESS
, r
== 0);
3441 case ARG_SERVICE_TXT
:
3442 r
= parse_boolean_argument("--service-txt=", optarg
, NULL
);
3445 SET_FLAG(arg_flags
, SD_RESOLVED_NO_TXT
, r
== 0);
3449 r
= parse_boolean_argument("--search=", optarg
, NULL
);
3452 SET_FLAG(arg_flags
, SD_RESOLVED_NO_SEARCH
, r
== 0);
3456 arg_pager_flags
|= PAGER_DISABLE
;
3460 r
= parse_json_argument(optarg
, &arg_json_format_flags
);
3467 arg_json_format_flags
= JSON_FORMAT_PRETTY_AUTO
|JSON_FORMAT_COLOR_AUTO
;
3474 assert_not_reached();
3477 if (arg_type
== 0 && arg_class
!= 0)
3478 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
3479 "--class= may only be used in conjunction with --type=.");
3481 if (arg_type
!= 0 && arg_class
== 0)
3482 arg_class
= DNS_CLASS_IN
;
3484 if (arg_class
!= 0 && arg_type
== 0)
3485 arg_type
= DNS_TYPE_A
;
3487 return 1 /* work to do */;
3490 static int native_main(int argc
, char *argv
[], sd_bus
*bus
) {
3492 static const Verb verbs
[] = {
3493 { "help", VERB_ANY
, VERB_ANY
, 0, verb_help
},
3494 { "status", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
, verb_status
},
3495 { "query", 2, VERB_ANY
, 0, verb_query
},
3496 { "service", 2, 4, 0, verb_service
},
3497 { "openpgp", 2, VERB_ANY
, 0, verb_openpgp
},
3498 { "tlsa", 2, VERB_ANY
, 0, verb_tlsa
},
3499 { "statistics", VERB_ANY
, 1, 0, show_statistics
},
3500 { "reset-statistics", VERB_ANY
, 1, 0, reset_statistics
},
3501 { "flush-caches", VERB_ANY
, 1, 0, flush_caches
},
3502 { "reset-server-features", VERB_ANY
, 1, 0, reset_server_features
},
3503 { "dns", VERB_ANY
, VERB_ANY
, 0, verb_dns
},
3504 { "domain", VERB_ANY
, VERB_ANY
, 0, verb_domain
},
3505 { "default-route", VERB_ANY
, 3, 0, verb_default_route
},
3506 { "llmnr", VERB_ANY
, 3, 0, verb_llmnr
},
3507 { "mdns", VERB_ANY
, 3, 0, verb_mdns
},
3508 { "dnsovertls", VERB_ANY
, 3, 0, verb_dns_over_tls
},
3509 { "dnssec", VERB_ANY
, 3, 0, verb_dnssec
},
3510 { "nta", VERB_ANY
, VERB_ANY
, 0, verb_nta
},
3511 { "revert", VERB_ANY
, 2, 0, verb_revert_link
},
3512 { "log-level", VERB_ANY
, 2, 0, verb_log_level
},
3513 { "monitor", VERB_ANY
, 1, 0, verb_monitor
},
3517 return dispatch_verb(argc
, argv
, verbs
, bus
);
3520 static int translate(const char *verb
, const char *single_arg
, size_t num_args
, char **args
, sd_bus
*bus
) {
3525 assert(num_args
== 0 || args
);
3527 num
= !!single_arg
+ num_args
+ 1;
3529 p
= fake
= newa0(char *, num
+ 1);
3530 *p
++ = (char *) verb
;
3532 *p
++ = (char *) single_arg
;
3533 for (size_t i
= 0; i
< num_args
; i
++)
3537 return native_main((int) num
, fake
, bus
);
3540 static int compat_main(int argc
, char *argv
[], sd_bus
*bus
) {
3544 case MODE_RESOLVE_HOST
:
3545 case MODE_RESOLVE_RECORD
:
3546 return translate("query", NULL
, argc
- optind
, argv
+ optind
, bus
);
3548 case MODE_RESOLVE_SERVICE
:
3549 return translate("service", NULL
, argc
- optind
, argv
+ optind
, bus
);
3551 case MODE_RESOLVE_OPENPGP
:
3552 return translate("openpgp", NULL
, argc
- optind
, argv
+ optind
, bus
);
3554 case MODE_RESOLVE_TLSA
:
3555 return translate("tlsa", arg_service_family
, argc
- optind
, argv
+ optind
, bus
);
3557 case MODE_STATISTICS
:
3558 return translate("statistics", NULL
, 0, NULL
, bus
);
3560 case MODE_RESET_STATISTICS
:
3561 return translate("reset-statistics", NULL
, 0, NULL
, bus
);
3563 case MODE_FLUSH_CACHES
:
3564 return translate("flush-caches", NULL
, 0, NULL
, bus
);
3566 case MODE_RESET_SERVER_FEATURES
:
3567 return translate("reset-server-features", NULL
, 0, NULL
, bus
);
3570 return translate("status", NULL
, argc
- optind
, argv
+ optind
, bus
);
3576 r
= translate("dns", arg_ifname
, strv_length(arg_set_dns
), arg_set_dns
, bus
);
3581 if (arg_set_domain
) {
3582 r
= translate("domain", arg_ifname
, strv_length(arg_set_domain
), arg_set_domain
, bus
);
3588 r
= translate("nta", arg_ifname
, strv_length(arg_set_nta
), arg_set_nta
, bus
);
3593 if (arg_set_llmnr
) {
3594 r
= translate("llmnr", arg_ifname
, 1, (char **) &arg_set_llmnr
, bus
);
3600 r
= translate("mdns", arg_ifname
, 1, (char **) &arg_set_mdns
, bus
);
3605 if (arg_set_dns_over_tls
) {
3606 r
= translate("dnsovertls", arg_ifname
, 1, (char **) &arg_set_dns_over_tls
, bus
);
3611 if (arg_set_dnssec
) {
3612 r
= translate("dnssec", arg_ifname
, 1, (char **) &arg_set_dnssec
, bus
);
3619 case MODE_REVERT_LINK
:
3622 return translate("revert", arg_ifname
, 0, NULL
, bus
);
3625 assert_not_reached();
3631 static int run(int argc
, char **argv
) {
3632 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
3633 bool compat
= false;
3636 setlocale(LC_ALL
, "");
3639 if (invoked_as(argv
, "resolvconf")) {
3641 r
= resolvconf_parse_argv(argc
, argv
);
3642 } else if (invoked_as(argv
, "systemd-resolve")) {
3644 r
= compat_parse_argv(argc
, argv
);
3646 r
= native_parse_argv(argc
, argv
);
3650 r
= sd_bus_open_system(&bus
);
3652 return log_error_errno(r
, "sd_bus_open_system: %m");
3655 return compat_main(argc
, argv
, bus
);
3657 return native_main(argc
, argv
, bus
);
3660 DEFINE_MAIN_FUNCTION(run
);