]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolvectl.c
Merge pull request #8959 from yuwata/bash-completion-analyze
[thirdparty/systemd.git] / src / resolve / resolvectl.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2014 Zbigniew Jędrzejewski-Szmek
6 ***/
7
8 #include <getopt.h>
9 #include <net/if.h>
10
11 #include "sd-bus.h"
12 #include "sd-netlink.h"
13
14 #include "af-list.h"
15 #include "alloc-util.h"
16 #include "bus-common-errors.h"
17 #include "bus-error.h"
18 #include "bus-util.h"
19 #include "dns-domain.h"
20 #include "escape.h"
21 #include "gcrypt-util.h"
22 #include "in-addr-util.h"
23 #include "netlink-util.h"
24 #include "pager.h"
25 #include "parse-util.h"
26 #include "resolvconf-compat.h"
27 #include "resolvectl.h"
28 #include "resolved-def.h"
29 #include "resolved-dns-packet.h"
30 #include "strv.h"
31 #include "terminal-util.h"
32 #include "verbs.h"
33
34 static int arg_family = AF_UNSPEC;
35 int arg_ifindex = 0;
36 const char *arg_ifname = NULL;
37 static uint16_t arg_type = 0;
38 static uint16_t arg_class = 0;
39 static bool arg_legend = true;
40 static uint64_t arg_flags = 0;
41 static bool arg_no_pager = false;
42 bool arg_ifindex_permissive = false; /* If true, don't generate an error if the specified interface index doesn't exist */
43 static const char *arg_service_family = NULL;
44
45 typedef enum RawType {
46 RAW_NONE,
47 RAW_PAYLOAD,
48 RAW_PACKET,
49 } RawType;
50 static RawType arg_raw = RAW_NONE;
51
52 ExecutionMode arg_mode = MODE_RESOLVE_HOST;
53
54 char **arg_set_dns = NULL;
55 char **arg_set_domain = NULL;
56 static const char *arg_set_llmnr = NULL;
57 static const char *arg_set_mdns = NULL;
58 static const char *arg_set_dnssec = NULL;
59 static char **arg_set_nta = NULL;
60
61 typedef enum StatusMode {
62 STATUS_ALL,
63 STATUS_DNS,
64 STATUS_DOMAIN,
65 STATUS_LLMNR,
66 STATUS_MDNS,
67 STATUS_DNSSEC,
68 STATUS_NTA,
69 } StatusMode;
70
71 static int parse_ifindex_with_warn(const char *s) {
72 int ifi;
73
74 assert(s);
75
76 if (parse_ifindex(s, &ifi) < 0) {
77 ifi = if_nametoindex(s);
78 if (ifi <= 0)
79 return log_error_errno(errno, "Unknown interface %s: %m", s);
80 }
81
82 return ifi;
83 }
84
85 static void print_source(uint64_t flags, usec_t rtt) {
86 char rtt_str[FORMAT_TIMESTAMP_MAX];
87
88 if (!arg_legend)
89 return;
90
91 if (flags == 0)
92 return;
93
94 fputs("\n-- Information acquired via", stdout);
95
96 if (flags != 0)
97 printf(" protocol%s%s%s%s%s",
98 flags & SD_RESOLVED_DNS ? " DNS" :"",
99 flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
100 flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
101 flags & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "",
102 flags & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : "");
103
104 assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
105
106 printf(" in %s", rtt_str);
107
108 fputc('.', stdout);
109 fputc('\n', stdout);
110
111 printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
112 }
113
114 static int resolve_host(sd_bus *bus, const char *name) {
115 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
116 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
117 const char *canonical = NULL;
118 char ifname[IF_NAMESIZE] = "";
119 unsigned c = 0;
120 int r;
121 uint64_t flags;
122 usec_t ts;
123
124 assert(name);
125
126 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
127 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
128
129 log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
130
131 r = sd_bus_message_new_method_call(
132 bus,
133 &req,
134 "org.freedesktop.resolve1",
135 "/org/freedesktop/resolve1",
136 "org.freedesktop.resolve1.Manager",
137 "ResolveHostname");
138 if (r < 0)
139 return bus_log_create_error(r);
140
141 r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
142 if (r < 0)
143 return bus_log_create_error(r);
144
145 ts = now(CLOCK_MONOTONIC);
146
147 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
148 if (r < 0)
149 return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r));
150
151 ts = now(CLOCK_MONOTONIC) - ts;
152
153 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
154 if (r < 0)
155 return bus_log_parse_error(r);
156
157 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
158 _cleanup_free_ char *pretty = NULL;
159 int ifindex, family;
160 const void *a;
161 size_t sz;
162
163 assert_cc(sizeof(int) == sizeof(int32_t));
164
165 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
166 if (r < 0)
167 return bus_log_parse_error(r);
168
169 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
170 if (r < 0)
171 return bus_log_parse_error(r);
172
173 r = sd_bus_message_exit_container(reply);
174 if (r < 0)
175 return bus_log_parse_error(r);
176
177 if (!IN_SET(family, AF_INET, AF_INET6)) {
178 log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
179 continue;
180 }
181
182 if (sz != FAMILY_ADDRESS_SIZE(family)) {
183 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
184 return -EINVAL;
185 }
186
187 ifname[0] = 0;
188 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
189 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
190
191 r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
192 if (r < 0)
193 return log_error_errno(r, "Failed to print address for %s: %m", name);
194
195 printf("%*s%s %s%s%s\n",
196 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
197 pretty,
198 isempty(ifname) ? "" : "%", ifname);
199
200 c++;
201 }
202 if (r < 0)
203 return bus_log_parse_error(r);
204
205 r = sd_bus_message_exit_container(reply);
206 if (r < 0)
207 return bus_log_parse_error(r);
208
209 r = sd_bus_message_read(reply, "st", &canonical, &flags);
210 if (r < 0)
211 return bus_log_parse_error(r);
212
213 if (!streq(name, canonical))
214 printf("%*s%s (%s)\n",
215 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
216 canonical);
217
218 if (c == 0) {
219 log_error("%s: no addresses found", name);
220 return -ESRCH;
221 }
222
223 print_source(flags, ts);
224
225 return 0;
226 }
227
228 static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
229 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
230 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
231 _cleanup_free_ char *pretty = NULL;
232 char ifname[IF_NAMESIZE] = "";
233 uint64_t flags;
234 unsigned c = 0;
235 usec_t ts;
236 int r;
237
238 assert(bus);
239 assert(IN_SET(family, AF_INET, AF_INET6));
240 assert(address);
241
242 if (ifindex <= 0)
243 ifindex = arg_ifindex;
244
245 r = in_addr_ifindex_to_string(family, address, ifindex, &pretty);
246 if (r < 0)
247 return log_oom();
248
249 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
250 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
251
252 log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
253
254 r = sd_bus_message_new_method_call(
255 bus,
256 &req,
257 "org.freedesktop.resolve1",
258 "/org/freedesktop/resolve1",
259 "org.freedesktop.resolve1.Manager",
260 "ResolveAddress");
261 if (r < 0)
262 return bus_log_create_error(r);
263
264 r = sd_bus_message_append(req, "ii", ifindex, family);
265 if (r < 0)
266 return bus_log_create_error(r);
267
268 r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
269 if (r < 0)
270 return bus_log_create_error(r);
271
272 r = sd_bus_message_append(req, "t", arg_flags);
273 if (r < 0)
274 return bus_log_create_error(r);
275
276 ts = now(CLOCK_MONOTONIC);
277
278 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
279 if (r < 0) {
280 log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
281 return r;
282 }
283
284 ts = now(CLOCK_MONOTONIC) - ts;
285
286 r = sd_bus_message_enter_container(reply, 'a', "(is)");
287 if (r < 0)
288 return bus_log_create_error(r);
289
290 while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
291 const char *n;
292
293 assert_cc(sizeof(int) == sizeof(int32_t));
294
295 r = sd_bus_message_read(reply, "is", &ifindex, &n);
296 if (r < 0)
297 return r;
298
299 r = sd_bus_message_exit_container(reply);
300 if (r < 0)
301 return r;
302
303 ifname[0] = 0;
304 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
305 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
306
307 printf("%*s%*s%*s%s %s\n",
308 (int) strlen(pretty), c == 0 ? pretty : "",
309 isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
310 (int) strlen(ifname), c == 0 ? ifname : "",
311 c == 0 ? ":" : " ",
312 n);
313
314 c++;
315 }
316 if (r < 0)
317 return bus_log_parse_error(r);
318
319 r = sd_bus_message_exit_container(reply);
320 if (r < 0)
321 return bus_log_parse_error(r);
322
323 r = sd_bus_message_read(reply, "t", &flags);
324 if (r < 0)
325 return bus_log_parse_error(r);
326
327 if (c == 0) {
328 log_error("%s: no names found", pretty);
329 return -ESRCH;
330 }
331
332 print_source(flags, ts);
333
334 return 0;
335 }
336
337 static int output_rr_packet(const void *d, size_t l, int ifindex) {
338 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
339 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
340 int r;
341 char ifname[IF_NAMESIZE] = "";
342
343 r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX);
344 if (r < 0)
345 return log_oom();
346
347 p->refuse_compression = true;
348
349 r = dns_packet_append_blob(p, d, l, NULL);
350 if (r < 0)
351 return log_oom();
352
353 r = dns_packet_read_rr(p, &rr, NULL, NULL);
354 if (r < 0)
355 return log_error_errno(r, "Failed to parse RR: %m");
356
357 if (arg_raw == RAW_PAYLOAD) {
358 void *data;
359 ssize_t k;
360
361 k = dns_resource_record_payload(rr, &data);
362 if (k < 0)
363 return log_error_errno(k, "Cannot dump RR: %m");
364 fwrite(data, 1, k, stdout);
365 } else {
366 const char *s;
367
368 s = dns_resource_record_to_string(rr);
369 if (!s)
370 return log_oom();
371
372 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
373 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
374
375 printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
376 }
377
378 return 0;
379 }
380
381 static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) {
382 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
383 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
384 char ifname[IF_NAMESIZE] = "";
385 unsigned n = 0;
386 uint64_t flags;
387 int r;
388 usec_t ts;
389 bool needs_authentication = false;
390
391 assert(name);
392
393 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
394 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
395
396 log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname);
397
398 r = sd_bus_message_new_method_call(
399 bus,
400 &req,
401 "org.freedesktop.resolve1",
402 "/org/freedesktop/resolve1",
403 "org.freedesktop.resolve1.Manager",
404 "ResolveRecord");
405 if (r < 0)
406 return bus_log_create_error(r);
407
408 r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags);
409 if (r < 0)
410 return bus_log_create_error(r);
411
412 ts = now(CLOCK_MONOTONIC);
413
414 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
415 if (r < 0) {
416 if (warn_missing || r != -ENXIO)
417 log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
418 return r;
419 }
420
421 ts = now(CLOCK_MONOTONIC) - ts;
422
423 r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
424 if (r < 0)
425 return bus_log_parse_error(r);
426
427 while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
428 uint16_t c, t;
429 int ifindex;
430 const void *d;
431 size_t l;
432
433 assert_cc(sizeof(int) == sizeof(int32_t));
434
435 r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
436 if (r < 0)
437 return bus_log_parse_error(r);
438
439 r = sd_bus_message_read_array(reply, 'y', &d, &l);
440 if (r < 0)
441 return bus_log_parse_error(r);
442
443 r = sd_bus_message_exit_container(reply);
444 if (r < 0)
445 return bus_log_parse_error(r);
446
447 if (arg_raw == RAW_PACKET) {
448 uint64_t u64 = htole64(l);
449
450 fwrite(&u64, sizeof(u64), 1, stdout);
451 fwrite(d, 1, l, stdout);
452 } else {
453 r = output_rr_packet(d, l, ifindex);
454 if (r < 0)
455 return r;
456 }
457
458 if (dns_type_needs_authentication(t))
459 needs_authentication = true;
460
461 n++;
462 }
463 if (r < 0)
464 return bus_log_parse_error(r);
465
466 r = sd_bus_message_exit_container(reply);
467 if (r < 0)
468 return bus_log_parse_error(r);
469
470 r = sd_bus_message_read(reply, "t", &flags);
471 if (r < 0)
472 return bus_log_parse_error(r);
473
474 if (n == 0) {
475 if (warn_missing)
476 log_error("%s: no records found", name);
477 return -ESRCH;
478 }
479
480 print_source(flags, ts);
481
482 if ((flags & SD_RESOLVED_AUTHENTICATED) == 0 && needs_authentication) {
483 fflush(stdout);
484
485 fprintf(stderr, "\n%s"
486 "WARNING: The resources shown contain cryptographic key data which could not be\n"
487 " authenticated. It is not suitable to authenticate any communication.\n"
488 " This is usually indication that DNSSEC authentication was not enabled\n"
489 " or is not available for the selected protocol or DNS servers.%s\n",
490 ansi_highlight_red(),
491 ansi_normal());
492 }
493
494 return 0;
495 }
496
497 static int resolve_rfc4501(sd_bus *bus, const char *name) {
498 uint16_t type = 0, class = 0;
499 const char *p, *q, *n;
500 int r;
501
502 assert(bus);
503 assert(name);
504 assert(startswith(name, "dns:"));
505
506 /* Parse RFC 4501 dns: URIs */
507
508 p = name + 4;
509
510 if (p[0] == '/') {
511 const char *e;
512
513 if (p[1] != '/')
514 goto invalid;
515
516 e = strchr(p + 2, '/');
517 if (!e)
518 goto invalid;
519
520 if (e != p + 2)
521 log_warning("DNS authority specification not supported; ignoring specified authority.");
522
523 p = e + 1;
524 }
525
526 q = strchr(p, '?');
527 if (q) {
528 n = strndupa(p, q - p);
529 q++;
530
531 for (;;) {
532 const char *f;
533
534 f = startswith_no_case(q, "class=");
535 if (f) {
536 _cleanup_free_ char *t = NULL;
537 const char *e;
538
539 if (class != 0) {
540 log_error("DNS class specified twice.");
541 return -EINVAL;
542 }
543
544 e = strchrnul(f, ';');
545 t = strndup(f, e - f);
546 if (!t)
547 return log_oom();
548
549 r = dns_class_from_string(t);
550 if (r < 0) {
551 log_error("Unknown DNS class %s.", t);
552 return -EINVAL;
553 }
554
555 class = r;
556
557 if (*e == ';') {
558 q = e + 1;
559 continue;
560 }
561
562 break;
563 }
564
565 f = startswith_no_case(q, "type=");
566 if (f) {
567 _cleanup_free_ char *t = NULL;
568 const char *e;
569
570 if (type != 0) {
571 log_error("DNS type specified twice.");
572 return -EINVAL;
573 }
574
575 e = strchrnul(f, ';');
576 t = strndup(f, e - f);
577 if (!t)
578 return log_oom();
579
580 r = dns_type_from_string(t);
581 if (r < 0) {
582 log_error("Unknown DNS type %s.", t);
583 return -EINVAL;
584 }
585
586 type = r;
587
588 if (*e == ';') {
589 q = e + 1;
590 continue;
591 }
592
593 break;
594 }
595
596 goto invalid;
597 }
598 } else
599 n = p;
600
601 if (class == 0)
602 class = arg_class ?: DNS_CLASS_IN;
603 if (type == 0)
604 type = arg_type ?: DNS_TYPE_A;
605
606 return resolve_record(bus, n, class, type, true);
607
608 invalid:
609 log_error("Invalid DNS URI: %s", name);
610 return -EINVAL;
611 }
612
613 static int verb_query(int argc, char **argv, void *userdata) {
614 sd_bus *bus = userdata;
615 char **p;
616 int q, r = 0;
617
618 if (arg_type != 0)
619 STRV_FOREACH(p, argv + 1) {
620 q = resolve_record(bus, *p, arg_class, arg_type, true);
621 if (q < 0)
622 r = q;
623 }
624
625 else
626 STRV_FOREACH(p, argv + 1) {
627 if (startswith(*p, "dns:"))
628 q = resolve_rfc4501(bus, *p);
629 else {
630 int family, ifindex;
631 union in_addr_union a;
632
633 q = in_addr_ifindex_from_string_auto(*p, &family, &a, &ifindex);
634 if (q >= 0)
635 q = resolve_address(bus, family, &a, ifindex);
636 else
637 q = resolve_host(bus, *p);
638 }
639 if (q < 0)
640 r = q;
641 }
642
643 return r;
644 }
645
646 static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) {
647 const char *canonical_name, *canonical_type, *canonical_domain;
648 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
649 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
650 char ifname[IF_NAMESIZE] = "";
651 size_t indent, sz;
652 uint64_t flags;
653 const char *p;
654 unsigned c;
655 usec_t ts;
656 int r;
657
658 assert(bus);
659 assert(domain);
660
661 name = empty_to_null(name);
662 type = empty_to_null(type);
663
664 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
665 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
666
667 if (name)
668 log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
669 else if (type)
670 log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
671 else
672 log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
673
674 r = sd_bus_message_new_method_call(
675 bus,
676 &req,
677 "org.freedesktop.resolve1",
678 "/org/freedesktop/resolve1",
679 "org.freedesktop.resolve1.Manager",
680 "ResolveService");
681 if (r < 0)
682 return bus_log_create_error(r);
683
684 r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags);
685 if (r < 0)
686 return bus_log_create_error(r);
687
688 ts = now(CLOCK_MONOTONIC);
689
690 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
691 if (r < 0)
692 return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r));
693
694 ts = now(CLOCK_MONOTONIC) - ts;
695
696 r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)");
697 if (r < 0)
698 return bus_log_parse_error(r);
699
700 indent =
701 (name ? strlen(name) + 1 : 0) +
702 (type ? strlen(type) + 1 : 0) +
703 strlen(domain) + 2;
704
705 c = 0;
706 while ((r = sd_bus_message_enter_container(reply, 'r', "qqqsa(iiay)s")) > 0) {
707 uint16_t priority, weight, port;
708 const char *hostname, *canonical;
709
710 r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname);
711 if (r < 0)
712 return bus_log_parse_error(r);
713
714 if (name)
715 printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " ");
716 if (type)
717 printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " ");
718
719 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
720 (int) strlen(domain), c == 0 ? domain : "",
721 c == 0 ? ":" : " ",
722 hostname, port,
723 priority, weight);
724
725 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
726 if (r < 0)
727 return bus_log_parse_error(r);
728
729 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
730 _cleanup_free_ char *pretty = NULL;
731 int ifindex, family;
732 const void *a;
733
734 assert_cc(sizeof(int) == sizeof(int32_t));
735
736 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
737 if (r < 0)
738 return bus_log_parse_error(r);
739
740 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
741 if (r < 0)
742 return bus_log_parse_error(r);
743
744 r = sd_bus_message_exit_container(reply);
745 if (r < 0)
746 return bus_log_parse_error(r);
747
748 if (!IN_SET(family, AF_INET, AF_INET6)) {
749 log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
750 continue;
751 }
752
753 if (sz != FAMILY_ADDRESS_SIZE(family)) {
754 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
755 return -EINVAL;
756 }
757
758 ifname[0] = 0;
759 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
760 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
761
762 r = in_addr_to_string(family, a, &pretty);
763 if (r < 0)
764 return log_error_errno(r, "Failed to print address for %s: %m", name);
765
766 printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname);
767 }
768 if (r < 0)
769 return bus_log_parse_error(r);
770
771 r = sd_bus_message_exit_container(reply);
772 if (r < 0)
773 return bus_log_parse_error(r);
774
775 r = sd_bus_message_read(reply, "s", &canonical);
776 if (r < 0)
777 return bus_log_parse_error(r);
778
779 if (!streq(hostname, canonical))
780 printf("%*s(%s)\n", (int) indent, "", canonical);
781
782 r = sd_bus_message_exit_container(reply);
783 if (r < 0)
784 return bus_log_parse_error(r);
785
786 c++;
787 }
788 if (r < 0)
789 return bus_log_parse_error(r);
790
791 r = sd_bus_message_exit_container(reply);
792 if (r < 0)
793 return bus_log_parse_error(r);
794
795 r = sd_bus_message_enter_container(reply, 'a', "ay");
796 if (r < 0)
797 return bus_log_parse_error(r);
798
799 while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) {
800 _cleanup_free_ char *escaped = NULL;
801
802 escaped = cescape_length(p, sz);
803 if (!escaped)
804 return log_oom();
805
806 printf("%*s%s\n", (int) indent, "", escaped);
807 }
808 if (r < 0)
809 return bus_log_parse_error(r);
810
811 r = sd_bus_message_exit_container(reply);
812 if (r < 0)
813 return bus_log_parse_error(r);
814
815 r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags);
816 if (r < 0)
817 return bus_log_parse_error(r);
818
819 canonical_name = empty_to_null(canonical_name);
820 canonical_type = empty_to_null(canonical_type);
821
822 if (!streq_ptr(name, canonical_name) ||
823 !streq_ptr(type, canonical_type) ||
824 !streq_ptr(domain, canonical_domain)) {
825
826 printf("%*s(", (int) indent, "");
827
828 if (canonical_name)
829 printf("%s/", canonical_name);
830 if (canonical_type)
831 printf("%s/", canonical_type);
832
833 printf("%s)\n", canonical_domain);
834 }
835
836 print_source(flags, ts);
837
838 return 0;
839 }
840
841 static int verb_service(int argc, char **argv, void *userdata) {
842 sd_bus *bus = userdata;
843
844 if (argc == 2)
845 return resolve_service(bus, NULL, NULL, argv[1]);
846 else if (argc == 3)
847 return resolve_service(bus, NULL, argv[1], argv[2]);
848 else
849 return resolve_service(bus, argv[1], argv[2], argv[3]);
850 }
851
852 static int resolve_openpgp(sd_bus *bus, const char *address) {
853 const char *domain, *full;
854 int r;
855 _cleanup_free_ char *hashed = NULL;
856
857 assert(bus);
858 assert(address);
859
860 domain = strrchr(address, '@');
861 if (!domain) {
862 log_error("Address does not contain '@': \"%s\"", address);
863 return -EINVAL;
864 } else if (domain == address || domain[1] == '\0') {
865 log_error("Address starts or ends with '@': \"%s\"", address);
866 return -EINVAL;
867 }
868 domain++;
869
870 r = string_hashsum_sha256(address, domain - 1 - address, &hashed);
871 if (r < 0)
872 return log_error_errno(r, "Hashing failed: %m");
873
874 strshorten(hashed, 56);
875
876 full = strjoina(hashed, "._openpgpkey.", domain);
877 log_debug("Looking up \"%s\".", full);
878
879 r = resolve_record(bus, full,
880 arg_class ?: DNS_CLASS_IN,
881 arg_type ?: DNS_TYPE_OPENPGPKEY, false);
882
883 if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */
884 hashed = NULL;
885 r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
886 if (r < 0)
887 return log_error_errno(r, "Hashing failed: %m");
888
889 full = strjoina(hashed, "._openpgpkey.", domain);
890 log_debug("Looking up \"%s\".", full);
891
892 return resolve_record(bus, full,
893 arg_class ?: DNS_CLASS_IN,
894 arg_type ?: DNS_TYPE_OPENPGPKEY, true);
895 }
896
897 return r;
898 }
899
900 static int verb_openpgp(int argc, char **argv, void *userdata) {
901 sd_bus *bus = userdata;
902 char **p;
903 int q, r = 0;
904
905 STRV_FOREACH(p, argv + 1) {
906 q = resolve_openpgp(bus, *p);
907 if (q < 0)
908 r = q;
909 }
910
911 return r;
912 }
913
914 static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) {
915 const char *port;
916 uint16_t port_num = 443;
917 _cleanup_free_ char *full = NULL;
918 int r;
919
920 assert(bus);
921 assert(address);
922
923 port = strrchr(address, ':');
924 if (port) {
925 r = parse_ip_port(port + 1, &port_num);
926 if (r < 0)
927 return log_error_errno(r, "Invalid port \"%s\".", port + 1);
928
929 address = strndupa(address, port - address);
930 }
931
932 r = asprintf(&full, "_%u._%s.%s",
933 port_num,
934 family,
935 address);
936 if (r < 0)
937 return log_oom();
938
939 log_debug("Looking up \"%s\".", full);
940
941 return resolve_record(bus, full,
942 arg_class ?: DNS_CLASS_IN,
943 arg_type ?: DNS_TYPE_TLSA, true);
944 }
945
946 static bool service_family_is_valid(const char *s) {
947 return STR_IN_SET(s, "tcp", "udp", "sctp");
948 }
949
950 static int verb_tlsa(int argc, char **argv, void *userdata) {
951 sd_bus *bus = userdata;
952 char **p, **args = argv + 1;
953 const char *family = "tcp";
954 int q, r = 0;
955
956 if (service_family_is_valid(argv[1])) {
957 family = argv[1];
958 args++;
959 }
960
961 STRV_FOREACH(p, args) {
962 q = resolve_tlsa(bus, family, *p);
963 if (q < 0)
964 r = q;
965 }
966
967 return r;
968 }
969
970 static int show_statistics(int argc, char **argv, void *userdata) {
971 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
972 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
973 sd_bus *bus = userdata;
974 uint64_t n_current_transactions, n_total_transactions,
975 cache_size, n_cache_hit, n_cache_miss,
976 n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate;
977 int r, dnssec_supported;
978
979 assert(bus);
980
981 r = sd_bus_get_property_trivial(bus,
982 "org.freedesktop.resolve1",
983 "/org/freedesktop/resolve1",
984 "org.freedesktop.resolve1.Manager",
985 "DNSSECSupported",
986 &error,
987 'b',
988 &dnssec_supported);
989 if (r < 0)
990 return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
991
992 printf("DNSSEC supported by current servers: %s%s%s\n\n",
993 ansi_highlight(),
994 yes_no(dnssec_supported),
995 ansi_normal());
996
997 r = sd_bus_get_property(bus,
998 "org.freedesktop.resolve1",
999 "/org/freedesktop/resolve1",
1000 "org.freedesktop.resolve1.Manager",
1001 "TransactionStatistics",
1002 &error,
1003 &reply,
1004 "(tt)");
1005 if (r < 0)
1006 return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r));
1007
1008 r = sd_bus_message_read(reply, "(tt)",
1009 &n_current_transactions,
1010 &n_total_transactions);
1011 if (r < 0)
1012 return bus_log_parse_error(r);
1013
1014 printf("%sTransactions%s\n"
1015 "Current Transactions: %" PRIu64 "\n"
1016 " Total Transactions: %" PRIu64 "\n",
1017 ansi_highlight(),
1018 ansi_normal(),
1019 n_current_transactions,
1020 n_total_transactions);
1021
1022 reply = sd_bus_message_unref(reply);
1023
1024 r = sd_bus_get_property(bus,
1025 "org.freedesktop.resolve1",
1026 "/org/freedesktop/resolve1",
1027 "org.freedesktop.resolve1.Manager",
1028 "CacheStatistics",
1029 &error,
1030 &reply,
1031 "(ttt)");
1032 if (r < 0)
1033 return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r));
1034
1035 r = sd_bus_message_read(reply, "(ttt)",
1036 &cache_size,
1037 &n_cache_hit,
1038 &n_cache_miss);
1039 if (r < 0)
1040 return bus_log_parse_error(r);
1041
1042 printf("\n%sCache%s\n"
1043 " Current Cache Size: %" PRIu64 "\n"
1044 " Cache Hits: %" PRIu64 "\n"
1045 " Cache Misses: %" PRIu64 "\n",
1046 ansi_highlight(),
1047 ansi_normal(),
1048 cache_size,
1049 n_cache_hit,
1050 n_cache_miss);
1051
1052 reply = sd_bus_message_unref(reply);
1053
1054 r = sd_bus_get_property(bus,
1055 "org.freedesktop.resolve1",
1056 "/org/freedesktop/resolve1",
1057 "org.freedesktop.resolve1.Manager",
1058 "DNSSECStatistics",
1059 &error,
1060 &reply,
1061 "(tttt)");
1062 if (r < 0)
1063 return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r));
1064
1065 r = sd_bus_message_read(reply, "(tttt)",
1066 &n_dnssec_secure,
1067 &n_dnssec_insecure,
1068 &n_dnssec_bogus,
1069 &n_dnssec_indeterminate);
1070 if (r < 0)
1071 return bus_log_parse_error(r);
1072
1073 printf("\n%sDNSSEC Verdicts%s\n"
1074 " Secure: %" PRIu64 "\n"
1075 " Insecure: %" PRIu64 "\n"
1076 " Bogus: %" PRIu64 "\n"
1077 " Indeterminate: %" PRIu64 "\n",
1078 ansi_highlight(),
1079 ansi_normal(),
1080 n_dnssec_secure,
1081 n_dnssec_insecure,
1082 n_dnssec_bogus,
1083 n_dnssec_indeterminate);
1084
1085 return 0;
1086 }
1087
1088 static int reset_statistics(int argc, char **argv, void *userdata) {
1089 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1090 sd_bus *bus = userdata;
1091 int r;
1092
1093 r = sd_bus_call_method(bus,
1094 "org.freedesktop.resolve1",
1095 "/org/freedesktop/resolve1",
1096 "org.freedesktop.resolve1.Manager",
1097 "ResetStatistics",
1098 &error,
1099 NULL,
1100 NULL);
1101 if (r < 0)
1102 return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r));
1103
1104 return 0;
1105 }
1106
1107 static int flush_caches(int argc, char **argv, void *userdata) {
1108 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1109 sd_bus *bus = userdata;
1110 int r;
1111
1112 r = sd_bus_call_method(bus,
1113 "org.freedesktop.resolve1",
1114 "/org/freedesktop/resolve1",
1115 "org.freedesktop.resolve1.Manager",
1116 "FlushCaches",
1117 &error,
1118 NULL,
1119 NULL);
1120 if (r < 0)
1121 return log_error_errno(r, "Failed to flush caches: %s", bus_error_message(&error, r));
1122
1123 return 0;
1124 }
1125
1126 static int reset_server_features(int argc, char **argv, void *userdata) {
1127 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1128 sd_bus *bus = userdata;
1129 int r;
1130
1131 r = sd_bus_call_method(bus,
1132 "org.freedesktop.resolve1",
1133 "/org/freedesktop/resolve1",
1134 "org.freedesktop.resolve1.Manager",
1135 "ResetServerFeatures",
1136 &error,
1137 NULL,
1138 NULL);
1139 if (r < 0)
1140 return log_error_errno(r, "Failed to reset server features: %s", bus_error_message(&error, r));
1141
1142 return 0;
1143 }
1144
1145 static int read_dns_server_one(sd_bus_message *m, bool with_ifindex, char **ret) {
1146 _cleanup_free_ char *pretty = NULL;
1147 int ifindex, family, r;
1148 const void *a;
1149 size_t sz;
1150
1151 assert(m);
1152 assert(ret);
1153
1154 r = sd_bus_message_enter_container(m, 'r', with_ifindex ? "iiay" : "iay");
1155 if (r <= 0)
1156 return r;
1157
1158 if (with_ifindex) {
1159 r = sd_bus_message_read(m, "i", &ifindex);
1160 if (r < 0)
1161 return r;
1162 }
1163
1164 r = sd_bus_message_read(m, "i", &family);
1165 if (r < 0)
1166 return r;
1167
1168 r = sd_bus_message_read_array(m, 'y', &a, &sz);
1169 if (r < 0)
1170 return r;
1171
1172 r = sd_bus_message_exit_container(m);
1173 if (r < 0)
1174 return r;
1175
1176 if (with_ifindex && ifindex != 0) {
1177 /* only show the global ones here */
1178 *ret = NULL;
1179 return 1;
1180 }
1181
1182 if (!IN_SET(family, AF_INET, AF_INET6)) {
1183 log_debug("Unexpected family, ignoring: %i", family);
1184
1185 *ret = NULL;
1186 return 1;
1187 }
1188
1189 if (sz != FAMILY_ADDRESS_SIZE(family)) {
1190 log_debug("Address size mismatch, ignoring.");
1191
1192 *ret = NULL;
1193 return 1;
1194 }
1195
1196 r = in_addr_to_string(family, a, &pretty);
1197 if (r < 0)
1198 return r;
1199
1200 *ret = TAKE_PTR(pretty);
1201
1202 return 1;
1203 }
1204
1205 static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1206 char ***l = userdata;
1207 int r;
1208
1209 assert(bus);
1210 assert(member);
1211 assert(m);
1212 assert(l);
1213
1214 r = sd_bus_message_enter_container(m, 'a', "(iay)");
1215 if (r < 0)
1216 return r;
1217
1218 for (;;) {
1219 char *pretty = NULL;
1220
1221 r = read_dns_server_one(m, false, &pretty);
1222 if (r < 0)
1223 return r;
1224 if (r == 0)
1225 break;
1226
1227 if (isempty(pretty))
1228 continue;
1229
1230 r = strv_consume(l, pretty);
1231 if (r < 0)
1232 return r;
1233 }
1234
1235 r = sd_bus_message_exit_container(m);
1236 if (r < 0)
1237 return r;
1238
1239 return 0;
1240 }
1241
1242 static int map_link_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1243 assert(m);
1244 assert(userdata);
1245
1246 return read_dns_server_one(m, false, userdata);
1247 }
1248
1249 static int read_domain_one(sd_bus_message *m, bool with_ifindex, char **ret) {
1250 _cleanup_free_ char *str = NULL;
1251 int ifindex, route_only, r;
1252 const char *domain;
1253
1254 assert(m);
1255 assert(ret);
1256
1257 if (with_ifindex)
1258 r = sd_bus_message_read(m, "(isb)", &ifindex, &domain, &route_only);
1259 else
1260 r = sd_bus_message_read(m, "(sb)", &domain, &route_only);
1261 if (r <= 0)
1262 return r;
1263
1264 if (with_ifindex && ifindex != 0) {
1265 /* only show the global ones here */
1266 *ret = NULL;
1267 return 1;
1268 }
1269
1270 if (route_only)
1271 str = strappend("~", domain);
1272 else
1273 str = strdup(domain);
1274 if (!str)
1275 return -ENOMEM;
1276
1277 *ret = TAKE_PTR(str);
1278
1279 return 1;
1280 }
1281
1282 static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1283 char ***l = userdata;
1284 int r;
1285
1286 assert(bus);
1287 assert(member);
1288 assert(m);
1289 assert(l);
1290
1291 r = sd_bus_message_enter_container(m, 'a', "(sb)");
1292 if (r < 0)
1293 return r;
1294
1295 for (;;) {
1296 char *pretty = NULL;
1297
1298 r = read_domain_one(m, false, &pretty);
1299 if (r < 0)
1300 return r;
1301 if (r == 0)
1302 break;
1303
1304 if (isempty(pretty))
1305 continue;
1306
1307 r = strv_consume(l, pretty);
1308 if (r < 0)
1309 return r;
1310 }
1311
1312 r = sd_bus_message_exit_container(m);
1313 if (r < 0)
1314 return r;
1315
1316 return 0;
1317 }
1318
1319 static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) {
1320 char **i;
1321
1322 printf("%sLink %i (%s)%s:",
1323 ansi_highlight(), ifindex, ifname, ansi_normal());
1324
1325 STRV_FOREACH(i, p)
1326 printf(" %s", *i);
1327
1328 printf("\n");
1329
1330 return 0;
1331 }
1332
1333 static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode mode, bool *empty_line) {
1334
1335 struct link_info {
1336 uint64_t scopes_mask;
1337 const char *llmnr;
1338 const char *mdns;
1339 const char *dnssec;
1340 char *current_dns;
1341 char **dns;
1342 char **domains;
1343 char **ntas;
1344 bool dnssec_supported;
1345 } link_info = {};
1346
1347 static const struct bus_properties_map property_map[] = {
1348 { "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) },
1349 { "DNS", "a(iay)", map_link_dns_servers, offsetof(struct link_info, dns) },
1350 { "CurrentDNSServer", "(iay)", map_link_current_dns_server, offsetof(struct link_info, current_dns) },
1351 { "Domains", "a(sb)", map_link_domains, offsetof(struct link_info, domains) },
1352 { "LLMNR", "s", NULL, offsetof(struct link_info, llmnr) },
1353 { "MulticastDNS", "s", NULL, offsetof(struct link_info, mdns) },
1354 { "DNSSEC", "s", NULL, offsetof(struct link_info, dnssec) },
1355 { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct link_info, ntas) },
1356 { "DNSSECSupported", "b", NULL, offsetof(struct link_info, dnssec_supported) },
1357 {}
1358 };
1359
1360 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1361 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1362 _cleanup_free_ char *ifi = NULL, *p = NULL;
1363 char ifname[IF_NAMESIZE] = "";
1364 char **i;
1365 int r;
1366
1367 assert(bus);
1368 assert(ifindex > 0);
1369
1370 if (!name) {
1371 if (!if_indextoname(ifindex, ifname))
1372 return log_error_errno(errno, "Failed to resolve interface name for %i: %m", ifindex);
1373
1374 name = ifname;
1375 }
1376
1377 if (asprintf(&ifi, "%i", ifindex) < 0)
1378 return log_oom();
1379
1380 r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi, &p);
1381 if (r < 0)
1382 return log_oom();
1383
1384 r = bus_map_all_properties(bus,
1385 "org.freedesktop.resolve1",
1386 p,
1387 property_map,
1388 BUS_MAP_BOOLEAN_AS_BOOL,
1389 &error,
1390 &m,
1391 &link_info);
1392 if (r < 0) {
1393 log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r));
1394 goto finish;
1395 }
1396
1397 (void) pager_open(arg_no_pager, false);
1398
1399 if (mode == STATUS_DNS) {
1400 r = status_print_strv_ifindex(ifindex, name, link_info.dns);
1401 goto finish;
1402 }
1403
1404 if (mode == STATUS_DOMAIN) {
1405 r = status_print_strv_ifindex(ifindex, name, link_info.domains);
1406 goto finish;
1407 }
1408
1409 if (mode == STATUS_NTA) {
1410 r = status_print_strv_ifindex(ifindex, name, link_info.ntas);
1411 goto finish;
1412 }
1413
1414 if (mode == STATUS_LLMNR) {
1415 printf("%sLink %i (%s)%s: %s\n",
1416 ansi_highlight(), ifindex, name, ansi_normal(),
1417 strna(link_info.llmnr));
1418
1419 r = 0;
1420 goto finish;
1421 }
1422
1423 if (mode == STATUS_MDNS) {
1424 printf("%sLink %i (%s)%s: %s\n",
1425 ansi_highlight(), ifindex, name, ansi_normal(),
1426 strna(link_info.mdns));
1427
1428 r = 0;
1429 goto finish;
1430 }
1431
1432 if (mode == STATUS_DNSSEC) {
1433 printf("%sLink %i (%s)%s: %s\n",
1434 ansi_highlight(), ifindex, name, ansi_normal(),
1435 strna(link_info.dnssec));
1436
1437 r = 0;
1438 goto finish;
1439 }
1440
1441 if (empty_line && *empty_line)
1442 fputc('\n', stdout);
1443
1444 printf("%sLink %i (%s)%s\n",
1445 ansi_highlight(), ifindex, name, ansi_normal());
1446
1447 if (link_info.scopes_mask == 0)
1448 printf(" Current Scopes: none\n");
1449 else
1450 printf(" Current Scopes:%s%s%s%s%s\n",
1451 link_info.scopes_mask & SD_RESOLVED_DNS ? " DNS" : "",
1452 link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
1453 link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
1454 link_info.scopes_mask & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "",
1455 link_info.scopes_mask & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : "");
1456
1457 printf(" LLMNR setting: %s\n"
1458 "MulticastDNS setting: %s\n"
1459 " DNSSEC setting: %s\n"
1460 " DNSSEC supported: %s\n",
1461 strna(link_info.llmnr),
1462 strna(link_info.mdns),
1463 strna(link_info.dnssec),
1464 yes_no(link_info.dnssec_supported));
1465
1466 if (link_info.current_dns)
1467 printf(" Current DNS Server: %s\n", link_info.current_dns);
1468
1469 STRV_FOREACH(i, link_info.dns) {
1470 printf(" %s %s\n",
1471 i == link_info.dns ? "DNS Servers:" : " ",
1472 *i);
1473 }
1474
1475 STRV_FOREACH(i, link_info.domains) {
1476 printf(" %s %s\n",
1477 i == link_info.domains ? "DNS Domain:" : " ",
1478 *i);
1479 }
1480
1481 STRV_FOREACH(i, link_info.ntas) {
1482 printf(" %s %s\n",
1483 i == link_info.ntas ? "DNSSEC NTA:" : " ",
1484 *i);
1485 }
1486
1487 if (empty_line)
1488 *empty_line = true;
1489
1490 r = 0;
1491
1492 finish:
1493 free(link_info.current_dns);
1494 strv_free(link_info.dns);
1495 strv_free(link_info.domains);
1496 strv_free(link_info.ntas);
1497 return r;
1498 }
1499
1500 static int map_global_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1501 char ***l = userdata;
1502 int r;
1503
1504 assert(bus);
1505 assert(member);
1506 assert(m);
1507 assert(l);
1508
1509 r = sd_bus_message_enter_container(m, 'a', "(iiay)");
1510 if (r < 0)
1511 return r;
1512
1513 for (;;) {
1514 char *pretty = NULL;
1515
1516 r = read_dns_server_one(m, true, &pretty);
1517 if (r < 0)
1518 return r;
1519 if (r == 0)
1520 break;
1521
1522 if (isempty(pretty))
1523 continue;
1524
1525 r = strv_consume(l, pretty);
1526 if (r < 0)
1527 return r;
1528 }
1529
1530 r = sd_bus_message_exit_container(m);
1531 if (r < 0)
1532 return r;
1533
1534 return 0;
1535 }
1536
1537 static int map_global_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1538 assert(m);
1539 assert(userdata);
1540
1541 return read_dns_server_one(m, true, userdata);
1542 }
1543
1544 static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1545 char ***l = userdata;
1546 int r;
1547
1548 assert(bus);
1549 assert(member);
1550 assert(m);
1551 assert(l);
1552
1553 r = sd_bus_message_enter_container(m, 'a', "(isb)");
1554 if (r < 0)
1555 return r;
1556
1557 for (;;) {
1558 char *pretty = NULL;
1559
1560 r = read_domain_one(m, true, &pretty);
1561 if (r < 0)
1562 return r;
1563 if (r == 0)
1564 break;
1565
1566 if (isempty(pretty))
1567 continue;
1568
1569 r = strv_consume(l, pretty);
1570 if (r < 0)
1571 return r;
1572 }
1573
1574 r = sd_bus_message_exit_container(m);
1575 if (r < 0)
1576 return r;
1577
1578 return 0;
1579 }
1580
1581 static int status_print_strv_global(char **p) {
1582 char **i;
1583
1584 printf("%sGlobal%s:", ansi_highlight(), ansi_normal());
1585
1586 STRV_FOREACH(i, p)
1587 printf(" %s", *i);
1588
1589 printf("\n");
1590
1591 return 0;
1592 }
1593
1594 static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
1595
1596 struct global_info {
1597 char *current_dns;
1598 char **dns;
1599 char **fallback_dns;
1600 char **domains;
1601 char **ntas;
1602 const char *llmnr;
1603 const char *mdns;
1604 const char *dnssec;
1605 bool dnssec_supported;
1606 } global_info = {};
1607
1608 static const struct bus_properties_map property_map[] = {
1609 { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
1610 { "FallbackDNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, fallback_dns) },
1611 { "CurrentDNSServer", "(iiay)", map_global_current_dns_server, offsetof(struct global_info, current_dns) },
1612 { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
1613 { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
1614 { "LLMNR", "s", NULL, offsetof(struct global_info, llmnr) },
1615 { "MulticastDNS", "s", NULL, offsetof(struct global_info, mdns) },
1616 { "DNSSEC", "s", NULL, offsetof(struct global_info, dnssec) },
1617 { "DNSSECSupported", "b", NULL, offsetof(struct global_info, dnssec_supported) },
1618 {}
1619 };
1620
1621 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1622 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1623 char **i;
1624 int r;
1625
1626 assert(bus);
1627 assert(empty_line);
1628
1629 r = bus_map_all_properties(bus,
1630 "org.freedesktop.resolve1",
1631 "/org/freedesktop/resolve1",
1632 property_map,
1633 BUS_MAP_BOOLEAN_AS_BOOL,
1634 &error,
1635 &m,
1636 &global_info);
1637 if (r < 0) {
1638 log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r));
1639 goto finish;
1640 }
1641
1642 (void) pager_open(arg_no_pager, false);
1643
1644 if (mode == STATUS_DNS) {
1645 r = status_print_strv_global(global_info.dns);
1646 goto finish;
1647 }
1648
1649 if (mode == STATUS_DOMAIN) {
1650 r = status_print_strv_global(global_info.domains);
1651 goto finish;
1652 }
1653
1654 if (mode == STATUS_NTA) {
1655 r = status_print_strv_global(global_info.ntas);
1656 goto finish;
1657 }
1658
1659 if (mode == STATUS_LLMNR) {
1660 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1661 strna(global_info.llmnr));
1662
1663 r = 0;
1664 goto finish;
1665 }
1666
1667 if (mode == STATUS_MDNS) {
1668 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1669 strna(global_info.mdns));
1670
1671 r = 0;
1672 goto finish;
1673 }
1674
1675 if (mode == STATUS_DNSSEC) {
1676 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
1677 strna(global_info.dnssec));
1678
1679 r = 0;
1680 goto finish;
1681 }
1682
1683 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1684
1685 printf(" LLMNR setting: %s\n"
1686 "MulticastDNS setting: %s\n"
1687 " DNSSEC setting: %s\n"
1688 " DNSSEC supported: %s\n",
1689 strna(global_info.llmnr),
1690 strna(global_info.mdns),
1691 strna(global_info.dnssec),
1692 yes_no(global_info.dnssec_supported));
1693
1694 if (global_info.current_dns)
1695 printf(" Current DNS Server: %s\n", global_info.current_dns);
1696
1697 STRV_FOREACH(i, global_info.dns) {
1698 printf(" %s %s\n",
1699 i == global_info.dns ? "DNS Servers:" : " ",
1700 *i);
1701 }
1702
1703 STRV_FOREACH(i, global_info.fallback_dns) {
1704 printf("%s %s\n",
1705 i == global_info.fallback_dns ? "Fallback DNS Servers:" : " ",
1706 *i);
1707 }
1708
1709 STRV_FOREACH(i, global_info.domains) {
1710 printf(" %s %s\n",
1711 i == global_info.domains ? "DNS Domain:" : " ",
1712 *i);
1713 }
1714
1715 strv_sort(global_info.ntas);
1716 STRV_FOREACH(i, global_info.ntas) {
1717 printf(" %s %s\n",
1718 i == global_info.ntas ? "DNSSEC NTA:" : " ",
1719 *i);
1720 }
1721
1722 *empty_line = true;
1723
1724 r = 0;
1725
1726 finish:
1727 free(global_info.current_dns);
1728 strv_free(global_info.dns);
1729 strv_free(global_info.fallback_dns);
1730 strv_free(global_info.domains);
1731 strv_free(global_info.ntas);
1732
1733 return r;
1734 }
1735
1736 static int status_all(sd_bus *bus, StatusMode mode) {
1737 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
1738 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
1739 sd_netlink_message *i;
1740 bool empty_line = false;
1741 int r;
1742
1743 assert(bus);
1744
1745 r = status_global(bus, mode, &empty_line);
1746 if (r < 0)
1747 return r;
1748
1749 r = sd_netlink_open(&rtnl);
1750 if (r < 0)
1751 return log_error_errno(r, "Failed to connect to netlink: %m");
1752
1753 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
1754 if (r < 0)
1755 return rtnl_log_create_error(r);
1756
1757 r = sd_netlink_message_request_dump(req, true);
1758 if (r < 0)
1759 return rtnl_log_create_error(r);
1760
1761 r = sd_netlink_call(rtnl, req, 0, &reply);
1762 if (r < 0)
1763 return log_error_errno(r, "Failed to enumerate links: %m");
1764
1765 r = 0;
1766 for (i = reply; i; i = sd_netlink_message_next(i)) {
1767 const char *name;
1768 int ifindex, q;
1769 uint16_t type;
1770
1771 q = sd_netlink_message_get_type(i, &type);
1772 if (q < 0)
1773 return rtnl_log_parse_error(q);
1774
1775 if (type != RTM_NEWLINK)
1776 continue;
1777
1778 q = sd_rtnl_message_link_get_ifindex(i, &ifindex);
1779 if (q < 0)
1780 return rtnl_log_parse_error(q);
1781
1782 if (ifindex == LOOPBACK_IFINDEX)
1783 continue;
1784
1785 q = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
1786 if (q < 0)
1787 return rtnl_log_parse_error(q);
1788
1789 q = status_ifindex(bus, ifindex, name, mode, &empty_line);
1790 if (q < 0 && r >= 0)
1791 r = q;
1792 }
1793
1794 return r;
1795 }
1796
1797 static int verb_status(int argc, char **argv, void *userdata) {
1798 sd_bus *bus = userdata;
1799 int q, r = 0;
1800
1801 if (argc > 1) {
1802 char **ifname;
1803 bool empty_line = false;
1804
1805 STRV_FOREACH(ifname, argv + 1) {
1806 int ifindex;
1807
1808 ifindex = parse_ifindex_with_warn(*ifname);
1809 if (ifindex < 0)
1810 continue;
1811
1812 q = status_ifindex(bus, ifindex, NULL, STATUS_ALL, &empty_line);
1813 if (q < 0)
1814 r = q;
1815 }
1816 } else
1817 r = status_all(bus, STATUS_ALL);
1818
1819 return r;
1820 }
1821
1822 static int log_interface_is_managed(int r, int ifindex) {
1823 char ifname[IFNAMSIZ];
1824
1825 return log_error_errno(r,
1826 "The specified interface %s is managed by systemd-networkd. Operation refused.\n"
1827 "Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.",
1828 strna(if_indextoname(ifindex, ifname)));
1829 }
1830
1831 static int verb_dns(int argc, char **argv, void *userdata) {
1832 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1833 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
1834 sd_bus *bus = userdata;
1835 int ifindex, r;
1836 char **p;
1837
1838 assert(bus);
1839
1840 if (argc <= 1)
1841 return status_all(bus, STATUS_DNS);
1842
1843 ifindex = parse_ifindex_with_warn(argv[1]);
1844 if (ifindex < 0)
1845 return ifindex;
1846
1847 if (ifindex == LOOPBACK_IFINDEX) {
1848 log_error("Interface can't be the loopback interface (lo). Sorry.");
1849 return -EINVAL;
1850 }
1851
1852 if (argc == 2)
1853 return status_ifindex(bus, ifindex, NULL, STATUS_DNS, NULL);
1854
1855 r = sd_bus_message_new_method_call(
1856 bus,
1857 &req,
1858 "org.freedesktop.resolve1",
1859 "/org/freedesktop/resolve1",
1860 "org.freedesktop.resolve1.Manager",
1861 "SetLinkDNS");
1862 if (r < 0)
1863 return bus_log_create_error(r);
1864
1865 r = sd_bus_message_append(req, "i", ifindex);
1866 if (r < 0)
1867 return bus_log_create_error(r);
1868
1869 r = sd_bus_message_open_container(req, 'a', "(iay)");
1870 if (r < 0)
1871 return bus_log_create_error(r);
1872
1873 STRV_FOREACH(p, argv + 2) {
1874 struct in_addr_data data;
1875
1876 r = in_addr_from_string_auto(*p, &data.family, &data.address);
1877 if (r < 0)
1878 return log_error_errno(r, "Failed to parse DNS server address: %s", *p);
1879
1880 r = sd_bus_message_open_container(req, 'r', "iay");
1881 if (r < 0)
1882 return bus_log_create_error(r);
1883
1884 r = sd_bus_message_append(req, "i", data.family);
1885 if (r < 0)
1886 return bus_log_create_error(r);
1887
1888 r = sd_bus_message_append_array(req, 'y', &data.address, FAMILY_ADDRESS_SIZE(data.family));
1889 if (r < 0)
1890 return bus_log_create_error(r);
1891
1892 r = sd_bus_message_close_container(req);
1893 if (r < 0)
1894 return bus_log_create_error(r);
1895 }
1896
1897 r = sd_bus_message_close_container(req);
1898 if (r < 0)
1899 return bus_log_create_error(r);
1900
1901 r = sd_bus_call(bus, req, 0, &error, NULL);
1902 if (r < 0) {
1903 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1904 return log_interface_is_managed(r, ifindex);
1905
1906 if (arg_ifindex_permissive &&
1907 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
1908 return 0;
1909
1910 return log_error_errno(r, "Failed to set DNS configuration: %s", bus_error_message(&error, r));
1911 }
1912
1913 return 0;
1914 }
1915
1916 static int verb_domain(int argc, char **argv, void *userdata) {
1917 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1918 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
1919 sd_bus *bus = userdata;
1920 int ifindex, r;
1921 char **p;
1922
1923 assert(bus);
1924
1925 if (argc <= 1)
1926 return status_all(bus, STATUS_DOMAIN);
1927
1928 ifindex = parse_ifindex_with_warn(argv[1]);
1929 if (ifindex < 0)
1930 return ifindex;
1931
1932 if (ifindex == LOOPBACK_IFINDEX) {
1933 log_error("Interface can't be the loopback interface (lo). Sorry.");
1934 return -EINVAL;
1935 }
1936
1937 if (argc == 2)
1938 return status_ifindex(bus, ifindex, NULL, STATUS_DOMAIN, NULL);
1939
1940 r = sd_bus_message_new_method_call(
1941 bus,
1942 &req,
1943 "org.freedesktop.resolve1",
1944 "/org/freedesktop/resolve1",
1945 "org.freedesktop.resolve1.Manager",
1946 "SetLinkDomains");
1947 if (r < 0)
1948 return bus_log_create_error(r);
1949
1950 r = sd_bus_message_append(req, "i", ifindex);
1951 if (r < 0)
1952 return bus_log_create_error(r);
1953
1954 r = sd_bus_message_open_container(req, 'a', "(sb)");
1955 if (r < 0)
1956 return bus_log_create_error(r);
1957
1958 STRV_FOREACH(p, argv + 2) {
1959 const char *n;
1960
1961 n = **p == '~' ? *p + 1 : *p;
1962
1963 r = dns_name_is_valid(n);
1964 if (r < 0)
1965 return log_error_errno(r, "Failed to validate specified domain %s: %m", n);
1966 if (r == 0) {
1967 log_error("Domain not valid: %s", n);
1968 return -EINVAL;
1969 }
1970
1971 r = sd_bus_message_append(req, "(sb)", n, **p == '~');
1972 if (r < 0)
1973 return bus_log_create_error(r);
1974 }
1975
1976 r = sd_bus_message_close_container(req);
1977 if (r < 0)
1978 return bus_log_create_error(r);
1979
1980 r = sd_bus_call(bus, req, 0, &error, NULL);
1981 if (r < 0) {
1982 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1983 return log_interface_is_managed(r, ifindex);
1984
1985 if (arg_ifindex_permissive &&
1986 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
1987 return 0;
1988
1989 return log_error_errno(r, "Failed to set domain configuration: %s", bus_error_message(&error, r));
1990 }
1991
1992 return 0;
1993 }
1994
1995 static int verb_llmnr(int argc, char **argv, void *userdata) {
1996 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1997 sd_bus *bus = userdata;
1998 int ifindex, r;
1999
2000 assert(bus);
2001
2002 if (argc <= 1)
2003 return status_all(bus, STATUS_LLMNR);
2004
2005 ifindex = parse_ifindex_with_warn(argv[1]);
2006 if (ifindex < 0)
2007 return ifindex;
2008
2009 if (ifindex == LOOPBACK_IFINDEX) {
2010 log_error("Interface can't be the loopback interface (lo). Sorry.");
2011 return -EINVAL;
2012 }
2013
2014 if (argc == 2)
2015 return status_ifindex(bus, ifindex, NULL, STATUS_LLMNR, NULL);
2016
2017 r = sd_bus_call_method(bus,
2018 "org.freedesktop.resolve1",
2019 "/org/freedesktop/resolve1",
2020 "org.freedesktop.resolve1.Manager",
2021 "SetLinkLLMNR",
2022 &error,
2023 NULL,
2024 "is", ifindex, argv[2]);
2025 if (r < 0) {
2026 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
2027 return log_interface_is_managed(r, ifindex);
2028
2029 if (arg_ifindex_permissive &&
2030 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2031 return 0;
2032
2033 return log_error_errno(r, "Failed to set LLMNR configuration: %s", bus_error_message(&error, r));
2034 }
2035
2036 return 0;
2037 }
2038
2039 static int verb_mdns(int argc, char **argv, void *userdata) {
2040 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2041 sd_bus *bus = userdata;
2042 int ifindex, r;
2043
2044 assert(bus);
2045
2046 if (argc <= 1)
2047 return status_all(bus, STATUS_MDNS);
2048
2049 ifindex = parse_ifindex_with_warn(argv[1]);
2050 if (ifindex < 0)
2051 return ifindex;
2052
2053 if (ifindex == LOOPBACK_IFINDEX) {
2054 log_error("Interface can't be the loopback interface (lo). Sorry.");
2055 return -EINVAL;
2056 }
2057
2058 if (argc == 2)
2059 return status_ifindex(bus, ifindex, NULL, STATUS_MDNS, NULL);
2060
2061 r = sd_bus_call_method(bus,
2062 "org.freedesktop.resolve1",
2063 "/org/freedesktop/resolve1",
2064 "org.freedesktop.resolve1.Manager",
2065 "SetLinkMulticastDNS",
2066 &error,
2067 NULL,
2068 "is", ifindex, argv[2]);
2069 if (r < 0) {
2070 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
2071 return log_interface_is_managed(r, ifindex);
2072
2073 if (arg_ifindex_permissive &&
2074 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2075 return 0;
2076
2077 return log_error_errno(r, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error, r));
2078 }
2079
2080 return 0;
2081 }
2082
2083 static int verb_dnssec(int argc, char **argv, void *userdata) {
2084 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2085 sd_bus *bus = userdata;
2086 int ifindex, r;
2087
2088 assert(bus);
2089
2090 if (argc <= 1)
2091 return status_all(bus, STATUS_DNSSEC);
2092
2093 ifindex = parse_ifindex_with_warn(argv[1]);
2094 if (ifindex < 0)
2095 return ifindex;
2096
2097 if (ifindex == LOOPBACK_IFINDEX) {
2098 log_error("Interface can't be the loopback interface (lo). Sorry.");
2099 return -EINVAL;
2100 }
2101
2102 if (argc == 2)
2103 return status_ifindex(bus, ifindex, NULL, STATUS_DNSSEC, NULL);
2104
2105 r = sd_bus_call_method(bus,
2106 "org.freedesktop.resolve1",
2107 "/org/freedesktop/resolve1",
2108 "org.freedesktop.resolve1.Manager",
2109 "SetLinkDNSSEC",
2110 &error,
2111 NULL,
2112 "is", ifindex, argv[2]);
2113 if (r < 0) {
2114 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
2115 return log_interface_is_managed(r, ifindex);
2116
2117 if (arg_ifindex_permissive &&
2118 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2119 return 0;
2120
2121 return log_error_errno(r, "Failed to set DNSSEC configuration: %s", bus_error_message(&error, r));
2122 }
2123
2124 return 0;
2125 }
2126
2127 static int verb_nta(int argc, char **argv, void *userdata) {
2128 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2129 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
2130 sd_bus *bus = userdata;
2131 int ifindex, i, r;
2132
2133 assert(bus);
2134
2135 if (argc <= 1)
2136 return status_all(bus, STATUS_NTA);
2137
2138 ifindex = parse_ifindex_with_warn(argv[1]);
2139 if (ifindex < 0)
2140 return ifindex;
2141
2142 if (ifindex == LOOPBACK_IFINDEX) {
2143 log_error("Interface can't be the loopback interface (lo). Sorry.");
2144 return -EINVAL;
2145 }
2146
2147 if (argc == 2)
2148 return status_ifindex(bus, ifindex, NULL, STATUS_NTA, NULL);
2149
2150 for (i = 2; i < argc; i++) {
2151 r = dns_name_is_valid(argv[i]);
2152 if (r < 0)
2153 return log_error_errno(r, "Failed to validate specified domain %s: %m", argv[i]);
2154 if (r == 0) {
2155 log_error("Domain not valid: %s", argv[i]);
2156 return -EINVAL;
2157 }
2158 }
2159
2160 r = sd_bus_message_new_method_call(
2161 bus,
2162 &req,
2163 "org.freedesktop.resolve1",
2164 "/org/freedesktop/resolve1",
2165 "org.freedesktop.resolve1.Manager",
2166 "SetLinkDNSSECNegativeTrustAnchors");
2167 if (r < 0)
2168 return bus_log_create_error(r);
2169
2170 r = sd_bus_message_append(req, "i", ifindex);
2171 if (r < 0)
2172 return bus_log_create_error(r);
2173
2174 r = sd_bus_message_append_strv(req, argv + 2);
2175 if (r < 0)
2176 return bus_log_create_error(r);
2177
2178 r = sd_bus_call(bus, req, 0, &error, NULL);
2179 if (r < 0) {
2180 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
2181 return log_interface_is_managed(r, ifindex);
2182
2183 if (arg_ifindex_permissive &&
2184 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2185 return 0;
2186
2187 return log_error_errno(r, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error, r));
2188 }
2189
2190 return 0;
2191 }
2192
2193 static int verb_revert_link(int argc, char **argv, void *userdata) {
2194 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2195 sd_bus *bus = userdata;
2196 int ifindex, r;
2197
2198 assert(bus);
2199
2200 ifindex = parse_ifindex_with_warn(argv[1]);
2201 if (ifindex < 0)
2202 return ifindex;
2203
2204 if (ifindex == LOOPBACK_IFINDEX) {
2205 log_error("Interface can't be the loopback interface (lo). Sorry.");
2206 return -EINVAL;
2207 }
2208
2209 r = sd_bus_call_method(bus,
2210 "org.freedesktop.resolve1",
2211 "/org/freedesktop/resolve1",
2212 "org.freedesktop.resolve1.Manager",
2213 "RevertLink",
2214 &error,
2215 NULL,
2216 "i", ifindex);
2217 if (r < 0) {
2218 if (arg_ifindex_permissive &&
2219 sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
2220 return 0;
2221
2222 return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
2223 }
2224
2225 return 0;
2226 }
2227
2228 static void help_protocol_types(void) {
2229 if (arg_legend)
2230 puts("Known protocol types:");
2231 puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6\nmdns\nmdns-ipv4\nmdns-ipv6");
2232 }
2233
2234 static void help_dns_types(void) {
2235 const char *t;
2236 int i;
2237
2238 if (arg_legend)
2239 puts("Known DNS RR types:");
2240 for (i = 0; i < _DNS_TYPE_MAX; i++) {
2241 t = dns_type_to_string(i);
2242 if (t)
2243 puts(t);
2244 }
2245 }
2246
2247 static void help_dns_classes(void) {
2248 const char *t;
2249 int i;
2250
2251 if (arg_legend)
2252 puts("Known DNS RR classes:");
2253 for (i = 0; i < _DNS_CLASS_MAX; i++) {
2254 t = dns_class_to_string(i);
2255 if (t)
2256 puts(t);
2257 }
2258 }
2259
2260 static void compat_help(void) {
2261 printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
2262 "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
2263 "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
2264 "%1$s [OPTIONS...] --statistics\n"
2265 "%1$s [OPTIONS...] --reset-statistics\n"
2266 "\n"
2267 "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n"
2268 " -h --help Show this help\n"
2269 " --version Show package version\n"
2270 " --no-pager Do not pipe output into a pager\n"
2271 " -4 Resolve IPv4 addresses\n"
2272 " -6 Resolve IPv6 addresses\n"
2273 " -i --interface=INTERFACE Look on interface\n"
2274 " -p --protocol=PROTO|help Look via protocol\n"
2275 " -t --type=TYPE|help Query RR with DNS type\n"
2276 " -c --class=CLASS|help Query RR with DNS class\n"
2277 " --service Resolve service (SRV)\n"
2278 " --service-address=BOOL Resolve address for services (default: yes)\n"
2279 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
2280 " --openpgp Query OpenPGP public key\n"
2281 " --tlsa Query TLS public key\n"
2282 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
2283 " --search=BOOL Use search domains for single-label names\n"
2284 " (default: yes)\n"
2285 " --raw[=payload|packet] Dump the answer as binary data\n"
2286 " --legend=BOOL Print headers and additional info (default: yes)\n"
2287 " --statistics Show resolver statistics\n"
2288 " --reset-statistics Reset resolver statistics\n"
2289 " --status Show link and server status\n"
2290 " --flush-caches Flush all local DNS caches\n"
2291 " --reset-server-features\n"
2292 " Forget learnt DNS server feature levels\n"
2293 " --set-dns=SERVER Set per-interface DNS server address\n"
2294 " --set-domain=DOMAIN Set per-interface search domain\n"
2295 " --set-llmnr=MODE Set per-interface LLMNR mode\n"
2296 " --set-mdns=MODE Set per-interface MulticastDNS mode\n"
2297 " --set-dnssec=MODE Set per-interface DNSSEC mode\n"
2298 " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
2299 " --revert Revert per-interface configuration\n"
2300 , program_invocation_short_name);
2301 }
2302
2303 static void native_help(void) {
2304 printf("%1$s [OPTIONS...] {COMMAND} ...\n"
2305 "\n"
2306 "Send control commands to the network name resolution manager, or\n"
2307 "resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n"
2308 "\n"
2309 " -h --help Show this help\n"
2310 " --version Show package version\n"
2311 " --no-pager Do not pipe output into a pager\n"
2312 " -4 Resolve IPv4 addresses\n"
2313 " -6 Resolve IPv6 addresses\n"
2314 " -i --interface=INTERFACE Look on interface\n"
2315 " -p --protocol=PROTO|help Look via protocol\n"
2316 " -t --type=TYPE|help Query RR with DNS type\n"
2317 " -c --class=CLASS|help Query RR with DNS class\n"
2318 " --service-address=BOOL Resolve address for services (default: yes)\n"
2319 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
2320 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
2321 " --search=BOOL Use search domains for single-label names\n"
2322 " (default: yes)\n"
2323 " --raw[=payload|packet] Dump the answer as binary data\n"
2324 " --legend=BOOL Print headers and additional info (default: yes)\n"
2325 "\n"
2326 "Commands:\n"
2327 " query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses\n"
2328 " service [[NAME] TYPE] DOMAIN Resolve service (SRV)\n"
2329 " openpgp EMAIL@DOMAIN... Query OpenPGP public key\n"
2330 " tlsa DOMAIN[:PORT]... Query TLS public key\n"
2331 " status [LINK...] Show link and server status\n"
2332 " statistics Show resolver statistics\n"
2333 " reset-statistics Reset resolver statistics\n"
2334 " flush-caches Flush all local DNS caches\n"
2335 " reset-server-features Forget learnt DNS server feature levels\n"
2336 " dns [LINK [SERVER...]] Get/set per-interface DNS server address\n"
2337 " domain [LINK [DOMAIN...]] Get/set per-interface search domain\n"
2338 " llmnr [LINK [MODE]] Get/set per-interface LLMNR mode\n"
2339 " mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode\n"
2340 " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n"
2341 " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n"
2342 " revert LINK Revert per-interface configuration\n"
2343 , program_invocation_short_name);
2344 }
2345
2346 static int verb_help(int argc, char **argv, void *userdata) {
2347 native_help();
2348 return 0;
2349 }
2350
2351 static int compat_parse_argv(int argc, char *argv[]) {
2352 enum {
2353 ARG_VERSION = 0x100,
2354 ARG_LEGEND,
2355 ARG_SERVICE,
2356 ARG_CNAME,
2357 ARG_SERVICE_ADDRESS,
2358 ARG_SERVICE_TXT,
2359 ARG_OPENPGP,
2360 ARG_TLSA,
2361 ARG_RAW,
2362 ARG_SEARCH,
2363 ARG_STATISTICS,
2364 ARG_RESET_STATISTICS,
2365 ARG_STATUS,
2366 ARG_FLUSH_CACHES,
2367 ARG_RESET_SERVER_FEATURES,
2368 ARG_NO_PAGER,
2369 ARG_SET_DNS,
2370 ARG_SET_DOMAIN,
2371 ARG_SET_LLMNR,
2372 ARG_SET_MDNS,
2373 ARG_SET_DNSSEC,
2374 ARG_SET_NTA,
2375 ARG_REVERT_LINK,
2376 };
2377
2378 static const struct option options[] = {
2379 { "help", no_argument, NULL, 'h' },
2380 { "version", no_argument, NULL, ARG_VERSION },
2381 { "type", required_argument, NULL, 't' },
2382 { "class", required_argument, NULL, 'c' },
2383 { "legend", required_argument, NULL, ARG_LEGEND },
2384 { "interface", required_argument, NULL, 'i' },
2385 { "protocol", required_argument, NULL, 'p' },
2386 { "cname", required_argument, NULL, ARG_CNAME },
2387 { "service", no_argument, NULL, ARG_SERVICE },
2388 { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
2389 { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
2390 { "openpgp", no_argument, NULL, ARG_OPENPGP },
2391 { "tlsa", optional_argument, NULL, ARG_TLSA },
2392 { "raw", optional_argument, NULL, ARG_RAW },
2393 { "search", required_argument, NULL, ARG_SEARCH },
2394 { "statistics", no_argument, NULL, ARG_STATISTICS, },
2395 { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
2396 { "status", no_argument, NULL, ARG_STATUS },
2397 { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES },
2398 { "reset-server-features", no_argument, NULL, ARG_RESET_SERVER_FEATURES },
2399 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
2400 { "set-dns", required_argument, NULL, ARG_SET_DNS },
2401 { "set-domain", required_argument, NULL, ARG_SET_DOMAIN },
2402 { "set-llmnr", required_argument, NULL, ARG_SET_LLMNR },
2403 { "set-mdns", required_argument, NULL, ARG_SET_MDNS },
2404 { "set-dnssec", required_argument, NULL, ARG_SET_DNSSEC },
2405 { "set-nta", required_argument, NULL, ARG_SET_NTA },
2406 { "revert", no_argument, NULL, ARG_REVERT_LINK },
2407 {}
2408 };
2409
2410 int c, r;
2411
2412 assert(argc >= 0);
2413 assert(argv);
2414
2415 while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
2416 switch(c) {
2417
2418 case 'h':
2419 compat_help();
2420 return 0; /* done */;
2421
2422 case ARG_VERSION:
2423 return version();
2424
2425 case '4':
2426 arg_family = AF_INET;
2427 break;
2428
2429 case '6':
2430 arg_family = AF_INET6;
2431 break;
2432
2433 case 'i':
2434 r = parse_ifindex_with_warn(optarg);
2435 if (r < 0)
2436 return r;
2437
2438 arg_ifname = optarg;
2439 arg_ifindex = r;
2440 break;
2441
2442 case 't':
2443 if (streq(optarg, "help")) {
2444 help_dns_types();
2445 return 0;
2446 }
2447
2448 r = dns_type_from_string(optarg);
2449 if (r < 0) {
2450 log_error("Failed to parse RR record type %s", optarg);
2451 return r;
2452 }
2453 arg_type = (uint16_t) r;
2454 assert((int) arg_type == r);
2455
2456 arg_mode = MODE_RESOLVE_RECORD;
2457 break;
2458
2459 case 'c':
2460 if (streq(optarg, "help")) {
2461 help_dns_classes();
2462 return 0;
2463 }
2464
2465 r = dns_class_from_string(optarg);
2466 if (r < 0) {
2467 log_error("Failed to parse RR record class %s", optarg);
2468 return r;
2469 }
2470 arg_class = (uint16_t) r;
2471 assert((int) arg_class == r);
2472
2473 break;
2474
2475 case ARG_LEGEND:
2476 r = parse_boolean(optarg);
2477 if (r < 0)
2478 return log_error_errno(r, "Failed to parse --legend= argument");
2479
2480 arg_legend = r;
2481 break;
2482
2483 case 'p':
2484 if (streq(optarg, "help")) {
2485 help_protocol_types();
2486 return 0;
2487 } else if (streq(optarg, "dns"))
2488 arg_flags |= SD_RESOLVED_DNS;
2489 else if (streq(optarg, "llmnr"))
2490 arg_flags |= SD_RESOLVED_LLMNR;
2491 else if (streq(optarg, "llmnr-ipv4"))
2492 arg_flags |= SD_RESOLVED_LLMNR_IPV4;
2493 else if (streq(optarg, "llmnr-ipv6"))
2494 arg_flags |= SD_RESOLVED_LLMNR_IPV6;
2495 else if (streq(optarg, "mdns"))
2496 arg_flags |= SD_RESOLVED_MDNS;
2497 else if (streq(optarg, "mdns-ipv4"))
2498 arg_flags |= SD_RESOLVED_MDNS_IPV4;
2499 else if (streq(optarg, "mdns-ipv6"))
2500 arg_flags |= SD_RESOLVED_MDNS_IPV6;
2501 else {
2502 log_error("Unknown protocol specifier: %s", optarg);
2503 return -EINVAL;
2504 }
2505
2506 break;
2507
2508 case ARG_SERVICE:
2509 arg_mode = MODE_RESOLVE_SERVICE;
2510 break;
2511
2512 case ARG_OPENPGP:
2513 arg_mode = MODE_RESOLVE_OPENPGP;
2514 break;
2515
2516 case ARG_TLSA:
2517 arg_mode = MODE_RESOLVE_TLSA;
2518 if (!optarg || service_family_is_valid(optarg))
2519 arg_service_family = optarg;
2520 else {
2521 log_error("Unknown service family \"%s\".", optarg);
2522 return -EINVAL;
2523 }
2524 break;
2525
2526 case ARG_RAW:
2527 if (on_tty()) {
2528 log_error("Refusing to write binary data to tty.");
2529 return -ENOTTY;
2530 }
2531
2532 if (optarg == NULL || streq(optarg, "payload"))
2533 arg_raw = RAW_PAYLOAD;
2534 else if (streq(optarg, "packet"))
2535 arg_raw = RAW_PACKET;
2536 else {
2537 log_error("Unknown --raw specifier \"%s\".", optarg);
2538 return -EINVAL;
2539 }
2540
2541 arg_legend = false;
2542 break;
2543
2544 case ARG_CNAME:
2545 r = parse_boolean(optarg);
2546 if (r < 0)
2547 return log_error_errno(r, "Failed to parse --cname= argument.");
2548 SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
2549 break;
2550
2551 case ARG_SERVICE_ADDRESS:
2552 r = parse_boolean(optarg);
2553 if (r < 0)
2554 return log_error_errno(r, "Failed to parse --service-address= argument.");
2555 SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
2556 break;
2557
2558 case ARG_SERVICE_TXT:
2559 r = parse_boolean(optarg);
2560 if (r < 0)
2561 return log_error_errno(r, "Failed to parse --service-txt= argument.");
2562 SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
2563 break;
2564
2565 case ARG_SEARCH:
2566 r = parse_boolean(optarg);
2567 if (r < 0)
2568 return log_error_errno(r, "Failed to parse --search argument.");
2569 SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
2570 break;
2571
2572 case ARG_STATISTICS:
2573 arg_mode = MODE_STATISTICS;
2574 break;
2575
2576 case ARG_RESET_STATISTICS:
2577 arg_mode = MODE_RESET_STATISTICS;
2578 break;
2579
2580 case ARG_FLUSH_CACHES:
2581 arg_mode = MODE_FLUSH_CACHES;
2582 break;
2583
2584 case ARG_RESET_SERVER_FEATURES:
2585 arg_mode = MODE_RESET_SERVER_FEATURES;
2586 break;
2587
2588 case ARG_STATUS:
2589 arg_mode = MODE_STATUS;
2590 break;
2591
2592 case ARG_NO_PAGER:
2593 arg_no_pager = true;
2594 break;
2595
2596 case ARG_SET_DNS:
2597 r = strv_extend(&arg_set_dns, optarg);
2598 if (r < 0)
2599 return log_oom();
2600
2601 arg_mode = MODE_SET_LINK;
2602 break;
2603
2604 case ARG_SET_DOMAIN:
2605 r = strv_extend(&arg_set_domain, optarg);
2606 if (r < 0)
2607 return log_oom();
2608
2609 arg_mode = MODE_SET_LINK;
2610 break;
2611
2612 case ARG_SET_LLMNR:
2613 arg_set_llmnr = optarg;
2614 arg_mode = MODE_SET_LINK;
2615 break;
2616
2617 case ARG_SET_MDNS:
2618 arg_set_mdns = optarg;
2619 arg_mode = MODE_SET_LINK;
2620 break;
2621
2622 case ARG_SET_DNSSEC:
2623 arg_set_dnssec = optarg;
2624 arg_mode = MODE_SET_LINK;
2625 break;
2626
2627 case ARG_SET_NTA:
2628 r = strv_extend(&arg_set_nta, optarg);
2629 if (r < 0)
2630 return log_oom();
2631
2632 arg_mode = MODE_SET_LINK;
2633 break;
2634
2635 case ARG_REVERT_LINK:
2636 arg_mode = MODE_REVERT_LINK;
2637 break;
2638
2639 case '?':
2640 return -EINVAL;
2641
2642 default:
2643 assert_not_reached("Unhandled option");
2644 }
2645
2646 if (arg_type == 0 && arg_class != 0) {
2647 log_error("--class= may only be used in conjunction with --type=.");
2648 return -EINVAL;
2649 }
2650
2651 if (arg_type != 0 && arg_mode == MODE_RESOLVE_SERVICE) {
2652 log_error("--service and --type= may not be combined.");
2653 return -EINVAL;
2654 }
2655
2656 if (arg_type != 0 && arg_class == 0)
2657 arg_class = DNS_CLASS_IN;
2658
2659 if (arg_class != 0 && arg_type == 0)
2660 arg_type = DNS_TYPE_A;
2661
2662 if (IN_SET(arg_mode, MODE_SET_LINK, MODE_REVERT_LINK)) {
2663
2664 if (arg_ifindex <= 0) {
2665 log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, --set-nta= and --revert require --interface=.");
2666 return -EINVAL;
2667 }
2668
2669 if (arg_ifindex == LOOPBACK_IFINDEX) {
2670 log_error("Interface can't be the loopback interface (lo). Sorry.");
2671 return -EINVAL;
2672 }
2673 }
2674
2675 return 1 /* work to do */;
2676 }
2677
2678 static int native_parse_argv(int argc, char *argv[]) {
2679 enum {
2680 ARG_VERSION = 0x100,
2681 ARG_LEGEND,
2682 ARG_CNAME,
2683 ARG_SERVICE_ADDRESS,
2684 ARG_SERVICE_TXT,
2685 ARG_RAW,
2686 ARG_SEARCH,
2687 ARG_NO_PAGER,
2688 };
2689
2690 static const struct option options[] = {
2691 { "help", no_argument, NULL, 'h' },
2692 { "version", no_argument, NULL, ARG_VERSION },
2693 { "type", required_argument, NULL, 't' },
2694 { "class", required_argument, NULL, 'c' },
2695 { "legend", required_argument, NULL, ARG_LEGEND },
2696 { "interface", required_argument, NULL, 'i' },
2697 { "protocol", required_argument, NULL, 'p' },
2698 { "cname", required_argument, NULL, ARG_CNAME },
2699 { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
2700 { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
2701 { "raw", optional_argument, NULL, ARG_RAW },
2702 { "search", required_argument, NULL, ARG_SEARCH },
2703 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
2704 {}
2705 };
2706
2707 int c, r;
2708
2709 assert(argc >= 0);
2710 assert(argv);
2711
2712 while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
2713 switch(c) {
2714
2715 case 'h':
2716 native_help();
2717 return 0; /* done */;
2718
2719 case ARG_VERSION:
2720 return version();
2721
2722 case '4':
2723 arg_family = AF_INET;
2724 break;
2725
2726 case '6':
2727 arg_family = AF_INET6;
2728 break;
2729
2730 case 'i':
2731 r = parse_ifindex_with_warn(optarg);
2732 if (r < 0)
2733 return r;
2734
2735 arg_ifindex = r;
2736 break;
2737
2738 case 't':
2739 if (streq(optarg, "help")) {
2740 help_dns_types();
2741 return 0;
2742 }
2743
2744 r = dns_type_from_string(optarg);
2745 if (r < 0) {
2746 log_error("Failed to parse RR record type %s", optarg);
2747 return r;
2748 }
2749 arg_type = (uint16_t) r;
2750 assert((int) arg_type == r);
2751
2752 break;
2753
2754 case 'c':
2755 if (streq(optarg, "help")) {
2756 help_dns_classes();
2757 return 0;
2758 }
2759
2760 r = dns_class_from_string(optarg);
2761 if (r < 0) {
2762 log_error("Failed to parse RR record class %s", optarg);
2763 return r;
2764 }
2765 arg_class = (uint16_t) r;
2766 assert((int) arg_class == r);
2767
2768 break;
2769
2770 case ARG_LEGEND:
2771 r = parse_boolean(optarg);
2772 if (r < 0)
2773 return log_error_errno(r, "Failed to parse --legend= argument");
2774
2775 arg_legend = r;
2776 break;
2777
2778 case 'p':
2779 if (streq(optarg, "help")) {
2780 help_protocol_types();
2781 return 0;
2782 } else if (streq(optarg, "dns"))
2783 arg_flags |= SD_RESOLVED_DNS;
2784 else if (streq(optarg, "llmnr"))
2785 arg_flags |= SD_RESOLVED_LLMNR;
2786 else if (streq(optarg, "llmnr-ipv4"))
2787 arg_flags |= SD_RESOLVED_LLMNR_IPV4;
2788 else if (streq(optarg, "llmnr-ipv6"))
2789 arg_flags |= SD_RESOLVED_LLMNR_IPV6;
2790 else if (streq(optarg, "mdns"))
2791 arg_flags |= SD_RESOLVED_MDNS;
2792 else if (streq(optarg, "mdns-ipv4"))
2793 arg_flags |= SD_RESOLVED_MDNS_IPV4;
2794 else if (streq(optarg, "mdns-ipv6"))
2795 arg_flags |= SD_RESOLVED_MDNS_IPV6;
2796 else {
2797 log_error("Unknown protocol specifier: %s", optarg);
2798 return -EINVAL;
2799 }
2800
2801 break;
2802
2803 case ARG_RAW:
2804 if (on_tty()) {
2805 log_error("Refusing to write binary data to tty.");
2806 return -ENOTTY;
2807 }
2808
2809 if (optarg == NULL || streq(optarg, "payload"))
2810 arg_raw = RAW_PAYLOAD;
2811 else if (streq(optarg, "packet"))
2812 arg_raw = RAW_PACKET;
2813 else {
2814 log_error("Unknown --raw specifier \"%s\".", optarg);
2815 return -EINVAL;
2816 }
2817
2818 arg_legend = false;
2819 break;
2820
2821 case ARG_CNAME:
2822 r = parse_boolean(optarg);
2823 if (r < 0)
2824 return log_error_errno(r, "Failed to parse --cname= argument.");
2825 SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
2826 break;
2827
2828 case ARG_SERVICE_ADDRESS:
2829 r = parse_boolean(optarg);
2830 if (r < 0)
2831 return log_error_errno(r, "Failed to parse --service-address= argument.");
2832 SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
2833 break;
2834
2835 case ARG_SERVICE_TXT:
2836 r = parse_boolean(optarg);
2837 if (r < 0)
2838 return log_error_errno(r, "Failed to parse --service-txt= argument.");
2839 SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
2840 break;
2841
2842 case ARG_SEARCH:
2843 r = parse_boolean(optarg);
2844 if (r < 0)
2845 return log_error_errno(r, "Failed to parse --search argument.");
2846 SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
2847 break;
2848
2849 case ARG_NO_PAGER:
2850 arg_no_pager = true;
2851 break;
2852
2853 case '?':
2854 return -EINVAL;
2855
2856 default:
2857 assert_not_reached("Unhandled option");
2858 }
2859
2860 if (arg_type == 0 && arg_class != 0) {
2861 log_error("--class= may only be used in conjunction with --type=.");
2862 return -EINVAL;
2863 }
2864
2865 if (arg_type != 0 && arg_class == 0)
2866 arg_class = DNS_CLASS_IN;
2867
2868 if (arg_class != 0 && arg_type == 0)
2869 arg_type = DNS_TYPE_A;
2870
2871 return 1 /* work to do */;
2872 }
2873
2874 static int native_main(int argc, char *argv[], sd_bus *bus) {
2875
2876 static const Verb verbs[] = {
2877 { "help", VERB_ANY, VERB_ANY, 0, verb_help },
2878 { "status", VERB_ANY, VERB_ANY, VERB_DEFAULT, verb_status },
2879 { "query", 2, VERB_ANY, 0, verb_query },
2880 { "service", 2, 4, 0, verb_service },
2881 { "openpgp", 2, VERB_ANY, 0, verb_openpgp },
2882 { "tlsa", 2, VERB_ANY, 0, verb_tlsa },
2883 { "statistics", VERB_ANY, 1, 0, show_statistics },
2884 { "reset-statistics", VERB_ANY, 1, 0, reset_statistics },
2885 { "flush-caches", VERB_ANY, 1, 0, flush_caches },
2886 { "reset-server-features", VERB_ANY, 1, 0, reset_server_features },
2887 { "dns", VERB_ANY, VERB_ANY, 0, verb_dns },
2888 { "domain", VERB_ANY, VERB_ANY, 0, verb_domain },
2889 { "llmnr", VERB_ANY, 3, 0, verb_llmnr },
2890 { "mdns", VERB_ANY, 3, 0, verb_mdns },
2891 { "dnssec", VERB_ANY, 3, 0, verb_dnssec },
2892 { "nta", VERB_ANY, VERB_ANY, 0, verb_nta },
2893 { "revert", 2, 2, 0, verb_revert_link },
2894 {}
2895 };
2896
2897 return dispatch_verb(argc, argv, verbs, bus);
2898 }
2899
2900 static int translate(const char *verb, const char *single_arg, size_t num_args, char **args, sd_bus *bus) {
2901 char **fake, **p;
2902 size_t num, i;
2903
2904 assert(verb);
2905 assert(num_args == 0 || args);
2906
2907 num = !!single_arg + num_args + 1;
2908
2909 p = fake = newa0(char *, num + 1);
2910 *p++ = (char *) verb;
2911 if (single_arg)
2912 *p++ = (char *) single_arg;
2913 for (i = 0; i < num_args; i++)
2914 *p++ = args[i];
2915
2916 optind = 0;
2917 return native_main((int) num, fake, bus);
2918 }
2919
2920 static int compat_main(int argc, char *argv[], sd_bus *bus) {
2921 int r = 0;
2922
2923 switch (arg_mode) {
2924 case MODE_RESOLVE_HOST:
2925 case MODE_RESOLVE_RECORD:
2926 return translate("query", NULL, argc - optind, argv + optind, bus);
2927
2928 case MODE_RESOLVE_SERVICE:
2929 return translate("service", NULL, argc - optind, argv + optind, bus);
2930
2931 case MODE_RESOLVE_OPENPGP:
2932 return translate("openpgp", NULL, argc - optind, argv + optind, bus);
2933
2934 case MODE_RESOLVE_TLSA:
2935 return translate("tlsa", arg_service_family, argc - optind, argv + optind, bus);
2936
2937 case MODE_STATISTICS:
2938 return translate("statistics", NULL, 0, NULL, bus);
2939
2940 case MODE_RESET_STATISTICS:
2941 return translate("reset-statistics", NULL, 0, NULL, bus);
2942
2943 case MODE_FLUSH_CACHES:
2944 return translate("flush-caches", NULL, 0, NULL, bus);
2945
2946 case MODE_RESET_SERVER_FEATURES:
2947 return translate("reset-server-features", NULL, 0, NULL, bus);
2948
2949 case MODE_STATUS:
2950 return translate("status", NULL, argc - optind, argv + optind, bus);
2951
2952 case MODE_SET_LINK:
2953 if (arg_set_dns) {
2954 r = translate("dns", arg_ifname, strv_length(arg_set_dns), arg_set_dns, bus);
2955 if (r < 0)
2956 return r;
2957 }
2958
2959 if (arg_set_domain) {
2960 r = translate("domain", arg_ifname, strv_length(arg_set_domain), arg_set_domain, bus);
2961 if (r < 0)
2962 return r;
2963 }
2964
2965 if (arg_set_nta) {
2966 r = translate("nta", arg_ifname, strv_length(arg_set_nta), arg_set_nta, bus);
2967 if (r < 0)
2968 return r;
2969 }
2970
2971 if (arg_set_llmnr) {
2972 r = translate("llmnr", arg_ifname, 1, (char **) &arg_set_llmnr, bus);
2973 if (r < 0)
2974 return r;
2975 }
2976
2977 if (arg_set_mdns) {
2978 r = translate("mdns", arg_ifname, 1, (char **) &arg_set_mdns, bus);
2979 if (r < 0)
2980 return r;
2981 }
2982
2983 if (arg_set_dnssec) {
2984 r = translate("dnssec", arg_ifname, 1, (char **) &arg_set_dnssec, bus);
2985 if (r < 0)
2986 return r;
2987 }
2988
2989 return r;
2990
2991 case MODE_REVERT_LINK:
2992 return translate("revert", arg_ifname, 0, NULL, bus);
2993
2994 case _MODE_INVALID:
2995 assert_not_reached("invalid mode");
2996 }
2997
2998 return 0;
2999 }
3000
3001 int main(int argc, char **argv) {
3002 sd_bus *bus = NULL;
3003 int r;
3004
3005 setlocale(LC_ALL, "");
3006 log_parse_environment();
3007 log_open();
3008
3009 if (streq(program_invocation_short_name, "resolvconf"))
3010 r = resolvconf_parse_argv(argc, argv);
3011 else if (streq(program_invocation_short_name, "systemd-resolve"))
3012 r = compat_parse_argv(argc, argv);
3013 else
3014 r = native_parse_argv(argc, argv);
3015 if (r <= 0)
3016 goto finish;
3017
3018 r = sd_bus_open_system(&bus);
3019 if (r < 0) {
3020 log_error_errno(r, "sd_bus_open_system: %m");
3021 goto finish;
3022 }
3023
3024 if (streq(program_invocation_short_name, "systemd-resolve"))
3025 r = compat_main(argc, argv, bus);
3026 else
3027 r = native_main(argc, argv, bus);
3028
3029 finish:
3030 /* make sure we terminate the bus connection first, and then close the
3031 * pager, see issue #3543 for the details. */
3032 sd_bus_flush_close_unref(bus);
3033 pager_close();
3034
3035 strv_free(arg_set_dns);
3036 strv_free(arg_set_domain);
3037 strv_free(arg_set_nta);
3038
3039 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
3040 }