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