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