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