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