]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolve-tool.c
resolved: fix confusion with generic data in unparsable packets
[thirdparty/systemd.git] / src / resolve / resolve-tool.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 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <getopt.h>
22 #include <net/if.h>
23
24 #include "sd-bus.h"
25 #include "sd-netlink.h"
26
27 #include "af-list.h"
28 #include "alloc-util.h"
29 #include "bus-common-errors.h"
30 #include "bus-error.h"
31 #include "bus-util.h"
32 #include "dns-domain.h"
33 #include "escape.h"
34 #include "gcrypt-util.h"
35 #include "in-addr-util.h"
36 #include "netlink-util.h"
37 #include "pager.h"
38 #include "parse-util.h"
39 #include "resolved-def.h"
40 #include "resolved-dns-packet.h"
41 #include "strv.h"
42 #include "terminal-util.h"
43
44 #define DNS_CALL_TIMEOUT_USEC (90*USEC_PER_SEC)
45
46 static int arg_family = AF_UNSPEC;
47 static int arg_ifindex = 0;
48 static uint16_t arg_type = 0;
49 static uint16_t arg_class = 0;
50 static bool arg_legend = true;
51 static uint64_t arg_flags = 0;
52 static bool arg_no_pager = false;
53
54 typedef enum ServiceFamily {
55 SERVICE_FAMILY_TCP,
56 SERVICE_FAMILY_UDP,
57 SERVICE_FAMILY_SCTP,
58 _SERVICE_FAMILY_INVALID = -1,
59 } ServiceFamily;
60 static ServiceFamily arg_service_family = SERVICE_FAMILY_TCP;
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 static enum {
70 MODE_RESOLVE_HOST,
71 MODE_RESOLVE_RECORD,
72 MODE_RESOLVE_SERVICE,
73 MODE_RESOLVE_OPENPGP,
74 MODE_RESOLVE_TLSA,
75 MODE_STATISTICS,
76 MODE_RESET_STATISTICS,
77 MODE_FLUSH_CACHES,
78 MODE_RESET_SERVER_FEATURES,
79 MODE_STATUS,
80 MODE_SET_LINK,
81 MODE_REVERT_LINK,
82 } arg_mode = MODE_RESOLVE_HOST;
83
84 static struct in_addr_data *arg_set_dns = NULL;
85 static size_t arg_n_set_dns = 0;
86 static char **arg_set_domain = NULL;
87 static char *arg_set_llmnr = NULL;
88 static char *arg_set_mdns = NULL;
89 static char *arg_set_dnssec = NULL;
90 static char **arg_set_nta = NULL;
91
92 static ServiceFamily service_family_from_string(const char *s) {
93 if (s == NULL || streq(s, "tcp"))
94 return SERVICE_FAMILY_TCP;
95 if (streq(s, "udp"))
96 return SERVICE_FAMILY_UDP;
97 if (streq(s, "sctp"))
98 return SERVICE_FAMILY_SCTP;
99 return _SERVICE_FAMILY_INVALID;
100 }
101
102 static const char* service_family_to_string(ServiceFamily service) {
103 switch(service) {
104 case SERVICE_FAMILY_TCP:
105 return "_tcp";
106 case SERVICE_FAMILY_UDP:
107 return "_udp";
108 case SERVICE_FAMILY_SCTP:
109 return "_sctp";
110 default:
111 assert_not_reached("invalid service");
112 }
113 }
114
115 static void print_source(uint64_t flags, usec_t rtt) {
116 char rtt_str[FORMAT_TIMESTAMP_MAX];
117
118 if (!arg_legend)
119 return;
120
121 if (flags == 0)
122 return;
123
124 fputs("\n-- Information acquired via", stdout);
125
126 if (flags != 0)
127 printf(" protocol%s%s%s%s%s",
128 flags & SD_RESOLVED_DNS ? " DNS" :"",
129 flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
130 flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
131 flags & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "",
132 flags & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : "");
133
134 assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
135
136 printf(" in %s", rtt_str);
137
138 fputc('.', stdout);
139 fputc('\n', stdout);
140
141 printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
142 }
143
144 static int resolve_host(sd_bus *bus, const char *name) {
145
146 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
147 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
148 const char *canonical = NULL;
149 char ifname[IF_NAMESIZE] = "";
150 unsigned c = 0;
151 int r;
152 uint64_t flags;
153 usec_t ts;
154
155 assert(name);
156
157 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
158 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
159
160 log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
161
162 r = sd_bus_message_new_method_call(
163 bus,
164 &req,
165 "org.freedesktop.resolve1",
166 "/org/freedesktop/resolve1",
167 "org.freedesktop.resolve1.Manager",
168 "ResolveHostname");
169 if (r < 0)
170 return bus_log_create_error(r);
171
172 r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
173 if (r < 0)
174 return bus_log_create_error(r);
175
176 ts = now(CLOCK_MONOTONIC);
177
178 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
179 if (r < 0)
180 return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r));
181
182 ts = now(CLOCK_MONOTONIC) - ts;
183
184 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
185 if (r < 0)
186 return bus_log_parse_error(r);
187
188 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
189 _cleanup_free_ char *pretty = NULL;
190 int ifindex, family;
191 const void *a;
192 size_t sz;
193
194 assert_cc(sizeof(int) == sizeof(int32_t));
195
196 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
197 if (r < 0)
198 return bus_log_parse_error(r);
199
200 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
201 if (r < 0)
202 return bus_log_parse_error(r);
203
204 r = sd_bus_message_exit_container(reply);
205 if (r < 0)
206 return bus_log_parse_error(r);
207
208 if (!IN_SET(family, AF_INET, AF_INET6)) {
209 log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
210 continue;
211 }
212
213 if (sz != FAMILY_ADDRESS_SIZE(family)) {
214 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
215 return -EINVAL;
216 }
217
218 ifname[0] = 0;
219 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
220 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
221
222 r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
223 if (r < 0)
224 return log_error_errno(r, "Failed to print address for %s: %m", name);
225
226 printf("%*s%s %s%s%s\n",
227 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
228 pretty,
229 isempty(ifname) ? "" : "%", ifname);
230
231 c++;
232 }
233 if (r < 0)
234 return bus_log_parse_error(r);
235
236 r = sd_bus_message_exit_container(reply);
237 if (r < 0)
238 return bus_log_parse_error(r);
239
240 r = sd_bus_message_read(reply, "st", &canonical, &flags);
241 if (r < 0)
242 return bus_log_parse_error(r);
243
244 if (!streq(name, canonical))
245 printf("%*s%s (%s)\n",
246 (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
247 canonical);
248
249 if (c == 0) {
250 log_error("%s: no addresses found", name);
251 return -ESRCH;
252 }
253
254 print_source(flags, ts);
255
256 return 0;
257 }
258
259 static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
260 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
261 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
262 _cleanup_free_ char *pretty = NULL;
263 char ifname[IF_NAMESIZE] = "";
264 uint64_t flags;
265 unsigned c = 0;
266 usec_t ts;
267 int r;
268
269 assert(bus);
270 assert(IN_SET(family, AF_INET, AF_INET6));
271 assert(address);
272
273 if (ifindex <= 0)
274 ifindex = arg_ifindex;
275
276 r = in_addr_ifindex_to_string(family, address, ifindex, &pretty);
277 if (r < 0)
278 return log_oom();
279
280 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
281 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
282
283 log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
284
285 r = sd_bus_message_new_method_call(
286 bus,
287 &req,
288 "org.freedesktop.resolve1",
289 "/org/freedesktop/resolve1",
290 "org.freedesktop.resolve1.Manager",
291 "ResolveAddress");
292 if (r < 0)
293 return bus_log_create_error(r);
294
295 r = sd_bus_message_append(req, "ii", ifindex, family);
296 if (r < 0)
297 return bus_log_create_error(r);
298
299 r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
300 if (r < 0)
301 return bus_log_create_error(r);
302
303 r = sd_bus_message_append(req, "t", arg_flags);
304 if (r < 0)
305 return bus_log_create_error(r);
306
307 ts = now(CLOCK_MONOTONIC);
308
309 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
310 if (r < 0) {
311 log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
312 return r;
313 }
314
315 ts = now(CLOCK_MONOTONIC) - ts;
316
317 r = sd_bus_message_enter_container(reply, 'a', "(is)");
318 if (r < 0)
319 return bus_log_create_error(r);
320
321 while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
322 const char *n;
323
324 assert_cc(sizeof(int) == sizeof(int32_t));
325
326 r = sd_bus_message_read(reply, "is", &ifindex, &n);
327 if (r < 0)
328 return r;
329
330 r = sd_bus_message_exit_container(reply);
331 if (r < 0)
332 return r;
333
334 ifname[0] = 0;
335 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
336 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
337
338 printf("%*s%*s%*s%s %s\n",
339 (int) strlen(pretty), c == 0 ? pretty : "",
340 isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
341 (int) strlen(ifname), c == 0 ? ifname : "",
342 c == 0 ? ":" : " ",
343 n);
344
345 c++;
346 }
347 if (r < 0)
348 return bus_log_parse_error(r);
349
350 r = sd_bus_message_exit_container(reply);
351 if (r < 0)
352 return bus_log_parse_error(r);
353
354 r = sd_bus_message_read(reply, "t", &flags);
355 if (r < 0)
356 return bus_log_parse_error(r);
357
358 if (c == 0) {
359 log_error("%s: no names found", pretty);
360 return -ESRCH;
361 }
362
363 print_source(flags, ts);
364
365 return 0;
366 }
367
368 static int output_rr_packet(const void *d, size_t l, int ifindex) {
369 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
370 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
371 int r;
372 char ifname[IF_NAMESIZE] = "";
373
374 r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX);
375 if (r < 0)
376 return log_oom();
377
378 p->refuse_compression = true;
379
380 r = dns_packet_append_blob(p, d, l, NULL);
381 if (r < 0)
382 return log_oom();
383
384 r = dns_packet_read_rr(p, &rr, NULL, NULL);
385 if (r < 0)
386 return log_error_errno(r, "Failed to parse RR: %m");
387
388 if (arg_raw == RAW_PAYLOAD) {
389 void *data;
390 ssize_t k;
391
392 k = dns_resource_record_payload(rr, &data);
393 if (k < 0)
394 return log_error_errno(k, "Cannot dump RR: %m");
395 fwrite(data, 1, k, stdout);
396 } else {
397 const char *s;
398
399 s = dns_resource_record_to_string(rr);
400 if (!s)
401 return log_oom();
402
403 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
404 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
405
406 printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
407 }
408
409 return 0;
410 }
411
412 static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) {
413 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
414 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
415 char ifname[IF_NAMESIZE] = "";
416 unsigned n = 0;
417 uint64_t flags;
418 int r;
419 usec_t ts;
420 bool needs_authentication = false;
421
422 assert(name);
423
424 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
425 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
426
427 log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname);
428
429 r = sd_bus_message_new_method_call(
430 bus,
431 &req,
432 "org.freedesktop.resolve1",
433 "/org/freedesktop/resolve1",
434 "org.freedesktop.resolve1.Manager",
435 "ResolveRecord");
436 if (r < 0)
437 return bus_log_create_error(r);
438
439 r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags);
440 if (r < 0)
441 return bus_log_create_error(r);
442
443 ts = now(CLOCK_MONOTONIC);
444
445 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
446 if (r < 0) {
447 if (warn_missing || r != -ENXIO)
448 log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
449 return r;
450 }
451
452 ts = now(CLOCK_MONOTONIC) - ts;
453
454 r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
455 if (r < 0)
456 return bus_log_parse_error(r);
457
458 while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
459 uint16_t c, t;
460 int ifindex;
461 const void *d;
462 size_t l;
463
464 assert_cc(sizeof(int) == sizeof(int32_t));
465
466 r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
467 if (r < 0)
468 return bus_log_parse_error(r);
469
470 r = sd_bus_message_read_array(reply, 'y', &d, &l);
471 if (r < 0)
472 return bus_log_parse_error(r);
473
474 r = sd_bus_message_exit_container(reply);
475 if (r < 0)
476 return bus_log_parse_error(r);
477
478 if (arg_raw == RAW_PACKET) {
479 uint64_t u64 = htole64(l);
480
481 fwrite(&u64, sizeof(u64), 1, stdout);
482 fwrite(d, 1, l, stdout);
483 } else {
484 r = output_rr_packet(d, l, ifindex);
485 if (r < 0)
486 return r;
487 }
488
489 if (dns_type_needs_authentication(t))
490 needs_authentication = true;
491
492 n++;
493 }
494 if (r < 0)
495 return bus_log_parse_error(r);
496
497 r = sd_bus_message_exit_container(reply);
498 if (r < 0)
499 return bus_log_parse_error(r);
500
501 r = sd_bus_message_read(reply, "t", &flags);
502 if (r < 0)
503 return bus_log_parse_error(r);
504
505 if (n == 0) {
506 if (warn_missing)
507 log_error("%s: no records found", name);
508 return -ESRCH;
509 }
510
511 print_source(flags, ts);
512
513 if ((flags & SD_RESOLVED_AUTHENTICATED) == 0 && needs_authentication) {
514 fflush(stdout);
515
516 fprintf(stderr, "\n%s"
517 "WARNING: The resources shown contain cryptographic key data which could not be\n"
518 " authenticated. It is not suitable to authenticate any communication.\n"
519 " This is usually indication that DNSSEC authentication was not enabled\n"
520 " or is not available for the selected protocol or DNS servers.%s\n",
521 ansi_highlight_red(),
522 ansi_normal());
523 }
524
525 return 0;
526 }
527
528 static int resolve_rfc4501(sd_bus *bus, const char *name) {
529 uint16_t type = 0, class = 0;
530 const char *p, *q, *n;
531 int r;
532
533 assert(bus);
534 assert(name);
535 assert(startswith(name, "dns:"));
536
537 /* Parse RFC 4501 dns: URIs */
538
539 p = name + 4;
540
541 if (p[0] == '/') {
542 const char *e;
543
544 if (p[1] != '/')
545 goto invalid;
546
547 e = strchr(p + 2, '/');
548 if (!e)
549 goto invalid;
550
551 if (e != p + 2)
552 log_warning("DNS authority specification not supported; ignoring specified authority.");
553
554 p = e + 1;
555 }
556
557 q = strchr(p, '?');
558 if (q) {
559 n = strndupa(p, q - p);
560 q++;
561
562 for (;;) {
563 const char *f;
564
565 f = startswith_no_case(q, "class=");
566 if (f) {
567 _cleanup_free_ char *t = NULL;
568 const char *e;
569
570 if (class != 0) {
571 log_error("DNS class 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_class_from_string(t);
581 if (r < 0) {
582 log_error("Unknown DNS class %s.", t);
583 return -EINVAL;
584 }
585
586 class = r;
587
588 if (*e == ';') {
589 q = e + 1;
590 continue;
591 }
592
593 break;
594 }
595
596 f = startswith_no_case(q, "type=");
597 if (f) {
598 _cleanup_free_ char *t = NULL;
599 const char *e;
600
601 if (type != 0) {
602 log_error("DNS type specified twice.");
603 return -EINVAL;
604 }
605
606 e = strchrnul(f, ';');
607 t = strndup(f, e - f);
608 if (!t)
609 return log_oom();
610
611 r = dns_type_from_string(t);
612 if (r < 0) {
613 log_error("Unknown DNS type %s.", t);
614 return -EINVAL;
615 }
616
617 type = r;
618
619 if (*e == ';') {
620 q = e + 1;
621 continue;
622 }
623
624 break;
625 }
626
627 goto invalid;
628 }
629 } else
630 n = p;
631
632 if (class == 0)
633 class = arg_class ?: DNS_CLASS_IN;
634 if (type == 0)
635 type = arg_type ?: DNS_TYPE_A;
636
637 return resolve_record(bus, n, class, type, true);
638
639 invalid:
640 log_error("Invalid DNS URI: %s", name);
641 return -EINVAL;
642 }
643
644 static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) {
645 const char *canonical_name, *canonical_type, *canonical_domain;
646 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
647 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
648 char ifname[IF_NAMESIZE] = "";
649 size_t indent, sz;
650 uint64_t flags;
651 const char *p;
652 unsigned c;
653 usec_t ts;
654 int r;
655
656 assert(bus);
657 assert(domain);
658
659 name = empty_to_null(name);
660 type = empty_to_null(type);
661
662 if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
663 return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
664
665 if (name)
666 log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
667 else if (type)
668 log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
669 else
670 log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
671
672 r = sd_bus_message_new_method_call(
673 bus,
674 &req,
675 "org.freedesktop.resolve1",
676 "/org/freedesktop/resolve1",
677 "org.freedesktop.resolve1.Manager",
678 "ResolveService");
679 if (r < 0)
680 return bus_log_create_error(r);
681
682 r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags);
683 if (r < 0)
684 return bus_log_create_error(r);
685
686 ts = now(CLOCK_MONOTONIC);
687
688 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
689 if (r < 0)
690 return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r));
691
692 ts = now(CLOCK_MONOTONIC) - ts;
693
694 r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)");
695 if (r < 0)
696 return bus_log_parse_error(r);
697
698 indent =
699 (name ? strlen(name) + 1 : 0) +
700 (type ? strlen(type) + 1 : 0) +
701 strlen(domain) + 2;
702
703 c = 0;
704 while ((r = sd_bus_message_enter_container(reply, 'r', "qqqsa(iiay)s")) > 0) {
705 uint16_t priority, weight, port;
706 const char *hostname, *canonical;
707
708 r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname);
709 if (r < 0)
710 return bus_log_parse_error(r);
711
712 if (name)
713 printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " ");
714 if (type)
715 printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " ");
716
717 printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
718 (int) strlen(domain), c == 0 ? domain : "",
719 c == 0 ? ":" : " ",
720 hostname, port,
721 priority, weight);
722
723 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
724 if (r < 0)
725 return bus_log_parse_error(r);
726
727 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
728 _cleanup_free_ char *pretty = NULL;
729 int ifindex, family;
730 const void *a;
731
732 assert_cc(sizeof(int) == sizeof(int32_t));
733
734 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
735 if (r < 0)
736 return bus_log_parse_error(r);
737
738 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
739 if (r < 0)
740 return bus_log_parse_error(r);
741
742 r = sd_bus_message_exit_container(reply);
743 if (r < 0)
744 return bus_log_parse_error(r);
745
746 if (!IN_SET(family, AF_INET, AF_INET6)) {
747 log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
748 continue;
749 }
750
751 if (sz != FAMILY_ADDRESS_SIZE(family)) {
752 log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
753 return -EINVAL;
754 }
755
756 ifname[0] = 0;
757 if (ifindex > 0 && !if_indextoname(ifindex, ifname))
758 log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
759
760 r = in_addr_to_string(family, a, &pretty);
761 if (r < 0)
762 return log_error_errno(r, "Failed to print address for %s: %m", name);
763
764 printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname);
765 }
766 if (r < 0)
767 return bus_log_parse_error(r);
768
769 r = sd_bus_message_exit_container(reply);
770 if (r < 0)
771 return bus_log_parse_error(r);
772
773 r = sd_bus_message_read(reply, "s", &canonical);
774 if (r < 0)
775 return bus_log_parse_error(r);
776
777 if (!streq(hostname, canonical))
778 printf("%*s(%s)\n", (int) indent, "", canonical);
779
780 r = sd_bus_message_exit_container(reply);
781 if (r < 0)
782 return bus_log_parse_error(r);
783
784 c++;
785 }
786 if (r < 0)
787 return bus_log_parse_error(r);
788
789 r = sd_bus_message_exit_container(reply);
790 if (r < 0)
791 return bus_log_parse_error(r);
792
793 r = sd_bus_message_enter_container(reply, 'a', "ay");
794 if (r < 0)
795 return bus_log_parse_error(r);
796
797 while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) {
798 _cleanup_free_ char *escaped = NULL;
799
800 escaped = cescape_length(p, sz);
801 if (!escaped)
802 return log_oom();
803
804 printf("%*s%s\n", (int) indent, "", escaped);
805 }
806 if (r < 0)
807 return bus_log_parse_error(r);
808
809 r = sd_bus_message_exit_container(reply);
810 if (r < 0)
811 return bus_log_parse_error(r);
812
813 r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags);
814 if (r < 0)
815 return bus_log_parse_error(r);
816
817 canonical_name = empty_to_null(canonical_name);
818 canonical_type = empty_to_null(canonical_type);
819
820 if (!streq_ptr(name, canonical_name) ||
821 !streq_ptr(type, canonical_type) ||
822 !streq_ptr(domain, canonical_domain)) {
823
824 printf("%*s(", (int) indent, "");
825
826 if (canonical_name)
827 printf("%s/", canonical_name);
828 if (canonical_type)
829 printf("%s/", canonical_type);
830
831 printf("%s)\n", canonical_domain);
832 }
833
834 print_source(flags, ts);
835
836 return 0;
837 }
838
839 static int resolve_openpgp(sd_bus *bus, const char *address) {
840 const char *domain, *full;
841 int r;
842 _cleanup_free_ char *hashed = NULL;
843
844 assert(bus);
845 assert(address);
846
847 domain = strrchr(address, '@');
848 if (!domain) {
849 log_error("Address does not contain '@': \"%s\"", address);
850 return -EINVAL;
851 } else if (domain == address || domain[1] == '\0') {
852 log_error("Address starts or ends with '@': \"%s\"", address);
853 return -EINVAL;
854 }
855 domain++;
856
857 r = string_hashsum_sha256(address, domain - 1 - address, &hashed);
858 if (r < 0)
859 return log_error_errno(r, "Hashing failed: %m");
860
861 strshorten(hashed, 56);
862
863 full = strjoina(hashed, "._openpgpkey.", domain);
864 log_debug("Looking up \"%s\".", full);
865
866 r = resolve_record(bus, full,
867 arg_class ?: DNS_CLASS_IN,
868 arg_type ?: DNS_TYPE_OPENPGPKEY, false);
869
870 if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */
871 hashed = NULL;
872 r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
873 if (r < 0)
874 return log_error_errno(r, "Hashing failed: %m");
875
876 full = strjoina(hashed, "._openpgpkey.", domain);
877 log_debug("Looking up \"%s\".", full);
878
879 return resolve_record(bus, full,
880 arg_class ?: DNS_CLASS_IN,
881 arg_type ?: DNS_TYPE_OPENPGPKEY, true);
882 }
883
884 return r;
885 }
886
887 static int resolve_tlsa(sd_bus *bus, const char *address) {
888 const char *port;
889 uint16_t port_num = 443;
890 _cleanup_free_ char *full = NULL;
891 int r;
892
893 assert(bus);
894 assert(address);
895
896 port = strrchr(address, ':');
897 if (port) {
898 r = parse_ip_port(port + 1, &port_num);
899 if (r < 0)
900 return log_error_errno(r, "Invalid port \"%s\".", port + 1);
901
902 address = strndupa(address, port - address);
903 }
904
905 r = asprintf(&full, "_%u.%s.%s",
906 port_num,
907 service_family_to_string(arg_service_family),
908 address);
909 if (r < 0)
910 return log_oom();
911
912 log_debug("Looking up \"%s\".", full);
913
914 return resolve_record(bus, full,
915 arg_class ?: DNS_CLASS_IN,
916 arg_type ?: DNS_TYPE_TLSA, true);
917 }
918
919 static int show_statistics(sd_bus *bus) {
920 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
921 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
922 uint64_t n_current_transactions, n_total_transactions,
923 cache_size, n_cache_hit, n_cache_miss,
924 n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate;
925 int r, dnssec_supported;
926
927 assert(bus);
928
929 r = sd_bus_get_property_trivial(bus,
930 "org.freedesktop.resolve1",
931 "/org/freedesktop/resolve1",
932 "org.freedesktop.resolve1.Manager",
933 "DNSSECSupported",
934 &error,
935 'b',
936 &dnssec_supported);
937 if (r < 0)
938 return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
939
940 printf("DNSSEC supported by current servers: %s%s%s\n\n",
941 ansi_highlight(),
942 yes_no(dnssec_supported),
943 ansi_normal());
944
945 r = sd_bus_get_property(bus,
946 "org.freedesktop.resolve1",
947 "/org/freedesktop/resolve1",
948 "org.freedesktop.resolve1.Manager",
949 "TransactionStatistics",
950 &error,
951 &reply,
952 "(tt)");
953 if (r < 0)
954 return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r));
955
956 r = sd_bus_message_read(reply, "(tt)",
957 &n_current_transactions,
958 &n_total_transactions);
959 if (r < 0)
960 return bus_log_parse_error(r);
961
962 printf("%sTransactions%s\n"
963 "Current Transactions: %" PRIu64 "\n"
964 " Total Transactions: %" PRIu64 "\n",
965 ansi_highlight(),
966 ansi_normal(),
967 n_current_transactions,
968 n_total_transactions);
969
970 reply = sd_bus_message_unref(reply);
971
972 r = sd_bus_get_property(bus,
973 "org.freedesktop.resolve1",
974 "/org/freedesktop/resolve1",
975 "org.freedesktop.resolve1.Manager",
976 "CacheStatistics",
977 &error,
978 &reply,
979 "(ttt)");
980 if (r < 0)
981 return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r));
982
983 r = sd_bus_message_read(reply, "(ttt)",
984 &cache_size,
985 &n_cache_hit,
986 &n_cache_miss);
987 if (r < 0)
988 return bus_log_parse_error(r);
989
990 printf("\n%sCache%s\n"
991 " Current Cache Size: %" PRIu64 "\n"
992 " Cache Hits: %" PRIu64 "\n"
993 " Cache Misses: %" PRIu64 "\n",
994 ansi_highlight(),
995 ansi_normal(),
996 cache_size,
997 n_cache_hit,
998 n_cache_miss);
999
1000 reply = sd_bus_message_unref(reply);
1001
1002 r = sd_bus_get_property(bus,
1003 "org.freedesktop.resolve1",
1004 "/org/freedesktop/resolve1",
1005 "org.freedesktop.resolve1.Manager",
1006 "DNSSECStatistics",
1007 &error,
1008 &reply,
1009 "(tttt)");
1010 if (r < 0)
1011 return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r));
1012
1013 r = sd_bus_message_read(reply, "(tttt)",
1014 &n_dnssec_secure,
1015 &n_dnssec_insecure,
1016 &n_dnssec_bogus,
1017 &n_dnssec_indeterminate);
1018 if (r < 0)
1019 return bus_log_parse_error(r);
1020
1021 printf("\n%sDNSSEC Verdicts%s\n"
1022 " Secure: %" PRIu64 "\n"
1023 " Insecure: %" PRIu64 "\n"
1024 " Bogus: %" PRIu64 "\n"
1025 " Indeterminate: %" PRIu64 "\n",
1026 ansi_highlight(),
1027 ansi_normal(),
1028 n_dnssec_secure,
1029 n_dnssec_insecure,
1030 n_dnssec_bogus,
1031 n_dnssec_indeterminate);
1032
1033 return 0;
1034 }
1035
1036 static int reset_statistics(sd_bus *bus) {
1037 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1038 int r;
1039
1040 r = sd_bus_call_method(bus,
1041 "org.freedesktop.resolve1",
1042 "/org/freedesktop/resolve1",
1043 "org.freedesktop.resolve1.Manager",
1044 "ResetStatistics",
1045 &error,
1046 NULL,
1047 NULL);
1048 if (r < 0)
1049 return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r));
1050
1051 return 0;
1052 }
1053
1054 static int flush_caches(sd_bus *bus) {
1055 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1056 int r;
1057
1058 r = sd_bus_call_method(bus,
1059 "org.freedesktop.resolve1",
1060 "/org/freedesktop/resolve1",
1061 "org.freedesktop.resolve1.Manager",
1062 "FlushCaches",
1063 &error,
1064 NULL,
1065 NULL);
1066 if (r < 0)
1067 return log_error_errno(r, "Failed to flush caches: %s", bus_error_message(&error, r));
1068
1069 return 0;
1070 }
1071
1072 static int reset_server_features(sd_bus *bus) {
1073 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1074 int r;
1075
1076 r = sd_bus_call_method(bus,
1077 "org.freedesktop.resolve1",
1078 "/org/freedesktop/resolve1",
1079 "org.freedesktop.resolve1.Manager",
1080 "ResetServerFeatures",
1081 &error,
1082 NULL,
1083 NULL);
1084 if (r < 0)
1085 return log_error_errno(r, "Failed to reset server features: %s", bus_error_message(&error, r));
1086
1087 return 0;
1088 }
1089
1090 static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1091 char ***l = userdata;
1092 int r;
1093
1094 assert(bus);
1095 assert(member);
1096 assert(m);
1097 assert(l);
1098
1099 r = sd_bus_message_enter_container(m, 'a', "(iay)");
1100 if (r < 0)
1101 return r;
1102
1103 for (;;) {
1104 const void *a;
1105 char *pretty;
1106 int family;
1107 size_t sz;
1108
1109 r = sd_bus_message_enter_container(m, 'r', "iay");
1110 if (r < 0)
1111 return r;
1112 if (r == 0)
1113 break;
1114
1115 r = sd_bus_message_read(m, "i", &family);
1116 if (r < 0)
1117 return r;
1118
1119 r = sd_bus_message_read_array(m, 'y', &a, &sz);
1120 if (r < 0)
1121 return r;
1122
1123 r = sd_bus_message_exit_container(m);
1124 if (r < 0)
1125 return r;
1126
1127 if (!IN_SET(family, AF_INET, AF_INET6)) {
1128 log_debug("Unexpected family, ignoring.");
1129 continue;
1130 }
1131
1132 if (sz != FAMILY_ADDRESS_SIZE(family)) {
1133 log_debug("Address size mismatch, ignoring.");
1134 continue;
1135 }
1136
1137 r = in_addr_to_string(family, a, &pretty);
1138 if (r < 0)
1139 return r;
1140
1141 r = strv_consume(l, pretty);
1142 if (r < 0)
1143 return r;
1144 }
1145
1146 r = sd_bus_message_exit_container(m);
1147 if (r < 0)
1148 return r;
1149
1150 return 0;
1151 }
1152
1153 static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1154 char ***l = userdata;
1155 int r;
1156
1157 assert(bus);
1158 assert(member);
1159 assert(m);
1160 assert(l);
1161
1162 r = sd_bus_message_enter_container(m, 'a', "(sb)");
1163 if (r < 0)
1164 return r;
1165
1166 for (;;) {
1167 const char *domain;
1168 int route_only;
1169 char *pretty;
1170
1171 r = sd_bus_message_read(m, "(sb)", &domain, &route_only);
1172 if (r < 0)
1173 return r;
1174 if (r == 0)
1175 break;
1176
1177 if (route_only)
1178 pretty = strappend("~", domain);
1179 else
1180 pretty = strdup(domain);
1181 if (!pretty)
1182 return -ENOMEM;
1183
1184 r = strv_consume(l, pretty);
1185 if (r < 0)
1186 return r;
1187 }
1188
1189 r = sd_bus_message_exit_container(m);
1190 if (r < 0)
1191 return r;
1192
1193 return 0;
1194 }
1195
1196 static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empty_line) {
1197
1198 struct link_info {
1199 uint64_t scopes_mask;
1200 char *llmnr;
1201 char *mdns;
1202 char *dnssec;
1203 char **dns;
1204 char **domains;
1205 char **ntas;
1206 int dnssec_supported;
1207 } link_info = {};
1208
1209 static const struct bus_properties_map property_map[] = {
1210 { "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) },
1211 { "DNS", "a(iay)", map_link_dns_servers, offsetof(struct link_info, dns) },
1212 { "Domains", "a(sb)", map_link_domains, offsetof(struct link_info, domains) },
1213 { "LLMNR", "s", NULL, offsetof(struct link_info, llmnr) },
1214 { "MulticastDNS", "s", NULL, offsetof(struct link_info, mdns) },
1215 { "DNSSEC", "s", NULL, offsetof(struct link_info, dnssec) },
1216 { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct link_info, ntas) },
1217 { "DNSSECSupported", "b", NULL, offsetof(struct link_info, dnssec_supported) },
1218 {}
1219 };
1220
1221 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1222 _cleanup_free_ char *ifi = NULL, *p = NULL;
1223 char ifname[IF_NAMESIZE] = "";
1224 char **i;
1225 int r;
1226
1227 assert(bus);
1228 assert(ifindex > 0);
1229 assert(empty_line);
1230
1231 if (!name) {
1232 if (!if_indextoname(ifindex, ifname))
1233 return log_error_errno(errno, "Failed to resolve interface name for %i: %m", ifindex);
1234
1235 name = ifname;
1236 }
1237
1238 if (asprintf(&ifi, "%i", ifindex) < 0)
1239 return log_oom();
1240
1241 r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi, &p);
1242 if (r < 0)
1243 return log_oom();
1244
1245 r = bus_map_all_properties(bus,
1246 "org.freedesktop.resolve1",
1247 p,
1248 property_map,
1249 &error,
1250 &link_info);
1251 if (r < 0) {
1252 log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r));
1253 goto finish;
1254 }
1255
1256 pager_open(arg_no_pager, false);
1257
1258 if (*empty_line)
1259 fputc('\n', stdout);
1260
1261 printf("%sLink %i (%s)%s\n",
1262 ansi_highlight(), ifindex, name, ansi_normal());
1263
1264 if (link_info.scopes_mask == 0)
1265 printf(" Current Scopes: none\n");
1266 else
1267 printf(" Current Scopes:%s%s%s%s%s\n",
1268 link_info.scopes_mask & SD_RESOLVED_DNS ? " DNS" : "",
1269 link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
1270 link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
1271 link_info.scopes_mask & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "",
1272 link_info.scopes_mask & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : "");
1273
1274 printf(" LLMNR setting: %s\n"
1275 "MulticastDNS setting: %s\n"
1276 " DNSSEC setting: %s\n"
1277 " DNSSEC supported: %s\n",
1278 strna(link_info.llmnr),
1279 strna(link_info.mdns),
1280 strna(link_info.dnssec),
1281 yes_no(link_info.dnssec_supported));
1282
1283 STRV_FOREACH(i, link_info.dns) {
1284 printf(" %s %s\n",
1285 i == link_info.dns ? "DNS Servers:" : " ",
1286 *i);
1287 }
1288
1289 STRV_FOREACH(i, link_info.domains) {
1290 printf(" %s %s\n",
1291 i == link_info.domains ? "DNS Domain:" : " ",
1292 *i);
1293 }
1294
1295 STRV_FOREACH(i, link_info.ntas) {
1296 printf(" %s %s\n",
1297 i == link_info.ntas ? "DNSSEC NTA:" : " ",
1298 *i);
1299 }
1300
1301 *empty_line = true;
1302
1303 r = 0;
1304
1305 finish:
1306 strv_free(link_info.dns);
1307 strv_free(link_info.domains);
1308 free(link_info.llmnr);
1309 free(link_info.mdns);
1310 free(link_info.dnssec);
1311 strv_free(link_info.ntas);
1312 return r;
1313 }
1314
1315 static int map_global_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1316 char ***l = userdata;
1317 int r;
1318
1319 assert(bus);
1320 assert(member);
1321 assert(m);
1322 assert(l);
1323
1324 r = sd_bus_message_enter_container(m, 'a', "(iiay)");
1325 if (r < 0)
1326 return r;
1327
1328 for (;;) {
1329 const void *a;
1330 char *pretty;
1331 int family, ifindex;
1332 size_t sz;
1333
1334 r = sd_bus_message_enter_container(m, 'r', "iiay");
1335 if (r < 0)
1336 return r;
1337 if (r == 0)
1338 break;
1339
1340 r = sd_bus_message_read(m, "ii", &ifindex, &family);
1341 if (r < 0)
1342 return r;
1343
1344 r = sd_bus_message_read_array(m, 'y', &a, &sz);
1345 if (r < 0)
1346 return r;
1347
1348 r = sd_bus_message_exit_container(m);
1349 if (r < 0)
1350 return r;
1351
1352 if (ifindex != 0) /* only show the global ones here */
1353 continue;
1354
1355 if (!IN_SET(family, AF_INET, AF_INET6)) {
1356 log_debug("Unexpected family, ignoring.");
1357 continue;
1358 }
1359
1360 if (sz != FAMILY_ADDRESS_SIZE(family)) {
1361 log_debug("Address size mismatch, ignoring.");
1362 continue;
1363 }
1364
1365 r = in_addr_to_string(family, a, &pretty);
1366 if (r < 0)
1367 return r;
1368
1369 r = strv_consume(l, pretty);
1370 if (r < 0)
1371 return r;
1372 }
1373
1374 r = sd_bus_message_exit_container(m);
1375 if (r < 0)
1376 return r;
1377
1378 return 0;
1379 }
1380
1381 static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1382 char ***l = userdata;
1383 int r;
1384
1385 assert(bus);
1386 assert(member);
1387 assert(m);
1388 assert(l);
1389
1390 r = sd_bus_message_enter_container(m, 'a', "(isb)");
1391 if (r < 0)
1392 return r;
1393
1394 for (;;) {
1395 const char *domain;
1396 int route_only, ifindex;
1397 char *pretty;
1398
1399 r = sd_bus_message_read(m, "(isb)", &ifindex, &domain, &route_only);
1400 if (r < 0)
1401 return r;
1402 if (r == 0)
1403 break;
1404
1405 if (ifindex != 0) /* only show the global ones here */
1406 continue;
1407
1408 if (route_only)
1409 pretty = strappend("~", domain);
1410 else
1411 pretty = strdup(domain);
1412 if (!pretty)
1413 return -ENOMEM;
1414
1415 r = strv_consume(l, pretty);
1416 if (r < 0)
1417 return r;
1418 }
1419
1420 r = sd_bus_message_exit_container(m);
1421 if (r < 0)
1422 return r;
1423
1424 return 0;
1425 }
1426
1427 static int status_global(sd_bus *bus, bool *empty_line) {
1428
1429 struct global_info {
1430 char **dns;
1431 char **domains;
1432 char **ntas;
1433 } global_info = {};
1434
1435 static const struct bus_properties_map property_map[] = {
1436 { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
1437 { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
1438 { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
1439 {}
1440 };
1441
1442 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1443 char **i;
1444 int r;
1445
1446 assert(bus);
1447 assert(empty_line);
1448
1449 r = bus_map_all_properties(bus,
1450 "org.freedesktop.resolve1",
1451 "/org/freedesktop/resolve1",
1452 property_map,
1453 &error,
1454 &global_info);
1455 if (r < 0) {
1456 log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r));
1457 goto finish;
1458 }
1459
1460 if (strv_isempty(global_info.dns) && strv_isempty(global_info.domains) && strv_isempty(global_info.ntas)) {
1461 r = 0;
1462 goto finish;
1463 }
1464
1465 pager_open(arg_no_pager, false);
1466
1467 printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
1468 STRV_FOREACH(i, global_info.dns) {
1469 printf(" %s %s\n",
1470 i == global_info.dns ? "DNS Servers:" : " ",
1471 *i);
1472 }
1473
1474 STRV_FOREACH(i, global_info.domains) {
1475 printf(" %s %s\n",
1476 i == global_info.domains ? "DNS Domain:" : " ",
1477 *i);
1478 }
1479
1480 strv_sort(global_info.ntas);
1481 STRV_FOREACH(i, global_info.ntas) {
1482 printf(" %s %s\n",
1483 i == global_info.ntas ? "DNSSEC NTA:" : " ",
1484 *i);
1485 }
1486
1487 *empty_line = true;
1488
1489 r = 0;
1490
1491 finish:
1492 strv_free(global_info.dns);
1493 strv_free(global_info.domains);
1494 strv_free(global_info.ntas);
1495
1496 return r;
1497 }
1498
1499 static int status_all(sd_bus *bus) {
1500 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
1501 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
1502 sd_netlink_message *i;
1503 bool empty_line = false;
1504 int r;
1505
1506 assert(bus);
1507
1508 r = status_global(bus, &empty_line);
1509 if (r < 0)
1510 return r;
1511
1512 r = sd_netlink_open(&rtnl);
1513 if (r < 0)
1514 return log_error_errno(r, "Failed to connect to netlink: %m");
1515
1516 r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
1517 if (r < 0)
1518 return rtnl_log_create_error(r);
1519
1520 r = sd_netlink_message_request_dump(req, true);
1521 if (r < 0)
1522 return rtnl_log_create_error(r);
1523
1524 r = sd_netlink_call(rtnl, req, 0, &reply);
1525 if (r < 0)
1526 return log_error_errno(r, "Failed to enumerate links: %m");
1527
1528 r = 0;
1529 for (i = reply; i; i = sd_netlink_message_next(i)) {
1530 const char *name;
1531 int ifindex, q;
1532 uint16_t type;
1533
1534 q = sd_netlink_message_get_type(i, &type);
1535 if (q < 0)
1536 return rtnl_log_parse_error(q);
1537
1538 if (type != RTM_NEWLINK)
1539 continue;
1540
1541 q = sd_rtnl_message_link_get_ifindex(i, &ifindex);
1542 if (q < 0)
1543 return rtnl_log_parse_error(q);
1544
1545 if (ifindex == LOOPBACK_IFINDEX)
1546 continue;
1547
1548 q = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
1549 if (q < 0)
1550 return rtnl_log_parse_error(q);
1551
1552 q = status_ifindex(bus, ifindex, name, &empty_line);
1553 if (q < 0 && r >= 0)
1554 r = q;
1555 }
1556
1557 return r;
1558 }
1559
1560 static int set_link(sd_bus *bus) {
1561 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1562 int r = 0, q;
1563
1564 assert(bus);
1565
1566 if (arg_n_set_dns > 0) {
1567 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
1568 size_t i;
1569
1570 q = sd_bus_message_new_method_call(
1571 bus,
1572 &req,
1573 "org.freedesktop.resolve1",
1574 "/org/freedesktop/resolve1",
1575 "org.freedesktop.resolve1.Manager",
1576 "SetLinkDNS");
1577 if (q < 0)
1578 return bus_log_create_error(q);
1579
1580 q = sd_bus_message_append(req, "i", arg_ifindex);
1581 if (q < 0)
1582 return bus_log_create_error(q);
1583
1584 q = sd_bus_message_open_container(req, 'a', "(iay)");
1585 if (q < 0)
1586 return bus_log_create_error(q);
1587
1588 for (i = 0; i < arg_n_set_dns; i++) {
1589 q = sd_bus_message_open_container(req, 'r', "iay");
1590 if (q < 0)
1591 return bus_log_create_error(q);
1592
1593 q = sd_bus_message_append(req, "i", arg_set_dns[i].family);
1594 if (q < 0)
1595 return bus_log_create_error(q);
1596
1597 q = sd_bus_message_append_array(req, 'y', &arg_set_dns[i].address, FAMILY_ADDRESS_SIZE(arg_set_dns[i].family));
1598 if (q < 0)
1599 return bus_log_create_error(q);
1600
1601 q = sd_bus_message_close_container(req);
1602 if (q < 0)
1603 return bus_log_create_error(q);
1604 }
1605
1606 q = sd_bus_message_close_container(req);
1607 if (q < 0)
1608 return bus_log_create_error(q);
1609
1610 q = sd_bus_call(bus, req, 0, &error, NULL);
1611 if (q < 0) {
1612 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1613 goto is_managed;
1614
1615 log_error_errno(q, "Failed to set DNS configuration: %s", bus_error_message(&error, q));
1616 if (r == 0)
1617 r = q;
1618 }
1619 }
1620
1621 if (!strv_isempty(arg_set_domain)) {
1622 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
1623 char **p;
1624
1625 q = sd_bus_message_new_method_call(
1626 bus,
1627 &req,
1628 "org.freedesktop.resolve1",
1629 "/org/freedesktop/resolve1",
1630 "org.freedesktop.resolve1.Manager",
1631 "SetLinkDomains");
1632 if (q < 0)
1633 return bus_log_create_error(q);
1634
1635 q = sd_bus_message_append(req, "i", arg_ifindex);
1636 if (q < 0)
1637 return bus_log_create_error(q);
1638
1639 q = sd_bus_message_open_container(req, 'a', "(sb)");
1640 if (q < 0)
1641 return bus_log_create_error(q);
1642
1643 STRV_FOREACH(p, arg_set_domain) {
1644 const char *n;
1645
1646 n = **p == '~' ? *p + 1 : *p;
1647 q = sd_bus_message_append(req, "(sb)", n, **p == '~');
1648 if (q < 0)
1649 return bus_log_create_error(q);
1650 }
1651
1652 q = sd_bus_message_close_container(req);
1653 if (q < 0)
1654 return bus_log_create_error(q);
1655
1656 q = sd_bus_call(bus, req, 0, &error, NULL);
1657 if (q < 0) {
1658 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1659 goto is_managed;
1660
1661 log_error_errno(q, "Failed to set domain configuration: %s", bus_error_message(&error, q));
1662 if (r == 0)
1663 r = q;
1664 }
1665 }
1666
1667 if (arg_set_llmnr) {
1668 q = sd_bus_call_method(bus,
1669 "org.freedesktop.resolve1",
1670 "/org/freedesktop/resolve1",
1671 "org.freedesktop.resolve1.Manager",
1672 "SetLinkLLMNR",
1673 &error,
1674 NULL,
1675 "is", arg_ifindex, arg_set_llmnr);
1676 if (q < 0) {
1677 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1678 goto is_managed;
1679
1680 log_error_errno(q, "Failed to set LLMNR configuration: %s", bus_error_message(&error, q));
1681 if (r == 0)
1682 r = q;
1683 }
1684 }
1685
1686 if (arg_set_mdns) {
1687 q = sd_bus_call_method(bus,
1688 "org.freedesktop.resolve1",
1689 "/org/freedesktop/resolve1",
1690 "org.freedesktop.resolve1.Manager",
1691 "SetLinkMulticastDNS",
1692 &error,
1693 NULL,
1694 "is", arg_ifindex, arg_set_mdns);
1695 if (q < 0) {
1696 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1697 goto is_managed;
1698
1699 log_error_errno(q, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error, q));
1700 if (r == 0)
1701 r = q;
1702 }
1703 }
1704
1705 if (arg_set_dnssec) {
1706 q = sd_bus_call_method(bus,
1707 "org.freedesktop.resolve1",
1708 "/org/freedesktop/resolve1",
1709 "org.freedesktop.resolve1.Manager",
1710 "SetLinkDNSSEC",
1711 &error,
1712 NULL,
1713 "is", arg_ifindex, arg_set_dnssec);
1714 if (q < 0) {
1715 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1716 goto is_managed;
1717
1718 log_error_errno(q, "Failed to set DNSSEC configuration: %s", bus_error_message(&error, q));
1719 if (r == 0)
1720 r = q;
1721 }
1722 }
1723
1724 if (!strv_isempty(arg_set_nta)) {
1725 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
1726
1727 q = sd_bus_message_new_method_call(
1728 bus,
1729 &req,
1730 "org.freedesktop.resolve1",
1731 "/org/freedesktop/resolve1",
1732 "org.freedesktop.resolve1.Manager",
1733 "SetLinkDNSSECNegativeTrustAnchors");
1734 if (q < 0)
1735 return bus_log_create_error(q);
1736
1737 q = sd_bus_message_append(req, "i", arg_ifindex);
1738 if (q < 0)
1739 return bus_log_create_error(q);
1740
1741 q = sd_bus_message_append_strv(req, arg_set_nta);
1742 if (q < 0)
1743 return bus_log_create_error(q);
1744
1745 q = sd_bus_call(bus, req, 0, &error, NULL);
1746 if (q < 0) {
1747 if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
1748 goto is_managed;
1749
1750 log_error_errno(q, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error, q));
1751 if (r == 0)
1752 r = q;
1753 }
1754 }
1755
1756 return r;
1757
1758 is_managed:
1759 {
1760 char ifname[IFNAMSIZ];
1761
1762 return log_error_errno(q,
1763 "The specified interface %s is managed by systemd-networkd. Operation refused.\n"
1764 "Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.", strna(if_indextoname(arg_ifindex, ifname)));
1765 }
1766 }
1767
1768 static int revert_link(sd_bus *bus) {
1769 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1770 int r;
1771
1772 assert(bus);
1773
1774 r = sd_bus_call_method(bus,
1775 "org.freedesktop.resolve1",
1776 "/org/freedesktop/resolve1",
1777 "org.freedesktop.resolve1.Manager",
1778 "RevertLink",
1779 &error,
1780 NULL,
1781 "i", arg_ifindex);
1782 if (r < 0)
1783 return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
1784
1785 return 0;
1786 }
1787
1788 static void help_protocol_types(void) {
1789 if (arg_legend)
1790 puts("Known protocol types:");
1791 puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6\nmdns\nmdns-ipv4\nmdns-ipv6");
1792 }
1793
1794 static void help_dns_types(void) {
1795 const char *t;
1796 int i;
1797
1798 if (arg_legend)
1799 puts("Known DNS RR types:");
1800 for (i = 0; i < _DNS_TYPE_MAX; i++) {
1801 t = dns_type_to_string(i);
1802 if (t)
1803 puts(t);
1804 }
1805 }
1806
1807 static void help_dns_classes(void) {
1808 const char *t;
1809 int i;
1810
1811 if (arg_legend)
1812 puts("Known DNS RR classes:");
1813 for (i = 0; i < _DNS_CLASS_MAX; i++) {
1814 t = dns_class_to_string(i);
1815 if (t)
1816 puts(t);
1817 }
1818 }
1819
1820 static void help(void) {
1821 printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
1822 "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
1823 "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
1824 "%1$s [OPTIONS...] --statistics\n"
1825 "%1$s [OPTIONS...] --reset-statistics\n"
1826 "\n"
1827 "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n"
1828 " -h --help Show this help\n"
1829 " --version Show package version\n"
1830 " --no-pager Do not pipe output into a pager\n"
1831 " -4 Resolve IPv4 addresses\n"
1832 " -6 Resolve IPv6 addresses\n"
1833 " -i --interface=INTERFACE Look on interface\n"
1834 " -p --protocol=PROTO|help Look via protocol\n"
1835 " -t --type=TYPE|help Query RR with DNS type\n"
1836 " -c --class=CLASS|help Query RR with DNS class\n"
1837 " --service Resolve service (SRV)\n"
1838 " --service-address=BOOL Resolve address for services (default: yes)\n"
1839 " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
1840 " --openpgp Query OpenPGP public key\n"
1841 " --tlsa Query TLS public key\n"
1842 " --cname=BOOL Follow CNAME redirects (default: yes)\n"
1843 " --search=BOOL Use search domains for single-label names\n"
1844 " (default: yes)\n"
1845 " --raw[=payload|packet] Dump the answer as binary data\n"
1846 " --legend=BOOL Print headers and additional info (default: yes)\n"
1847 " --statistics Show resolver statistics\n"
1848 " --reset-statistics Reset resolver statistics\n"
1849 " --status Show link and server status\n"
1850 " --flush-caches Flush all local DNS caches\n"
1851 " --reset-server-features\n"
1852 " Forget learnt DNS server feature levels\n"
1853 " --set-dns=SERVER Set per-interface DNS server address\n"
1854 " --set-domain=DOMAIN Set per-interface search domain\n"
1855 " --set-llmnr=MODE Set per-interface LLMNR mode\n"
1856 " --set-mdns=MODE Set per-interface MulticastDNS mode\n"
1857 " --set-dnssec=MODE Set per-interface DNSSEC mode\n"
1858 " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
1859 " --revert Revert per-interface configuration\n"
1860 , program_invocation_short_name);
1861 }
1862
1863 static int parse_argv(int argc, char *argv[]) {
1864 enum {
1865 ARG_VERSION = 0x100,
1866 ARG_LEGEND,
1867 ARG_SERVICE,
1868 ARG_CNAME,
1869 ARG_SERVICE_ADDRESS,
1870 ARG_SERVICE_TXT,
1871 ARG_OPENPGP,
1872 ARG_TLSA,
1873 ARG_RAW,
1874 ARG_SEARCH,
1875 ARG_STATISTICS,
1876 ARG_RESET_STATISTICS,
1877 ARG_STATUS,
1878 ARG_FLUSH_CACHES,
1879 ARG_RESET_SERVER_FEATURES,
1880 ARG_NO_PAGER,
1881 ARG_SET_DNS,
1882 ARG_SET_DOMAIN,
1883 ARG_SET_LLMNR,
1884 ARG_SET_MDNS,
1885 ARG_SET_DNSSEC,
1886 ARG_SET_NTA,
1887 ARG_REVERT_LINK,
1888 };
1889
1890 static const struct option options[] = {
1891 { "help", no_argument, NULL, 'h' },
1892 { "version", no_argument, NULL, ARG_VERSION },
1893 { "type", required_argument, NULL, 't' },
1894 { "class", required_argument, NULL, 'c' },
1895 { "legend", required_argument, NULL, ARG_LEGEND },
1896 { "interface", required_argument, NULL, 'i' },
1897 { "protocol", required_argument, NULL, 'p' },
1898 { "cname", required_argument, NULL, ARG_CNAME },
1899 { "service", no_argument, NULL, ARG_SERVICE },
1900 { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
1901 { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
1902 { "openpgp", no_argument, NULL, ARG_OPENPGP },
1903 { "tlsa", optional_argument, NULL, ARG_TLSA },
1904 { "raw", optional_argument, NULL, ARG_RAW },
1905 { "search", required_argument, NULL, ARG_SEARCH },
1906 { "statistics", no_argument, NULL, ARG_STATISTICS, },
1907 { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
1908 { "status", no_argument, NULL, ARG_STATUS },
1909 { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES },
1910 { "reset-server-features", no_argument, NULL, ARG_RESET_SERVER_FEATURES },
1911 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1912 { "set-dns", required_argument, NULL, ARG_SET_DNS },
1913 { "set-domain", required_argument, NULL, ARG_SET_DOMAIN },
1914 { "set-llmnr", required_argument, NULL, ARG_SET_LLMNR },
1915 { "set-mdns", required_argument, NULL, ARG_SET_MDNS },
1916 { "set-dnssec", required_argument, NULL, ARG_SET_DNSSEC },
1917 { "set-nta", required_argument, NULL, ARG_SET_NTA },
1918 { "revert", no_argument, NULL, ARG_REVERT_LINK },
1919 {}
1920 };
1921
1922 int c, r;
1923
1924 assert(argc >= 0);
1925 assert(argv);
1926
1927 while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
1928 switch(c) {
1929
1930 case 'h':
1931 help();
1932 return 0; /* done */;
1933
1934 case ARG_VERSION:
1935 return version();
1936
1937 case '4':
1938 arg_family = AF_INET;
1939 break;
1940
1941 case '6':
1942 arg_family = AF_INET6;
1943 break;
1944
1945 case 'i': {
1946 int ifi;
1947
1948 if (parse_ifindex(optarg, &ifi) >= 0)
1949 arg_ifindex = ifi;
1950 else {
1951 ifi = if_nametoindex(optarg);
1952 if (ifi <= 0)
1953 return log_error_errno(errno, "Unknown interface %s: %m", optarg);
1954
1955 arg_ifindex = ifi;
1956 }
1957
1958 break;
1959 }
1960
1961 case 't':
1962 if (streq(optarg, "help")) {
1963 help_dns_types();
1964 return 0;
1965 }
1966
1967 r = dns_type_from_string(optarg);
1968 if (r < 0) {
1969 log_error("Failed to parse RR record type %s", optarg);
1970 return r;
1971 }
1972 arg_type = (uint16_t) r;
1973 assert((int) arg_type == r);
1974
1975 arg_mode = MODE_RESOLVE_RECORD;
1976 break;
1977
1978 case 'c':
1979 if (streq(optarg, "help")) {
1980 help_dns_classes();
1981 return 0;
1982 }
1983
1984 r = dns_class_from_string(optarg);
1985 if (r < 0) {
1986 log_error("Failed to parse RR record class %s", optarg);
1987 return r;
1988 }
1989 arg_class = (uint16_t) r;
1990 assert((int) arg_class == r);
1991
1992 break;
1993
1994 case ARG_LEGEND:
1995 r = parse_boolean(optarg);
1996 if (r < 0)
1997 return log_error_errno(r, "Failed to parse --legend= argument");
1998
1999 arg_legend = r;
2000 break;
2001
2002 case 'p':
2003 if (streq(optarg, "help")) {
2004 help_protocol_types();
2005 return 0;
2006 } else if (streq(optarg, "dns"))
2007 arg_flags |= SD_RESOLVED_DNS;
2008 else if (streq(optarg, "llmnr"))
2009 arg_flags |= SD_RESOLVED_LLMNR;
2010 else if (streq(optarg, "llmnr-ipv4"))
2011 arg_flags |= SD_RESOLVED_LLMNR_IPV4;
2012 else if (streq(optarg, "llmnr-ipv6"))
2013 arg_flags |= SD_RESOLVED_LLMNR_IPV6;
2014 else if (streq(optarg, "mdns"))
2015 arg_flags |= SD_RESOLVED_MDNS;
2016 else if (streq(optarg, "mdns-ipv4"))
2017 arg_flags |= SD_RESOLVED_MDNS_IPV4;
2018 else if (streq(optarg, "mdns-ipv6"))
2019 arg_flags |= SD_RESOLVED_MDNS_IPV6;
2020 else {
2021 log_error("Unknown protocol specifier: %s", optarg);
2022 return -EINVAL;
2023 }
2024
2025 break;
2026
2027 case ARG_SERVICE:
2028 arg_mode = MODE_RESOLVE_SERVICE;
2029 break;
2030
2031 case ARG_OPENPGP:
2032 arg_mode = MODE_RESOLVE_OPENPGP;
2033 break;
2034
2035 case ARG_TLSA:
2036 arg_mode = MODE_RESOLVE_TLSA;
2037 arg_service_family = service_family_from_string(optarg);
2038 if (arg_service_family < 0) {
2039 log_error("Unknown service family \"%s\".", optarg);
2040 return -EINVAL;
2041 }
2042 break;
2043
2044 case ARG_RAW:
2045 if (on_tty()) {
2046 log_error("Refusing to write binary data to tty.");
2047 return -ENOTTY;
2048 }
2049
2050 if (optarg == NULL || streq(optarg, "payload"))
2051 arg_raw = RAW_PAYLOAD;
2052 else if (streq(optarg, "packet"))
2053 arg_raw = RAW_PACKET;
2054 else {
2055 log_error("Unknown --raw specifier \"%s\".", optarg);
2056 return -EINVAL;
2057 }
2058
2059 arg_legend = false;
2060 break;
2061
2062 case ARG_CNAME:
2063 r = parse_boolean(optarg);
2064 if (r < 0)
2065 return log_error_errno(r, "Failed to parse --cname= argument.");
2066 SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
2067 break;
2068
2069 case ARG_SERVICE_ADDRESS:
2070 r = parse_boolean(optarg);
2071 if (r < 0)
2072 return log_error_errno(r, "Failed to parse --service-address= argument.");
2073 SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
2074 break;
2075
2076 case ARG_SERVICE_TXT:
2077 r = parse_boolean(optarg);
2078 if (r < 0)
2079 return log_error_errno(r, "Failed to parse --service-txt= argument.");
2080 SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
2081 break;
2082
2083 case ARG_SEARCH:
2084 r = parse_boolean(optarg);
2085 if (r < 0)
2086 return log_error_errno(r, "Failed to parse --search argument.");
2087 SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
2088 break;
2089
2090 case ARG_STATISTICS:
2091 arg_mode = MODE_STATISTICS;
2092 break;
2093
2094 case ARG_RESET_STATISTICS:
2095 arg_mode = MODE_RESET_STATISTICS;
2096 break;
2097
2098 case ARG_FLUSH_CACHES:
2099 arg_mode = MODE_FLUSH_CACHES;
2100 break;
2101
2102 case ARG_RESET_SERVER_FEATURES:
2103 arg_mode = MODE_RESET_SERVER_FEATURES;
2104 break;
2105
2106 case ARG_STATUS:
2107 arg_mode = MODE_STATUS;
2108 break;
2109
2110 case ARG_NO_PAGER:
2111 arg_no_pager = true;
2112 break;
2113
2114 case ARG_SET_DNS: {
2115 struct in_addr_data data, *n;
2116
2117 r = in_addr_from_string_auto(optarg, &data.family, &data.address);
2118 if (r < 0)
2119 return log_error_errno(r, "Failed to parse DNS server address: %s", optarg);
2120
2121 n = realloc(arg_set_dns, sizeof(struct in_addr_data) * (arg_n_set_dns + 1));
2122 if (!n)
2123 return log_oom();
2124 arg_set_dns = n;
2125
2126 arg_set_dns[arg_n_set_dns++] = data;
2127 arg_mode = MODE_SET_LINK;
2128 break;
2129 }
2130
2131 case ARG_SET_DOMAIN: {
2132 const char *p;
2133
2134 p = optarg[0] == '~' ? optarg + 1 : optarg;
2135
2136 r = dns_name_is_valid(p);
2137 if (r < 0)
2138 return log_error_errno(r, "Failed to validate specified domain %s: %m", p);
2139 if (r == 0)
2140 return log_error_errno(r, "Domain not valid: %s", p);
2141
2142 r = strv_extend(&arg_set_domain, optarg);
2143 if (r < 0)
2144 return log_oom();
2145
2146 arg_mode = MODE_SET_LINK;
2147 break;
2148 }
2149
2150 case ARG_SET_LLMNR:
2151 r = free_and_strdup(&arg_set_llmnr, optarg);
2152 if (r < 0)
2153 return log_oom();
2154
2155 arg_mode = MODE_SET_LINK;
2156 break;
2157
2158 case ARG_SET_MDNS:
2159 r = free_and_strdup(&arg_set_mdns, optarg);
2160 if (r < 0)
2161 return log_oom();
2162
2163 arg_mode = MODE_SET_LINK;
2164 break;
2165
2166 case ARG_SET_DNSSEC:
2167 r = free_and_strdup(&arg_set_dnssec, optarg);
2168 if (r < 0)
2169 return log_oom();
2170
2171 arg_mode = MODE_SET_LINK;
2172 break;
2173
2174 case ARG_SET_NTA:
2175 r = dns_name_is_valid(optarg);
2176 if (r < 0)
2177 return log_error_errno(r, "Failed to validate specified domain %s: %m", optarg);
2178 if (r == 0)
2179 return log_error_errno(r, "Domain not valid: %s", optarg);
2180
2181 r = strv_extend(&arg_set_nta, optarg);
2182 if (r < 0)
2183 return log_oom();
2184
2185 arg_mode = MODE_SET_LINK;
2186 break;
2187
2188 case ARG_REVERT_LINK:
2189 arg_mode = MODE_REVERT_LINK;
2190 break;
2191
2192 case '?':
2193 return -EINVAL;
2194
2195 default:
2196 assert_not_reached("Unhandled option");
2197 }
2198
2199 if (arg_type == 0 && arg_class != 0) {
2200 log_error("--class= may only be used in conjunction with --type=.");
2201 return -EINVAL;
2202 }
2203
2204 if (arg_type != 0 && arg_mode == MODE_RESOLVE_SERVICE) {
2205 log_error("--service and --type= may not be combined.");
2206 return -EINVAL;
2207 }
2208
2209 if (arg_type != 0 && arg_class == 0)
2210 arg_class = DNS_CLASS_IN;
2211
2212 if (arg_class != 0 && arg_type == 0)
2213 arg_type = DNS_TYPE_A;
2214
2215 if (IN_SET(arg_mode, MODE_SET_LINK, MODE_REVERT_LINK)) {
2216
2217 if (arg_ifindex <= 0) {
2218 log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, --set-nta= and --revert require --interface=.");
2219 return -EINVAL;
2220 }
2221
2222 if (arg_ifindex == LOOPBACK_IFINDEX) {
2223 log_error("Interface can't be the loopback interface (lo). Sorry.");
2224 return -EINVAL;
2225 }
2226 }
2227
2228 return 1 /* work to do */;
2229 }
2230
2231 int main(int argc, char **argv) {
2232 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
2233 int r;
2234
2235 log_parse_environment();
2236 log_open();
2237
2238 r = parse_argv(argc, argv);
2239 if (r <= 0)
2240 goto finish;
2241
2242 r = sd_bus_open_system(&bus);
2243 if (r < 0) {
2244 log_error_errno(r, "sd_bus_open_system: %m");
2245 goto finish;
2246 }
2247
2248 switch (arg_mode) {
2249
2250 case MODE_RESOLVE_HOST:
2251 if (optind >= argc) {
2252 log_error("No arguments passed.");
2253 r = -EINVAL;
2254 goto finish;
2255 }
2256
2257 while (argv[optind]) {
2258 int family, ifindex, k;
2259 union in_addr_union a;
2260
2261 if (startswith(argv[optind], "dns:"))
2262 k = resolve_rfc4501(bus, argv[optind]);
2263 else {
2264 k = in_addr_ifindex_from_string_auto(argv[optind], &family, &a, &ifindex);
2265 if (k >= 0)
2266 k = resolve_address(bus, family, &a, ifindex);
2267 else
2268 k = resolve_host(bus, argv[optind]);
2269 }
2270
2271 if (r == 0)
2272 r = k;
2273
2274 optind++;
2275 }
2276 break;
2277
2278 case MODE_RESOLVE_RECORD:
2279 if (optind >= argc) {
2280 log_error("No arguments passed.");
2281 r = -EINVAL;
2282 goto finish;
2283 }
2284
2285 while (argv[optind]) {
2286 int k;
2287
2288 k = resolve_record(bus, argv[optind], arg_class, arg_type, true);
2289 if (r == 0)
2290 r = k;
2291
2292 optind++;
2293 }
2294 break;
2295
2296 case MODE_RESOLVE_SERVICE:
2297 if (argc < optind + 1) {
2298 log_error("Domain specification required.");
2299 r = -EINVAL;
2300 goto finish;
2301
2302 } else if (argc == optind + 1)
2303 r = resolve_service(bus, NULL, NULL, argv[optind]);
2304 else if (argc == optind + 2)
2305 r = resolve_service(bus, NULL, argv[optind], argv[optind+1]);
2306 else if (argc == optind + 3)
2307 r = resolve_service(bus, argv[optind], argv[optind+1], argv[optind+2]);
2308 else {
2309 log_error("Too many arguments.");
2310 r = -EINVAL;
2311 goto finish;
2312 }
2313
2314 break;
2315
2316 case MODE_RESOLVE_OPENPGP:
2317 if (argc < optind + 1) {
2318 log_error("E-mail address required.");
2319 r = -EINVAL;
2320 goto finish;
2321
2322 }
2323
2324 r = 0;
2325 while (optind < argc) {
2326 int k;
2327
2328 k = resolve_openpgp(bus, argv[optind++]);
2329 if (k < 0)
2330 r = k;
2331 }
2332 break;
2333
2334 case MODE_RESOLVE_TLSA:
2335 if (argc < optind + 1) {
2336 log_error("Domain name required.");
2337 r = -EINVAL;
2338 goto finish;
2339
2340 }
2341
2342 r = 0;
2343 while (optind < argc) {
2344 int k;
2345
2346 k = resolve_tlsa(bus, argv[optind++]);
2347 if (k < 0)
2348 r = k;
2349 }
2350 break;
2351
2352 case MODE_STATISTICS:
2353 if (argc > optind) {
2354 log_error("Too many arguments.");
2355 r = -EINVAL;
2356 goto finish;
2357 }
2358
2359 r = show_statistics(bus);
2360 break;
2361
2362 case MODE_RESET_STATISTICS:
2363 if (argc > optind) {
2364 log_error("Too many arguments.");
2365 r = -EINVAL;
2366 goto finish;
2367 }
2368
2369 r = reset_statistics(bus);
2370 break;
2371
2372 case MODE_FLUSH_CACHES:
2373 if (argc > optind) {
2374 log_error("Too many arguments.");
2375 r = -EINVAL;
2376 goto finish;
2377 }
2378
2379 r = flush_caches(bus);
2380 break;
2381
2382 case MODE_RESET_SERVER_FEATURES:
2383 if (argc > optind) {
2384 log_error("Too many arguments.");
2385 r = -EINVAL;
2386 goto finish;
2387 }
2388
2389 r = reset_server_features(bus);
2390 break;
2391
2392 case MODE_STATUS:
2393
2394 if (argc > optind) {
2395 char **ifname;
2396 bool empty_line = false;
2397
2398 r = 0;
2399 STRV_FOREACH(ifname, argv + optind) {
2400 int ifindex, q;
2401
2402 q = parse_ifindex(argv[optind], &ifindex);
2403 if (q < 0) {
2404 ifindex = if_nametoindex(argv[optind]);
2405 if (ifindex <= 0) {
2406 log_error_errno(errno, "Failed to resolve interface name: %s", argv[optind]);
2407 continue;
2408 }
2409 }
2410
2411 q = status_ifindex(bus, ifindex, NULL, &empty_line);
2412 if (q < 0 && r >= 0)
2413 r = q;
2414 }
2415 } else
2416 r = status_all(bus);
2417
2418 break;
2419
2420
2421 case MODE_SET_LINK:
2422 if (argc > optind) {
2423 log_error("Too many arguments.");
2424 r = -EINVAL;
2425 goto finish;
2426 }
2427
2428 r = set_link(bus);
2429 break;
2430
2431 case MODE_REVERT_LINK:
2432 if (argc > optind) {
2433 log_error("Too many arguments.");
2434 r = -EINVAL;
2435 goto finish;
2436 }
2437
2438 r = revert_link(bus);
2439 break;
2440 }
2441
2442 finish:
2443 pager_close();
2444
2445 free(arg_set_dns);
2446 strv_free(arg_set_domain);
2447 free(arg_set_llmnr);
2448 free(arg_set_mdns);
2449 free(arg_set_dnssec);
2450 strv_free(arg_set_nta);
2451
2452 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
2453 }