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