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