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