]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
resolved: add enablers for DNS-SD
[thirdparty/systemd.git] / src / resolve / resolved-manager.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
091a364c
TG
2/***
3 This file is part of systemd.
4
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
07630cea
LP
21#include <netinet/in.h>
22#include <poll.h>
74b2466e 23#include <sys/ioctl.h>
091a364c 24
349cc4a5 25#if HAVE_LIBIDN2
87057e24
ZJS
26#include <idn2.h>
27#endif
28
a2a416f7 29#include "af-list.h"
b5efdb8a 30#include "alloc-util.h"
943ef07c 31#include "dirent-util.h"
07630cea 32#include "dns-domain.h"
3ffd4af2 33#include "fd-util.h"
a5a807e6 34#include "fileio-label.h"
07630cea 35#include "hostname-util.h"
c004493c 36#include "io-util.h"
07630cea
LP
37#include "netlink-util.h"
38#include "network-internal.h"
822db23c 39#include "ordered-set.h"
6bedfcbb 40#include "parse-util.h"
3df3e884 41#include "random-util.h"
39d8db04 42#include "resolved-bus.h"
07630cea 43#include "resolved-conf.h"
6501dd31 44#include "resolved-dnssd.h"
b30bf55d 45#include "resolved-dns-stub.h"
dd0bc0f1 46#include "resolved-etc-hosts.h"
5f402ae8 47#include "resolved-llmnr.h"
07630cea 48#include "resolved-manager.h"
bc7702b0 49#include "resolved-mdns.h"
dd0bc0f1 50#include "resolved-resolv-conf.h"
07630cea 51#include "socket-util.h"
8b43440b 52#include "string-table.h"
07630cea
LP
53#include "string-util.h"
54#include "utf8.h"
74b2466e
LP
55
56#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
57
1c4baffc 58static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e
LP
59 Manager *m = userdata;
60 uint16_t type;
61 Link *l;
62 int ifindex, r;
63
64 assert(rtnl);
65 assert(m);
66 assert(mm);
67
1c4baffc 68 r = sd_netlink_message_get_type(mm, &type);
74b2466e
LP
69 if (r < 0)
70 goto fail;
71
72 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
73 if (r < 0)
74 goto fail;
75
76 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
77
78 switch (type) {
79
a2a416f7
LP
80 case RTM_NEWLINK:{
81 bool is_new = !l;
74b2466e 82
a2a416f7 83 if (!l) {
74b2466e
LP
84 r = link_new(m, &l, ifindex);
85 if (r < 0)
86 goto fail;
87 }
88
943ef07c 89 r = link_process_rtnl(l, mm);
74b2466e
LP
90 if (r < 0)
91 goto fail;
92
943ef07c 93 r = link_update(l);
21d73c87
LP
94 if (r < 0)
95 goto fail;
96
a2a416f7
LP
97 if (is_new)
98 log_debug("Found new link %i/%s", ifindex, l->name);
99
74b2466e 100 break;
a2a416f7 101 }
74b2466e
LP
102
103 case RTM_DELLINK:
104 if (l) {
a2a416f7 105 log_debug("Removing link %i/%s", l->ifindex, l->name);
943ef07c 106 link_remove_user(l);
74b2466e
LP
107 link_free(l);
108 }
109
110 break;
111 }
112
113 return 0;
114
115fail:
da927ba9 116 log_warning_errno(r, "Failed to process RTNL link message: %m");
74b2466e
LP
117 return 0;
118}
119
1c4baffc 120static int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e
LP
121 Manager *m = userdata;
122 union in_addr_union address;
74b2466e 123 uint16_t type;
0dd25fb9 124 int r, ifindex, family;
74b2466e
LP
125 LinkAddress *a;
126 Link *l;
127
128 assert(rtnl);
129 assert(mm);
130 assert(m);
131
1c4baffc 132 r = sd_netlink_message_get_type(mm, &type);
74b2466e
LP
133 if (r < 0)
134 goto fail;
135
136 r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
137 if (r < 0)
138 goto fail;
139
140 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
141 if (!l)
142 return 0;
143
144 r = sd_rtnl_message_addr_get_family(mm, &family);
145 if (r < 0)
146 goto fail;
147
148 switch (family) {
149
150 case AF_INET:
1c4baffc 151 r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
74b2466e 152 if (r < 0) {
1c4baffc 153 r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
74b2466e
LP
154 if (r < 0)
155 goto fail;
156 }
157
158 break;
159
160 case AF_INET6:
1c4baffc 161 r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
74b2466e 162 if (r < 0) {
1c4baffc 163 r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e
LP
164 if (r < 0)
165 goto fail;
166 }
167
168 break;
169
170 default:
171 return 0;
172 }
173
174 a = link_find_address(l, family, &address);
175
176 switch (type) {
177
178 case RTM_NEWADDR:
179
180 if (!a) {
181 r = link_address_new(l, &a, family, &address);
182 if (r < 0)
183 return r;
184 }
185
186 r = link_address_update_rtnl(a, mm);
187 if (r < 0)
188 return r;
189
190 break;
191
192 case RTM_DELADDR:
3e044c49 193 link_address_free(a);
74b2466e
LP
194 break;
195 }
196
197 return 0;
198
199fail:
da927ba9 200 log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e
LP
201 return 0;
202}
203
74b2466e 204static int manager_rtnl_listen(Manager *m) {
4afd3348 205 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
1c4baffc 206 sd_netlink_message *i;
74b2466e
LP
207 int r;
208
209 assert(m);
210
cc98b302 211 /* First, subscribe to interfaces coming and going */
1c4baffc 212 r = sd_netlink_open(&m->rtnl);
74b2466e
LP
213 if (r < 0)
214 return r;
215
2d895038 216 r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT);
74b2466e
LP
217 if (r < 0)
218 return r;
219
1c4baffc 220 r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
74b2466e
LP
221 if (r < 0)
222 return r;
223
1c4baffc 224 r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
74b2466e
LP
225 if (r < 0)
226 return r;
227
1c4baffc 228 r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e
LP
229 if (r < 0)
230 return r;
091a364c 231
1c4baffc 232 r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e
LP
233 if (r < 0)
234 return r;
235
236 /* Then, enumerate all links */
237 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
238 if (r < 0)
239 return r;
240
1c4baffc 241 r = sd_netlink_message_request_dump(req, true);
74b2466e
LP
242 if (r < 0)
243 return r;
244
1c4baffc 245 r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e
LP
246 if (r < 0)
247 return r;
248
1c4baffc 249 for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e
LP
250 r = manager_process_link(m->rtnl, i, m);
251 if (r < 0)
252 return r;
253 }
254
1c4baffc
TG
255 req = sd_netlink_message_unref(req);
256 reply = sd_netlink_message_unref(reply);
74b2466e
LP
257
258 /* Finally, enumerate all addresses, too */
259 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
260 if (r < 0)
261 return r;
262
1c4baffc 263 r = sd_netlink_message_request_dump(req, true);
74b2466e
LP
264 if (r < 0)
265 return r;
266
1c4baffc 267 r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e
LP
268 if (r < 0)
269 return r;
270
1c4baffc 271 for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e
LP
272 r = manager_process_address(m->rtnl, i, m);
273 if (r < 0)
274 return r;
275 }
276
277 return r;
278}
279
280static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
281 Manager *m = userdata;
282 Iterator i;
283 Link *l;
284 int r;
285
286 assert(m);
287
288 sd_network_monitor_flush(m->network_monitor);
289
290 HASHMAP_FOREACH(l, m->links, i) {
943ef07c 291 r = link_update(l);
74b2466e 292 if (r < 0)
da927ba9 293 log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
74b2466e
LP
294 }
295
7207052d 296 (void) manager_write_resolv_conf(m);
74b2466e
LP
297
298 return 0;
299}
300
301static int manager_network_monitor_listen(Manager *m) {
302 int r, fd, events;
303
304 assert(m);
305
0014a4ad 306 r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e
LP
307 if (r < 0)
308 return r;
309
310 fd = sd_network_monitor_get_fd(m->network_monitor);
311 if (fd < 0)
312 return fd;
313
314 events = sd_network_monitor_get_events(m->network_monitor);
315 if (events < 0)
316 return events;
317
318 r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
319 if (r < 0)
2d895038
LP
320 return r;
321
322 r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5);
323 if (r < 0)
74b2466e
LP
324 return r;
325
aa4a9deb
LP
326 (void) sd_event_source_set_description(m->network_event_source, "network-monitor");
327
74b2466e
LP
328 return 0;
329}
330
e96de0ce 331static int determine_hostname(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) {
eb60f9cd 332 _cleanup_free_ char *h = NULL, *n = NULL;
349cc4a5 333#if HAVE_LIBIDN2
87057e24 334 _cleanup_free_ char *utf8 = NULL;
349cc4a5 335#elif HAVE_LIBIDN
87057e24
ZJS
336 int k;
337#endif
78c6a153 338 char label[DNS_LABEL_MAX];
87057e24
ZJS
339 const char *p, *decoded;
340 int r;
eb60f9cd 341
e96de0ce 342 assert(full_hostname);
78c6a153
LP
343 assert(llmnr_hostname);
344 assert(mdns_hostname);
345
a25b0dc8 346 /* Extract and normalize the first label of the locally configured hostname, and check it's not "localhost". */
eb60f9cd 347
a25b0dc8
LP
348 r = gethostname_strict(&h);
349 if (r < 0)
350 return log_debug_errno(r, "Can't determine system hostname: %m");
eb60f9cd 351
78c6a153 352 p = h;
87057e24 353 r = dns_label_unescape(&p, label, sizeof label);
78c6a153
LP
354 if (r < 0)
355 return log_error_errno(r, "Failed to unescape host name: %m");
356 if (r == 0) {
a25b0dc8 357 log_error("Couldn't find a single label in hostname.");
78c6a153
LP
358 return -EINVAL;
359 }
360
349cc4a5 361#if HAVE_LIBIDN2
87057e24
ZJS
362 r = idn2_to_unicode_8z8z(label, &utf8, 0);
363 if (r != IDN2_OK)
364 return log_error("Failed to undo IDNA: %s", idn2_strerror(r));
365 assert(utf8_is_valid(utf8));
366
367 r = strlen(utf8);
368 decoded = utf8;
349cc4a5 369#elif HAVE_LIBIDN
87057e24 370 k = dns_label_undo_idna(label, r, label, sizeof label);
78c6a153
LP
371 if (k < 0)
372 return log_error_errno(k, "Failed to undo IDNA: %m");
373 if (k > 0)
374 r = k;
375
376 if (!utf8_is_valid(label)) {
eb60f9cd
LP
377 log_error("System hostname is not UTF-8 clean.");
378 return -EINVAL;
379 }
87057e24
ZJS
380 decoded = label;
381#else
382 decoded = label; /* no decoding */
383#endif
eb60f9cd 384
87057e24 385 r = dns_label_escape_new(decoded, r, &n);
78c6a153
LP
386 if (r < 0)
387 return log_error_errno(r, "Failed to escape host name: %m");
388
389 if (is_localhost(n)) {
390 log_debug("System hostname is 'localhost', ignoring.");
391 return -EINVAL;
eb60f9cd
LP
392 }
393
78c6a153
LP
394 r = dns_name_concat(n, "local", mdns_hostname);
395 if (r < 0)
396 return log_error_errno(r, "Failed to determine mDNS hostname: %m");
397
398 *llmnr_hostname = n;
eb60f9cd
LP
399 n = NULL;
400
e96de0ce
LP
401 *full_hostname = h;
402 h = NULL;
403
eb60f9cd
LP
404 return 0;
405}
406
a25b0dc8
LP
407static const char *fallback_hostname(void) {
408
409 /* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it to be
410 * "localhost" even if that's the compiled in hostname. In this case, let's revert to "linux" instead. */
411
412 if (is_localhost(FALLBACK_HOSTNAME))
413 return "linux";
414
415 return FALLBACK_HOSTNAME;
416}
417
418static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) {
419 _cleanup_free_ char *n = NULL, *m = NULL;
420 char label[DNS_LABEL_MAX], *h;
421 const char *p;
422 int r;
423
424 assert(full_hostname);
425 assert(llmnr_hostname);
426 assert(mdns_hostname);
427
428 p = fallback_hostname();
429 r = dns_label_unescape(&p, label, sizeof(label));
430 if (r < 0)
431 return log_error_errno(r, "Failed to unescape fallback host name: %m");
432
433 assert(r > 0); /* The fallback hostname must have at least one label */
434
435 r = dns_label_escape_new(label, r, &n);
436 if (r < 0)
437 return log_error_errno(r, "Failed to escape fallback hostname: %m");
438
439 r = dns_name_concat(n, "local", &m);
440 if (r < 0)
441 return log_error_errno(r, "Failed to concatenate mDNS hostname: %m");
442
443 h = strdup(fallback_hostname());
444 if (!h)
445 return log_oom();
446
447 *llmnr_hostname = n;
448 n = NULL;
449
450 *mdns_hostname = m;
451 m = NULL;
452
453 *full_hostname = h;
454
455 return 0;
456}
457
eb60f9cd 458static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
e96de0ce 459 _cleanup_free_ char *full_hostname = NULL, *llmnr_hostname = NULL, *mdns_hostname = NULL;
eb60f9cd
LP
460 Manager *m = userdata;
461 int r;
462
463 assert(m);
464
e96de0ce 465 r = determine_hostname(&full_hostname, &llmnr_hostname, &mdns_hostname);
eb60f9cd
LP
466 if (r < 0)
467 return 0; /* ignore invalid hostnames */
468
e96de0ce
LP
469 if (streq(full_hostname, m->full_hostname) &&
470 streq(llmnr_hostname, m->llmnr_hostname) &&
471 streq(mdns_hostname, m->mdns_hostname))
eb60f9cd
LP
472 return 0;
473
e96de0ce 474 log_info("System hostname changed to '%s'.", full_hostname);
78c6a153 475
e96de0ce
LP
476 free_and_replace(m->full_hostname, full_hostname);
477 free_and_replace(m->llmnr_hostname, llmnr_hostname);
478 free_and_replace(m->mdns_hostname, mdns_hostname);
eb60f9cd
LP
479
480 manager_refresh_rrs(m);
481
482 return 0;
483}
484
485static int manager_watch_hostname(Manager *m) {
eb60f9cd
LP
486 int r;
487
488 assert(m);
489
490 m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
491 if (m->hostname_fd < 0) {
56f64d95 492 log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd
LP
493 return 0;
494 }
495
496 r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
497 if (r < 0) {
498 if (r == -EPERM)
499 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
500 m->hostname_fd = safe_close(m->hostname_fd);
8d3d7072
MS
501 else
502 return log_error_errno(r, "Failed to add hostname event source: %m");
eb60f9cd
LP
503 }
504
aa4a9deb
LP
505 (void) sd_event_source_set_description(m->hostname_event_source, "hostname");
506
e96de0ce 507 r = determine_hostname(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname);
eb60f9cd 508 if (r < 0) {
a25b0dc8 509 log_info("Defaulting to hostname '%s'.", fallback_hostname());
78c6a153 510
a25b0dc8
LP
511 r = make_fallback_hostnames(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname);
512 if (r < 0)
513 return r;
eb60f9cd 514 } else
e96de0ce 515 log_info("Using system hostname '%s'.", m->full_hostname);
eb60f9cd
LP
516
517 return 0;
518}
519
4d506d6b
LP
520static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
521 _cleanup_free_ char *buffer = NULL;
522 _cleanup_fclose_ FILE *f = NULL;
523 Manager *m = userdata;
cf84484a 524 DnsServer *server;
4d506d6b
LP
525 size_t size = 0;
526 DnsScope *scope;
cf84484a
LP
527 Iterator i;
528 Link *l;
4d506d6b
LP
529
530 assert(s);
531 assert(si);
532 assert(m);
533
534 f = open_memstream(&buffer, &size);
535 if (!f)
536 return log_oom();
537
538 LIST_FOREACH(scopes, scope, m->dns_scopes)
539 dns_scope_dump(scope, f);
540
cf84484a
LP
541 LIST_FOREACH(servers, server, m->dns_servers)
542 dns_server_dump(server, f);
543 LIST_FOREACH(servers, server, m->fallback_dns_servers)
544 dns_server_dump(server, f);
545 HASHMAP_FOREACH(l, m->links, i)
546 LIST_FOREACH(servers, server, l->dns_servers)
547 dns_server_dump(server, f);
548
4d506d6b
LP
549 if (fflush_and_check(f) < 0)
550 return log_oom();
551
552 log_dump(LOG_INFO, buffer);
553 return 0;
554}
555
bc81447e
LP
556static int manager_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
557 Manager *m = userdata;
bc81447e
LP
558
559 assert(s);
560 assert(si);
561 assert(m);
562
ba35662f 563 manager_flush_caches(m);
ba35662f 564
bc81447e
LP
565 return 0;
566}
567
d55b0463
LP
568static int manager_sigrtmin1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
569 Manager *m = userdata;
570
571 assert(s);
572 assert(si);
573 assert(m);
574
575 manager_reset_server_features(m);
576 return 0;
577}
578
091a364c 579int manager_new(Manager **ret) {
74b2466e 580 _cleanup_(manager_freep) Manager *m = NULL;
091a364c
TG
581 int r;
582
c92e531c
LP
583 assert(ret);
584
091a364c
TG
585 m = new0(Manager, 1);
586 if (!m)
587 return -ENOMEM;
588
1716f6dc 589 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97 590 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
bc7702b0 591 m->mdns_ipv4_fd = m->mdns_ipv6_fd = -1;
b30bf55d 592 m->dns_stub_udp_fd = m->dns_stub_tcp_fd = -1;
eb60f9cd 593 m->hostname_fd = -1;
1716f6dc 594
af49ca27 595 m->llmnr_support = RESOLVE_SUPPORT_YES;
7bef8e8e 596 m->mdns_support = RESOLVE_SUPPORT_YES;
61ecb465 597 m->dnssec_mode = DEFAULT_DNSSEC_MODE;
ceeddf79 598 m->enable_cache = true;
1ae43295 599 m->dns_stub_listener_mode = DNS_STUB_LISTENER_UDP;
5cb36f41 600 m->read_resolv_conf = true;
00fa60ae 601 m->need_builtin_fallbacks = true;
dd0bc0f1 602 m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY;
091a364c 603
0d2cd476
LP
604 r = dns_trust_anchor_load(&m->trust_anchor);
605 if (r < 0)
606 return r;
607
ad6c0475
LP
608 r = manager_parse_config_file(m);
609 if (r < 0)
5ce497b5 610 log_warning_errno(r, "Failed to parse configuration file: %m");
ad6c0475 611
091a364c
TG
612 r = sd_event_default(&m->event);
613 if (r < 0)
614 return r;
615
616 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
617 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
618
619 sd_event_set_watchdog(m->event, true);
620
eb60f9cd
LP
621 r = manager_watch_hostname(m);
622 if (r < 0)
623 return r;
624
6501dd31
DR
625 r = dnssd_load(m);
626 if (r < 0)
627 log_warning_errno(r, "Failed to load DNS-SD configuration files: %m");
628
1716f6dc 629 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
630 if (r < 0)
631 return r;
632
633 r = manager_network_monitor_listen(m);
634 if (r < 0)
635 return r;
636
637 r = manager_rtnl_listen(m);
638 if (r < 0)
639 return r;
640
641 r = manager_connect_bus(m);
642 if (r < 0)
643 return r;
644
4d506d6b 645 (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
bc81447e 646 (void) sd_event_add_signal(m->event, &m->sigusr2_event_source, SIGUSR2, manager_sigusr2, m);
d55b0463 647 (void) sd_event_add_signal(m->event, &m->sigrtmin1_event_source, SIGRTMIN+1, manager_sigrtmin1, m);
4d506d6b 648
943ef07c
LP
649 manager_cleanup_saved_user(m);
650
091a364c
TG
651 *ret = m;
652 m = NULL;
653
654 return 0;
655}
656
edc501d4
LP
657int manager_start(Manager *m) {
658 int r;
659
660 assert(m);
661
b30bf55d
LP
662 r = manager_dns_stub_start(m);
663 if (r < 0)
664 return r;
665
edc501d4
LP
666 return 0;
667}
668
74b2466e
LP
669Manager *manager_free(Manager *m) {
670 Link *l;
6501dd31 671 DnssdService *s;
091a364c
TG
672
673 if (!m)
74b2466e
LP
674 return NULL;
675
4b95f179
LP
676 dns_server_unlink_all(m->dns_servers);
677 dns_server_unlink_all(m->fallback_dns_servers);
a51c1048
LP
678 dns_search_domain_unlink_all(m->search_domains);
679
74b2466e
LP
680 while ((l = hashmap_first(m->links)))
681 link_free(l);
f0e15467
LP
682
683 while (m->dns_queries)
684 dns_query_free(m->dns_queries);
74b2466e 685
cab5b059
LP
686 dns_scope_free(m->unicast_scope);
687
b30bf55d
LP
688 /* At this point only orphaned streams should remain. All others should have been freed already by their
689 * owners */
690 while (m->dns_streams)
691 dns_stream_unref(m->dns_streams);
692
f0e15467
LP
693 hashmap_free(m->links);
694 hashmap_free(m->dns_transactions);
695
096b6773
LP
696 sd_event_source_unref(m->network_event_source);
697 sd_network_monitor_unref(m->network_monitor);
091a364c 698
a564ca2f
LP
699 sd_netlink_unref(m->rtnl);
700 sd_event_source_unref(m->rtnl_event_source);
701
edc501d4 702 manager_llmnr_stop(m);
bc7702b0 703 manager_mdns_stop(m);
b30bf55d 704 manager_dns_stub_stop(m);
623a4c97 705
902bb5d8 706 sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e
LP
707 sd_event_source_unref(m->bus_retry_event_source);
708 sd_bus_unref(m->bus);
091a364c 709
4d506d6b 710 sd_event_source_unref(m->sigusr1_event_source);
bc81447e 711 sd_event_source_unref(m->sigusr2_event_source);
d55b0463 712 sd_event_source_unref(m->sigrtmin1_event_source);
4d506d6b 713
74b2466e 714 sd_event_unref(m->event);
623a4c97 715
78c6a153
LP
716 dns_resource_key_unref(m->llmnr_host_ipv4_key);
717 dns_resource_key_unref(m->llmnr_host_ipv6_key);
400cb36e
DR
718 dns_resource_key_unref(m->mdns_host_ipv4_key);
719 dns_resource_key_unref(m->mdns_host_ipv6_key);
eb60f9cd 720
eb60f9cd 721 sd_event_source_unref(m->hostname_event_source);
d9fcf2ba 722 safe_close(m->hostname_fd);
e96de0ce
LP
723
724 free(m->full_hostname);
78c6a153
LP
725 free(m->llmnr_hostname);
726 free(m->mdns_hostname);
eb60f9cd 727
6501dd31
DR
728 while ((s = hashmap_first(m->dnssd_services)))
729 dnssd_service_free(s);
730 hashmap_free(m->dnssd_services);
731
0d2cd476 732 dns_trust_anchor_flush(&m->trust_anchor);
dd0bc0f1 733 manager_etc_hosts_flush(m);
0d2cd476 734
6b430fdb 735 return mfree(m);
091a364c
TG
736}
737
1716f6dc 738int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 739 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
740 union {
741 struct cmsghdr header; /* For alignment */
40a1eebd 742 uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
1716f6dc 743 + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97 744 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dc
LP
745 } control;
746 union sockaddr_union sa;
74b2466e 747 struct msghdr mh = {};
1716f6dc 748 struct cmsghdr *cmsg;
74b2466e 749 struct iovec iov;
4edc2c9b
LP
750 ssize_t ms, l;
751 int r;
74b2466e
LP
752
753 assert(m);
1716f6dc 754 assert(fd >= 0);
74b2466e
LP
755 assert(ret);
756
4edc2c9b 757 ms = next_datagram_size_fd(fd);
74b2466e 758 if (ms < 0)
4edc2c9b 759 return ms;
74b2466e 760
51027656 761 r = dns_packet_new(&p, protocol, ms, DNS_PACKET_SIZE_MAX);
74b2466e
LP
762 if (r < 0)
763 return r;
764
765 iov.iov_base = DNS_PACKET_DATA(p);
766 iov.iov_len = p->allocated;
767
1716f6dc
LP
768 mh.msg_name = &sa.sa;
769 mh.msg_namelen = sizeof(sa);
74b2466e
LP
770 mh.msg_iov = &iov;
771 mh.msg_iovlen = 1;
1716f6dc
LP
772 mh.msg_control = &control;
773 mh.msg_controllen = sizeof(control);
74b2466e 774
a38d9945 775 l = recvmsg(fd, &mh, 0);
f134289a
EV
776 if (l == 0)
777 return 0;
74b2466e 778 if (l < 0) {
4c701096 779 if (IN_SET(errno, EAGAIN, EINTR))
74b2466e
LP
780 return 0;
781
782 return -errno;
091a364c
TG
783 }
784
1716f6dc
LP
785 assert(!(mh.msg_flags & MSG_CTRUNC));
786 assert(!(mh.msg_flags & MSG_TRUNC));
787
74b2466e 788 p->size = (size_t) l;
091a364c 789
1716f6dc 790 p->family = sa.sa.sa_family;
623a4c97
LP
791 p->ipproto = IPPROTO_UDP;
792 if (p->family == AF_INET) {
1716f6dc 793 p->sender.in = sa.in.sin_addr;
623a4c97
LP
794 p->sender_port = be16toh(sa.in.sin_port);
795 } else if (p->family == AF_INET6) {
1716f6dc 796 p->sender.in6 = sa.in6.sin6_addr;
623a4c97
LP
797 p->sender_port = be16toh(sa.in6.sin6_port);
798 p->ifindex = sa.in6.sin6_scope_id;
799 } else
1716f6dc 800 return -EAFNOSUPPORT;
74b2466e 801
2a1288ff 802 CMSG_FOREACH(cmsg, &mh) {
74b2466e 803
1716f6dc
LP
804 if (cmsg->cmsg_level == IPPROTO_IPV6) {
805 assert(p->family == AF_INET6);
74b2466e 806
1716f6dc 807 switch (cmsg->cmsg_type) {
74b2466e 808
1716f6dc
LP
809 case IPV6_PKTINFO: {
810 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 811
623a4c97
LP
812 if (p->ifindex <= 0)
813 p->ifindex = i->ipi6_ifindex;
814
1716f6dc
LP
815 p->destination.in6 = i->ipi6_addr;
816 break;
817 }
74b2466e 818
1716f6dc
LP
819 case IPV6_HOPLIMIT:
820 p->ttl = *(int *) CMSG_DATA(cmsg);
821 break;
74b2466e 822
1716f6dc
LP
823 }
824 } else if (cmsg->cmsg_level == IPPROTO_IP) {
825 assert(p->family == AF_INET);
74b2466e 826
1716f6dc 827 switch (cmsg->cmsg_type) {
74b2466e 828
1716f6dc
LP
829 case IP_PKTINFO: {
830 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 831
623a4c97
LP
832 if (p->ifindex <= 0)
833 p->ifindex = i->ipi_ifindex;
834
1716f6dc
LP
835 p->destination.in = i->ipi_addr;
836 break;
837 }
74b2466e 838
623a4c97 839 case IP_TTL:
1716f6dc
LP
840 p->ttl = *(int *) CMSG_DATA(cmsg);
841 break;
842 }
843 }
844 }
74b2466e 845
623a4c97
LP
846 /* The Linux kernel sets the interface index to the loopback
847 * device if the packet came from the local host since it
848 * avoids the routing table in such a case. Let's unset the
849 * interface index in such a case. */
a5f03596 850 if (p->ifindex == LOOPBACK_IFINDEX)
623a4c97
LP
851 p->ifindex = 0;
852
86ad4cd7
TG
853 if (protocol != DNS_PROTOCOL_DNS) {
854 /* If we don't know the interface index still, we look for the
855 * first local interface with a matching address. Yuck! */
856 if (p->ifindex <= 0)
857 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
858 }
623a4c97 859
74b2466e
LP
860 *ret = p;
861 p = NULL;
862
863 return 1;
864}
865
74b2466e
LP
866static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
867 int r;
868
869 assert(fd >= 0);
870 assert(mh);
871
872 for (;;) {
873 if (sendmsg(fd, mh, flags) >= 0)
874 return 0;
875
876 if (errno == EINTR)
877 continue;
878
879 if (errno != EAGAIN)
880 return -errno;
881
882 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
883 if (r < 0)
884 return r;
885 if (r == 0)
886 return -ETIMEDOUT;
887 }
888}
889
72290734
TG
890static int write_loop(int fd, void *message, size_t length) {
891 int r;
892
893 assert(fd >= 0);
894 assert(message);
895
896 for (;;) {
897 if (write(fd, message, length) >= 0)
898 return 0;
899
900 if (errno == EINTR)
901 continue;
902
903 if (errno != EAGAIN)
904 return -errno;
905
906 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
907 if (r < 0)
908 return r;
909 if (r == 0)
910 return -ETIMEDOUT;
911 }
912}
913
914int manager_write(Manager *m, int fd, DnsPacket *p) {
915 int r;
916
deb3f3d3 917 log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
72290734
TG
918
919 r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
920 if (r < 0)
921 return r;
922
923 return 0;
924}
925
b30bf55d
LP
926static int manager_ipv4_send(
927 Manager *m,
928 int fd,
929 int ifindex,
930 const struct in_addr *destination,
931 uint16_t port,
932 const struct in_addr *source,
933 DnsPacket *p) {
74b2466e
LP
934 union sockaddr_union sa = {
935 .in.sin_family = AF_INET,
74b2466e 936 };
1716f6dc
LP
937 union {
938 struct cmsghdr header; /* For alignment */
939 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
940 } control;
74b2466e
LP
941 struct msghdr mh = {};
942 struct iovec iov;
74b2466e
LP
943
944 assert(m);
1716f6dc 945 assert(fd >= 0);
b30bf55d 946 assert(destination);
1716f6dc 947 assert(port > 0);
74b2466e
LP
948 assert(p);
949
74b2466e
LP
950 iov.iov_base = DNS_PACKET_DATA(p);
951 iov.iov_len = p->size;
091a364c 952
b30bf55d 953 sa.in.sin_addr = *destination;
1716f6dc 954 sa.in.sin_port = htobe16(port),
091a364c 955
74b2466e
LP
956 mh.msg_iov = &iov;
957 mh.msg_iovlen = 1;
958 mh.msg_name = &sa.sa;
959 mh.msg_namelen = sizeof(sa.in);
091a364c 960
74b2466e
LP
961 if (ifindex > 0) {
962 struct cmsghdr *cmsg;
963 struct in_pktinfo *pi;
964
965 zero(control);
966
1716f6dc 967 mh.msg_control = &control;
74b2466e
LP
968 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
969
970 cmsg = CMSG_FIRSTHDR(&mh);
971 cmsg->cmsg_len = mh.msg_controllen;
972 cmsg->cmsg_level = IPPROTO_IP;
973 cmsg->cmsg_type = IP_PKTINFO;
974
975 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
976 pi->ipi_ifindex = ifindex;
b30bf55d
LP
977
978 if (source)
979 pi->ipi_spec_dst = *source;
74b2466e
LP
980 }
981
982 return sendmsg_loop(fd, &mh, 0);
983}
984
b30bf55d
LP
985static int manager_ipv6_send(
986 Manager *m,
987 int fd,
988 int ifindex,
989 const struct in6_addr *destination,
990 uint16_t port,
991 const struct in6_addr *source,
992 DnsPacket *p) {
993
74b2466e
LP
994 union sockaddr_union sa = {
995 .in6.sin6_family = AF_INET6,
74b2466e 996 };
1716f6dc
LP
997 union {
998 struct cmsghdr header; /* For alignment */
999 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1000 } control;
74b2466e
LP
1001 struct msghdr mh = {};
1002 struct iovec iov;
74b2466e
LP
1003
1004 assert(m);
1716f6dc 1005 assert(fd >= 0);
b30bf55d 1006 assert(destination);
1716f6dc 1007 assert(port > 0);
74b2466e
LP
1008 assert(p);
1009
74b2466e
LP
1010 iov.iov_base = DNS_PACKET_DATA(p);
1011 iov.iov_len = p->size;
1012
b30bf55d 1013 sa.in6.sin6_addr = *destination;
1716f6dc 1014 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
1015 sa.in6.sin6_scope_id = ifindex;
1016
1017 mh.msg_iov = &iov;
1018 mh.msg_iovlen = 1;
1019 mh.msg_name = &sa.sa;
1020 mh.msg_namelen = sizeof(sa.in6);
1021
1022 if (ifindex > 0) {
1023 struct cmsghdr *cmsg;
1024 struct in6_pktinfo *pi;
1025
1026 zero(control);
1027
1716f6dc 1028 mh.msg_control = &control;
74b2466e
LP
1029 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
1030
1031 cmsg = CMSG_FIRSTHDR(&mh);
1032 cmsg->cmsg_len = mh.msg_controllen;
1033 cmsg->cmsg_level = IPPROTO_IPV6;
1034 cmsg->cmsg_type = IPV6_PKTINFO;
1035
1036 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
1037 pi->ipi6_ifindex = ifindex;
b30bf55d
LP
1038
1039 if (source)
1040 pi->ipi6_addr = *source;
74b2466e
LP
1041 }
1042
1043 return sendmsg_loop(fd, &mh, 0);
1044}
1045
b30bf55d
LP
1046int manager_send(
1047 Manager *m,
1048 int fd,
1049 int ifindex,
1050 int family,
1051 const union in_addr_union *destination,
1052 uint16_t port,
1053 const union in_addr_union *source,
1054 DnsPacket *p) {
1055
1716f6dc
LP
1056 assert(m);
1057 assert(fd >= 0);
b30bf55d 1058 assert(destination);
1716f6dc
LP
1059 assert(port > 0);
1060 assert(p);
1061
deb3f3d3 1062 log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
a2a416f7 1063
1716f6dc 1064 if (family == AF_INET)
b30bf55d 1065 return manager_ipv4_send(m, fd, ifindex, &destination->in, port, &source->in, p);
2817157b 1066 if (family == AF_INET6)
b30bf55d 1067 return manager_ipv6_send(m, fd, ifindex, &destination->in6, port, &source->in6, p);
1716f6dc
LP
1068
1069 return -EAFNOSUPPORT;
1070}
1071
e1c95994
LP
1072uint32_t manager_find_mtu(Manager *m) {
1073 uint32_t mtu = 0;
1074 Link *l;
1075 Iterator i;
1076
1077 /* If we don't know on which link a DNS packet would be
1078 * delivered, let's find the largest MTU that works on all
1079 * interfaces we know of */
1080
1081 HASHMAP_FOREACH(l, m->links, i) {
1082 if (l->mtu <= 0)
1083 continue;
1084
1085 if (mtu <= 0 || l->mtu < mtu)
1086 mtu = l->mtu;
1087 }
1088
1089 return mtu;
1090}
1716f6dc 1091
623a4c97 1092int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1093 LinkAddress *a;
1094
1095 assert(m);
1096
4e945a6f 1097 a = manager_find_link_address(m, family, in_addr);
ec2c5e43
LP
1098 if (a)
1099 return a->link->ifindex;
1100
1101 return 0;
1102}
1103
eb60f9cd
LP
1104void manager_refresh_rrs(Manager *m) {
1105 Iterator i;
1106 Link *l;
1107
1108 assert(m);
1109
78c6a153
LP
1110 m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
1111 m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
400cb36e
DR
1112 m->mdns_host_ipv4_key = dns_resource_key_unref(m->mdns_host_ipv4_key);
1113 m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key);
eb60f9cd
LP
1114
1115 HASHMAP_FOREACH(l, m->links, i) {
1116 link_add_rrs(l, true);
1117 link_add_rrs(l, false);
1118 }
1119}
1120
ec2c5e43
LP
1121int manager_next_hostname(Manager *m) {
1122 const char *p;
556a2294 1123 uint64_t u, a;
78c6a153
LP
1124 char *h, *k;
1125 int r;
623a4c97
LP
1126
1127 assert(m);
1128
78c6a153 1129 p = strchr(m->llmnr_hostname, 0);
ec2c5e43
LP
1130 assert(p);
1131
78c6a153 1132 while (p > m->llmnr_hostname) {
ec2c5e43
LP
1133 if (!strchr("0123456789", p[-1]))
1134 break;
1135
1136 p--;
1137 }
1138
1139 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
1140 u = 1;
1141
556a2294
LP
1142 /* Add a random number to the old value. This way we can avoid
1143 * that two hosts pick the same hostname, win on IPv4 and lose
1144 * on IPv6 (or vice versa), and pick the same hostname
1145 * replacement hostname, ad infinitum. We still want the
1146 * numbers to go up monotonically, hence we just add a random
1147 * value 1..10 */
1148
1149 random_bytes(&a, sizeof(a));
1150 u += 1 + a % 10;
ec2c5e43 1151
78c6a153 1152 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
ec2c5e43
LP
1153 return -ENOMEM;
1154
78c6a153
LP
1155 r = dns_name_concat(h, "local", &k);
1156 if (r < 0) {
1157 free(h);
1158 return r;
1159 }
1160
1161 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
1162
1163 free(m->llmnr_hostname);
1164 m->llmnr_hostname = h;
ec2c5e43 1165
78c6a153
LP
1166 free(m->mdns_hostname);
1167 m->mdns_hostname = k;
ec2c5e43 1168
eb60f9cd 1169 manager_refresh_rrs(m);
623a4c97
LP
1170
1171 return 0;
1172}
ec2c5e43 1173
4e945a6f 1174LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1175 Iterator i;
1176 Link *l;
1177
1178 assert(m);
1179
1180 HASHMAP_FOREACH(l, m->links, i) {
1181 LinkAddress *a;
1182
1183 a = link_find_address(l, family, in_addr);
1184 if (a)
1185 return a;
1186 }
1187
1188 return NULL;
1189}
1190
a4076574 1191bool manager_our_packet(Manager *m, DnsPacket *p) {
ec2c5e43
LP
1192 assert(m);
1193 assert(p);
1194
4e945a6f 1195 return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e43 1196}
4e945a6f 1197
a4076574
LP
1198DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
1199 Link *l;
1200
1201 assert(m);
1202 assert(p);
1203
1204 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1205 if (!l)
1206 return NULL;
1207
b4f1862d
DM
1208 switch (p->protocol) {
1209 case DNS_PROTOCOL_LLMNR:
a4076574
LP
1210 if (p->family == AF_INET)
1211 return l->llmnr_ipv4_scope;
1212 else if (p->family == AF_INET6)
1213 return l->llmnr_ipv6_scope;
b4f1862d
DM
1214
1215 break;
1216
1217 case DNS_PROTOCOL_MDNS:
1218 if (p->family == AF_INET)
1219 return l->mdns_ipv4_scope;
1220 else if (p->family == AF_INET6)
1221 return l->mdns_ipv6_scope;
1222
1223 break;
1224
1225 default:
1226 break;
a4076574
LP
1227 }
1228
1229 return NULL;
1230}
1231
902bb5d8
LP
1232void manager_verify_all(Manager *m) {
1233 DnsScope *s;
1234
1235 assert(m);
1236
1237 LIST_FOREACH(scopes, s, m->dns_scopes)
1238 dns_zone_verify_all(&s->zone);
1239}
1240
78c6a153 1241int manager_is_own_hostname(Manager *m, const char *name) {
78c6a153
LP
1242 int r;
1243
1244 assert(m);
1245 assert(name);
1246
1247 if (m->llmnr_hostname) {
1248 r = dns_name_equal(name, m->llmnr_hostname);
1249 if (r != 0)
1250 return r;
1251 }
1252
e96de0ce
LP
1253 if (m->mdns_hostname) {
1254 r = dns_name_equal(name, m->mdns_hostname);
1255 if (r != 0)
1256 return r;
1257 }
1258
1259 if (m->full_hostname)
1260 return dns_name_equal(name, m->full_hostname);
78c6a153
LP
1261
1262 return 0;
1263}
1264
9176a57c
LP
1265int manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
1266 DnsServer *s;
1267 Iterator i;
1268 Link *l;
1269 int r;
1270
1271 assert(m);
1272 assert(dns);
1273
1274 r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
1275 if (r < 0)
1276 return r;
1277
1278 /* First add the system-wide servers and domains */
1279 LIST_FOREACH(servers, s, m->dns_servers) {
1280 r = ordered_set_put(*dns, s);
1281 if (r == -EEXIST)
1282 continue;
1283 if (r < 0)
1284 return r;
1285 }
1286
1287 /* Then, add the per-link servers */
1288 HASHMAP_FOREACH(l, m->links, i) {
1289 LIST_FOREACH(servers, s, l->dns_servers) {
1290 r = ordered_set_put(*dns, s);
1291 if (r == -EEXIST)
1292 continue;
1293 if (r < 0)
1294 return r;
1295 }
1296 }
1297
1298 /* If we found nothing, add the fallback servers */
1299 if (ordered_set_isempty(*dns)) {
1300 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1301 r = ordered_set_put(*dns, s);
1302 if (r == -EEXIST)
1303 continue;
1304 if (r < 0)
1305 return r;
1306 }
1307 }
1308
1309 return 0;
1310}
1311
94363cbb
MP
1312/* filter_route is a tri-state:
1313 * < 0: no filtering
1314 * = 0 or false: return only domains which should be used for searching
1315 * > 0 or true: return only domains which are for routing only
1316 */
6f7da49d 1317int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) {
9176a57c
LP
1318 DnsSearchDomain *d;
1319 Iterator i;
1320 Link *l;
1321 int r;
1322
1323 assert(m);
1324 assert(domains);
1325
1326 r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops);
1327 if (r < 0)
1328 return r;
1329
1330 LIST_FOREACH(domains, d, m->search_domains) {
6f7da49d
LP
1331
1332 if (filter_route >= 0 &&
1333 d->route_only != !!filter_route)
1334 continue;
1335
9176a57c
LP
1336 r = ordered_set_put(*domains, d->name);
1337 if (r == -EEXIST)
1338 continue;
1339 if (r < 0)
1340 return r;
1341 }
1342
1343 HASHMAP_FOREACH(l, m->links, i) {
1344
1345 LIST_FOREACH(domains, d, l->search_domains) {
6f7da49d
LP
1346
1347 if (filter_route >= 0 &&
1348 d->route_only != !!filter_route)
1349 continue;
1350
9176a57c
LP
1351 r = ordered_set_put(*domains, d->name);
1352 if (r == -EEXIST)
1353 continue;
1354 if (r < 0)
1355 return r;
1356 }
1357 }
1358
1359 return 0;
1360}
c69fa7e3
LP
1361
1362DnssecMode manager_get_dnssec_mode(Manager *m) {
1363 assert(m);
1364
1365 if (m->dnssec_mode != _DNSSEC_MODE_INVALID)
1366 return m->dnssec_mode;
1367
1368 return DNSSEC_NO;
1369}
1370
1371bool manager_dnssec_supported(Manager *m) {
1372 DnsServer *server;
1373 Iterator i;
1374 Link *l;
1375
1376 assert(m);
1377
1378 if (manager_get_dnssec_mode(m) == DNSSEC_NO)
1379 return false;
1380
1381 server = manager_get_dns_server(m);
1382 if (server && !dns_server_dnssec_supported(server))
1383 return false;
1384
1385 HASHMAP_FOREACH(l, m->links, i)
1386 if (!link_dnssec_supported(l))
1387 return false;
1388
1389 return true;
1390}
59c5b597
LP
1391
1392void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) {
1393
1394 assert(verdict >= 0);
1395 assert(verdict < _DNSSEC_VERDICT_MAX);
1396
1397 if (log_get_max_level() >= LOG_DEBUG) {
202b76ae 1398 char s[DNS_RESOURCE_KEY_STRING_MAX];
59c5b597 1399
202b76ae
ZJS
1400 log_debug("Found verdict for lookup %s: %s",
1401 dns_resource_key_to_string(key, s, sizeof s),
1402 dnssec_verdict_to_string(verdict));
59c5b597
LP
1403 }
1404
1405 m->n_dnssec_verdict[verdict]++;
1406}
011696f7
LP
1407
1408bool manager_routable(Manager *m, int family) {
1409 Iterator i;
1410 Link *l;
1411
1412 assert(m);
1413
1414 /* Returns true if the host has at least one interface with a routable address of the specified type */
1415
1416 HASHMAP_FOREACH(l, m->links, i)
1417 if (link_relevant(l, family, false))
1418 return true;
1419
1420 return false;
1421}
ba35662f
LP
1422
1423void manager_flush_caches(Manager *m) {
1424 DnsScope *scope;
1425
1426 assert(m);
1427
1428 LIST_FOREACH(scopes, scope, m->dns_scopes)
1429 dns_cache_flush(&scope->cache);
aac57b35
ZJS
1430
1431 log_info("Flushed all caches.");
ba35662f 1432}
943ef07c 1433
59c0fd0e
LP
1434void manager_reset_server_features(Manager *m) {
1435 Iterator i;
1436 Link *l;
1437
1438 dns_server_reset_features_all(m->dns_servers);
1439 dns_server_reset_features_all(m->fallback_dns_servers);
1440
1441 HASHMAP_FOREACH(l, m->links, i)
1442 dns_server_reset_features_all(l->dns_servers);
1443
1444 log_info("Resetting learnt feature levels on all servers.");
1445}
1446
943ef07c
LP
1447void manager_cleanup_saved_user(Manager *m) {
1448 _cleanup_closedir_ DIR *d = NULL;
1449 struct dirent *de;
1450 int r;
1451
1452 assert(m);
1453
1454 /* Clean up all saved per-link files in /run/systemd/resolve/netif/ that don't have a matching interface
1455 * anymore. These files are created to persist settings pushed in by the user via the bus, so that resolved can
1456 * be restarted without losing this data. */
1457
1458 d = opendir("/run/systemd/resolve/netif/");
1459 if (!d) {
1460 if (errno == ENOENT)
1461 return;
1462
1463 log_warning_errno(errno, "Failed to open interface directory: %m");
1464 return;
1465 }
1466
1467 FOREACH_DIRENT_ALL(de, d, log_error_errno(errno, "Failed to read interface directory: %m")) {
1468 _cleanup_free_ char *p = NULL;
1469 int ifindex;
1470 Link *l;
1471
1472 if (!IN_SET(de->d_type, DT_UNKNOWN, DT_REG))
1473 continue;
1474
49bfc877 1475 if (dot_or_dot_dot(de->d_name))
943ef07c
LP
1476 continue;
1477
1478 r = parse_ifindex(de->d_name, &ifindex);
1479 if (r < 0) /* Probably some temporary file from a previous run. Delete it */
1480 goto rm;
1481
1482 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1483 if (!l) /* link vanished */
1484 goto rm;
1485
1486 if (l->is_managed) /* now managed by networkd, hence the bus settings are useless */
1487 goto rm;
1488
1489 continue;
1490
1491 rm:
1492 p = strappend("/run/systemd/resolve/netif/", de->d_name);
1493 if (!p) {
1494 log_oom();
1495 return;
1496 }
1497
1498 (void) unlink(p);
1499 }
1500}