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