]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
hwdb: Update database of Bluetooth company identifiers
[thirdparty/systemd.git] / src / resolve / resolved-manager.c
CommitLineData
091a364c
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
091a364c 22#include <resolv.h>
74b2466e 23#include <sys/ioctl.h>
0a6f50c0 24#include <poll.h>
74b2466e 25#include <netinet/in.h>
091a364c 26
1c4baffc 27#include "netlink-util.h"
091a364c 28#include "network-internal.h"
74b2466e 29#include "socket-util.h"
a2a416f7 30#include "af-list.h"
eb60f9cd 31#include "utf8.h"
a5a807e6 32#include "fileio-label.h"
822db23c 33#include "ordered-set.h"
3df3e884 34#include "random-util.h"
958b66ea 35#include "hostname-util.h"
4e945a6f 36
4ad7f276 37#include "dns-domain.h"
39d8db04
LP
38#include "resolved-conf.h"
39#include "resolved-bus.h"
40#include "resolved-manager.h"
5f402ae8 41#include "resolved-llmnr.h"
74b2466e
LP
42
43#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
44
1c4baffc 45static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e
LP
46 Manager *m = userdata;
47 uint16_t type;
48 Link *l;
49 int ifindex, r;
50
51 assert(rtnl);
52 assert(m);
53 assert(mm);
54
1c4baffc 55 r = sd_netlink_message_get_type(mm, &type);
74b2466e
LP
56 if (r < 0)
57 goto fail;
58
59 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
60 if (r < 0)
61 goto fail;
62
63 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
64
65 switch (type) {
66
a2a416f7
LP
67 case RTM_NEWLINK:{
68 bool is_new = !l;
74b2466e 69
a2a416f7 70 if (!l) {
74b2466e
LP
71 r = link_new(m, &l, ifindex);
72 if (r < 0)
73 goto fail;
74 }
75
76 r = link_update_rtnl(l, mm);
77 if (r < 0)
78 goto fail;
79
21d73c87
LP
80 r = link_update_monitor(l);
81 if (r < 0)
82 goto fail;
83
a2a416f7
LP
84 if (is_new)
85 log_debug("Found new link %i/%s", ifindex, l->name);
86
74b2466e 87 break;
a2a416f7 88 }
74b2466e
LP
89
90 case RTM_DELLINK:
91 if (l) {
a2a416f7 92 log_debug("Removing link %i/%s", l->ifindex, l->name);
74b2466e
LP
93 link_free(l);
94 }
95
96 break;
97 }
98
99 return 0;
100
101fail:
da927ba9 102 log_warning_errno(r, "Failed to process RTNL link message: %m");
74b2466e
LP
103 return 0;
104}
105
1c4baffc 106static int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e
LP
107 Manager *m = userdata;
108 union in_addr_union address;
74b2466e 109 uint16_t type;
0dd25fb9 110 int r, ifindex, family;
74b2466e
LP
111 LinkAddress *a;
112 Link *l;
113
114 assert(rtnl);
115 assert(mm);
116 assert(m);
117
1c4baffc 118 r = sd_netlink_message_get_type(mm, &type);
74b2466e
LP
119 if (r < 0)
120 goto fail;
121
122 r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
123 if (r < 0)
124 goto fail;
125
126 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
127 if (!l)
128 return 0;
129
130 r = sd_rtnl_message_addr_get_family(mm, &family);
131 if (r < 0)
132 goto fail;
133
134 switch (family) {
135
136 case AF_INET:
1c4baffc 137 r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
74b2466e 138 if (r < 0) {
1c4baffc 139 r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
74b2466e
LP
140 if (r < 0)
141 goto fail;
142 }
143
144 break;
145
146 case AF_INET6:
1c4baffc 147 r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
74b2466e 148 if (r < 0) {
1c4baffc 149 r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e
LP
150 if (r < 0)
151 goto fail;
152 }
153
154 break;
155
156 default:
157 return 0;
158 }
159
160 a = link_find_address(l, family, &address);
161
162 switch (type) {
163
164 case RTM_NEWADDR:
165
166 if (!a) {
167 r = link_address_new(l, &a, family, &address);
168 if (r < 0)
169 return r;
170 }
171
172 r = link_address_update_rtnl(a, mm);
173 if (r < 0)
174 return r;
175
176 break;
177
178 case RTM_DELADDR:
3e044c49 179 link_address_free(a);
74b2466e
LP
180 break;
181 }
182
183 return 0;
184
185fail:
da927ba9 186 log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e
LP
187 return 0;
188}
189
74b2466e 190static int manager_rtnl_listen(Manager *m) {
1c4baffc
TG
191 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
192 sd_netlink_message *i;
74b2466e
LP
193 int r;
194
195 assert(m);
196
cc98b302 197 /* First, subscribe to interfaces coming and going */
1c4baffc 198 r = sd_netlink_open(&m->rtnl);
74b2466e
LP
199 if (r < 0)
200 return r;
201
1c4baffc 202 r = sd_netlink_attach_event(m->rtnl, m->event, 0);
74b2466e
LP
203 if (r < 0)
204 return r;
205
1c4baffc 206 r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
74b2466e
LP
207 if (r < 0)
208 return r;
209
1c4baffc 210 r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
74b2466e
LP
211 if (r < 0)
212 return r;
213
1c4baffc 214 r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e
LP
215 if (r < 0)
216 return r;
091a364c 217
1c4baffc 218 r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e
LP
219 if (r < 0)
220 return r;
221
222 /* Then, enumerate all links */
223 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
224 if (r < 0)
225 return r;
226
1c4baffc 227 r = sd_netlink_message_request_dump(req, true);
74b2466e
LP
228 if (r < 0)
229 return r;
230
1c4baffc 231 r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e
LP
232 if (r < 0)
233 return r;
234
1c4baffc 235 for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e
LP
236 r = manager_process_link(m->rtnl, i, m);
237 if (r < 0)
238 return r;
239 }
240
1c4baffc
TG
241 req = sd_netlink_message_unref(req);
242 reply = sd_netlink_message_unref(reply);
74b2466e
LP
243
244 /* Finally, enumerate all addresses, too */
245 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
246 if (r < 0)
247 return r;
248
1c4baffc 249 r = sd_netlink_message_request_dump(req, true);
74b2466e
LP
250 if (r < 0)
251 return r;
252
1c4baffc 253 r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e
LP
254 if (r < 0)
255 return r;
256
1c4baffc 257 for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e
LP
258 r = manager_process_address(m->rtnl, i, m);
259 if (r < 0)
260 return r;
261 }
262
263 return r;
264}
265
266static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
267 Manager *m = userdata;
268 Iterator i;
269 Link *l;
270 int r;
271
272 assert(m);
273
274 sd_network_monitor_flush(m->network_monitor);
275
276 HASHMAP_FOREACH(l, m->links, i) {
277 r = link_update_monitor(l);
278 if (r < 0)
da927ba9 279 log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
74b2466e
LP
280 }
281
282 r = manager_write_resolv_conf(m);
283 if (r < 0)
da927ba9 284 log_warning_errno(r, "Could not update resolv.conf: %m");
74b2466e
LP
285
286 return 0;
287}
288
289static int manager_network_monitor_listen(Manager *m) {
290 int r, fd, events;
291
292 assert(m);
293
0014a4ad 294 r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e
LP
295 if (r < 0)
296 return r;
297
298 fd = sd_network_monitor_get_fd(m->network_monitor);
299 if (fd < 0)
300 return fd;
301
302 events = sd_network_monitor_get_events(m->network_monitor);
303 if (events < 0)
304 return events;
305
306 r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
307 if (r < 0)
308 return r;
309
310 return 0;
311}
312
78c6a153 313static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
eb60f9cd 314 _cleanup_free_ char *h = NULL, *n = NULL;
78c6a153
LP
315 char label[DNS_LABEL_MAX];
316 const char *p;
317 int r, k;
eb60f9cd 318
78c6a153
LP
319 assert(llmnr_hostname);
320 assert(mdns_hostname);
321
322 /* Extract and normalize the first label of the locally
323 * configured hostname, and check it's not "localhost". */
eb60f9cd
LP
324
325 h = gethostname_malloc();
326 if (!h)
327 return log_oom();
328
78c6a153
LP
329 p = h;
330 r = dns_label_unescape(&p, label, sizeof(label));
331 if (r < 0)
332 return log_error_errno(r, "Failed to unescape host name: %m");
333 if (r == 0) {
334 log_error("Couldn't find a single label in hosntame.");
335 return -EINVAL;
336 }
337
338 k = dns_label_undo_idna(label, r, label, sizeof(label));
339 if (k < 0)
340 return log_error_errno(k, "Failed to undo IDNA: %m");
341 if (k > 0)
342 r = k;
343
344 if (!utf8_is_valid(label)) {
eb60f9cd
LP
345 log_error("System hostname is not UTF-8 clean.");
346 return -EINVAL;
347 }
348
78c6a153
LP
349 r = dns_label_escape(label, r, &n);
350 if (r < 0)
351 return log_error_errno(r, "Failed to escape host name: %m");
352
353 if (is_localhost(n)) {
354 log_debug("System hostname is 'localhost', ignoring.");
355 return -EINVAL;
eb60f9cd
LP
356 }
357
78c6a153
LP
358 r = dns_name_concat(n, "local", mdns_hostname);
359 if (r < 0)
360 return log_error_errno(r, "Failed to determine mDNS hostname: %m");
361
362 *llmnr_hostname = n;
eb60f9cd
LP
363 n = NULL;
364
365 return 0;
366}
367
368static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
78c6a153 369 _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
eb60f9cd
LP
370 Manager *m = userdata;
371 int r;
372
373 assert(m);
374
78c6a153 375 r = determine_hostname(&llmnr_hostname, &mdns_hostname);
eb60f9cd
LP
376 if (r < 0)
377 return 0; /* ignore invalid hostnames */
378
78c6a153 379 if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
eb60f9cd
LP
380 return 0;
381
78c6a153
LP
382 log_info("System hostname changed to '%s'.", llmnr_hostname);
383
384 free(m->llmnr_hostname);
385 free(m->mdns_hostname);
386
387 m->llmnr_hostname = llmnr_hostname;
388 m->mdns_hostname = mdns_hostname;
389
390 llmnr_hostname = mdns_hostname = NULL;
eb60f9cd
LP
391
392 manager_refresh_rrs(m);
393
394 return 0;
395}
396
397static int manager_watch_hostname(Manager *m) {
eb60f9cd
LP
398 int r;
399
400 assert(m);
401
402 m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
403 if (m->hostname_fd < 0) {
56f64d95 404 log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd
LP
405 return 0;
406 }
407
408 r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
409 if (r < 0) {
410 if (r == -EPERM)
411 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
412 m->hostname_fd = safe_close(m->hostname_fd);
8d3d7072
MS
413 else
414 return log_error_errno(r, "Failed to add hostname event source: %m");
eb60f9cd
LP
415 }
416
78c6a153 417 r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
eb60f9cd
LP
418 if (r < 0) {
419 log_info("Defaulting to hostname 'linux'.");
78c6a153
LP
420 m->llmnr_hostname = strdup("linux");
421 if (!m->llmnr_hostname)
422 return log_oom();
423
424 m->mdns_hostname = strdup("linux.local");
425 if (!m->mdns_hostname)
eb60f9cd
LP
426 return log_oom();
427 } else
78c6a153 428 log_info("Using system hostname '%s'.", m->llmnr_hostname);
eb60f9cd
LP
429
430 return 0;
431}
432
091a364c 433int manager_new(Manager **ret) {
74b2466e 434 _cleanup_(manager_freep) Manager *m = NULL;
091a364c
TG
435 int r;
436
c92e531c
LP
437 assert(ret);
438
091a364c
TG
439 m = new0(Manager, 1);
440 if (!m)
441 return -ENOMEM;
442
1716f6dc 443 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97 444 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
eb60f9cd 445 m->hostname_fd = -1;
1716f6dc 446
4e945a6f 447 m->llmnr_support = SUPPORT_YES;
5cb36f41 448 m->read_resolv_conf = true;
091a364c 449
4e945a6f 450 r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
091a364c
TG
451 if (r < 0)
452 return r;
453
454 r = sd_event_default(&m->event);
455 if (r < 0)
456 return r;
457
458 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
459 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
460
461 sd_event_set_watchdog(m->event, true);
462
eb60f9cd
LP
463 r = manager_watch_hostname(m);
464 if (r < 0)
465 return r;
466
1716f6dc 467 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
468 if (r < 0)
469 return r;
470
471 r = manager_network_monitor_listen(m);
472 if (r < 0)
473 return r;
474
475 r = manager_rtnl_listen(m);
476 if (r < 0)
477 return r;
478
479 r = manager_connect_bus(m);
480 if (r < 0)
481 return r;
482
091a364c
TG
483 *ret = m;
484 m = NULL;
485
486 return 0;
487}
488
edc501d4
LP
489int manager_start(Manager *m) {
490 int r;
491
492 assert(m);
493
494 r = manager_llmnr_start(m);
495 if (r < 0)
496 return r;
497
498 return 0;
499}
500
74b2466e
LP
501Manager *manager_free(Manager *m) {
502 Link *l;
091a364c
TG
503
504 if (!m)
74b2466e
LP
505 return NULL;
506
74b2466e
LP
507 while ((l = hashmap_first(m->links)))
508 link_free(l);
f0e15467
LP
509
510 while (m->dns_queries)
511 dns_query_free(m->dns_queries);
74b2466e 512
3e684349
LP
513 manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
514 manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
091a364c 515
cab5b059
LP
516 dns_scope_free(m->unicast_scope);
517
f0e15467
LP
518 hashmap_free(m->links);
519 hashmap_free(m->dns_transactions);
520
096b6773
LP
521 sd_event_source_unref(m->network_event_source);
522 sd_network_monitor_unref(m->network_monitor);
091a364c 523
edc501d4 524 manager_llmnr_stop(m);
623a4c97 525
902bb5d8 526 sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e
LP
527 sd_event_source_unref(m->bus_retry_event_source);
528 sd_bus_unref(m->bus);
091a364c 529
74b2466e 530 sd_event_unref(m->event);
623a4c97 531
78c6a153
LP
532 dns_resource_key_unref(m->llmnr_host_ipv4_key);
533 dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd
LP
534
535 safe_close(m->hostname_fd);
536 sd_event_source_unref(m->hostname_event_source);
78c6a153
LP
537 free(m->llmnr_hostname);
538 free(m->mdns_hostname);
eb60f9cd 539
091a364c 540 free(m);
74b2466e
LP
541
542 return NULL;
091a364c
TG
543}
544
5cb36f41
LP
545int manager_read_resolv_conf(Manager *m) {
546 _cleanup_fclose_ FILE *f = NULL;
547 struct stat st, own;
548 char line[LINE_MAX];
549 DnsServer *s, *nx;
550 usec_t t;
551 int r;
552
553 assert(m);
554
555 /* Reads the system /etc/resolv.conf, if it exists and is not
556 * symlinked to our own resolv.conf instance */
557
558 if (!m->read_resolv_conf)
559 return 0;
560
561 r = stat("/etc/resolv.conf", &st);
562 if (r < 0) {
563 if (errno != ENOENT)
56f64d95 564 log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41
LP
565 r = -errno;
566 goto clear;
567 }
568
569 /* Have we already seen the file? */
570 t = timespec_load(&st.st_mtim);
571 if (t == m->resolv_conf_mtime)
572 return 0;
573
574 m->resolv_conf_mtime = t;
575
576 /* Is it symlinked to our own file? */
577 if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
578 st.st_dev == own.st_dev &&
579 st.st_ino == own.st_ino) {
580 r = 0;
581 goto clear;
582 }
583
584 f = fopen("/etc/resolv.conf", "re");
585 if (!f) {
586 if (errno != ENOENT)
56f64d95 587 log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41
LP
588 r = -errno;
589 goto clear;
590 }
591
592 if (fstat(fileno(f), &st) < 0) {
56f64d95 593 log_error_errno(errno, "Failed to stat open file: %m");
5cb36f41
LP
594 r = -errno;
595 goto clear;
596 }
597
598 LIST_FOREACH(servers, s, m->dns_servers)
599 s->marked = true;
600
601 FOREACH_LINE(line, f, r = -errno; goto clear) {
602 union in_addr_union address;
603 int family;
604 char *l;
605 const char *a;
606
607 truncate_nl(line);
608
609 l = strstrip(line);
610 if (*l == '#' || *l == ';')
611 continue;
612
613 a = first_word(l, "nameserver");
614 if (!a)
615 continue;
616
617 r = in_addr_from_string_auto(a, &family, &address);
618 if (r < 0) {
619 log_warning("Failed to parse name server %s.", a);
620 continue;
621 }
622
623 LIST_FOREACH(servers, s, m->dns_servers)
624 if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
625 break;
626
627 if (s)
628 s->marked = false;
629 else {
630 r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
631 if (r < 0)
632 goto clear;
633 }
634 }
635
636 LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
91b14d6f
TG
637 if (s->marked) {
638 LIST_REMOVE(servers, m->dns_servers, s);
639 dns_server_unref(s);
640 }
5cb36f41 641
36a03ca2
LP
642 /* Whenever /etc/resolv.conf changes, start using the first
643 * DNS server of it. This is useful to deal with broken
644 * network managing implementations (like NetworkManager),
645 * that when connecting to a VPN place both the VPN DNS
646 * servers and the local ones in /etc/resolv.conf. Without
647 * resetting the DNS server to use back to the first entry we
648 * will continue to use the local one thus being unable to
649 * resolve VPN domains. */
650 manager_set_dns_server(m, m->dns_servers);
651
5cb36f41
LP
652 return 0;
653
654clear:
91b14d6f
TG
655 while (m->dns_servers) {
656 s = m->dns_servers;
657
658 LIST_REMOVE(servers, m->dns_servers, s);
659 dns_server_unref(s);
660 }
5cb36f41
LP
661
662 return r;
663}
664
bda2c408 665static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
74b2466e
LP
666 _cleanup_free_ char *t = NULL;
667 int r;
091a364c 668
74b2466e 669 assert(s);
091a364c 670 assert(f);
091a364c
TG
671 assert(count);
672
74b2466e 673 r = in_addr_to_string(s->family, &s->address, &t);
4e945a6f 674 if (r < 0) {
da927ba9 675 log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
091a364c
TG
676 return;
677 }
678
679 if (*count == MAXNS)
87f5a193 680 fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
091a364c 681
74b2466e 682 fprintf(f, "nameserver %s\n", t);
091a364c
TG
683 (*count) ++;
684}
685
822db23c
LP
686static void write_resolv_conf_search(
687 const char *domain, FILE *f,
688 unsigned *count,
689 unsigned *length) {
690
bda2c408
TG
691 assert(domain);
692 assert(f);
693 assert(length);
694
695 if (*count >= MAXDNSRCH ||
696 *length + strlen(domain) > 256) {
697 if (*count == MAXDNSRCH)
698 fputs(" # Too many search domains configured, remaining ones ignored.", f);
699 if (*length <= 256)
700 fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
701
702 return;
703 }
704
705 fprintf(f, " %s", domain);
706
707 (*length) += strlen(domain);
708 (*count) ++;
709}
710
822db23c 711static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
4713135e
ZJS
712 Iterator i;
713
714 fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
715 "# Third party programs must not access this file directly, but\n"
716 "# only through the symlink at /etc/resolv.conf. To manage\n"
717 "# resolv.conf(5) in a different way, replace the symlink by a\n"
718 "# static file or a different symlink.\n\n", f);
719
822db23c 720 if (ordered_set_isempty(dns))
4713135e
ZJS
721 fputs("# No DNS servers known.\n", f);
722 else {
723 DnsServer *s;
724 unsigned count = 0;
725
822db23c 726 ORDERED_SET_FOREACH(s, dns, i)
4713135e
ZJS
727 write_resolv_conf_server(s, f, &count);
728 }
729
822db23c 730 if (!ordered_set_isempty(domains)) {
4713135e
ZJS
731 unsigned length = 0, count = 0;
732 char *domain;
733
734 fputs("search", f);
822db23c 735 ORDERED_SET_FOREACH(domain, domains, i)
4713135e
ZJS
736 write_resolv_conf_search(domain, f, &count, &length);
737 fputs("\n", f);
738 }
739
740 return fflush_and_check(f);
741}
742
74b2466e 743int manager_write_resolv_conf(Manager *m) {
4e945a6f 744 static const char path[] = "/run/systemd/resolve/resolv.conf";
091a364c
TG
745 _cleanup_free_ char *temp_path = NULL;
746 _cleanup_fclose_ FILE *f = NULL;
822db23c 747 _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
74b2466e
LP
748 DnsServer *s;
749 Iterator i;
750 Link *l;
751 int r;
091a364c
TG
752
753 assert(m);
754
5cb36f41
LP
755 /* Read the system /etc/resolv.conf first */
756 manager_read_resolv_conf(m);
757
87f5a193 758 /* Add the full list to a set, to filter out duplicates */
822db23c 759 dns = ordered_set_new(&dns_server_hash_ops);
87f5a193
LP
760 if (!dns)
761 return -ENOMEM;
762
822db23c 763 domains = ordered_set_new(&dns_name_hash_ops);
bda2c408
TG
764 if (!domains)
765 return -ENOMEM;
766
87f5a193
LP
767 /* First add the system-wide servers */
768 LIST_FOREACH(servers, s, m->dns_servers) {
822db23c 769 r = ordered_set_put(dns, s);
87f5a193
LP
770 if (r == -EEXIST)
771 continue;
772 if (r < 0)
773 return r;
774 }
775
bda2c408
TG
776 /* Then, add the per-link servers and domains */
777 HASHMAP_FOREACH(l, m->links, i) {
778 char **domain;
779
87f5a193 780 LIST_FOREACH(servers, s, l->dns_servers) {
822db23c 781 r = ordered_set_put(dns, s);
87f5a193
LP
782 if (r == -EEXIST)
783 continue;
784 if (r < 0)
785 return r;
786 }
787
bda2c408
TG
788 if (!l->unicast_scope)
789 continue;
790
791 STRV_FOREACH(domain, l->unicast_scope->domains) {
822db23c 792 r = ordered_set_put(domains, *domain);
bda2c408
TG
793 if (r == -EEXIST)
794 continue;
795 if (r < 0)
796 return r;
797 }
798 }
799
87f5a193 800 /* If we found nothing, add the fallback servers */
822db23c 801 if (ordered_set_isempty(dns)) {
87f5a193 802 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
822db23c 803 r = ordered_set_put(dns, s);
87f5a193
LP
804 if (r == -EEXIST)
805 continue;
806 if (r < 0)
807 return r;
808 }
809 }
810
a5a807e6 811 r = fopen_temporary_label(path, path, &f, &temp_path);
091a364c
TG
812 if (r < 0)
813 return r;
814
815 fchmod(fileno(f), 0644);
816
4713135e 817 r = write_resolv_conf_contents(f, dns, domains);
74b2466e
LP
818 if (r < 0)
819 goto fail;
820
821 if (rename(temp_path, path) < 0) {
822 r = -errno;
823 goto fail;
824 }
091a364c 825
74b2466e 826 return 0;
091a364c 827
74b2466e 828fail:
822db23c
LP
829 (void) unlink(path);
830 (void) unlink(temp_path);
74b2466e
LP
831 return r;
832}
091a364c 833
1716f6dc 834int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 835 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
836 union {
837 struct cmsghdr header; /* For alignment */
40a1eebd 838 uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
1716f6dc 839 + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97 840 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dc
LP
841 } control;
842 union sockaddr_union sa;
74b2466e 843 struct msghdr mh = {};
1716f6dc 844 struct cmsghdr *cmsg;
74b2466e 845 struct iovec iov;
1716f6dc 846 int ms = 0, r;
74b2466e
LP
847 ssize_t l;
848
849 assert(m);
1716f6dc 850 assert(fd >= 0);
74b2466e
LP
851 assert(ret);
852
74b2466e
LP
853 r = ioctl(fd, FIONREAD, &ms);
854 if (r < 0)
855 return -errno;
856 if (ms < 0)
857 return -EIO;
858
1716f6dc 859 r = dns_packet_new(&p, protocol, ms);
74b2466e
LP
860 if (r < 0)
861 return r;
862
863 iov.iov_base = DNS_PACKET_DATA(p);
864 iov.iov_len = p->allocated;
865
1716f6dc
LP
866 mh.msg_name = &sa.sa;
867 mh.msg_namelen = sizeof(sa);
74b2466e
LP
868 mh.msg_iov = &iov;
869 mh.msg_iovlen = 1;
1716f6dc
LP
870 mh.msg_control = &control;
871 mh.msg_controllen = sizeof(control);
74b2466e 872
a38d9945 873 l = recvmsg(fd, &mh, 0);
74b2466e 874 if (l < 0) {
ad867662 875 if (errno == EAGAIN || errno == EINTR)
74b2466e
LP
876 return 0;
877
878 return -errno;
091a364c
TG
879 }
880
74b2466e
LP
881 if (l <= 0)
882 return -EIO;
091a364c 883
1716f6dc
LP
884 assert(!(mh.msg_flags & MSG_CTRUNC));
885 assert(!(mh.msg_flags & MSG_TRUNC));
886
74b2466e 887 p->size = (size_t) l;
091a364c 888
1716f6dc 889 p->family = sa.sa.sa_family;
623a4c97
LP
890 p->ipproto = IPPROTO_UDP;
891 if (p->family == AF_INET) {
1716f6dc 892 p->sender.in = sa.in.sin_addr;
623a4c97
LP
893 p->sender_port = be16toh(sa.in.sin_port);
894 } else if (p->family == AF_INET6) {
1716f6dc 895 p->sender.in6 = sa.in6.sin6_addr;
623a4c97
LP
896 p->sender_port = be16toh(sa.in6.sin6_port);
897 p->ifindex = sa.in6.sin6_scope_id;
898 } else
1716f6dc 899 return -EAFNOSUPPORT;
74b2466e 900
2a1288ff 901 CMSG_FOREACH(cmsg, &mh) {
74b2466e 902
1716f6dc
LP
903 if (cmsg->cmsg_level == IPPROTO_IPV6) {
904 assert(p->family == AF_INET6);
74b2466e 905
1716f6dc 906 switch (cmsg->cmsg_type) {
74b2466e 907
1716f6dc
LP
908 case IPV6_PKTINFO: {
909 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 910
623a4c97
LP
911 if (p->ifindex <= 0)
912 p->ifindex = i->ipi6_ifindex;
913
1716f6dc
LP
914 p->destination.in6 = i->ipi6_addr;
915 break;
916 }
74b2466e 917
1716f6dc
LP
918 case IPV6_HOPLIMIT:
919 p->ttl = *(int *) CMSG_DATA(cmsg);
920 break;
74b2466e 921
1716f6dc
LP
922 }
923 } else if (cmsg->cmsg_level == IPPROTO_IP) {
924 assert(p->family == AF_INET);
74b2466e 925
1716f6dc 926 switch (cmsg->cmsg_type) {
74b2466e 927
1716f6dc
LP
928 case IP_PKTINFO: {
929 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 930
623a4c97
LP
931 if (p->ifindex <= 0)
932 p->ifindex = i->ipi_ifindex;
933
1716f6dc
LP
934 p->destination.in = i->ipi_addr;
935 break;
936 }
74b2466e 937
623a4c97 938 case IP_TTL:
1716f6dc
LP
939 p->ttl = *(int *) CMSG_DATA(cmsg);
940 break;
941 }
942 }
943 }
74b2466e 944
623a4c97
LP
945 /* The Linux kernel sets the interface index to the loopback
946 * device if the packet came from the local host since it
947 * avoids the routing table in such a case. Let's unset the
948 * interface index in such a case. */
a5f03596 949 if (p->ifindex == LOOPBACK_IFINDEX)
623a4c97
LP
950 p->ifindex = 0;
951
86ad4cd7
TG
952 if (protocol != DNS_PROTOCOL_DNS) {
953 /* If we don't know the interface index still, we look for the
954 * first local interface with a matching address. Yuck! */
955 if (p->ifindex <= 0)
956 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
957 }
623a4c97 958
74b2466e
LP
959 *ret = p;
960 p = NULL;
961
962 return 1;
963}
964
74b2466e
LP
965static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
966 int r;
967
968 assert(fd >= 0);
969 assert(mh);
970
971 for (;;) {
972 if (sendmsg(fd, mh, flags) >= 0)
973 return 0;
974
975 if (errno == EINTR)
976 continue;
977
978 if (errno != EAGAIN)
979 return -errno;
980
981 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
982 if (r < 0)
983 return r;
984 if (r == 0)
985 return -ETIMEDOUT;
986 }
987}
988
72290734
TG
989static int write_loop(int fd, void *message, size_t length) {
990 int r;
991
992 assert(fd >= 0);
993 assert(message);
994
995 for (;;) {
996 if (write(fd, message, length) >= 0)
997 return 0;
998
999 if (errno == EINTR)
1000 continue;
1001
1002 if (errno != EAGAIN)
1003 return -errno;
1004
1005 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
1006 if (r < 0)
1007 return r;
1008 if (r == 0)
1009 return -ETIMEDOUT;
1010 }
1011}
1012
1013int manager_write(Manager *m, int fd, DnsPacket *p) {
1014 int r;
1015
1016 log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
1017
1018 r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
1019 if (r < 0)
1020 return r;
1021
1022 return 0;
1023}
1024
623a4c97 1025static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
1026 union sockaddr_union sa = {
1027 .in.sin_family = AF_INET,
74b2466e 1028 };
1716f6dc
LP
1029 union {
1030 struct cmsghdr header; /* For alignment */
1031 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
1032 } control;
74b2466e
LP
1033 struct msghdr mh = {};
1034 struct iovec iov;
74b2466e
LP
1035
1036 assert(m);
1716f6dc
LP
1037 assert(fd >= 0);
1038 assert(addr);
1039 assert(port > 0);
74b2466e
LP
1040 assert(p);
1041
74b2466e
LP
1042 iov.iov_base = DNS_PACKET_DATA(p);
1043 iov.iov_len = p->size;
091a364c 1044
1716f6dc
LP
1045 sa.in.sin_addr = *addr;
1046 sa.in.sin_port = htobe16(port),
091a364c 1047
74b2466e
LP
1048 mh.msg_iov = &iov;
1049 mh.msg_iovlen = 1;
1050 mh.msg_name = &sa.sa;
1051 mh.msg_namelen = sizeof(sa.in);
091a364c 1052
74b2466e
LP
1053 if (ifindex > 0) {
1054 struct cmsghdr *cmsg;
1055 struct in_pktinfo *pi;
1056
1057 zero(control);
1058
1716f6dc 1059 mh.msg_control = &control;
74b2466e
LP
1060 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
1061
1062 cmsg = CMSG_FIRSTHDR(&mh);
1063 cmsg->cmsg_len = mh.msg_controllen;
1064 cmsg->cmsg_level = IPPROTO_IP;
1065 cmsg->cmsg_type = IP_PKTINFO;
1066
1067 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
1068 pi->ipi_ifindex = ifindex;
1069 }
1070
1071 return sendmsg_loop(fd, &mh, 0);
1072}
1073
623a4c97 1074static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
1075 union sockaddr_union sa = {
1076 .in6.sin6_family = AF_INET6,
74b2466e 1077 };
1716f6dc
LP
1078 union {
1079 struct cmsghdr header; /* For alignment */
1080 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1081 } control;
74b2466e
LP
1082 struct msghdr mh = {};
1083 struct iovec iov;
74b2466e
LP
1084
1085 assert(m);
1716f6dc
LP
1086 assert(fd >= 0);
1087 assert(addr);
1088 assert(port > 0);
74b2466e
LP
1089 assert(p);
1090
74b2466e
LP
1091 iov.iov_base = DNS_PACKET_DATA(p);
1092 iov.iov_len = p->size;
1093
1716f6dc
LP
1094 sa.in6.sin6_addr = *addr;
1095 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
1096 sa.in6.sin6_scope_id = ifindex;
1097
1098 mh.msg_iov = &iov;
1099 mh.msg_iovlen = 1;
1100 mh.msg_name = &sa.sa;
1101 mh.msg_namelen = sizeof(sa.in6);
1102
1103 if (ifindex > 0) {
1104 struct cmsghdr *cmsg;
1105 struct in6_pktinfo *pi;
1106
1107 zero(control);
1108
1716f6dc 1109 mh.msg_control = &control;
74b2466e
LP
1110 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
1111
1112 cmsg = CMSG_FIRSTHDR(&mh);
1113 cmsg->cmsg_len = mh.msg_controllen;
1114 cmsg->cmsg_level = IPPROTO_IPV6;
1115 cmsg->cmsg_type = IPV6_PKTINFO;
1116
1117 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
1118 pi->ipi6_ifindex = ifindex;
1119 }
1120
1121 return sendmsg_loop(fd, &mh, 0);
1122}
1123
623a4c97 1124int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dc
LP
1125 assert(m);
1126 assert(fd >= 0);
1127 assert(addr);
1128 assert(port > 0);
1129 assert(p);
1130
a2a416f7
LP
1131 log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
1132
1716f6dc
LP
1133 if (family == AF_INET)
1134 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1135 else if (family == AF_INET6)
1136 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
1137
1138 return -EAFNOSUPPORT;
1139}
1140
2c27fbca 1141DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
74b2466e
LP
1142 DnsServer *s;
1143
1144 assert(m);
1145 assert(in_addr);
1146
4e945a6f 1147 LIST_FOREACH(servers, s, m->dns_servers)
5cb36f41 1148 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca 1149 return s;
74b2466e 1150
4e945a6f 1151 LIST_FOREACH(servers, s, m->fallback_dns_servers)
5cb36f41 1152 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca 1153 return s;
74b2466e 1154
2c27fbca 1155 return NULL;
4e945a6f
LP
1156}
1157
2c27fbca 1158DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
4e945a6f
LP
1159 assert(m);
1160
1161 if (m->current_dns_server == s)
1162 return s;
1163
1164 if (s) {
1165 _cleanup_free_ char *ip = NULL;
1166
1167 in_addr_to_string(s->family, &s->address, &ip);
1168 log_info("Switching to system DNS server %s.", strna(ip));
2c27fbca 1169 }
4e945a6f
LP
1170
1171 m->current_dns_server = s;
2c27fbca
LP
1172
1173 if (m->unicast_scope)
1174 dns_cache_flush(&m->unicast_scope->cache);
1175
4e945a6f 1176 return s;
74b2466e
LP
1177}
1178
1179DnsServer *manager_get_dns_server(Manager *m) {
4e945a6f 1180 Link *l;
74b2466e
LP
1181 assert(m);
1182
5cb36f41
LP
1183 /* Try to read updates resolv.conf */
1184 manager_read_resolv_conf(m);
1185
74b2466e 1186 if (!m->current_dns_server)
4e945a6f
LP
1187 manager_set_dns_server(m, m->dns_servers);
1188
1189 if (!m->current_dns_server) {
1190 bool found = false;
1191 Iterator i;
1192
1193 /* No DNS servers configured, let's see if there are
1194 * any on any links. If not, we use the fallback
1195 * servers */
1196
1197 HASHMAP_FOREACH(l, m->links, i)
1198 if (l->dns_servers) {
1199 found = true;
1200 break;
1201 }
1202
1203 if (!found)
1204 manager_set_dns_server(m, m->fallback_dns_servers);
1205 }
74b2466e
LP
1206
1207 return m->current_dns_server;
1208}
1209
1210void manager_next_dns_server(Manager *m) {
1211 assert(m);
1212
4e945a6f
LP
1213 /* If there's currently no DNS server set, then the next
1214 * manager_get_dns_server() will find one */
74b2466e
LP
1215 if (!m->current_dns_server)
1216 return;
1217
4e945a6f 1218 /* Change to the next one */
74b2466e 1219 if (m->current_dns_server->servers_next) {
4e945a6f 1220 manager_set_dns_server(m, m->current_dns_server->servers_next);
74b2466e
LP
1221 return;
1222 }
1223
4e945a6f
LP
1224 /* If there was no next one, then start from the beginning of
1225 * the list */
1226 if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
1227 manager_set_dns_server(m, m->fallback_dns_servers);
1228 else
1229 manager_set_dns_server(m, m->dns_servers);
091a364c 1230}
e1c95994
LP
1231
1232uint32_t manager_find_mtu(Manager *m) {
1233 uint32_t mtu = 0;
1234 Link *l;
1235 Iterator i;
1236
1237 /* If we don't know on which link a DNS packet would be
1238 * delivered, let's find the largest MTU that works on all
1239 * interfaces we know of */
1240
1241 HASHMAP_FOREACH(l, m->links, i) {
1242 if (l->mtu <= 0)
1243 continue;
1244
1245 if (mtu <= 0 || l->mtu < mtu)
1246 mtu = l->mtu;
1247 }
1248
1249 return mtu;
1250}
1716f6dc 1251
623a4c97 1252int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1253 LinkAddress *a;
1254
1255 assert(m);
1256
4e945a6f 1257 a = manager_find_link_address(m, family, in_addr);
ec2c5e43
LP
1258 if (a)
1259 return a->link->ifindex;
1260
1261 return 0;
1262}
1263
eb60f9cd
LP
1264void manager_refresh_rrs(Manager *m) {
1265 Iterator i;
1266 Link *l;
1267
1268 assert(m);
1269
78c6a153
LP
1270 m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
1271 m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd
LP
1272
1273 HASHMAP_FOREACH(l, m->links, i) {
1274 link_add_rrs(l, true);
1275 link_add_rrs(l, false);
1276 }
1277}
1278
ec2c5e43
LP
1279int manager_next_hostname(Manager *m) {
1280 const char *p;
556a2294 1281 uint64_t u, a;
78c6a153
LP
1282 char *h, *k;
1283 int r;
623a4c97
LP
1284
1285 assert(m);
1286
78c6a153 1287 p = strchr(m->llmnr_hostname, 0);
ec2c5e43
LP
1288 assert(p);
1289
78c6a153 1290 while (p > m->llmnr_hostname) {
ec2c5e43
LP
1291 if (!strchr("0123456789", p[-1]))
1292 break;
1293
1294 p--;
1295 }
1296
1297 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
1298 u = 1;
1299
556a2294
LP
1300 /* Add a random number to the old value. This way we can avoid
1301 * that two hosts pick the same hostname, win on IPv4 and lose
1302 * on IPv6 (or vice versa), and pick the same hostname
1303 * replacement hostname, ad infinitum. We still want the
1304 * numbers to go up monotonically, hence we just add a random
1305 * value 1..10 */
1306
1307 random_bytes(&a, sizeof(a));
1308 u += 1 + a % 10;
ec2c5e43 1309
78c6a153 1310 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
ec2c5e43
LP
1311 return -ENOMEM;
1312
78c6a153
LP
1313 r = dns_name_concat(h, "local", &k);
1314 if (r < 0) {
1315 free(h);
1316 return r;
1317 }
1318
1319 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
1320
1321 free(m->llmnr_hostname);
1322 m->llmnr_hostname = h;
ec2c5e43 1323
78c6a153
LP
1324 free(m->mdns_hostname);
1325 m->mdns_hostname = k;
ec2c5e43 1326
eb60f9cd 1327 manager_refresh_rrs(m);
623a4c97
LP
1328
1329 return 0;
1330}
ec2c5e43 1331
4e945a6f 1332LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1333 Iterator i;
1334 Link *l;
1335
1336 assert(m);
1337
1338 HASHMAP_FOREACH(l, m->links, i) {
1339 LinkAddress *a;
1340
1341 a = link_find_address(l, family, in_addr);
1342 if (a)
1343 return a;
1344 }
1345
1346 return NULL;
1347}
1348
a4076574 1349bool manager_our_packet(Manager *m, DnsPacket *p) {
ec2c5e43
LP
1350 assert(m);
1351 assert(p);
1352
4e945a6f 1353 return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e43 1354}
4e945a6f 1355
a4076574
LP
1356DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
1357 Link *l;
1358
1359 assert(m);
1360 assert(p);
1361
1362 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1363 if (!l)
1364 return NULL;
1365
1366 if (p->protocol == DNS_PROTOCOL_LLMNR) {
1367 if (p->family == AF_INET)
1368 return l->llmnr_ipv4_scope;
1369 else if (p->family == AF_INET6)
1370 return l->llmnr_ipv6_scope;
1371 }
1372
1373 return NULL;
1374}
1375
902bb5d8
LP
1376void manager_verify_all(Manager *m) {
1377 DnsScope *s;
1378
1379 assert(m);
1380
1381 LIST_FOREACH(scopes, s, m->dns_scopes)
1382 dns_zone_verify_all(&s->zone);
1383}
1384
3e684349 1385void manager_flush_dns_servers(Manager *m, DnsServerType t) {
91b14d6f
TG
1386 DnsServer *s;
1387
3e684349
LP
1388 assert(m);
1389
1390 if (t == DNS_SERVER_SYSTEM)
91b14d6f
TG
1391 while (m->dns_servers) {
1392 s = m->dns_servers;
1393
1394 LIST_REMOVE(servers, m->dns_servers, s);
1395 dns_server_unref(s);
1396 }
3e684349
LP
1397
1398 if (t == DNS_SERVER_FALLBACK)
91b14d6f
TG
1399 while (m->fallback_dns_servers) {
1400 s = m->fallback_dns_servers;
1401
1402 LIST_REMOVE(servers, m->fallback_dns_servers, s);
1403 dns_server_unref(s);
1404 }
3e684349
LP
1405}
1406
78c6a153 1407int manager_is_own_hostname(Manager *m, const char *name) {
78c6a153
LP
1408 int r;
1409
1410 assert(m);
1411 assert(name);
1412
1413 if (m->llmnr_hostname) {
1414 r = dns_name_equal(name, m->llmnr_hostname);
1415 if (r != 0)
1416 return r;
1417 }
1418
1419 if (m->mdns_hostname)
1420 return dns_name_equal(name, m->mdns_hostname);
1421
1422 return 0;
1423}
1424
4e945a6f
LP
1425static const char* const support_table[_SUPPORT_MAX] = {
1426 [SUPPORT_NO] = "no",
1427 [SUPPORT_YES] = "yes",
1428 [SUPPORT_RESOLVE] = "resolve",
1429};
1430DEFINE_STRING_TABLE_LOOKUP(support, Support);