]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
Merge pull request #1428 from franciozzy/tagenhance
[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
4d506d6b
LP
433static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
434 _cleanup_free_ char *buffer = NULL;
435 _cleanup_fclose_ FILE *f = NULL;
436 Manager *m = userdata;
437 size_t size = 0;
438 DnsScope *scope;
439
440 assert(s);
441 assert(si);
442 assert(m);
443
444 f = open_memstream(&buffer, &size);
445 if (!f)
446 return log_oom();
447
448 LIST_FOREACH(scopes, scope, m->dns_scopes)
449 dns_scope_dump(scope, f);
450
451 if (fflush_and_check(f) < 0)
452 return log_oom();
453
454 log_dump(LOG_INFO, buffer);
455 return 0;
456}
457
091a364c 458int manager_new(Manager **ret) {
74b2466e 459 _cleanup_(manager_freep) Manager *m = NULL;
091a364c
TG
460 int r;
461
c92e531c
LP
462 assert(ret);
463
091a364c
TG
464 m = new0(Manager, 1);
465 if (!m)
466 return -ENOMEM;
467
1716f6dc 468 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97 469 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
eb60f9cd 470 m->hostname_fd = -1;
1716f6dc 471
4e945a6f 472 m->llmnr_support = SUPPORT_YES;
5cb36f41 473 m->read_resolv_conf = true;
091a364c 474
4e945a6f 475 r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
091a364c
TG
476 if (r < 0)
477 return r;
478
479 r = sd_event_default(&m->event);
480 if (r < 0)
481 return r;
482
483 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
484 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
485
486 sd_event_set_watchdog(m->event, true);
487
eb60f9cd
LP
488 r = manager_watch_hostname(m);
489 if (r < 0)
490 return r;
491
1716f6dc 492 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
493 if (r < 0)
494 return r;
495
496 r = manager_network_monitor_listen(m);
497 if (r < 0)
498 return r;
499
500 r = manager_rtnl_listen(m);
501 if (r < 0)
502 return r;
503
504 r = manager_connect_bus(m);
505 if (r < 0)
506 return r;
507
4d506d6b
LP
508 (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
509
091a364c
TG
510 *ret = m;
511 m = NULL;
512
513 return 0;
514}
515
edc501d4
LP
516int manager_start(Manager *m) {
517 int r;
518
519 assert(m);
520
521 r = manager_llmnr_start(m);
522 if (r < 0)
523 return r;
524
525 return 0;
526}
527
74b2466e
LP
528Manager *manager_free(Manager *m) {
529 Link *l;
091a364c
TG
530
531 if (!m)
74b2466e
LP
532 return NULL;
533
74b2466e
LP
534 while ((l = hashmap_first(m->links)))
535 link_free(l);
f0e15467
LP
536
537 while (m->dns_queries)
538 dns_query_free(m->dns_queries);
74b2466e 539
3e684349
LP
540 manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
541 manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
091a364c 542
cab5b059
LP
543 dns_scope_free(m->unicast_scope);
544
f0e15467
LP
545 hashmap_free(m->links);
546 hashmap_free(m->dns_transactions);
547
096b6773
LP
548 sd_event_source_unref(m->network_event_source);
549 sd_network_monitor_unref(m->network_monitor);
091a364c 550
edc501d4 551 manager_llmnr_stop(m);
623a4c97 552
902bb5d8 553 sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e
LP
554 sd_event_source_unref(m->bus_retry_event_source);
555 sd_bus_unref(m->bus);
091a364c 556
4d506d6b
LP
557 sd_event_source_unref(m->sigusr1_event_source);
558
74b2466e 559 sd_event_unref(m->event);
623a4c97 560
78c6a153
LP
561 dns_resource_key_unref(m->llmnr_host_ipv4_key);
562 dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd 563
eb60f9cd 564 sd_event_source_unref(m->hostname_event_source);
d9fcf2ba 565 safe_close(m->hostname_fd);
78c6a153
LP
566 free(m->llmnr_hostname);
567 free(m->mdns_hostname);
eb60f9cd 568
091a364c 569 free(m);
74b2466e
LP
570
571 return NULL;
091a364c
TG
572}
573
5cb36f41
LP
574int manager_read_resolv_conf(Manager *m) {
575 _cleanup_fclose_ FILE *f = NULL;
576 struct stat st, own;
577 char line[LINE_MAX];
578 DnsServer *s, *nx;
579 usec_t t;
580 int r;
581
582 assert(m);
583
584 /* Reads the system /etc/resolv.conf, if it exists and is not
585 * symlinked to our own resolv.conf instance */
586
587 if (!m->read_resolv_conf)
588 return 0;
589
590 r = stat("/etc/resolv.conf", &st);
591 if (r < 0) {
592 if (errno != ENOENT)
56f64d95 593 log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41
LP
594 r = -errno;
595 goto clear;
596 }
597
598 /* Have we already seen the file? */
599 t = timespec_load(&st.st_mtim);
600 if (t == m->resolv_conf_mtime)
601 return 0;
602
603 m->resolv_conf_mtime = t;
604
605 /* Is it symlinked to our own file? */
606 if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
607 st.st_dev == own.st_dev &&
608 st.st_ino == own.st_ino) {
609 r = 0;
610 goto clear;
611 }
612
613 f = fopen("/etc/resolv.conf", "re");
614 if (!f) {
615 if (errno != ENOENT)
56f64d95 616 log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41
LP
617 r = -errno;
618 goto clear;
619 }
620
621 if (fstat(fileno(f), &st) < 0) {
76ef789d 622 r = log_error_errno(errno, "Failed to stat open file: %m");
5cb36f41
LP
623 goto clear;
624 }
625
626 LIST_FOREACH(servers, s, m->dns_servers)
627 s->marked = true;
628
629 FOREACH_LINE(line, f, r = -errno; goto clear) {
630 union in_addr_union address;
631 int family;
632 char *l;
633 const char *a;
634
635 truncate_nl(line);
636
637 l = strstrip(line);
638 if (*l == '#' || *l == ';')
639 continue;
640
641 a = first_word(l, "nameserver");
642 if (!a)
643 continue;
644
645 r = in_addr_from_string_auto(a, &family, &address);
646 if (r < 0) {
647 log_warning("Failed to parse name server %s.", a);
648 continue;
649 }
650
651 LIST_FOREACH(servers, s, m->dns_servers)
652 if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
653 break;
654
655 if (s)
656 s->marked = false;
657 else {
658 r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
659 if (r < 0)
660 goto clear;
661 }
662 }
663
664 LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
91b14d6f
TG
665 if (s->marked) {
666 LIST_REMOVE(servers, m->dns_servers, s);
667 dns_server_unref(s);
668 }
5cb36f41 669
36a03ca2
LP
670 /* Whenever /etc/resolv.conf changes, start using the first
671 * DNS server of it. This is useful to deal with broken
672 * network managing implementations (like NetworkManager),
673 * that when connecting to a VPN place both the VPN DNS
674 * servers and the local ones in /etc/resolv.conf. Without
675 * resetting the DNS server to use back to the first entry we
676 * will continue to use the local one thus being unable to
677 * resolve VPN domains. */
678 manager_set_dns_server(m, m->dns_servers);
679
5cb36f41
LP
680 return 0;
681
682clear:
91b14d6f
TG
683 while (m->dns_servers) {
684 s = m->dns_servers;
685
686 LIST_REMOVE(servers, m->dns_servers, s);
687 dns_server_unref(s);
688 }
5cb36f41
LP
689
690 return r;
691}
692
bda2c408 693static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
74b2466e
LP
694 _cleanup_free_ char *t = NULL;
695 int r;
091a364c 696
74b2466e 697 assert(s);
091a364c 698 assert(f);
091a364c
TG
699 assert(count);
700
74b2466e 701 r = in_addr_to_string(s->family, &s->address, &t);
4e945a6f 702 if (r < 0) {
da927ba9 703 log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
091a364c
TG
704 return;
705 }
706
707 if (*count == MAXNS)
87f5a193 708 fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
091a364c 709
74b2466e 710 fprintf(f, "nameserver %s\n", t);
091a364c
TG
711 (*count) ++;
712}
713
822db23c
LP
714static void write_resolv_conf_search(
715 const char *domain, FILE *f,
716 unsigned *count,
717 unsigned *length) {
718
bda2c408
TG
719 assert(domain);
720 assert(f);
721 assert(length);
722
723 if (*count >= MAXDNSRCH ||
724 *length + strlen(domain) > 256) {
725 if (*count == MAXDNSRCH)
726 fputs(" # Too many search domains configured, remaining ones ignored.", f);
727 if (*length <= 256)
728 fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
729
730 return;
731 }
732
733 fprintf(f, " %s", domain);
734
735 (*length) += strlen(domain);
736 (*count) ++;
737}
738
822db23c 739static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
4713135e
ZJS
740 Iterator i;
741
742 fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
743 "# Third party programs must not access this file directly, but\n"
744 "# only through the symlink at /etc/resolv.conf. To manage\n"
745 "# resolv.conf(5) in a different way, replace the symlink by a\n"
746 "# static file or a different symlink.\n\n", f);
747
822db23c 748 if (ordered_set_isempty(dns))
4713135e
ZJS
749 fputs("# No DNS servers known.\n", f);
750 else {
751 DnsServer *s;
752 unsigned count = 0;
753
822db23c 754 ORDERED_SET_FOREACH(s, dns, i)
4713135e
ZJS
755 write_resolv_conf_server(s, f, &count);
756 }
757
822db23c 758 if (!ordered_set_isempty(domains)) {
4713135e
ZJS
759 unsigned length = 0, count = 0;
760 char *domain;
761
762 fputs("search", f);
822db23c 763 ORDERED_SET_FOREACH(domain, domains, i)
4713135e
ZJS
764 write_resolv_conf_search(domain, f, &count, &length);
765 fputs("\n", f);
766 }
767
768 return fflush_and_check(f);
769}
770
74b2466e 771int manager_write_resolv_conf(Manager *m) {
4e945a6f 772 static const char path[] = "/run/systemd/resolve/resolv.conf";
091a364c
TG
773 _cleanup_free_ char *temp_path = NULL;
774 _cleanup_fclose_ FILE *f = NULL;
822db23c 775 _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
74b2466e
LP
776 DnsServer *s;
777 Iterator i;
778 Link *l;
779 int r;
091a364c
TG
780
781 assert(m);
782
5cb36f41
LP
783 /* Read the system /etc/resolv.conf first */
784 manager_read_resolv_conf(m);
785
87f5a193 786 /* Add the full list to a set, to filter out duplicates */
822db23c 787 dns = ordered_set_new(&dns_server_hash_ops);
87f5a193
LP
788 if (!dns)
789 return -ENOMEM;
790
822db23c 791 domains = ordered_set_new(&dns_name_hash_ops);
bda2c408
TG
792 if (!domains)
793 return -ENOMEM;
794
87f5a193
LP
795 /* First add the system-wide servers */
796 LIST_FOREACH(servers, s, m->dns_servers) {
822db23c 797 r = ordered_set_put(dns, s);
87f5a193
LP
798 if (r == -EEXIST)
799 continue;
800 if (r < 0)
801 return r;
802 }
803
bda2c408
TG
804 /* Then, add the per-link servers and domains */
805 HASHMAP_FOREACH(l, m->links, i) {
806 char **domain;
807
87f5a193 808 LIST_FOREACH(servers, s, l->dns_servers) {
822db23c 809 r = ordered_set_put(dns, s);
87f5a193
LP
810 if (r == -EEXIST)
811 continue;
812 if (r < 0)
813 return r;
814 }
815
bda2c408
TG
816 if (!l->unicast_scope)
817 continue;
818
819 STRV_FOREACH(domain, l->unicast_scope->domains) {
822db23c 820 r = ordered_set_put(domains, *domain);
bda2c408
TG
821 if (r == -EEXIST)
822 continue;
823 if (r < 0)
824 return r;
825 }
826 }
827
87f5a193 828 /* If we found nothing, add the fallback servers */
822db23c 829 if (ordered_set_isempty(dns)) {
87f5a193 830 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
822db23c 831 r = ordered_set_put(dns, s);
87f5a193
LP
832 if (r == -EEXIST)
833 continue;
834 if (r < 0)
835 return r;
836 }
837 }
838
a5a807e6 839 r = fopen_temporary_label(path, path, &f, &temp_path);
091a364c
TG
840 if (r < 0)
841 return r;
842
843 fchmod(fileno(f), 0644);
844
4713135e 845 r = write_resolv_conf_contents(f, dns, domains);
74b2466e
LP
846 if (r < 0)
847 goto fail;
848
849 if (rename(temp_path, path) < 0) {
850 r = -errno;
851 goto fail;
852 }
091a364c 853
74b2466e 854 return 0;
091a364c 855
74b2466e 856fail:
822db23c
LP
857 (void) unlink(path);
858 (void) unlink(temp_path);
74b2466e
LP
859 return r;
860}
091a364c 861
1716f6dc 862int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 863 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
864 union {
865 struct cmsghdr header; /* For alignment */
40a1eebd 866 uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
1716f6dc 867 + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97 868 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dc
LP
869 } control;
870 union sockaddr_union sa;
74b2466e 871 struct msghdr mh = {};
1716f6dc 872 struct cmsghdr *cmsg;
74b2466e 873 struct iovec iov;
1716f6dc 874 int ms = 0, r;
74b2466e
LP
875 ssize_t l;
876
877 assert(m);
1716f6dc 878 assert(fd >= 0);
74b2466e
LP
879 assert(ret);
880
74b2466e
LP
881 r = ioctl(fd, FIONREAD, &ms);
882 if (r < 0)
883 return -errno;
884 if (ms < 0)
885 return -EIO;
886
1716f6dc 887 r = dns_packet_new(&p, protocol, ms);
74b2466e
LP
888 if (r < 0)
889 return r;
890
891 iov.iov_base = DNS_PACKET_DATA(p);
892 iov.iov_len = p->allocated;
893
1716f6dc
LP
894 mh.msg_name = &sa.sa;
895 mh.msg_namelen = sizeof(sa);
74b2466e
LP
896 mh.msg_iov = &iov;
897 mh.msg_iovlen = 1;
1716f6dc
LP
898 mh.msg_control = &control;
899 mh.msg_controllen = sizeof(control);
74b2466e 900
a38d9945 901 l = recvmsg(fd, &mh, 0);
74b2466e 902 if (l < 0) {
ad867662 903 if (errno == EAGAIN || errno == EINTR)
74b2466e
LP
904 return 0;
905
906 return -errno;
091a364c
TG
907 }
908
74b2466e
LP
909 if (l <= 0)
910 return -EIO;
091a364c 911
1716f6dc
LP
912 assert(!(mh.msg_flags & MSG_CTRUNC));
913 assert(!(mh.msg_flags & MSG_TRUNC));
914
74b2466e 915 p->size = (size_t) l;
091a364c 916
1716f6dc 917 p->family = sa.sa.sa_family;
623a4c97
LP
918 p->ipproto = IPPROTO_UDP;
919 if (p->family == AF_INET) {
1716f6dc 920 p->sender.in = sa.in.sin_addr;
623a4c97
LP
921 p->sender_port = be16toh(sa.in.sin_port);
922 } else if (p->family == AF_INET6) {
1716f6dc 923 p->sender.in6 = sa.in6.sin6_addr;
623a4c97
LP
924 p->sender_port = be16toh(sa.in6.sin6_port);
925 p->ifindex = sa.in6.sin6_scope_id;
926 } else
1716f6dc 927 return -EAFNOSUPPORT;
74b2466e 928
2a1288ff 929 CMSG_FOREACH(cmsg, &mh) {
74b2466e 930
1716f6dc
LP
931 if (cmsg->cmsg_level == IPPROTO_IPV6) {
932 assert(p->family == AF_INET6);
74b2466e 933
1716f6dc 934 switch (cmsg->cmsg_type) {
74b2466e 935
1716f6dc
LP
936 case IPV6_PKTINFO: {
937 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 938
623a4c97
LP
939 if (p->ifindex <= 0)
940 p->ifindex = i->ipi6_ifindex;
941
1716f6dc
LP
942 p->destination.in6 = i->ipi6_addr;
943 break;
944 }
74b2466e 945
1716f6dc
LP
946 case IPV6_HOPLIMIT:
947 p->ttl = *(int *) CMSG_DATA(cmsg);
948 break;
74b2466e 949
1716f6dc
LP
950 }
951 } else if (cmsg->cmsg_level == IPPROTO_IP) {
952 assert(p->family == AF_INET);
74b2466e 953
1716f6dc 954 switch (cmsg->cmsg_type) {
74b2466e 955
1716f6dc
LP
956 case IP_PKTINFO: {
957 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 958
623a4c97
LP
959 if (p->ifindex <= 0)
960 p->ifindex = i->ipi_ifindex;
961
1716f6dc
LP
962 p->destination.in = i->ipi_addr;
963 break;
964 }
74b2466e 965
623a4c97 966 case IP_TTL:
1716f6dc
LP
967 p->ttl = *(int *) CMSG_DATA(cmsg);
968 break;
969 }
970 }
971 }
74b2466e 972
623a4c97
LP
973 /* The Linux kernel sets the interface index to the loopback
974 * device if the packet came from the local host since it
975 * avoids the routing table in such a case. Let's unset the
976 * interface index in such a case. */
a5f03596 977 if (p->ifindex == LOOPBACK_IFINDEX)
623a4c97
LP
978 p->ifindex = 0;
979
86ad4cd7
TG
980 if (protocol != DNS_PROTOCOL_DNS) {
981 /* If we don't know the interface index still, we look for the
982 * first local interface with a matching address. Yuck! */
983 if (p->ifindex <= 0)
984 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
985 }
623a4c97 986
74b2466e
LP
987 *ret = p;
988 p = NULL;
989
990 return 1;
991}
992
74b2466e
LP
993static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
994 int r;
995
996 assert(fd >= 0);
997 assert(mh);
998
999 for (;;) {
1000 if (sendmsg(fd, mh, flags) >= 0)
1001 return 0;
1002
1003 if (errno == EINTR)
1004 continue;
1005
1006 if (errno != EAGAIN)
1007 return -errno;
1008
1009 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
1010 if (r < 0)
1011 return r;
1012 if (r == 0)
1013 return -ETIMEDOUT;
1014 }
1015}
1016
72290734
TG
1017static int write_loop(int fd, void *message, size_t length) {
1018 int r;
1019
1020 assert(fd >= 0);
1021 assert(message);
1022
1023 for (;;) {
1024 if (write(fd, message, length) >= 0)
1025 return 0;
1026
1027 if (errno == EINTR)
1028 continue;
1029
1030 if (errno != EAGAIN)
1031 return -errno;
1032
1033 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
1034 if (r < 0)
1035 return r;
1036 if (r == 0)
1037 return -ETIMEDOUT;
1038 }
1039}
1040
1041int manager_write(Manager *m, int fd, DnsPacket *p) {
1042 int r;
1043
1044 log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
1045
1046 r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
1047 if (r < 0)
1048 return r;
1049
1050 return 0;
1051}
1052
623a4c97 1053static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
1054 union sockaddr_union sa = {
1055 .in.sin_family = AF_INET,
74b2466e 1056 };
1716f6dc
LP
1057 union {
1058 struct cmsghdr header; /* For alignment */
1059 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
1060 } control;
74b2466e
LP
1061 struct msghdr mh = {};
1062 struct iovec iov;
74b2466e
LP
1063
1064 assert(m);
1716f6dc
LP
1065 assert(fd >= 0);
1066 assert(addr);
1067 assert(port > 0);
74b2466e
LP
1068 assert(p);
1069
74b2466e
LP
1070 iov.iov_base = DNS_PACKET_DATA(p);
1071 iov.iov_len = p->size;
091a364c 1072
1716f6dc
LP
1073 sa.in.sin_addr = *addr;
1074 sa.in.sin_port = htobe16(port),
091a364c 1075
74b2466e
LP
1076 mh.msg_iov = &iov;
1077 mh.msg_iovlen = 1;
1078 mh.msg_name = &sa.sa;
1079 mh.msg_namelen = sizeof(sa.in);
091a364c 1080
74b2466e
LP
1081 if (ifindex > 0) {
1082 struct cmsghdr *cmsg;
1083 struct in_pktinfo *pi;
1084
1085 zero(control);
1086
1716f6dc 1087 mh.msg_control = &control;
74b2466e
LP
1088 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
1089
1090 cmsg = CMSG_FIRSTHDR(&mh);
1091 cmsg->cmsg_len = mh.msg_controllen;
1092 cmsg->cmsg_level = IPPROTO_IP;
1093 cmsg->cmsg_type = IP_PKTINFO;
1094
1095 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
1096 pi->ipi_ifindex = ifindex;
1097 }
1098
1099 return sendmsg_loop(fd, &mh, 0);
1100}
1101
623a4c97 1102static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
1103 union sockaddr_union sa = {
1104 .in6.sin6_family = AF_INET6,
74b2466e 1105 };
1716f6dc
LP
1106 union {
1107 struct cmsghdr header; /* For alignment */
1108 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1109 } control;
74b2466e
LP
1110 struct msghdr mh = {};
1111 struct iovec iov;
74b2466e
LP
1112
1113 assert(m);
1716f6dc
LP
1114 assert(fd >= 0);
1115 assert(addr);
1116 assert(port > 0);
74b2466e
LP
1117 assert(p);
1118
74b2466e
LP
1119 iov.iov_base = DNS_PACKET_DATA(p);
1120 iov.iov_len = p->size;
1121
1716f6dc
LP
1122 sa.in6.sin6_addr = *addr;
1123 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
1124 sa.in6.sin6_scope_id = ifindex;
1125
1126 mh.msg_iov = &iov;
1127 mh.msg_iovlen = 1;
1128 mh.msg_name = &sa.sa;
1129 mh.msg_namelen = sizeof(sa.in6);
1130
1131 if (ifindex > 0) {
1132 struct cmsghdr *cmsg;
1133 struct in6_pktinfo *pi;
1134
1135 zero(control);
1136
1716f6dc 1137 mh.msg_control = &control;
74b2466e
LP
1138 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
1139
1140 cmsg = CMSG_FIRSTHDR(&mh);
1141 cmsg->cmsg_len = mh.msg_controllen;
1142 cmsg->cmsg_level = IPPROTO_IPV6;
1143 cmsg->cmsg_type = IPV6_PKTINFO;
1144
1145 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
1146 pi->ipi6_ifindex = ifindex;
1147 }
1148
1149 return sendmsg_loop(fd, &mh, 0);
1150}
1151
623a4c97 1152int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dc
LP
1153 assert(m);
1154 assert(fd >= 0);
1155 assert(addr);
1156 assert(port > 0);
1157 assert(p);
1158
a2a416f7
LP
1159 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));
1160
1716f6dc
LP
1161 if (family == AF_INET)
1162 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1163 else if (family == AF_INET6)
1164 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
1165
1166 return -EAFNOSUPPORT;
1167}
1168
2c27fbca 1169DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
74b2466e
LP
1170 DnsServer *s;
1171
1172 assert(m);
1173 assert(in_addr);
1174
4e945a6f 1175 LIST_FOREACH(servers, s, m->dns_servers)
5cb36f41 1176 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca 1177 return s;
74b2466e 1178
4e945a6f 1179 LIST_FOREACH(servers, s, m->fallback_dns_servers)
5cb36f41 1180 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca 1181 return s;
74b2466e 1182
2c27fbca 1183 return NULL;
4e945a6f
LP
1184}
1185
2c27fbca 1186DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
4e945a6f
LP
1187 assert(m);
1188
1189 if (m->current_dns_server == s)
1190 return s;
1191
1192 if (s) {
1193 _cleanup_free_ char *ip = NULL;
1194
1195 in_addr_to_string(s->family, &s->address, &ip);
1196 log_info("Switching to system DNS server %s.", strna(ip));
2c27fbca 1197 }
4e945a6f
LP
1198
1199 m->current_dns_server = s;
2c27fbca
LP
1200
1201 if (m->unicast_scope)
1202 dns_cache_flush(&m->unicast_scope->cache);
1203
4e945a6f 1204 return s;
74b2466e
LP
1205}
1206
1207DnsServer *manager_get_dns_server(Manager *m) {
4e945a6f 1208 Link *l;
74b2466e
LP
1209 assert(m);
1210
5cb36f41
LP
1211 /* Try to read updates resolv.conf */
1212 manager_read_resolv_conf(m);
1213
74b2466e 1214 if (!m->current_dns_server)
4e945a6f
LP
1215 manager_set_dns_server(m, m->dns_servers);
1216
1217 if (!m->current_dns_server) {
1218 bool found = false;
1219 Iterator i;
1220
1221 /* No DNS servers configured, let's see if there are
1222 * any on any links. If not, we use the fallback
1223 * servers */
1224
1225 HASHMAP_FOREACH(l, m->links, i)
1226 if (l->dns_servers) {
1227 found = true;
1228 break;
1229 }
1230
1231 if (!found)
1232 manager_set_dns_server(m, m->fallback_dns_servers);
1233 }
74b2466e
LP
1234
1235 return m->current_dns_server;
1236}
1237
1238void manager_next_dns_server(Manager *m) {
1239 assert(m);
1240
4e945a6f
LP
1241 /* If there's currently no DNS server set, then the next
1242 * manager_get_dns_server() will find one */
74b2466e
LP
1243 if (!m->current_dns_server)
1244 return;
1245
4e945a6f 1246 /* Change to the next one */
74b2466e 1247 if (m->current_dns_server->servers_next) {
4e945a6f 1248 manager_set_dns_server(m, m->current_dns_server->servers_next);
74b2466e
LP
1249 return;
1250 }
1251
4e945a6f
LP
1252 /* If there was no next one, then start from the beginning of
1253 * the list */
1254 if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
1255 manager_set_dns_server(m, m->fallback_dns_servers);
1256 else
1257 manager_set_dns_server(m, m->dns_servers);
091a364c 1258}
e1c95994
LP
1259
1260uint32_t manager_find_mtu(Manager *m) {
1261 uint32_t mtu = 0;
1262 Link *l;
1263 Iterator i;
1264
1265 /* If we don't know on which link a DNS packet would be
1266 * delivered, let's find the largest MTU that works on all
1267 * interfaces we know of */
1268
1269 HASHMAP_FOREACH(l, m->links, i) {
1270 if (l->mtu <= 0)
1271 continue;
1272
1273 if (mtu <= 0 || l->mtu < mtu)
1274 mtu = l->mtu;
1275 }
1276
1277 return mtu;
1278}
1716f6dc 1279
623a4c97 1280int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1281 LinkAddress *a;
1282
1283 assert(m);
1284
4e945a6f 1285 a = manager_find_link_address(m, family, in_addr);
ec2c5e43
LP
1286 if (a)
1287 return a->link->ifindex;
1288
1289 return 0;
1290}
1291
eb60f9cd
LP
1292void manager_refresh_rrs(Manager *m) {
1293 Iterator i;
1294 Link *l;
1295
1296 assert(m);
1297
78c6a153
LP
1298 m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
1299 m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd
LP
1300
1301 HASHMAP_FOREACH(l, m->links, i) {
1302 link_add_rrs(l, true);
1303 link_add_rrs(l, false);
1304 }
1305}
1306
ec2c5e43
LP
1307int manager_next_hostname(Manager *m) {
1308 const char *p;
556a2294 1309 uint64_t u, a;
78c6a153
LP
1310 char *h, *k;
1311 int r;
623a4c97
LP
1312
1313 assert(m);
1314
78c6a153 1315 p = strchr(m->llmnr_hostname, 0);
ec2c5e43
LP
1316 assert(p);
1317
78c6a153 1318 while (p > m->llmnr_hostname) {
ec2c5e43
LP
1319 if (!strchr("0123456789", p[-1]))
1320 break;
1321
1322 p--;
1323 }
1324
1325 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
1326 u = 1;
1327
556a2294
LP
1328 /* Add a random number to the old value. This way we can avoid
1329 * that two hosts pick the same hostname, win on IPv4 and lose
1330 * on IPv6 (or vice versa), and pick the same hostname
1331 * replacement hostname, ad infinitum. We still want the
1332 * numbers to go up monotonically, hence we just add a random
1333 * value 1..10 */
1334
1335 random_bytes(&a, sizeof(a));
1336 u += 1 + a % 10;
ec2c5e43 1337
78c6a153 1338 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
ec2c5e43
LP
1339 return -ENOMEM;
1340
78c6a153
LP
1341 r = dns_name_concat(h, "local", &k);
1342 if (r < 0) {
1343 free(h);
1344 return r;
1345 }
1346
1347 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
1348
1349 free(m->llmnr_hostname);
1350 m->llmnr_hostname = h;
ec2c5e43 1351
78c6a153
LP
1352 free(m->mdns_hostname);
1353 m->mdns_hostname = k;
ec2c5e43 1354
eb60f9cd 1355 manager_refresh_rrs(m);
623a4c97
LP
1356
1357 return 0;
1358}
ec2c5e43 1359
4e945a6f 1360LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1361 Iterator i;
1362 Link *l;
1363
1364 assert(m);
1365
1366 HASHMAP_FOREACH(l, m->links, i) {
1367 LinkAddress *a;
1368
1369 a = link_find_address(l, family, in_addr);
1370 if (a)
1371 return a;
1372 }
1373
1374 return NULL;
1375}
1376
a4076574 1377bool manager_our_packet(Manager *m, DnsPacket *p) {
ec2c5e43
LP
1378 assert(m);
1379 assert(p);
1380
4e945a6f 1381 return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e43 1382}
4e945a6f 1383
a4076574
LP
1384DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
1385 Link *l;
1386
1387 assert(m);
1388 assert(p);
1389
1390 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1391 if (!l)
1392 return NULL;
1393
1394 if (p->protocol == DNS_PROTOCOL_LLMNR) {
1395 if (p->family == AF_INET)
1396 return l->llmnr_ipv4_scope;
1397 else if (p->family == AF_INET6)
1398 return l->llmnr_ipv6_scope;
1399 }
1400
1401 return NULL;
1402}
1403
902bb5d8
LP
1404void manager_verify_all(Manager *m) {
1405 DnsScope *s;
1406
1407 assert(m);
1408
1409 LIST_FOREACH(scopes, s, m->dns_scopes)
1410 dns_zone_verify_all(&s->zone);
1411}
1412
3e684349 1413void manager_flush_dns_servers(Manager *m, DnsServerType t) {
91b14d6f
TG
1414 DnsServer *s;
1415
3e684349
LP
1416 assert(m);
1417
1418 if (t == DNS_SERVER_SYSTEM)
91b14d6f
TG
1419 while (m->dns_servers) {
1420 s = m->dns_servers;
1421
1422 LIST_REMOVE(servers, m->dns_servers, s);
1423 dns_server_unref(s);
1424 }
3e684349
LP
1425
1426 if (t == DNS_SERVER_FALLBACK)
91b14d6f
TG
1427 while (m->fallback_dns_servers) {
1428 s = m->fallback_dns_servers;
1429
1430 LIST_REMOVE(servers, m->fallback_dns_servers, s);
1431 dns_server_unref(s);
1432 }
3e684349
LP
1433}
1434
78c6a153 1435int manager_is_own_hostname(Manager *m, const char *name) {
78c6a153
LP
1436 int r;
1437
1438 assert(m);
1439 assert(name);
1440
1441 if (m->llmnr_hostname) {
1442 r = dns_name_equal(name, m->llmnr_hostname);
1443 if (r != 0)
1444 return r;
1445 }
1446
1447 if (m->mdns_hostname)
1448 return dns_name_equal(name, m->mdns_hostname);
1449
1450 return 0;
1451}
1452
4e945a6f
LP
1453static const char* const support_table[_SUPPORT_MAX] = {
1454 [SUPPORT_NO] = "no",
1455 [SUPPORT_YES] = "yes",
1456 [SUPPORT_RESOLVE] = "resolve",
1457};
1458DEFINE_STRING_TABLE_LOOKUP(support, Support);