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