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