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