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