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