]> git.proxmox.com Git - systemd.git/blob - src/resolve/resolvectl.c
4d300792f231598fc3fce53007c1d71b7c9f75b5
[systemd.git] / src / resolve / resolvectl.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4 #include <locale.h>
5 #include <net/if.h>
6
7 #include "sd-bus.h"
8 #include "sd-netlink.h"
9
10 #include "af-list.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"
19 #include "escape.h"
20 #include "format-table.h"
21 #include "format-util.h"
22 #include "gcrypt-util.h"
23 #include "hostname-util.h"
24 #include "json.h"
25 #include "main-func.h"
26 #include "missing_network.h"
27 #include "netlink-util.h"
28 #include "openssl-util.h"
29 #include "pager.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"
43 #include "strv.h"
44 #include "terminal-util.h"
45 #include "utf8.h"
46 #include "varlink.h"
47 #include "verb-log-control.h"
48 #include "verbs.h"
49
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;
61
62 typedef enum RawType {
63 RAW_NONE,
64 RAW_PAYLOAD,
65 RAW_PACKET,
66 } RawType;
67 static RawType arg_raw = RAW_NONE;
68
69 ExecutionMode arg_mode = MODE_RESOLVE_HOST;
70
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;
78
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);
83
84 typedef enum StatusMode {
85 STATUS_ALL,
86 STATUS_DNS,
87 STATUS_DOMAIN,
88 STATUS_DEFAULT_ROUTE,
89 STATUS_LLMNR,
90 STATUS_MDNS,
91 STATUS_PRIVATE,
92 STATUS_DNSSEC,
93 STATUS_NTA,
94 } StatusMode;
95
96 typedef struct InterfaceInfo {
97 int index;
98 const char *name;
99 } InterfaceInfo;
100
101 static int interface_info_compare(const InterfaceInfo *a, const InterfaceInfo *b) {
102 int r;
103
104 r = CMP(a->index, b->index);
105 if (r != 0)
106 return r;
107
108 return strcmp_ptr(a->name, b->name);
109 }
110
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;
114 int r;
115
116 assert(s);
117
118 if (drop_protocol_specifier) {
119 _cleanup_free_ char *buf = NULL;
120 int ifindex_longest_name = -ENODEV;
121
122 /* When invoked as resolvconf, drop the protocol specifier(s) at the end. */
123
124 buf = strdup(s);
125 if (!buf)
126 return log_oom();
127
128 for (;;) {
129 r = rtnl_resolve_interface(&rtnl, buf);
130 if (r > 0) {
131 if (ifindex_longest_name <= 0)
132 ifindex_longest_name = r;
133
134 r = strv_extend(&found, buf);
135 if (r < 0)
136 return log_oom();
137 }
138
139 char *dot = strrchr(buf, '.');
140 if (!dot)
141 break;
142
143 *dot = '\0';
144 }
145
146 unsigned n = strv_length(found);
147 if (n > 1) {
148 _cleanup_free_ char *joined = NULL;
149
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);
153
154 } else if (n == 1) {
155 const char *proto;
156
157 proto = ASSERT_PTR(startswith(s, found[0]));
158 if (!isempty(proto))
159 log_info("Dropped protocol specifier '%s' from '%s'. Using '%s' (ifindex=%i).",
160 proto, s, found[0], ifindex_longest_name);
161 }
162
163 r = ifindex_longest_name;
164 } else
165 r = rtnl_resolve_interface(&rtnl, s);
166 if (r < 0) {
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);
169 return 0; /* done */
170 }
171 return log_error_errno(r, "Failed to resolve interface \"%s\": %m", s);
172 }
173
174 if (arg_ifindex > 0 && arg_ifindex != r)
175 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing.");
176
177 arg_ifindex = r;
178 return free_and_strdup_warn(&arg_ifname, found ? found[0] : s); /* found */
179 }
180
181 static void print_source(uint64_t flags, usec_t rtt) {
182 if (!arg_legend)
183 return;
184
185 if (flags == 0)
186 return;
187
188 printf("\n%s-- Information acquired via", ansi_grey());
189
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" : "");
196
197 printf(" in %s.%s\n"
198 "%s-- Data is authenticated: %s; Data was acquired via local or encrypted transport: %s%s\n",
199 FORMAT_TIMESPAN(rtt, 100),
200 ansi_normal(),
201 ansi_grey(),
202 yes_no(flags & SD_RESOLVED_AUTHENTICATED),
203 yes_no(flags & SD_RESOLVED_CONFIDENTIAL),
204 ansi_normal());
205
206 if ((flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC)) != 0)
207 printf("%s-- Data from:%s%s%s%s%s%s\n",
208 ansi_grey(),
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" : "",
214 ansi_normal());
215 }
216
217 static void print_ifindex_comment(int printed_so_far, int ifindex) {
218 char ifname[IF_NAMESIZE];
219 int r;
220
221 if (ifindex <= 0)
222 return;
223
224 r = format_ifname(ifindex, ifname);
225 if (r < 0)
226 return (void) log_warning_errno(r, "Failed to resolve interface name for index %i, ignoring: %m", ifindex);
227
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());
231 }
232
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));
236
237 return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(error, r));
238 }
239
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;
244 unsigned c = 0;
245 uint64_t flags;
246 usec_t ts;
247 int r;
248
249 assert(name);
250
251 log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname);
252
253 r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveHostname");
254 if (r < 0)
255 return bus_log_create_error(r);
256
257 r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
258 if (r < 0)
259 return bus_log_create_error(r);
260
261 ts = now(CLOCK_MONOTONIC);
262
263 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
264 if (r < 0)
265 return resolve_host_error(name, r, &error);
266
267 ts = now(CLOCK_MONOTONIC) - ts;
268
269 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
270 if (r < 0)
271 return bus_log_parse_error(r);
272
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;
277
278 assert_cc(sizeof(int) == sizeof(int32_t));
279
280 r = sd_bus_message_read(reply, "i", &ifindex);
281 if (r < 0)
282 return bus_log_parse_error(r);
283
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));
288
289 r = sd_bus_message_exit_container(reply);
290 if (r < 0)
291 return bus_log_parse_error(r);
292
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));
295 continue;
296 }
297
298 r = in_addr_ifindex_to_string(family, &a, ifindex, &pretty);
299 if (r < 0)
300 return log_error_errno(r, "Failed to print address for %s: %m", name);
301
302 k = printf("%*s%s %s%s%s",
303 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
304 ansi_highlight(), pretty, ansi_normal());
305
306 print_ifindex_comment(k, ifindex);
307 fputc('\n', stdout);
308
309 c++;
310 }
311 if (r < 0)
312 return bus_log_parse_error(r);
313
314 r = sd_bus_message_exit_container(reply);
315 if (r < 0)
316 return bus_log_parse_error(r);
317
318 r = sd_bus_message_read(reply, "st", &canonical, &flags);
319 if (r < 0)
320 return bus_log_parse_error(r);
321
322 if (!streq(name, canonical))
323 printf("%*s%s (%s)\n",
324 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
325 canonical);
326
327 if (c == 0)
328 return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
329 "%s: no addresses found", name);
330
331 print_source(flags, ts);
332
333 return 0;
334 }
335
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;
340 uint64_t flags;
341 unsigned c = 0;
342 usec_t ts;
343 int r;
344
345 assert(bus);
346 assert(IN_SET(family, AF_INET, AF_INET6));
347 assert(address);
348
349 if (ifindex <= 0)
350 ifindex = arg_ifindex;
351
352 r = in_addr_ifindex_to_string(family, address, ifindex, &pretty);
353 if (r < 0)
354 return log_oom();
355
356 log_debug("Resolving %s.", pretty);
357
358 r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveAddress");
359 if (r < 0)
360 return bus_log_create_error(r);
361
362 r = sd_bus_message_append(req, "ii", ifindex, family);
363 if (r < 0)
364 return bus_log_create_error(r);
365
366 r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
367 if (r < 0)
368 return bus_log_create_error(r);
369
370 r = sd_bus_message_append(req, "t", arg_flags);
371 if (r < 0)
372 return bus_log_create_error(r);
373
374 ts = now(CLOCK_MONOTONIC);
375
376 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
377 if (r < 0)
378 return log_error_errno(r, "%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
379
380 ts = now(CLOCK_MONOTONIC) - ts;
381
382 r = sd_bus_message_enter_container(reply, 'a', "(is)");
383 if (r < 0)
384 return bus_log_create_error(r);
385
386 while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
387 const char *n;
388 int k;
389
390 assert_cc(sizeof(int) == sizeof(int32_t));
391
392 r = sd_bus_message_read(reply, "is", &ifindex, &n);
393 if (r < 0)
394 return r;
395
396 r = sd_bus_message_exit_container(reply);
397 if (r < 0)
398 return r;
399
400 k = printf("%*s%s %s%s%s",
401 (int) strlen(pretty), c == 0 ? pretty : "",
402 c == 0 ? ":" : " ",
403 ansi_highlight(), n, ansi_normal());
404
405 print_ifindex_comment(k, ifindex);
406 fputc('\n', stdout);
407
408 c++;
409 }
410 if (r < 0)
411 return bus_log_parse_error(r);
412
413 r = sd_bus_message_exit_container(reply);
414 if (r < 0)
415 return bus_log_parse_error(r);
416
417 r = sd_bus_message_read(reply, "t", &flags);
418 if (r < 0)
419 return bus_log_parse_error(r);
420
421 if (c == 0)
422 return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
423 "%s: no names found", pretty);
424
425 print_source(flags, ts);
426
427 return 0;
428 }
429
430 static int output_rr_packet(const void *d, size_t l, int ifindex) {
431 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
432 int r;
433
434 r = dns_resource_record_new_from_raw(&rr, d, l);
435 if (r < 0)
436 return log_error_errno(r, "Failed to parse RR: %m");
437
438 if (arg_raw == RAW_PAYLOAD) {
439 void *data;
440 ssize_t k;
441
442 k = dns_resource_record_payload(rr, &data);
443 if (k < 0)
444 return log_error_errno(k, "Cannot dump RR: %m");
445 fwrite(data, 1, k, stdout);
446 } else {
447 const char *s;
448 int k;
449
450 s = dns_resource_record_to_string(rr);
451 if (!s)
452 return log_oom();
453
454 k = printf("%s", s);
455 print_ifindex_comment(k, ifindex);
456 fputc('\n', stdout);
457 }
458
459 return 0;
460 }
461
462 static int idna_candidate(const char *name, char **ret) {
463 _cleanup_free_ char *idnafied = NULL;
464 int r;
465
466 assert(name);
467 assert(ret);
468
469 r = dns_name_apply_idna(name, &idnafied);
470 if (r < 0)
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);
474 return true;
475 }
476
477 *ret = NULL;
478 return false;
479 }
480
481 static bool single_label_nonsynthetic(const char *name) {
482 _cleanup_free_ char *first_label = NULL;
483 int r;
484
485 if (!dns_name_is_single_label(name))
486 return false;
487
488 if (is_localhost(name) || is_gateway_hostname(name))
489 return false;
490
491 r = resolve_system_hostname(NULL, &first_label);
492 if (r < 0) {
493 log_warning_errno(r, "Failed to determine the hostname: %m");
494 return false;
495 }
496
497 return !streq(name, first_label);
498 }
499
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;
505 unsigned n = 0;
506 uint64_t flags;
507 usec_t ts;
508 int r;
509
510 assert(name);
511
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);
513
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.)");
517
518 r = idna_candidate(name, &idnafied);
519 if (r < 0)
520 return r;
521 if (r > 0)
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.",
524 idnafied);
525
526 r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveRecord");
527 if (r < 0)
528 return bus_log_create_error(r);
529
530 r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags);
531 if (r < 0)
532 return bus_log_create_error(r);
533
534 ts = now(CLOCK_MONOTONIC);
535
536 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
537 if (r < 0) {
538 if (warn_missing || r != -ENXIO)
539 log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
540 return r;
541 }
542
543 ts = now(CLOCK_MONOTONIC) - ts;
544
545 r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
546 if (r < 0)
547 return bus_log_parse_error(r);
548
549 while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
550 uint16_t c, t;
551 int ifindex;
552 const void *d;
553 size_t l;
554
555 assert_cc(sizeof(int) == sizeof(int32_t));
556
557 r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
558 if (r < 0)
559 return bus_log_parse_error(r);
560
561 r = sd_bus_message_read_array(reply, 'y', &d, &l);
562 if (r < 0)
563 return bus_log_parse_error(r);
564
565 r = sd_bus_message_exit_container(reply);
566 if (r < 0)
567 return bus_log_parse_error(r);
568
569 if (arg_raw == RAW_PACKET) {
570 uint64_t u64 = htole64(l);
571
572 fwrite(&u64, sizeof(u64), 1, stdout);
573 fwrite(d, 1, l, stdout);
574 } else {
575 r = output_rr_packet(d, l, ifindex);
576 if (r < 0)
577 return r;
578 }
579
580 if (dns_type_needs_authentication(t))
581 needs_authentication = true;
582
583 n++;
584 }
585 if (r < 0)
586 return bus_log_parse_error(r);
587
588 r = sd_bus_message_exit_container(reply);
589 if (r < 0)
590 return bus_log_parse_error(r);
591
592 r = sd_bus_message_read(reply, "t", &flags);
593 if (r < 0)
594 return bus_log_parse_error(r);
595
596 if (n == 0) {
597 if (warn_missing)
598 log_error("%s: no records found", name);
599 return -ESRCH;
600 }
601
602 print_source(flags, ts);
603
604 if ((flags & SD_RESOLVED_AUTHENTICATED) == 0 && needs_authentication) {
605 fflush(stdout);
606
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(),
613 ansi_normal());
614 }
615
616 return 0;
617 }
618
619 static int resolve_rfc4501(sd_bus *bus, const char *name) {
620 uint16_t type = 0, class = 0;
621 const char *p, *q, *n;
622 int r;
623
624 assert(bus);
625 assert(name);
626 assert(startswith(name, "dns:"));
627
628 /* Parse RFC 4501 dns: URIs */
629
630 p = name + 4;
631
632 if (p[0] == '/') {
633 const char *e;
634
635 if (p[1] != '/')
636 goto invalid;
637
638 e = strchr(p + 2, '/');
639 if (!e)
640 goto invalid;
641
642 if (e != p + 2)
643 log_warning("DNS authority specification not supported; ignoring specified authority.");
644
645 p = e + 1;
646 }
647
648 q = strchr(p, '?');
649 if (q) {
650 n = strndupa_safe(p, q - p);
651 q++;
652
653 for (;;) {
654 const char *f;
655
656 f = startswith_no_case(q, "class=");
657 if (f) {
658 _cleanup_free_ char *t = NULL;
659 const char *e;
660
661 if (class != 0)
662 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
663 "DNS class specified twice.");
664
665 e = strchrnul(f, ';');
666 t = strndup(f, e - f);
667 if (!t)
668 return log_oom();
669
670 r = dns_class_from_string(t);
671 if (r < 0)
672 return log_error_errno(r, "Unknown DNS class %s.", t);
673
674 class = r;
675
676 if (*e == ';') {
677 q = e + 1;
678 continue;
679 }
680
681 break;
682 }
683
684 f = startswith_no_case(q, "type=");
685 if (f) {
686 _cleanup_free_ char *t = NULL;
687 const char *e;
688
689 if (type != 0)
690 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
691 "DNS type specified twice.");
692
693 e = strchrnul(f, ';');
694 t = strndup(f, e - f);
695 if (!t)
696 return log_oom();
697
698 r = dns_type_from_string(t);
699 if (r < 0)
700 return log_error_errno(r, "Unknown DNS type %s: %m", t);
701
702 type = r;
703
704 if (*e == ';') {
705 q = e + 1;
706 continue;
707 }
708
709 break;
710 }
711
712 goto invalid;
713 }
714 } else
715 n = p;
716
717 if (class == 0)
718 class = arg_class ?: DNS_CLASS_IN;
719 if (type == 0)
720 type = arg_type ?: DNS_TYPE_A;
721
722 return resolve_record(bus, n, class, type, true);
723
724 invalid:
725 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
726 "Invalid DNS URI: %s", name);
727 }
728
729 static int verb_query(int argc, char **argv, void *userdata) {
730 sd_bus *bus = userdata;
731 int q, r = 0;
732
733 if (arg_type != 0)
734 STRV_FOREACH(p, argv + 1) {
735 q = resolve_record(bus, *p, arg_class, arg_type, true);
736 if (q < 0)
737 r = q;
738 }
739
740 else
741 STRV_FOREACH(p, argv + 1) {
742 if (startswith(*p, "dns:"))
743 q = resolve_rfc4501(bus, *p);
744 else {
745 int family, ifindex;
746 union in_addr_union a;
747
748 q = in_addr_ifindex_from_string_auto(*p, &family, &a, &ifindex);
749 if (q >= 0)
750 q = resolve_address(bus, family, &a, ifindex);
751 else
752 q = resolve_host(bus, *p);
753 }
754 if (q < 0)
755 r = q;
756 }
757
758 return r;
759 }
760
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;
765 size_t indent, sz;
766 uint64_t flags;
767 const char *p;
768 unsigned c;
769 usec_t ts;
770 int r;
771
772 assert(bus);
773 assert(domain);
774
775 name = empty_to_null(name);
776 type = empty_to_null(type);
777
778 if (name)
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);
780 else if (type)
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);
782 else
783 log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname);
784
785 r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveService");
786 if (r < 0)
787 return bus_log_create_error(r);
788
789 r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags);
790 if (r < 0)
791 return bus_log_create_error(r);
792
793 ts = now(CLOCK_MONOTONIC);
794
795 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
796 if (r < 0)
797 return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r));
798
799 ts = now(CLOCK_MONOTONIC) - ts;
800
801 r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)");
802 if (r < 0)
803 return bus_log_parse_error(r);
804
805 indent =
806 (name ? strlen(name) + 1 : 0) +
807 (type ? strlen(type) + 1 : 0) +
808 strlen(domain) + 2;
809
810 c = 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;
814
815 r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname);
816 if (r < 0)
817 return bus_log_parse_error(r);
818
819 if (name)
820 printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " ");
821 if (type)
822 printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " ");
823
824 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
825 (int) strlen(domain), c == 0 ? domain : "",
826 c == 0 ? ":" : " ",
827 hostname, port,
828 priority, weight);
829
830 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
831 if (r < 0)
832 return bus_log_parse_error(r);
833
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;
838
839 assert_cc(sizeof(int) == sizeof(int32_t));
840
841 r = sd_bus_message_read(reply, "i", &ifindex);
842 if (r < 0)
843 return bus_log_parse_error(r);
844
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));
849
850 r = sd_bus_message_exit_container(reply);
851 if (r < 0)
852 return bus_log_parse_error(r);
853
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));
856 continue;
857 }
858
859 r = in_addr_ifindex_to_string(family, &a, ifindex, &pretty);
860 if (r < 0)
861 return log_error_errno(r, "Failed to print address for %s: %m", name);
862
863 k = printf("%*s%s", (int) indent, "", pretty);
864 print_ifindex_comment(k, ifindex);
865 fputc('\n', stdout);
866 }
867 if (r < 0)
868 return bus_log_parse_error(r);
869
870 r = sd_bus_message_exit_container(reply);
871 if (r < 0)
872 return bus_log_parse_error(r);
873
874 r = sd_bus_message_read(reply, "s", &canonical);
875 if (r < 0)
876 return bus_log_parse_error(r);
877
878 if (!streq(hostname, canonical))
879 printf("%*s(%s)\n", (int) indent, "", canonical);
880
881 r = sd_bus_message_exit_container(reply);
882 if (r < 0)
883 return bus_log_parse_error(r);
884
885 c++;
886 }
887 if (r < 0)
888 return bus_log_parse_error(r);
889
890 r = sd_bus_message_exit_container(reply);
891 if (r < 0)
892 return bus_log_parse_error(r);
893
894 r = sd_bus_message_enter_container(reply, 'a', "ay");
895 if (r < 0)
896 return bus_log_parse_error(r);
897
898 while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) {
899 _cleanup_free_ char *escaped = NULL;
900
901 escaped = cescape_length(p, sz);
902 if (!escaped)
903 return log_oom();
904
905 printf("%*s%s\n", (int) indent, "", escaped);
906 }
907 if (r < 0)
908 return bus_log_parse_error(r);
909
910 r = sd_bus_message_exit_container(reply);
911 if (r < 0)
912 return bus_log_parse_error(r);
913
914 r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags);
915 if (r < 0)
916 return bus_log_parse_error(r);
917
918 canonical_name = empty_to_null(canonical_name);
919 canonical_type = empty_to_null(canonical_type);
920
921 if (!streq_ptr(name, canonical_name) ||
922 !streq_ptr(type, canonical_type) ||
923 !streq_ptr(domain, canonical_domain)) {
924
925 printf("%*s(", (int) indent, "");
926
927 if (canonical_name)
928 printf("%s/", canonical_name);
929 if (canonical_type)
930 printf("%s/", canonical_type);
931
932 printf("%s)\n", canonical_domain);
933 }
934
935 print_source(flags, ts);
936
937 return 0;
938 }
939
940 static int verb_service(int argc, char **argv, void *userdata) {
941 sd_bus *bus = userdata;
942
943 if (argc == 2)
944 return resolve_service(bus, NULL, NULL, argv[1]);
945 else if (argc == 3)
946 return resolve_service(bus, NULL, argv[1], argv[2]);
947 else
948 return resolve_service(bus, argv[1], argv[2], argv[3]);
949 }
950
951 static int resolve_openpgp(sd_bus *bus, const char *address) {
952 const char *domain, *full;
953 int r;
954 _cleanup_free_ char *hashed = NULL;
955
956 assert(bus);
957 assert(address);
958
959 domain = strrchr(address, '@');
960 if (!domain)
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);
966 domain++;
967
968 r = string_hashsum_sha256(address, domain - 1 - address, &hashed);
969 if (r < 0)
970 return log_error_errno(r, "Hashing failed: %m");
971
972 strshorten(hashed, 56);
973
974 full = strjoina(hashed, "._openpgpkey.", domain);
975 log_debug("Looking up \"%s\".", full);
976
977 r = resolve_record(bus, full,
978 arg_class ?: DNS_CLASS_IN,
979 arg_type ?: DNS_TYPE_OPENPGPKEY, false);
980
981 if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */
982 hashed = mfree(hashed);
983 r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
984 if (r < 0)
985 return log_error_errno(r, "Hashing failed: %m");
986
987 full = strjoina(hashed, "._openpgpkey.", domain);
988 log_debug("Looking up \"%s\".", full);
989
990 return resolve_record(bus, full,
991 arg_class ?: DNS_CLASS_IN,
992 arg_type ?: DNS_TYPE_OPENPGPKEY, true);
993 }
994
995 return r;
996 }
997
998 static int verb_openpgp(int argc, char **argv, void *userdata) {
999 sd_bus *bus = userdata;
1000 int q, r = 0;
1001
1002 STRV_FOREACH(p, argv + 1) {
1003 q = resolve_openpgp(bus, *p);
1004 if (q < 0)
1005 r = q;
1006 }
1007
1008 return r;
1009 }
1010
1011 static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) {
1012 const char *port;
1013 uint16_t port_num = 443;
1014 _cleanup_free_ char *full = NULL;
1015 int r;
1016
1017 assert(bus);
1018 assert(address);
1019
1020 port = strrchr(address, ':');
1021 if (port) {
1022 r = parse_ip_port(port + 1, &port_num);
1023 if (r < 0)
1024 return log_error_errno(r, "Invalid port \"%s\".", port + 1);
1025
1026 address = strndupa_safe(address, port - address);
1027 }
1028
1029 r = asprintf(&full, "_%u._%s.%s",
1030 port_num,
1031 family,
1032 address);
1033 if (r < 0)
1034 return log_oom();
1035
1036 log_debug("Looking up \"%s\".", full);
1037
1038 return resolve_record(bus, full,
1039 arg_class ?: DNS_CLASS_IN,
1040 arg_type ?: DNS_TYPE_TLSA, true);
1041 }
1042
1043 static bool service_family_is_valid(const char *s) {
1044 return STR_IN_SET(s, "tcp", "udp", "sctp");
1045 }
1046
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";
1051 int q, r = 0;
1052
1053 if (service_family_is_valid(argv[1])) {
1054 family = argv[1];
1055 args++;
1056 }
1057
1058 STRV_FOREACH(p, args) {
1059 q = resolve_tlsa(bus, family, *p);
1060 if (q < 0)
1061 r = q;
1062 }
1063
1064 return r;
1065 }
1066
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;
1076
1077 r = bus_get_property_trivial(bus, bus_resolve_mgr, "DNSSECSupported", &error, 'b', &dnssec_supported);
1078 if (r < 0)
1079 return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
1080
1081 printf("DNSSEC supported by current servers: %s%s%s\n\n",
1082 ansi_highlight(),
1083 yes_no(dnssec_supported),
1084 ansi_normal());
1085
1086 r = bus_get_property(bus, bus_resolve_mgr, "TransactionStatistics", &error, &reply, "(tt)");
1087 if (r < 0)
1088 return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r));
1089
1090 r = sd_bus_message_read(reply, "(tt)",
1091 &n_current_transactions,
1092 &n_total_transactions);
1093 if (r < 0)
1094 return bus_log_parse_error(r);
1095
1096 reply = sd_bus_message_unref(reply);
1097
1098 r = bus_get_property(bus, bus_resolve_mgr, "CacheStatistics", &error, &reply, "(ttt)");
1099 if (r < 0)
1100 return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r));
1101
1102 r = sd_bus_message_read(reply, "(ttt)",
1103 &cache_size,
1104 &n_cache_hit,
1105 &n_cache_miss);
1106 if (r < 0)
1107 return bus_log_parse_error(r);
1108
1109 reply = sd_bus_message_unref(reply);
1110
1111 r = bus_get_property(bus, bus_resolve_mgr, "DNSSECStatistics", &error, &reply, "(tttt)");
1112 if (r < 0)
1113 return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r));
1114
1115 r = sd_bus_message_read(reply, "(tttt)",
1116 &n_dnssec_secure,
1117 &n_dnssec_insecure,
1118 &n_dnssec_bogus,
1119 &n_dnssec_indeterminate);
1120 if (r < 0)
1121 return bus_log_parse_error(r);
1122
1123 table = table_new("key", "value");
1124 if (!table)
1125 return log_oom();
1126
1127 table_set_header(table, false);
1128
1129 r = table_add_many(table,
1130 TABLE_STRING, "Transactions",
1131 TABLE_SET_COLOR, ansi_highlight(),
1132 TABLE_EMPTY,
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,
1142 TABLE_EMPTY,
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,
1154 TABLE_EMPTY,
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);
1164 if (r < 0)
1165 table_log_add_error(r);
1166
1167 r = table_print(table, NULL);
1168 if (r < 0)
1169 return table_log_print_error(r);
1170
1171 return 0;
1172 }
1173
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;
1177 int r;
1178
1179 r = bus_call_method(bus, bus_resolve_mgr, "ResetStatistics", &error, NULL, NULL);
1180 if (r < 0)
1181 return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r));
1182
1183 return 0;
1184 }
1185
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;
1189 int r;
1190
1191 r = bus_call_method(bus, bus_resolve_mgr, "FlushCaches", &error, NULL, NULL);
1192 if (r < 0)
1193 return log_error_errno(r, "Failed to flush caches: %s", bus_error_message(&error, r));
1194
1195 return 0;
1196 }
1197
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;
1201 int r;
1202
1203 r = bus_call_method(bus, bus_resolve_mgr, "ResetServerFeatures", &error, NULL, NULL);
1204 if (r < 0)
1205 return log_error_errno(r, "Failed to reset server features: %s", bus_error_message(&error, r));
1206
1207 return 0;
1208 }
1209
1210 static int read_dns_server_one(
1211 sd_bus_message *m,
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) */
1215 char **ret) {
1216
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;
1222 int family, r, k;
1223 uint16_t port = 0;
1224
1225 assert(m);
1226 assert(ret);
1227
1228 r = sd_bus_message_enter_container(m, 'r', with_ifindex ? (extended ? "iiayqs" : "iiay") : (extended ? "iayqs" : "iay"));
1229 if (r <= 0)
1230 return r;
1231
1232 if (with_ifindex) {
1233 r = sd_bus_message_read(m, "i", &ifindex);
1234 if (r < 0)
1235 return r;
1236 }
1237
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))
1240 return k;
1241
1242 if (extended) {
1243 r = sd_bus_message_read(m, "q", &port);
1244 if (r < 0)
1245 return r;
1246
1247 r = sd_bus_message_read(m, "s", &name);
1248 if (r < 0)
1249 return r;
1250 }
1251
1252 r = sd_bus_message_exit_container(m);
1253 if (r < 0)
1254 return r;
1255
1256 if (k < 0) {
1257 log_debug("Invalid DNS server, ignoring: %s", bus_error_message(&error, k));
1258 *ret = NULL;
1259 return 1;
1260 }
1261
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. */
1264 *ret = NULL;
1265 return 1;
1266 }
1267
1268 r = in_addr_port_ifindex_name_to_string(family, &a, port, ifindex, name, &pretty);
1269 if (r < 0)
1270 return r;
1271
1272 *ret = TAKE_PTR(pretty);
1273
1274 return 1;
1275 }
1276
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);
1279 int r;
1280
1281 assert(bus);
1282 assert(member);
1283 assert(m);
1284
1285 r = sd_bus_message_enter_container(m, 'a', extended ? "(iayqs)" : "(iay)");
1286 if (r < 0)
1287 return r;
1288
1289 for (;;) {
1290 _cleanup_free_ char *pretty = NULL;
1291
1292 r = read_dns_server_one(m, /* with_ifindex= */ false, extended, /* only_global= */ false, &pretty);
1293 if (r < 0)
1294 return r;
1295 if (r == 0)
1296 break;
1297
1298 if (isempty(pretty))
1299 continue;
1300
1301 r = strv_consume(l, TAKE_PTR(pretty));
1302 if (r < 0)
1303 return r;
1304 }
1305
1306 r = sd_bus_message_exit_container(m);
1307 if (r < 0)
1308 return r;
1309
1310 return 0;
1311 }
1312
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);
1315 }
1316
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);
1319 }
1320
1321 static int map_link_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1322 assert(m);
1323 assert(userdata);
1324
1325 return read_dns_server_one(m, /* with_ifindex= */ false, /* extended= */ false, /* only_global= */ false, userdata);
1326 }
1327
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) {
1329 assert(m);
1330 assert(userdata);
1331
1332 return read_dns_server_one(m, /* with_ifindex= */ false, /* extended= */ true, /* only_global= */ false, userdata);
1333 }
1334
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;
1338 const char *domain;
1339
1340 assert(m);
1341 assert(ret);
1342
1343 if (with_ifindex)
1344 r = sd_bus_message_read(m, "(isb)", &ifindex, &domain, &route_only);
1345 else
1346 r = sd_bus_message_read(m, "(sb)", &domain, &route_only);
1347 if (r <= 0)
1348 return r;
1349
1350 if (with_ifindex && ifindex != 0) {
1351 /* only show the global ones here */
1352 *ret = NULL;
1353 return 1;
1354 }
1355
1356 if (route_only)
1357 str = strjoin("~", domain);
1358 else
1359 str = strdup(domain);
1360 if (!str)
1361 return -ENOMEM;
1362
1363 *ret = TAKE_PTR(str);
1364
1365 return 1;
1366 }
1367
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);
1370 int r;
1371
1372 assert(bus);
1373 assert(member);
1374 assert(m);
1375
1376 r = sd_bus_message_enter_container(m, 'a', "(sb)");
1377 if (r < 0)
1378 return r;
1379
1380 for (;;) {
1381 _cleanup_free_ char *pretty = NULL;
1382
1383 r = read_domain_one(m, false, &pretty);
1384 if (r < 0)
1385 return r;
1386 if (r == 0)
1387 break;
1388
1389 if (isempty(pretty))
1390 continue;
1391
1392 r = strv_consume(l, TAKE_PTR(pretty));
1393 if (r < 0)
1394 return r;
1395 }
1396
1397 r = sd_bus_message_exit_container(m);
1398 if (r < 0)
1399 return r;
1400
1401 strv_sort(*l);
1402
1403 return 0;
1404 }
1405
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 */
1408 int pos1, pos2;
1409
1410 if (ifname)
1411 printf("%s%nLink %i (%s)%n%s:", ansi_highlight(), &pos1, ifindex, ifname, &pos2, ansi_normal());
1412 else
1413 printf("%s%nGlobal%n%s:", ansi_highlight(), &pos1, &pos2, ansi_normal());
1414
1415 size_t cols = columns(), position = pos2 - pos1 + 2;
1416
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. */
1420
1421 if (position <= indent || size_add(size_add(position, 1), our_len) < cols) {
1422 printf(" %s", *i);
1423 position = size_add(size_add(position, 1), our_len);
1424 } else {
1425 printf("\n%*s%s", (int) indent, "", *i);
1426 position = size_add(our_len, indent);
1427 }
1428 }
1429
1430 printf("\n");
1431
1432 return 0;
1433 }
1434
1435 static int status_print_strv_global(char **p) {
1436 return status_print_strv_ifindex(0, NULL, p);
1437 }
1438
1439 typedef struct LinkInfo {
1440 uint64_t scopes_mask;
1441 const char *llmnr;
1442 const char *mdns;
1443 const char *dns_over_tls;
1444 const char *dnssec;
1445 char *current_dns;
1446 char *current_dns_ex;
1447 char **dns;
1448 char **dns_ex;
1449 char **domains;
1450 char **ntas;
1451 bool dnssec_supported;
1452 bool default_route;
1453 } LinkInfo;
1454
1455 typedef struct GlobalInfo {
1456 char *current_dns;
1457 char *current_dns_ex;
1458 char **dns;
1459 char **dns_ex;
1460 char **fallback_dns;
1461 char **fallback_dns_ex;
1462 char **domains;
1463 char **ntas;
1464 const char *llmnr;
1465 const char *mdns;
1466 const char *dns_over_tls;
1467 const char *dnssec;
1468 const char *resolv_conf_mode;
1469 bool dnssec_supported;
1470 } GlobalInfo;
1471
1472 static void link_info_clear(LinkInfo *p) {
1473 free(p->current_dns);
1474 free(p->current_dns_ex);
1475 strv_free(p->dns);
1476 strv_free(p->dns_ex);
1477 strv_free(p->domains);
1478 strv_free(p->ntas);
1479 }
1480
1481 static void global_info_clear(GlobalInfo *p) {
1482 free(p->current_dns);
1483 free(p->current_dns_ex);
1484 strv_free(p->dns);
1485 strv_free(p->dns_ex);
1486 strv_free(p->fallback_dns);
1487 strv_free(p->fallback_dns_ex);
1488 strv_free(p->domains);
1489 strv_free(p->ntas);
1490 }
1491
1492 static int dump_list(Table *table, const char *prefix, char * const *l) {
1493 int r;
1494
1495 if (strv_isempty(l))
1496 return 0;
1497
1498 r = table_add_many(table,
1499 TABLE_STRING, prefix,
1500 TABLE_STRV_WRAPPED, l);
1501 if (r < 0)
1502 return table_log_add_error(r);
1503
1504 return 0;
1505 }
1506
1507 static int strv_extend_extended_bool(char ***strv, const char *name, const char *value) {
1508 int r;
1509
1510 if (value) {
1511 r = parse_boolean(value);
1512 if (r >= 0)
1513 return strv_extendf(strv, "%s%s", plus_minus(r), name);
1514 }
1515
1516 return strv_extendf(strv, "%s=%s", name, value ?: "???");
1517 }
1518
1519 static char** link_protocol_status(const LinkInfo *info) {
1520 _cleanup_strv_free_ char **s = NULL;
1521
1522 if (strv_extendf(&s, "%sDefaultRoute", plus_minus(info->default_route)) < 0)
1523 return NULL;
1524
1525 if (strv_extend_extended_bool(&s, "LLMNR", info->llmnr) < 0)
1526 return NULL;
1527
1528 if (strv_extend_extended_bool(&s, "mDNS", info->mdns) < 0)
1529 return NULL;
1530
1531 if (strv_extend_extended_bool(&s, "DNSOverTLS", info->dns_over_tls) < 0)
1532 return NULL;
1533
1534 if (strv_extendf(&s, "DNSSEC=%s/%s",
1535 info->dnssec ?: "???",
1536 info->dnssec_supported ? "supported" : "unsupported") < 0)
1537 return NULL;
1538
1539 return TAKE_PTR(s);
1540 }
1541
1542 static char** global_protocol_status(const GlobalInfo *info) {
1543 _cleanup_strv_free_ char **s = NULL;
1544
1545 if (strv_extend_extended_bool(&s, "LLMNR", info->llmnr) < 0)
1546 return NULL;
1547
1548 if (strv_extend_extended_bool(&s, "mDNS", info->mdns) < 0)
1549 return NULL;
1550
1551 if (strv_extend_extended_bool(&s, "DNSOverTLS", info->dns_over_tls) < 0)
1552 return NULL;
1553
1554 if (strv_extendf(&s, "DNSSEC=%s/%s",
1555 info->dnssec ?: "???",
1556 info->dnssec_supported ? "supported" : "unsupported") < 0)
1557 return NULL;
1558
1559 return TAKE_PTR(s);
1560 }
1561
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) },
1577 {}
1578 };
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];
1585 int r;
1586
1587 assert(bus);
1588 assert(ifindex > 0);
1589
1590 if (!name) {
1591 r = format_ifname(ifindex, ifname);
1592 if (r < 0)
1593 return log_error_errno(r, "Failed to resolve interface name for %i: %m", ifindex);
1594
1595 name = ifname;
1596 }
1597
1598 xsprintf(ifi, "%i", ifindex);
1599 r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi, &p);
1600 if (r < 0)
1601 return log_oom();
1602
1603 r = bus_map_all_properties(bus,
1604 "org.freedesktop.resolve1",
1605 p,
1606 property_map,
1607 BUS_MAP_BOOLEAN_AS_BOOL,
1608 &error,
1609 &m,
1610 &link_info);
1611 if (r < 0)
1612 return log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r));
1613
1614 pager_open(arg_pager_flags);
1615
1616 if (mode == STATUS_DNS)
1617 return status_print_strv_ifindex(ifindex, name, link_info.dns_ex ?: link_info.dns);
1618
1619 if (mode == STATUS_DOMAIN)
1620 return status_print_strv_ifindex(ifindex, name, link_info.domains);
1621
1622 if (mode == STATUS_NTA)
1623 return status_print_strv_ifindex(ifindex, name, link_info.ntas);
1624
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));
1629
1630 return 0;
1631 }
1632
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));
1637
1638 return 0;
1639 }
1640
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));
1645
1646 return 0;
1647 }
1648
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));
1653
1654 return 0;
1655 }
1656
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));
1661
1662 return 0;
1663 }
1664
1665 if (empty_line && *empty_line)
1666 fputc('\n', stdout);
1667
1668 printf("%sLink %i (%s)%s\n",
1669 ansi_highlight(), ifindex, name, ansi_normal());
1670
1671 table = table_new("key", "value");
1672 if (!table)
1673 return log_oom();
1674
1675 table_set_header(table, false);
1676
1677 r = table_add_many(table,
1678 TABLE_STRING, "Current Scopes:",
1679 TABLE_SET_ALIGN_PERCENT, 100);
1680 if (r < 0)
1681 return table_log_add_error(r);
1682
1683 if (link_info.scopes_mask == 0)
1684 r = table_add_cell(table, NULL, TABLE_STRING, "none");
1685 else {
1686 _cleanup_free_ char *buf = NULL;
1687 size_t len;
1688
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)
1695 return log_oom();
1696
1697 len = strlen(buf);
1698 assert(len > 0);
1699 buf[len - 1] = '\0';
1700
1701 r = table_add_cell(table, NULL, TABLE_STRING, buf);
1702 }
1703 if (r < 0)
1704 return table_log_add_error(r);
1705
1706 _cleanup_strv_free_ char **pstatus = link_protocol_status(&link_info);
1707 if (!pstatus)
1708 return log_oom();
1709
1710 r = table_add_many(table,
1711 TABLE_STRING, "Protocols:",
1712 TABLE_STRV_WRAPPED, pstatus);
1713 if (r < 0)
1714 return table_log_add_error(r);
1715
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);
1720 if (r < 0)
1721 return table_log_add_error(r);
1722 }
1723
1724 r = dump_list(table, "DNS Servers:", link_info.dns_ex ?: link_info.dns);
1725 if (r < 0)
1726 return r;
1727
1728 r = dump_list(table, "DNS Domain:", link_info.domains);
1729 if (r < 0)
1730 return r;
1731
1732 r = table_print(table, NULL);
1733 if (r < 0)
1734 return table_log_print_error(r);
1735
1736 if (empty_line)
1737 *empty_line = true;
1738
1739 return 0;
1740 }
1741
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);
1744 int r;
1745
1746 assert(bus);
1747 assert(member);
1748 assert(m);
1749
1750 r = sd_bus_message_enter_container(m, 'a', extended ? "(iiayqs)" : "(iiay)");
1751 if (r < 0)
1752 return r;
1753
1754 for (;;) {
1755 _cleanup_free_ char *pretty = NULL;
1756
1757 r = read_dns_server_one(m, /* with_ifindex= */ true, extended, /* only_global= */ true, &pretty);
1758 if (r < 0)
1759 return r;
1760 if (r == 0)
1761 break;
1762
1763 if (isempty(pretty))
1764 continue;
1765
1766 r = strv_consume(l, TAKE_PTR(pretty));
1767 if (r < 0)
1768 return r;
1769 }
1770
1771 r = sd_bus_message_exit_container(m);
1772 if (r < 0)
1773 return r;
1774
1775 return 0;
1776 }
1777
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);
1780 }
1781
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);
1784 }
1785
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);
1788 }
1789
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);
1792 }
1793
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);
1796 int r;
1797
1798 assert(bus);
1799 assert(member);
1800 assert(m);
1801
1802 r = sd_bus_message_enter_container(m, 'a', "(isb)");
1803 if (r < 0)
1804 return r;
1805
1806 for (;;) {
1807 _cleanup_free_ char *pretty = NULL;
1808
1809 r = read_domain_one(m, true, &pretty);
1810 if (r < 0)
1811 return r;
1812 if (r == 0)
1813 break;
1814
1815 if (isempty(pretty))
1816 continue;
1817
1818 r = strv_consume(l, TAKE_PTR(pretty));
1819 if (r < 0)
1820 return r;
1821 }
1822
1823 r = sd_bus_message_exit_container(m);
1824 if (r < 0)
1825 return r;
1826
1827 strv_sort(*l);
1828
1829 return 0;
1830 }
1831
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) },
1848 {}
1849 };
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;
1854 int r;
1855
1856 assert(bus);
1857 assert(empty_line);
1858
1859 r = bus_map_all_properties(bus,
1860 "org.freedesktop.resolve1",
1861 "/org/freedesktop/resolve1",
1862 property_map,
1863 BUS_MAP_BOOLEAN_AS_BOOL,
1864 &error,
1865 &m,
1866 &global_info);
1867 if (r < 0)
1868 return log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r));
1869
1870 pager_open(arg_pager_flags);
1871
1872 if (mode == STATUS_DNS)
1873 return status_print_strv_global(global_info.dns_ex ?: global_info.dns);
1874
1875 if (mode == STATUS_DOMAIN)
1876 return status_print_strv_global(global_info.domains);
1877
1878 if (mode == STATUS_NTA)
1879 return status_print_strv_global(global_info.ntas);
1880
1881 if (mode == STATUS_LLMNR) {
1882 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1883 strna(global_info.llmnr));
1884
1885 return 0;
1886 }
1887
1888 if (mode == STATUS_MDNS) {
1889 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1890 strna(global_info.mdns));
1891
1892 return 0;
1893 }
1894
1895 if (mode == STATUS_PRIVATE) {
1896 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1897 strna(global_info.dns_over_tls));
1898
1899 return 0;
1900 }
1901
1902 if (mode == STATUS_DNSSEC) {
1903 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1904 strna(global_info.dnssec));
1905
1906 return 0;
1907 }
1908
1909 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1910
1911 table = table_new("key", "value");
1912 if (!table)
1913 return log_oom();
1914
1915 table_set_header(table, false);
1916
1917 _cleanup_strv_free_ char **pstatus = global_protocol_status(&global_info);
1918 if (!pstatus)
1919 return log_oom();
1920
1921 r = table_add_many(table,
1922 TABLE_STRING, "Protocols:",
1923 TABLE_SET_ALIGN_PERCENT, 100,
1924 TABLE_STRV_WRAPPED, pstatus);
1925 if (r < 0)
1926 return table_log_add_error(r);
1927
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);
1932 if (r < 0)
1933 return table_log_add_error(r);
1934 }
1935
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);
1940 if (r < 0)
1941 return table_log_add_error(r);
1942 }
1943
1944 r = dump_list(table, "DNS Servers", global_info.dns_ex ?: global_info.dns);
1945 if (r < 0)
1946 return r;
1947
1948 r = dump_list(table, "Fallback DNS Servers", global_info.fallback_dns_ex ?: global_info.fallback_dns);
1949 if (r < 0)
1950 return r;
1951
1952 r = dump_list(table, "DNS Domain", global_info.domains);
1953 if (r < 0)
1954 return r;
1955
1956 r = table_print(table, NULL);
1957 if (r < 0)
1958 return table_log_print_error(r);
1959
1960 *empty_line = true;
1961
1962 return 0;
1963 }
1964
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;
1969 int r;
1970
1971 assert(bus);
1972
1973 r = status_global(bus, mode, &empty_line);
1974 if (r < 0)
1975 return r;
1976
1977 r = sd_netlink_open(&rtnl);
1978 if (r < 0)
1979 return log_error_errno(r, "Failed to connect to netlink: %m");
1980
1981 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
1982 if (r < 0)
1983 return rtnl_log_create_error(r);
1984
1985 r = sd_netlink_message_set_request_dump(req, true);
1986 if (r < 0)
1987 return rtnl_log_create_error(r);
1988
1989 r = sd_netlink_call(rtnl, req, 0, &reply);
1990 if (r < 0)
1991 return log_error_errno(r, "Failed to enumerate links: %m");
1992
1993 _cleanup_free_ InterfaceInfo *infos = NULL;
1994 size_t n_infos = 0;
1995
1996 for (sd_netlink_message *i = reply; i; i = sd_netlink_message_next(i)) {
1997 const char *name;
1998 int ifindex;
1999 uint16_t type;
2000
2001 r = sd_netlink_message_get_type(i, &type);
2002 if (r < 0)
2003 return rtnl_log_parse_error(r);
2004
2005 if (type != RTM_NEWLINK)
2006 continue;
2007
2008 r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
2009 if (r < 0)
2010 return rtnl_log_parse_error(r);
2011
2012 if (ifindex == LOOPBACK_IFINDEX)
2013 continue;
2014
2015 r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
2016 if (r < 0)
2017 return rtnl_log_parse_error(r);
2018
2019 if (!GREEDY_REALLOC(infos, n_infos + 1))
2020 return log_oom();
2021
2022 infos[n_infos++] = (InterfaceInfo) { ifindex, name };
2023 }
2024
2025 typesafe_qsort(infos, n_infos, interface_info_compare);
2026
2027 r = 0;
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)
2031 r = q;
2032 }
2033
2034 return r;
2035 }
2036
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;
2040 int r = 0;
2041
2042 if (argc > 1) {
2043 bool empty_line = false;
2044
2045 STRV_FOREACH(ifname, argv + 1) {
2046 int ifindex, q;
2047
2048 ifindex = rtnl_resolve_interface(&rtnl, *ifname);
2049 if (ifindex < 0) {
2050 log_warning_errno(ifindex, "Failed to resolve interface \"%s\", ignoring: %m", *ifname);
2051 continue;
2052 }
2053
2054 q = status_ifindex(bus, ifindex, NULL, STATUS_ALL, &empty_line);
2055 if (q < 0)
2056 r = q;
2057 }
2058 } else
2059 r = status_all(bus, STATUS_ALL);
2060
2061 return r;
2062 }
2063
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;
2066 int r;
2067
2068 r = bus_message_new_method_call(bus, &req, locator, extended ? "SetLinkDNSEx" : "SetLinkDNS");
2069 if (r < 0)
2070 return bus_log_create_error(r);
2071
2072 r = sd_bus_message_append(req, "i", arg_ifindex);
2073 if (r < 0)
2074 return bus_log_create_error(r);
2075
2076 r = sd_bus_message_open_container(req, 'a', extended ? "(iayqs)" : "(iay)");
2077 if (r < 0)
2078 return bus_log_create_error(r);
2079
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;
2086 uint16_t port;
2087 int ifindex;
2088
2089 r = in_addr_port_ifindex_name_from_string_auto(*p, &data.family, &data.address, &port, &ifindex, &name);
2090 if (r < 0)
2091 return log_error_errno(r, "Failed to parse DNS server address: %s", *p);
2092
2093 if (ifindex != 0 && ifindex != arg_ifindex)
2094 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid ifindex: %i", ifindex);
2095
2096 r = sd_bus_message_open_container(req, 'r', extended ? "iayqs" : "iay");
2097 if (r < 0)
2098 return bus_log_create_error(r);
2099
2100 r = sd_bus_message_append(req, "i", data.family);
2101 if (r < 0)
2102 return bus_log_create_error(r);
2103
2104 r = sd_bus_message_append_array(req, 'y', &data.address, FAMILY_ADDRESS_SIZE(data.family));
2105 if (r < 0)
2106 return bus_log_create_error(r);
2107
2108 if (extended) {
2109 r = sd_bus_message_append(req, "q", port);
2110 if (r < 0)
2111 return bus_log_create_error(r);
2112
2113 r = sd_bus_message_append(req, "s", name);
2114 if (r < 0)
2115 return bus_log_create_error(r);
2116 }
2117
2118 r = sd_bus_message_close_container(req);
2119 if (r < 0)
2120 return bus_log_create_error(r);
2121 }
2122
2123 r = sd_bus_message_close_container(req);
2124 if (r < 0)
2125 return bus_log_create_error(r);
2126
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);
2131 }
2132 return r;
2133 }
2134
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);
2138 int r;
2139
2140 if (argc >= 2) {
2141 r = ifname_mangle(argv[1]);
2142 if (r < 0)
2143 return r;
2144 }
2145
2146 if (arg_ifindex <= 0)
2147 return status_all(bus, STATUS_DNS);
2148
2149 if (argc < 3)
2150 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL);
2151
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);
2155
2156 r = call_dns(bus, argv + 2, bus_network_mgr, &error, true);
2157 }
2158 if (r < 0) {
2159 if (arg_ifindex_permissive &&
2160 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2161 return 0;
2162
2163 return log_error_errno(r, "Failed to set DNS configuration: %s", bus_error_message(&error, r));
2164 }
2165
2166 return 0;
2167 }
2168
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;
2171 int r;
2172
2173 r = bus_message_new_method_call(bus, &req, locator, "SetLinkDomains");
2174 if (r < 0)
2175 return bus_log_create_error(r);
2176
2177 r = sd_bus_message_append(req, "i", arg_ifindex);
2178 if (r < 0)
2179 return bus_log_create_error(r);
2180
2181 r = sd_bus_message_open_container(req, 'a', "(sb)");
2182 if (r < 0)
2183 return bus_log_create_error(r);
2184
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) {
2189 const char *n;
2190
2191 n = **p == '~' ? *p + 1 : *p;
2192
2193 r = dns_name_is_valid(n);
2194 if (r < 0)
2195 return log_error_errno(r, "Failed to validate specified domain %s: %m", n);
2196 if (r == 0)
2197 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2198 "Domain not valid: %s",
2199 n);
2200
2201 r = sd_bus_message_append(req, "(sb)", n, **p == '~');
2202 if (r < 0)
2203 return bus_log_create_error(r);
2204 }
2205
2206 r = sd_bus_message_close_container(req);
2207 if (r < 0)
2208 return bus_log_create_error(r);
2209
2210 return sd_bus_call(bus, req, 0, error, NULL);
2211 }
2212
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);
2216 int r;
2217
2218 if (argc >= 2) {
2219 r = ifname_mangle(argv[1]);
2220 if (r < 0)
2221 return r;
2222 }
2223
2224 if (arg_ifindex <= 0)
2225 return status_all(bus, STATUS_DOMAIN);
2226
2227 if (argc < 3)
2228 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL);
2229
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);
2233
2234 r = call_domain(bus, argv + 2, bus_network_mgr, &error);
2235 }
2236 if (r < 0) {
2237 if (arg_ifindex_permissive &&
2238 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2239 return 0;
2240
2241 return log_error_errno(r, "Failed to set domain configuration: %s", bus_error_message(&error, r));
2242 }
2243
2244 return 0;
2245 }
2246
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);
2250 int r, b;
2251
2252 if (argc >= 2) {
2253 r = ifname_mangle(argv[1]);
2254 if (r < 0)
2255 return r;
2256 }
2257
2258 if (arg_ifindex <= 0)
2259 return status_all(bus, STATUS_DEFAULT_ROUTE);
2260
2261 if (argc < 3)
2262 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DEFAULT_ROUTE, NULL);
2263
2264 b = parse_boolean(argv[2]);
2265 if (b < 0)
2266 return log_error_errno(b, "Failed to parse boolean argument: %s", argv[2]);
2267
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);
2271
2272 r = bus_call_method(bus, bus_network_mgr, "SetLinkDefaultRoute", &error, NULL, "ib", arg_ifindex, b);
2273 }
2274 if (r < 0) {
2275 if (arg_ifindex_permissive &&
2276 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2277 return 0;
2278
2279 return log_error_errno(r, "Failed to set default route configuration: %s", bus_error_message(&error, r));
2280 }
2281
2282 return 0;
2283 }
2284
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);
2288 int r;
2289
2290 if (argc >= 2) {
2291 r = ifname_mangle(argv[1]);
2292 if (r < 0)
2293 return r;
2294 }
2295
2296 if (arg_ifindex <= 0)
2297 return status_all(bus, STATUS_LLMNR);
2298
2299 if (argc < 3)
2300 return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL);
2301
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);
2305
2306 r = bus_call_method(bus, bus_network_mgr, "SetLinkLLMNR", &error, NULL, "is", arg_ifindex, argv[2]);
2307 }
2308 if (r < 0) {
2309 if (arg_ifindex_permissive &&
2310 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2311 return 0;
2312
2313 return log_error_errno(r, "Failed to set LLMNR configuration: %s", bus_error_message(&error, r));
2314 }
2315
2316 return 0;
2317 }
2318
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);
2322 int r;
2323
2324 if (argc >= 2) {
2325 r = ifname_mangle(argv[1]);
2326 if (r < 0)
2327 return r;
2328 }
2329
2330 if (arg_ifindex <= 0)
2331 return status_all(bus, STATUS_MDNS);
2332
2333 if (argc < 3)
2334 return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL);
2335
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);
2339
2340 r = bus_call_method(
2341 bus,
2342 bus_network_mgr,
2343 "SetLinkMulticastDNS",
2344 &error,
2345 NULL,
2346 "is", arg_ifindex, argv[2]);
2347 }
2348 if (r < 0) {
2349 if (arg_ifindex_permissive &&
2350 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2351 return 0;
2352
2353 return log_error_errno(r, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error, r));
2354 }
2355
2356 return 0;
2357 }
2358
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);
2362 int r;
2363
2364 if (argc >= 2) {
2365 r = ifname_mangle(argv[1]);
2366 if (r < 0)
2367 return r;
2368 }
2369
2370 if (arg_ifindex <= 0)
2371 return status_all(bus, STATUS_PRIVATE);
2372
2373 if (argc < 3)
2374 return status_ifindex(bus, arg_ifindex, NULL, STATUS_PRIVATE, NULL);
2375
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);
2379
2380 r = bus_call_method(
2381 bus,
2382 bus_network_mgr,
2383 "SetLinkDNSOverTLS",
2384 &error,
2385 NULL,
2386 "is", arg_ifindex, argv[2]);
2387 }
2388 if (r < 0) {
2389 if (arg_ifindex_permissive &&
2390 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2391 return 0;
2392
2393 return log_error_errno(r, "Failed to set DNSOverTLS configuration: %s", bus_error_message(&error, r));
2394 }
2395
2396 return 0;
2397 }
2398
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);
2402 int r;
2403
2404 if (argc >= 2) {
2405 r = ifname_mangle(argv[1]);
2406 if (r < 0)
2407 return r;
2408 }
2409
2410 if (arg_ifindex <= 0)
2411 return status_all(bus, STATUS_DNSSEC);
2412
2413 if (argc < 3)
2414 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNSSEC, NULL);
2415
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);
2419
2420 r = bus_call_method(bus, bus_network_mgr, "SetLinkDNSSEC", &error, NULL, "is", arg_ifindex, argv[2]);
2421 }
2422 if (r < 0) {
2423 if (arg_ifindex_permissive &&
2424 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2425 return 0;
2426
2427 return log_error_errno(r, "Failed to set DNSSEC configuration: %s", bus_error_message(&error, r));
2428 }
2429
2430 return 0;
2431 }
2432
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;
2435 int r;
2436
2437 r = bus_message_new_method_call(bus, &req, locator, "SetLinkDNSSECNegativeTrustAnchors");
2438 if (r < 0)
2439 return bus_log_create_error(r);
2440
2441 r = sd_bus_message_append(req, "i", arg_ifindex);
2442 if (r < 0)
2443 return bus_log_create_error(r);
2444
2445 r = sd_bus_message_append_strv(req, nta);
2446 if (r < 0)
2447 return bus_log_create_error(r);
2448
2449 return sd_bus_call(bus, req, 0, error, NULL);
2450 }
2451
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);
2455 int r;
2456 bool clear;
2457
2458 if (argc >= 2) {
2459 r = ifname_mangle(argv[1]);
2460 if (r < 0)
2461 return r;
2462 }
2463
2464 if (arg_ifindex <= 0)
2465 return status_all(bus, STATUS_NTA);
2466
2467 if (argc < 3)
2468 return status_ifindex(bus, arg_ifindex, NULL, STATUS_NTA, NULL);
2469
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(""));
2473
2474 if (!clear)
2475 STRV_FOREACH(p, argv + 2) {
2476 r = dns_name_is_valid(*p);
2477 if (r < 0)
2478 return log_error_errno(r, "Failed to validate specified domain %s: %m", *p);
2479 if (r == 0)
2480 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2481 "Domain not valid: %s",
2482 *p);
2483 }
2484
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);
2488
2489 r = call_nta(bus, clear ? NULL : argv + 2, bus_network_mgr, &error);
2490 }
2491 if (r < 0) {
2492 if (arg_ifindex_permissive &&
2493 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2494 return 0;
2495
2496 return log_error_errno(r, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error, r));
2497 }
2498
2499 return 0;
2500 }
2501
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);
2505 int r;
2506
2507 if (argc >= 2) {
2508 r = ifname_mangle(argv[1]);
2509 if (r < 0)
2510 return r;
2511 }
2512
2513 if (arg_ifindex <= 0)
2514 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface argument required.");
2515
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);
2519
2520 r = bus_call_method(bus, bus_network_mgr, "RevertLinkDNS", &error, NULL, "i", arg_ifindex);
2521 }
2522 if (r < 0) {
2523 if (arg_ifindex_permissive &&
2524 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2525 return 0;
2526
2527 return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
2528 }
2529
2530 return 0;
2531 }
2532
2533 static int verb_log_level(int argc, char *argv[], void *userdata) {
2534 sd_bus *bus = ASSERT_PTR(userdata);
2535
2536 assert(IN_SET(argc, 1, 2));
2537
2538 return verb_log_control_common(bus, "org.freedesktop.resolve1", argv[0], argc == 2 ? argv[1] : NULL);
2539 }
2540
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;
2545 int r;
2546
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 },
2551 {}
2552 };
2553
2554 assert(v);
2555 assert(ret_key);
2556
2557 r = json_dispatch(v, dispatch_table, NULL, 0, NULL);
2558 if (r < 0)
2559 return r;
2560
2561 key = dns_resource_key_new(class, type, name);
2562 if (!key)
2563 return -ENOMEM;
2564
2565 *ret_key = TAKE_PTR(key);
2566 return 0;
2567 }
2568
2569 static int print_question(char prefix, const char *color, JsonVariant *question) {
2570 JsonVariant *q = NULL;
2571 int r;
2572
2573 assert(color);
2574
2575 JSON_VARIANT_ARRAY_FOREACH(q, question) {
2576 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
2577 char buf[DNS_RESOURCE_KEY_STRING_MAX];
2578
2579 r = monitor_rkey_from_json(q, &key);
2580 if (r < 0) {
2581 log_warning_errno(r, "Received monitor message with invalid question key, ignoring: %m");
2582 continue;
2583 }
2584
2585 printf("%s%s %c%s: %s\n",
2586 color,
2587 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT),
2588 prefix,
2589 ansi_normal(),
2590 dns_resource_key_to_string(key, buf, sizeof(buf)));
2591 }
2592
2593 return 0;
2594 }
2595
2596 static int print_answer(JsonVariant *answer) {
2597 JsonVariant *a;
2598 int r;
2599
2600 JSON_VARIANT_ARRAY_FOREACH(a, answer) {
2601 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
2602 _cleanup_free_ void *d = NULL;
2603 JsonVariant *jraw;
2604 const char *s;
2605 size_t l;
2606
2607 jraw = json_variant_by_key(a, "raw");
2608 if (!jraw) {
2609 log_warning("Received monitor answer lacking valid raw data, ignoring.");
2610 continue;
2611 }
2612
2613 r = json_variant_unbase64(jraw, &d, &l);
2614 if (r < 0) {
2615 log_warning_errno(r, "Failed to undo base64 encoding of monitor answer raw data, ignoring.");
2616 continue;
2617 }
2618
2619 r = dns_resource_record_new_from_raw(&rr, d, l);
2620 if (r < 0) {
2621 log_warning_errno(r, "Failed to parse monitor answer RR, ignoring: %m");
2622 continue;
2623 }
2624
2625 s = dns_resource_record_to_string(rr);
2626 if (!s)
2627 return log_oom();
2628
2629 printf("%s%s A%s: %s\n",
2630 ansi_highlight_yellow(),
2631 special_glyph(SPECIAL_GLYPH_ARROW_LEFT),
2632 ansi_normal(),
2633 s);
2634 }
2635
2636 return 0;
2637 }
2638
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;
2643
2644 assert(v);
2645
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 },
2653 {}
2654 };
2655
2656 r = json_dispatch(v, dispatch_table, NULL, 0, NULL);
2657 if (r < 0)
2658 return (void) log_warning("Received malformed monitor message, ignoring.");
2659
2660 /* First show the current question */
2661 print_question('Q', ansi_highlight_cyan(), question);
2662
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);
2665
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),
2669 ansi_normal(),
2670 strna(streq_ptr(state, "errno") ? errno_to_name(error) :
2671 streq_ptr(state, "rcode-failure") ? dns_rcode_to_string(rcode) :
2672 state));
2673
2674 print_answer(answer);
2675 }
2676
2677 static int monitor_reply(
2678 Varlink *link,
2679 JsonVariant *parameters,
2680 const char *error_id,
2681 VarlinkReplyFlags flags,
2682 void *userdata) {
2683
2684 assert(link);
2685
2686 if (error_id) {
2687 bool disconnect;
2688
2689 disconnect = streq(error_id, VARLINK_ERROR_DISCONNECTED);
2690 if (disconnect)
2691 log_info("Disconnected.");
2692 else
2693 log_error("Varlink error: %s", error_id);
2694
2695 (void) sd_event_exit(ASSERT_PTR(varlink_get_event(link)), disconnect ? EXIT_SUCCESS : EXIT_FAILURE);
2696 return 0;
2697 }
2698
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");
2704 return 0;
2705 }
2706
2707 if (arg_json_format_flags & JSON_FORMAT_OFF) {
2708 monitor_query_dump(parameters);
2709 printf("\n");
2710 } else
2711 json_variant_dump(parameters, arg_json_format_flags, NULL, NULL);
2712
2713 fflush(stdout);
2714
2715 return 0;
2716 }
2717
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;
2721 int r, c;
2722
2723 r = sd_event_default(&event);
2724 if (r < 0)
2725 return log_error_errno(r, "Failed to get event loop: %m");
2726
2727 r = sd_event_set_signal_exit(event, true);
2728 if (r < 0)
2729 return log_error_errno(r, "Failed to enable exit on SIGINT/SIGTERM: %m");
2730
2731 r = varlink_connect_address(&vl, "/run/systemd/resolve/io.systemd.Resolve.Monitor");
2732 if (r < 0)
2733 return log_error_errno(r, "Failed to connect to query monitoring service /run/systemd/resolve/io.systemd.Resolve.Monitor: %m");
2734
2735 r = varlink_set_relative_timeout(vl, USEC_INFINITY); /* We want the monitor to run basically forever */
2736 if (r < 0)
2737 return log_error_errno(r, "Failed to set varlink time-out: %m");
2738
2739 r = varlink_attach_event(vl, event, SD_EVENT_PRIORITY_NORMAL);
2740 if (r < 0)
2741 return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
2742
2743 r = varlink_bind_reply(vl, monitor_reply);
2744 if (r < 0)
2745 return log_error_errno(r, "Failed to bind reply callback to varlink connection: %m");
2746
2747 r = varlink_observe(vl, "io.systemd.Resolve.Monitor.SubscribeQueryResults", NULL);
2748 if (r < 0)
2749 return log_error_errno(r, "Failed to issue SubscribeQueryResults() varlink call: %m");
2750
2751 r = sd_event_loop(event);
2752 if (r < 0)
2753 return log_error_errno(r, "Failed to run event loop: %m");
2754
2755 r = sd_event_get_exit_code(event, &c);
2756 if (r < 0)
2757 return log_error_errno(r, "Failed to get exit code: %m");
2758
2759 return c;
2760 }
2761
2762 static void help_protocol_types(void) {
2763 if (arg_legend)
2764 puts("Known protocol types:");
2765 puts("dns\n"
2766 "llmnr\n"
2767 "llmnr-ipv4\n"
2768 "llmnr-ipv6\n"
2769 "mdns\n"
2770 "mdns-ipv4\n"
2771 "mdns-ipv6");
2772 }
2773
2774 static void help_dns_types(void) {
2775 if (arg_legend)
2776 puts("Known DNS RR types:");
2777
2778 DUMP_STRING_TABLE(dns_type, int, _DNS_TYPE_MAX);
2779 }
2780
2781 static void help_dns_classes(void) {
2782 if (arg_legend)
2783 puts("Known DNS RR classes:");
2784
2785 DUMP_STRING_TABLE(dns_class, int, _DNS_CLASS_MAX);
2786 }
2787
2788 static int compat_help(void) {
2789 _cleanup_free_ char *link = NULL;
2790 int r;
2791
2792 r = terminal_urlify_man("resolvectl", "1", &link);
2793 if (r < 0)
2794 return log_oom();
2795
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"
2801 "\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"
2819 " (default: yes)\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,
2838 ansi_highlight(),
2839 ansi_normal(),
2840 link);
2841
2842 return 0;
2843 }
2844
2845 static int native_help(void) {
2846 _cleanup_free_ char *link = NULL;
2847 int r;
2848
2849 r = terminal_urlify_man("resolvectl", "1", &link);
2850 if (r < 0)
2851 return log_oom();
2852
2853 printf("%s [OPTIONS...] COMMAND ...\n"
2854 "\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"
2857 "\nCommands:\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"
2878 "\nOptions:\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"
2897 " yes)\n"
2898 " --network=BOOL Allow response from network (default: yes)\n"
2899 " --search=BOOL Use search domains for single-label names (default:\n"
2900 " yes)\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"
2905 " otherwise\n"
2906 "\nSee the %s for details.\n",
2907 program_invocation_short_name,
2908 ansi_highlight(),
2909 ansi_normal(),
2910 ansi_highlight(),
2911 ansi_normal(),
2912 link);
2913
2914 return 0;
2915 }
2916
2917 static int verb_help(int argc, char **argv, void *userdata) {
2918 return native_help();
2919 }
2920
2921 static int compat_parse_argv(int argc, char *argv[]) {
2922 enum {
2923 ARG_VERSION = 0x100,
2924 ARG_LEGEND,
2925 ARG_SERVICE,
2926 ARG_CNAME,
2927 ARG_SERVICE_ADDRESS,
2928 ARG_SERVICE_TXT,
2929 ARG_OPENPGP,
2930 ARG_TLSA,
2931 ARG_RAW,
2932 ARG_SEARCH,
2933 ARG_STATISTICS,
2934 ARG_RESET_STATISTICS,
2935 ARG_STATUS,
2936 ARG_FLUSH_CACHES,
2937 ARG_RESET_SERVER_FEATURES,
2938 ARG_NO_PAGER,
2939 ARG_SET_DNS,
2940 ARG_SET_DOMAIN,
2941 ARG_SET_LLMNR,
2942 ARG_SET_MDNS,
2943 ARG_SET_PRIVATE,
2944 ARG_SET_DNSSEC,
2945 ARG_SET_NTA,
2946 ARG_REVERT_LINK,
2947 };
2948
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 },
2979 {}
2980 };
2981
2982 int c, r;
2983
2984 assert(argc >= 0);
2985 assert(argv);
2986
2987 while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
2988 switch (c) {
2989
2990 case 'h':
2991 return compat_help();
2992
2993 case ARG_VERSION:
2994 return version();
2995
2996 case '4':
2997 arg_family = AF_INET;
2998 break;
2999
3000 case '6':
3001 arg_family = AF_INET6;
3002 break;
3003
3004 case 'i':
3005 r = ifname_mangle(optarg);
3006 if (r < 0)
3007 return r;
3008 break;
3009
3010 case 't':
3011 if (streq(optarg, "help")) {
3012 help_dns_types();
3013 return 0;
3014 }
3015
3016 r = dns_type_from_string(optarg);
3017 if (r < 0)
3018 return log_error_errno(r, "Failed to parse RR record type %s: %m", optarg);
3019
3020 arg_type = (uint16_t) r;
3021 assert((int) arg_type == r);
3022
3023 arg_mode = MODE_RESOLVE_RECORD;
3024 break;
3025
3026 case 'c':
3027 if (streq(optarg, "help")) {
3028 help_dns_classes();
3029 return 0;
3030 }
3031
3032 r = dns_class_from_string(optarg);
3033 if (r < 0)
3034 return log_error_errno(r, "Failed to parse RR record class %s: %m", optarg);
3035
3036 arg_class = (uint16_t) r;
3037 assert((int) arg_class == r);
3038
3039 break;
3040
3041 case ARG_LEGEND:
3042 r = parse_boolean_argument("--legend=", optarg, &arg_legend);
3043 if (r < 0)
3044 return r;
3045 break;
3046
3047 case 'p':
3048 if (streq(optarg, "help")) {
3049 help_protocol_types();
3050 return 0;
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;
3065 else
3066 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3067 "Unknown protocol specifier: %s", optarg);
3068
3069 break;
3070
3071 case ARG_SERVICE:
3072 arg_mode = MODE_RESOLVE_SERVICE;
3073 break;
3074
3075 case ARG_OPENPGP:
3076 arg_mode = MODE_RESOLVE_OPENPGP;
3077 break;
3078
3079 case ARG_TLSA:
3080 arg_mode = MODE_RESOLVE_TLSA;
3081 if (!optarg || service_family_is_valid(optarg))
3082 arg_service_family = optarg;
3083 else
3084 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3085 "Unknown service family \"%s\".", optarg);
3086 break;
3087
3088 case ARG_RAW:
3089 if (on_tty())
3090 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
3091 "Refusing to write binary data to tty.");
3092
3093 if (optarg == NULL || streq(optarg, "payload"))
3094 arg_raw = RAW_PAYLOAD;
3095 else if (streq(optarg, "packet"))
3096 arg_raw = RAW_PACKET;
3097 else
3098 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3099 "Unknown --raw specifier \"%s\".",
3100 optarg);
3101
3102 arg_legend = false;
3103 break;
3104
3105 case ARG_CNAME:
3106 r = parse_boolean_argument("--cname=", optarg, NULL);
3107 if (r < 0)
3108 return r;
3109 SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
3110 break;
3111
3112 case ARG_SERVICE_ADDRESS:
3113 r = parse_boolean_argument("--service-address=", optarg, NULL);
3114 if (r < 0)
3115 return r;
3116 SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
3117 break;
3118
3119 case ARG_SERVICE_TXT:
3120 r = parse_boolean_argument("--service-txt=", optarg, NULL);
3121 if (r < 0)
3122 return r;
3123 SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
3124 break;
3125
3126 case ARG_SEARCH:
3127 r = parse_boolean_argument("--search=", optarg, NULL);
3128 if (r < 0)
3129 return r;
3130 SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
3131 break;
3132
3133 case ARG_STATISTICS:
3134 arg_mode = MODE_STATISTICS;
3135 break;
3136
3137 case ARG_RESET_STATISTICS:
3138 arg_mode = MODE_RESET_STATISTICS;
3139 break;
3140
3141 case ARG_FLUSH_CACHES:
3142 arg_mode = MODE_FLUSH_CACHES;
3143 break;
3144
3145 case ARG_RESET_SERVER_FEATURES:
3146 arg_mode = MODE_RESET_SERVER_FEATURES;
3147 break;
3148
3149 case ARG_STATUS:
3150 arg_mode = MODE_STATUS;
3151 break;
3152
3153 case ARG_NO_PAGER:
3154 arg_pager_flags |= PAGER_DISABLE;
3155 break;
3156
3157 case ARG_SET_DNS:
3158 r = strv_extend(&arg_set_dns, optarg);
3159 if (r < 0)
3160 return log_oom();
3161
3162 arg_mode = MODE_SET_LINK;
3163 break;
3164
3165 case ARG_SET_DOMAIN:
3166 r = strv_extend(&arg_set_domain, optarg);
3167 if (r < 0)
3168 return log_oom();
3169
3170 arg_mode = MODE_SET_LINK;
3171 break;
3172
3173 case ARG_SET_LLMNR:
3174 arg_set_llmnr = optarg;
3175 arg_mode = MODE_SET_LINK;
3176 break;
3177
3178 case ARG_SET_MDNS:
3179 arg_set_mdns = optarg;
3180 arg_mode = MODE_SET_LINK;
3181 break;
3182
3183 case ARG_SET_PRIVATE:
3184 arg_set_dns_over_tls = optarg;
3185 arg_mode = MODE_SET_LINK;
3186 break;
3187
3188 case ARG_SET_DNSSEC:
3189 arg_set_dnssec = optarg;
3190 arg_mode = MODE_SET_LINK;
3191 break;
3192
3193 case ARG_SET_NTA:
3194 r = strv_extend(&arg_set_nta, optarg);
3195 if (r < 0)
3196 return log_oom();
3197
3198 arg_mode = MODE_SET_LINK;
3199 break;
3200
3201 case ARG_REVERT_LINK:
3202 arg_mode = MODE_REVERT_LINK;
3203 break;
3204
3205 case '?':
3206 return -EINVAL;
3207
3208 default:
3209 assert_not_reached();
3210 }
3211
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=.");
3215
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.");
3219
3220 if (arg_type != 0 && arg_class == 0)
3221 arg_class = DNS_CLASS_IN;
3222
3223 if (arg_class != 0 && arg_type == 0)
3224 arg_type = DNS_TYPE_A;
3225
3226 if (IN_SET(arg_mode, MODE_SET_LINK, MODE_REVERT_LINK)) {
3227
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=.");
3231 }
3232
3233 return 1 /* work to do */;
3234 }
3235
3236 static int native_parse_argv(int argc, char *argv[]) {
3237 enum {
3238 ARG_VERSION = 0x100,
3239 ARG_LEGEND,
3240 ARG_CNAME,
3241 ARG_VALIDATE,
3242 ARG_SYNTHESIZE,
3243 ARG_CACHE,
3244 ARG_ZONE,
3245 ARG_TRUST_ANCHOR,
3246 ARG_NETWORK,
3247 ARG_SERVICE_ADDRESS,
3248 ARG_SERVICE_TXT,
3249 ARG_RAW,
3250 ARG_SEARCH,
3251 ARG_NO_PAGER,
3252 ARG_JSON,
3253 };
3254
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 },
3276 {}
3277 };
3278
3279 int c, r;
3280
3281 assert(argc >= 0);
3282 assert(argv);
3283
3284 while ((c = getopt_long(argc, argv, "h46i:t:c:p:j", options, NULL)) >= 0)
3285 switch (c) {
3286
3287 case 'h':
3288 return native_help();
3289
3290 case ARG_VERSION:
3291 return version();
3292
3293 case '4':
3294 arg_family = AF_INET;
3295 break;
3296
3297 case '6':
3298 arg_family = AF_INET6;
3299 break;
3300
3301 case 'i':
3302 r = ifname_mangle(optarg);
3303 if (r < 0)
3304 return r;
3305 break;
3306
3307 case 't':
3308 if (streq(optarg, "help")) {
3309 help_dns_types();
3310 return 0;
3311 }
3312
3313 r = dns_type_from_string(optarg);
3314 if (r < 0)
3315 return log_error_errno(r, "Failed to parse RR record type %s: %m", optarg);
3316
3317 arg_type = (uint16_t) r;
3318 assert((int) arg_type == r);
3319
3320 break;
3321
3322 case 'c':
3323 if (streq(optarg, "help")) {
3324 help_dns_classes();
3325 return 0;
3326 }
3327
3328 r = dns_class_from_string(optarg);
3329 if (r < 0)
3330 return log_error_errno(r, "Failed to parse RR record class %s: %m", optarg);
3331
3332 arg_class = (uint16_t) r;
3333 assert((int) arg_class == r);
3334
3335 break;
3336
3337 case ARG_LEGEND:
3338 r = parse_boolean_argument("--legend=", optarg, &arg_legend);
3339 if (r < 0)
3340 return r;
3341 break;
3342
3343 case 'p':
3344 if (streq(optarg, "help")) {
3345 help_protocol_types();
3346 return 0;
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;
3361 else
3362 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3363 "Unknown protocol specifier: %s",
3364 optarg);
3365
3366 break;
3367
3368 case ARG_RAW:
3369 if (on_tty())
3370 return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
3371 "Refusing to write binary data to tty.");
3372
3373 if (optarg == NULL || streq(optarg, "payload"))
3374 arg_raw = RAW_PAYLOAD;
3375 else if (streq(optarg, "packet"))
3376 arg_raw = RAW_PACKET;
3377 else
3378 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3379 "Unknown --raw specifier \"%s\".",
3380 optarg);
3381
3382 arg_legend = false;
3383 break;
3384
3385 case ARG_CNAME:
3386 r = parse_boolean_argument("--cname=", optarg, NULL);
3387 if (r < 0)
3388 return r;
3389 SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
3390 break;
3391
3392 case ARG_VALIDATE:
3393 r = parse_boolean_argument("--validate=", optarg, NULL);
3394 if (r < 0)
3395 return r;
3396 SET_FLAG(arg_flags, SD_RESOLVED_NO_VALIDATE, r == 0);
3397 break;
3398
3399 case ARG_SYNTHESIZE:
3400 r = parse_boolean_argument("--synthesize=", optarg, NULL);
3401 if (r < 0)
3402 return r;
3403 SET_FLAG(arg_flags, SD_RESOLVED_NO_SYNTHESIZE, r == 0);
3404 break;
3405
3406 case ARG_CACHE:
3407 r = parse_boolean_argument("--cache=", optarg, NULL);
3408 if (r < 0)
3409 return r;
3410 SET_FLAG(arg_flags, SD_RESOLVED_NO_CACHE, r == 0);
3411 break;
3412
3413 case ARG_ZONE:
3414 r = parse_boolean_argument("--zone=", optarg, NULL);
3415 if (r < 0)
3416 return r;
3417 SET_FLAG(arg_flags, SD_RESOLVED_NO_ZONE, r == 0);
3418 break;
3419
3420 case ARG_TRUST_ANCHOR:
3421 r = parse_boolean_argument("--trust-anchor=", optarg, NULL);
3422 if (r < 0)
3423 return r;
3424 SET_FLAG(arg_flags, SD_RESOLVED_NO_TRUST_ANCHOR, r == 0);
3425 break;
3426
3427 case ARG_NETWORK:
3428 r = parse_boolean_argument("--network=", optarg, NULL);
3429 if (r < 0)
3430 return r;
3431 SET_FLAG(arg_flags, SD_RESOLVED_NO_NETWORK, r == 0);
3432 break;
3433
3434 case ARG_SERVICE_ADDRESS:
3435 r = parse_boolean_argument("--service-address=", optarg, NULL);
3436 if (r < 0)
3437 return r;
3438 SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
3439 break;
3440
3441 case ARG_SERVICE_TXT:
3442 r = parse_boolean_argument("--service-txt=", optarg, NULL);
3443 if (r < 0)
3444 return r;
3445 SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
3446 break;
3447
3448 case ARG_SEARCH:
3449 r = parse_boolean_argument("--search=", optarg, NULL);
3450 if (r < 0)
3451 return r;
3452 SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
3453 break;
3454
3455 case ARG_NO_PAGER:
3456 arg_pager_flags |= PAGER_DISABLE;
3457 break;
3458
3459 case ARG_JSON:
3460 r = parse_json_argument(optarg, &arg_json_format_flags);
3461 if (r <= 0)
3462 return r;
3463
3464 break;
3465
3466 case 'j':
3467 arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO;
3468 break;
3469
3470 case '?':
3471 return -EINVAL;
3472
3473 default:
3474 assert_not_reached();
3475 }
3476
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=.");
3480
3481 if (arg_type != 0 && arg_class == 0)
3482 arg_class = DNS_CLASS_IN;
3483
3484 if (arg_class != 0 && arg_type == 0)
3485 arg_type = DNS_TYPE_A;
3486
3487 return 1 /* work to do */;
3488 }
3489
3490 static int native_main(int argc, char *argv[], sd_bus *bus) {
3491
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 },
3514 {}
3515 };
3516
3517 return dispatch_verb(argc, argv, verbs, bus);
3518 }
3519
3520 static int translate(const char *verb, const char *single_arg, size_t num_args, char **args, sd_bus *bus) {
3521 char **fake, **p;
3522 size_t num;
3523
3524 assert(verb);
3525 assert(num_args == 0 || args);
3526
3527 num = !!single_arg + num_args + 1;
3528
3529 p = fake = newa0(char *, num + 1);
3530 *p++ = (char *) verb;
3531 if (single_arg)
3532 *p++ = (char *) single_arg;
3533 for (size_t i = 0; i < num_args; i++)
3534 *p++ = args[i];
3535
3536 optind = 0;
3537 return native_main((int) num, fake, bus);
3538 }
3539
3540 static int compat_main(int argc, char *argv[], sd_bus *bus) {
3541 int r = 0;
3542
3543 switch (arg_mode) {
3544 case MODE_RESOLVE_HOST:
3545 case MODE_RESOLVE_RECORD:
3546 return translate("query", NULL, argc - optind, argv + optind, bus);
3547
3548 case MODE_RESOLVE_SERVICE:
3549 return translate("service", NULL, argc - optind, argv + optind, bus);
3550
3551 case MODE_RESOLVE_OPENPGP:
3552 return translate("openpgp", NULL, argc - optind, argv + optind, bus);
3553
3554 case MODE_RESOLVE_TLSA:
3555 return translate("tlsa", arg_service_family, argc - optind, argv + optind, bus);
3556
3557 case MODE_STATISTICS:
3558 return translate("statistics", NULL, 0, NULL, bus);
3559
3560 case MODE_RESET_STATISTICS:
3561 return translate("reset-statistics", NULL, 0, NULL, bus);
3562
3563 case MODE_FLUSH_CACHES:
3564 return translate("flush-caches", NULL, 0, NULL, bus);
3565
3566 case MODE_RESET_SERVER_FEATURES:
3567 return translate("reset-server-features", NULL, 0, NULL, bus);
3568
3569 case MODE_STATUS:
3570 return translate("status", NULL, argc - optind, argv + optind, bus);
3571
3572 case MODE_SET_LINK:
3573 assert(arg_ifname);
3574
3575 if (arg_set_dns) {
3576 r = translate("dns", arg_ifname, strv_length(arg_set_dns), arg_set_dns, bus);
3577 if (r < 0)
3578 return r;
3579 }
3580
3581 if (arg_set_domain) {
3582 r = translate("domain", arg_ifname, strv_length(arg_set_domain), arg_set_domain, bus);
3583 if (r < 0)
3584 return r;
3585 }
3586
3587 if (arg_set_nta) {
3588 r = translate("nta", arg_ifname, strv_length(arg_set_nta), arg_set_nta, bus);
3589 if (r < 0)
3590 return r;
3591 }
3592
3593 if (arg_set_llmnr) {
3594 r = translate("llmnr", arg_ifname, 1, (char **) &arg_set_llmnr, bus);
3595 if (r < 0)
3596 return r;
3597 }
3598
3599 if (arg_set_mdns) {
3600 r = translate("mdns", arg_ifname, 1, (char **) &arg_set_mdns, bus);
3601 if (r < 0)
3602 return r;
3603 }
3604
3605 if (arg_set_dns_over_tls) {
3606 r = translate("dnsovertls", arg_ifname, 1, (char **) &arg_set_dns_over_tls, bus);
3607 if (r < 0)
3608 return r;
3609 }
3610
3611 if (arg_set_dnssec) {
3612 r = translate("dnssec", arg_ifname, 1, (char **) &arg_set_dnssec, bus);
3613 if (r < 0)
3614 return r;
3615 }
3616
3617 return r;
3618
3619 case MODE_REVERT_LINK:
3620 assert(arg_ifname);
3621
3622 return translate("revert", arg_ifname, 0, NULL, bus);
3623
3624 case _MODE_INVALID:
3625 assert_not_reached();
3626 }
3627
3628 return 0;
3629 }
3630
3631 static int run(int argc, char **argv) {
3632 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
3633 bool compat = false;
3634 int r;
3635
3636 setlocale(LC_ALL, "");
3637 log_setup();
3638
3639 if (invoked_as(argv, "resolvconf")) {
3640 compat = true;
3641 r = resolvconf_parse_argv(argc, argv);
3642 } else if (invoked_as(argv, "systemd-resolve")) {
3643 compat = true;
3644 r = compat_parse_argv(argc, argv);
3645 } else
3646 r = native_parse_argv(argc, argv);
3647 if (r <= 0)
3648 return r;
3649
3650 r = sd_bus_open_system(&bus);
3651 if (r < 0)
3652 return log_error_errno(r, "sd_bus_open_system: %m");
3653
3654 if (compat)
3655 return compat_main(argc, argv, bus);
3656
3657 return native_main(argc, argv, bus);
3658 }
3659
3660 DEFINE_MAIN_FUNCTION(run);