]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/resolve/resolved-manager.c
resolved: fix the rcode to SUCCESS if we find at least one matching RR in a DNS response
[thirdparty/systemd.git] / src / resolve / resolved-manager.c
... / ...
CommitLineData
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
22#include <netinet/in.h>
23#include <poll.h>
24#include <sys/ioctl.h>
25
26#include "af-list.h"
27#include "alloc-util.h"
28#include "dns-domain.h"
29#include "fd-util.h"
30#include "fileio-label.h"
31#include "hostname-util.h"
32#include "io-util.h"
33#include "netlink-util.h"
34#include "network-internal.h"
35#include "ordered-set.h"
36#include "parse-util.h"
37#include "random-util.h"
38#include "resolved-bus.h"
39#include "resolved-conf.h"
40#include "resolved-etc-hosts.h"
41#include "resolved-llmnr.h"
42#include "resolved-manager.h"
43#include "resolved-mdns.h"
44#include "resolved-resolv-conf.h"
45#include "socket-util.h"
46#include "string-table.h"
47#include "string-util.h"
48#include "utf8.h"
49
50#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
51
52static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
53 Manager *m = userdata;
54 uint16_t type;
55 Link *l;
56 int ifindex, r;
57
58 assert(rtnl);
59 assert(m);
60 assert(mm);
61
62 r = sd_netlink_message_get_type(mm, &type);
63 if (r < 0)
64 goto fail;
65
66 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
67 if (r < 0)
68 goto fail;
69
70 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
71
72 switch (type) {
73
74 case RTM_NEWLINK:{
75 bool is_new = !l;
76
77 if (!l) {
78 r = link_new(m, &l, ifindex);
79 if (r < 0)
80 goto fail;
81 }
82
83 r = link_update_rtnl(l, mm);
84 if (r < 0)
85 goto fail;
86
87 r = link_update_monitor(l);
88 if (r < 0)
89 goto fail;
90
91 if (is_new)
92 log_debug("Found new link %i/%s", ifindex, l->name);
93
94 break;
95 }
96
97 case RTM_DELLINK:
98 if (l) {
99 log_debug("Removing link %i/%s", l->ifindex, l->name);
100 link_free(l);
101 }
102
103 break;
104 }
105
106 return 0;
107
108fail:
109 log_warning_errno(r, "Failed to process RTNL link message: %m");
110 return 0;
111}
112
113static int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
114 Manager *m = userdata;
115 union in_addr_union address;
116 uint16_t type;
117 int r, ifindex, family;
118 LinkAddress *a;
119 Link *l;
120
121 assert(rtnl);
122 assert(mm);
123 assert(m);
124
125 r = sd_netlink_message_get_type(mm, &type);
126 if (r < 0)
127 goto fail;
128
129 r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
130 if (r < 0)
131 goto fail;
132
133 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
134 if (!l)
135 return 0;
136
137 r = sd_rtnl_message_addr_get_family(mm, &family);
138 if (r < 0)
139 goto fail;
140
141 switch (family) {
142
143 case AF_INET:
144 r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
145 if (r < 0) {
146 r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
147 if (r < 0)
148 goto fail;
149 }
150
151 break;
152
153 case AF_INET6:
154 r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
155 if (r < 0) {
156 r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
157 if (r < 0)
158 goto fail;
159 }
160
161 break;
162
163 default:
164 return 0;
165 }
166
167 a = link_find_address(l, family, &address);
168
169 switch (type) {
170
171 case RTM_NEWADDR:
172
173 if (!a) {
174 r = link_address_new(l, &a, family, &address);
175 if (r < 0)
176 return r;
177 }
178
179 r = link_address_update_rtnl(a, mm);
180 if (r < 0)
181 return r;
182
183 break;
184
185 case RTM_DELADDR:
186 link_address_free(a);
187 break;
188 }
189
190 return 0;
191
192fail:
193 log_warning_errno(r, "Failed to process RTNL address message: %m");
194 return 0;
195}
196
197static int manager_rtnl_listen(Manager *m) {
198 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
199 sd_netlink_message *i;
200 int r;
201
202 assert(m);
203
204 /* First, subscribe to interfaces coming and going */
205 r = sd_netlink_open(&m->rtnl);
206 if (r < 0)
207 return r;
208
209 r = sd_netlink_attach_event(m->rtnl, m->event, 0);
210 if (r < 0)
211 return r;
212
213 r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
214 if (r < 0)
215 return r;
216
217 r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
218 if (r < 0)
219 return r;
220
221 r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
222 if (r < 0)
223 return r;
224
225 r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
226 if (r < 0)
227 return r;
228
229 /* Then, enumerate all links */
230 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
231 if (r < 0)
232 return r;
233
234 r = sd_netlink_message_request_dump(req, true);
235 if (r < 0)
236 return r;
237
238 r = sd_netlink_call(m->rtnl, req, 0, &reply);
239 if (r < 0)
240 return r;
241
242 for (i = reply; i; i = sd_netlink_message_next(i)) {
243 r = manager_process_link(m->rtnl, i, m);
244 if (r < 0)
245 return r;
246 }
247
248 req = sd_netlink_message_unref(req);
249 reply = sd_netlink_message_unref(reply);
250
251 /* Finally, enumerate all addresses, too */
252 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
253 if (r < 0)
254 return r;
255
256 r = sd_netlink_message_request_dump(req, true);
257 if (r < 0)
258 return r;
259
260 r = sd_netlink_call(m->rtnl, req, 0, &reply);
261 if (r < 0)
262 return r;
263
264 for (i = reply; i; i = sd_netlink_message_next(i)) {
265 r = manager_process_address(m->rtnl, i, m);
266 if (r < 0)
267 return r;
268 }
269
270 return r;
271}
272
273static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
274 Manager *m = userdata;
275 Iterator i;
276 Link *l;
277 int r;
278
279 assert(m);
280
281 sd_network_monitor_flush(m->network_monitor);
282
283 HASHMAP_FOREACH(l, m->links, i) {
284 r = link_update_monitor(l);
285 if (r < 0)
286 log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
287 }
288
289 r = manager_write_resolv_conf(m);
290 if (r < 0)
291 log_warning_errno(r, "Could not update resolv.conf: %m");
292
293 return 0;
294}
295
296static int manager_network_monitor_listen(Manager *m) {
297 int r, fd, events;
298
299 assert(m);
300
301 r = sd_network_monitor_new(&m->network_monitor, NULL);
302 if (r < 0)
303 return r;
304
305 fd = sd_network_monitor_get_fd(m->network_monitor);
306 if (fd < 0)
307 return fd;
308
309 events = sd_network_monitor_get_events(m->network_monitor);
310 if (events < 0)
311 return events;
312
313 r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
314 if (r < 0)
315 return r;
316
317 (void) sd_event_source_set_description(m->network_event_source, "network-monitor");
318
319 return 0;
320}
321
322static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
323 _cleanup_free_ char *h = NULL, *n = NULL;
324 char label[DNS_LABEL_MAX];
325 const char *p;
326 int r, k;
327
328 assert(llmnr_hostname);
329 assert(mdns_hostname);
330
331 /* Extract and normalize the first label of the locally
332 * configured hostname, and check it's not "localhost". */
333
334 h = gethostname_malloc();
335 if (!h)
336 return log_oom();
337
338 p = h;
339 r = dns_label_unescape(&p, label, sizeof(label));
340 if (r < 0)
341 return log_error_errno(r, "Failed to unescape host name: %m");
342 if (r == 0) {
343 log_error("Couldn't find a single label in hosntame.");
344 return -EINVAL;
345 }
346
347 k = dns_label_undo_idna(label, r, label, sizeof(label));
348 if (k < 0)
349 return log_error_errno(k, "Failed to undo IDNA: %m");
350 if (k > 0)
351 r = k;
352
353 if (!utf8_is_valid(label)) {
354 log_error("System hostname is not UTF-8 clean.");
355 return -EINVAL;
356 }
357
358 r = dns_label_escape_new(label, r, &n);
359 if (r < 0)
360 return log_error_errno(r, "Failed to escape host name: %m");
361
362 if (is_localhost(n)) {
363 log_debug("System hostname is 'localhost', ignoring.");
364 return -EINVAL;
365 }
366
367 r = dns_name_concat(n, "local", mdns_hostname);
368 if (r < 0)
369 return log_error_errno(r, "Failed to determine mDNS hostname: %m");
370
371 *llmnr_hostname = n;
372 n = NULL;
373
374 return 0;
375}
376
377static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
378 _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
379 Manager *m = userdata;
380 int r;
381
382 assert(m);
383
384 r = determine_hostname(&llmnr_hostname, &mdns_hostname);
385 if (r < 0)
386 return 0; /* ignore invalid hostnames */
387
388 if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
389 return 0;
390
391 log_info("System hostname changed to '%s'.", llmnr_hostname);
392
393 free(m->llmnr_hostname);
394 free(m->mdns_hostname);
395
396 m->llmnr_hostname = llmnr_hostname;
397 m->mdns_hostname = mdns_hostname;
398
399 llmnr_hostname = mdns_hostname = NULL;
400
401 manager_refresh_rrs(m);
402
403 return 0;
404}
405
406static int manager_watch_hostname(Manager *m) {
407 int r;
408
409 assert(m);
410
411 m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
412 if (m->hostname_fd < 0) {
413 log_warning_errno(errno, "Failed to watch hostname: %m");
414 return 0;
415 }
416
417 r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
418 if (r < 0) {
419 if (r == -EPERM)
420 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
421 m->hostname_fd = safe_close(m->hostname_fd);
422 else
423 return log_error_errno(r, "Failed to add hostname event source: %m");
424 }
425
426 (void) sd_event_source_set_description(m->hostname_event_source, "hostname");
427
428 r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
429 if (r < 0) {
430 log_info("Defaulting to hostname 'linux'.");
431 m->llmnr_hostname = strdup("linux");
432 if (!m->llmnr_hostname)
433 return log_oom();
434
435 m->mdns_hostname = strdup("linux.local");
436 if (!m->mdns_hostname)
437 return log_oom();
438 } else
439 log_info("Using system hostname '%s'.", m->llmnr_hostname);
440
441 return 0;
442}
443
444static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
445 _cleanup_free_ char *buffer = NULL;
446 _cleanup_fclose_ FILE *f = NULL;
447 Manager *m = userdata;
448 size_t size = 0;
449 DnsScope *scope;
450
451 assert(s);
452 assert(si);
453 assert(m);
454
455 f = open_memstream(&buffer, &size);
456 if (!f)
457 return log_oom();
458
459 LIST_FOREACH(scopes, scope, m->dns_scopes)
460 dns_scope_dump(scope, f);
461
462 if (fflush_and_check(f) < 0)
463 return log_oom();
464
465 log_dump(LOG_INFO, buffer);
466 return 0;
467}
468
469int manager_new(Manager **ret) {
470 _cleanup_(manager_freep) Manager *m = NULL;
471 int r;
472
473 assert(ret);
474
475 m = new0(Manager, 1);
476 if (!m)
477 return -ENOMEM;
478
479 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
480 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
481 m->mdns_ipv4_fd = m->mdns_ipv6_fd = -1;
482 m->hostname_fd = -1;
483
484 m->llmnr_support = RESOLVE_SUPPORT_YES;
485 m->mdns_support = RESOLVE_SUPPORT_NO;
486 m->dnssec_mode = DNSSEC_NO;
487 m->read_resolv_conf = true;
488 m->need_builtin_fallbacks = true;
489 m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY;
490
491 r = dns_trust_anchor_load(&m->trust_anchor);
492 if (r < 0)
493 return r;
494
495 r = manager_parse_config_file(m);
496 if (r < 0)
497 return r;
498
499 r = sd_event_default(&m->event);
500 if (r < 0)
501 return r;
502
503 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
504 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
505
506 sd_event_set_watchdog(m->event, true);
507
508 r = manager_watch_hostname(m);
509 if (r < 0)
510 return r;
511
512 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
513 if (r < 0)
514 return r;
515
516 r = manager_network_monitor_listen(m);
517 if (r < 0)
518 return r;
519
520 r = manager_rtnl_listen(m);
521 if (r < 0)
522 return r;
523
524 r = manager_connect_bus(m);
525 if (r < 0)
526 return r;
527
528 (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
529
530 *ret = m;
531 m = NULL;
532
533 return 0;
534}
535
536int manager_start(Manager *m) {
537 int r;
538
539 assert(m);
540
541 r = manager_llmnr_start(m);
542 if (r < 0)
543 return r;
544
545 r = manager_mdns_start(m);
546 if (r < 0)
547 return r;
548
549 return 0;
550}
551
552Manager *manager_free(Manager *m) {
553 Link *l;
554
555 if (!m)
556 return NULL;
557
558 dns_server_unlink_all(m->dns_servers);
559 dns_server_unlink_all(m->fallback_dns_servers);
560 dns_search_domain_unlink_all(m->search_domains);
561
562 while ((l = hashmap_first(m->links)))
563 link_free(l);
564
565 while (m->dns_queries)
566 dns_query_free(m->dns_queries);
567
568 dns_scope_free(m->unicast_scope);
569
570 hashmap_free(m->links);
571 hashmap_free(m->dns_transactions);
572
573 sd_event_source_unref(m->network_event_source);
574 sd_network_monitor_unref(m->network_monitor);
575
576 sd_netlink_unref(m->rtnl);
577 sd_event_source_unref(m->rtnl_event_source);
578
579 manager_llmnr_stop(m);
580 manager_mdns_stop(m);
581
582 sd_bus_slot_unref(m->prepare_for_sleep_slot);
583 sd_event_source_unref(m->bus_retry_event_source);
584 sd_bus_unref(m->bus);
585
586 sd_event_source_unref(m->sigusr1_event_source);
587
588 sd_event_unref(m->event);
589
590 dns_resource_key_unref(m->llmnr_host_ipv4_key);
591 dns_resource_key_unref(m->llmnr_host_ipv6_key);
592
593 sd_event_source_unref(m->hostname_event_source);
594 safe_close(m->hostname_fd);
595 free(m->llmnr_hostname);
596 free(m->mdns_hostname);
597
598 dns_trust_anchor_flush(&m->trust_anchor);
599 manager_etc_hosts_flush(m);
600
601 free(m);
602
603 return NULL;
604}
605
606int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
607 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
608 union {
609 struct cmsghdr header; /* For alignment */
610 uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
611 + CMSG_SPACE(int) /* ttl/hoplimit */
612 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
613 } control;
614 union sockaddr_union sa;
615 struct msghdr mh = {};
616 struct cmsghdr *cmsg;
617 struct iovec iov;
618 int ms = 0, r;
619 ssize_t l;
620
621 assert(m);
622 assert(fd >= 0);
623 assert(ret);
624
625 r = ioctl(fd, FIONREAD, &ms);
626 if (r < 0)
627 return -errno;
628 if (ms < 0)
629 return -EIO;
630
631 r = dns_packet_new(&p, protocol, ms);
632 if (r < 0)
633 return r;
634
635 iov.iov_base = DNS_PACKET_DATA(p);
636 iov.iov_len = p->allocated;
637
638 mh.msg_name = &sa.sa;
639 mh.msg_namelen = sizeof(sa);
640 mh.msg_iov = &iov;
641 mh.msg_iovlen = 1;
642 mh.msg_control = &control;
643 mh.msg_controllen = sizeof(control);
644
645 l = recvmsg(fd, &mh, 0);
646 if (l < 0) {
647 if (errno == EAGAIN || errno == EINTR)
648 return 0;
649
650 return -errno;
651 }
652
653 if (l <= 0)
654 return -EIO;
655
656 assert(!(mh.msg_flags & MSG_CTRUNC));
657 assert(!(mh.msg_flags & MSG_TRUNC));
658
659 p->size = (size_t) l;
660
661 p->family = sa.sa.sa_family;
662 p->ipproto = IPPROTO_UDP;
663 if (p->family == AF_INET) {
664 p->sender.in = sa.in.sin_addr;
665 p->sender_port = be16toh(sa.in.sin_port);
666 } else if (p->family == AF_INET6) {
667 p->sender.in6 = sa.in6.sin6_addr;
668 p->sender_port = be16toh(sa.in6.sin6_port);
669 p->ifindex = sa.in6.sin6_scope_id;
670 } else
671 return -EAFNOSUPPORT;
672
673 CMSG_FOREACH(cmsg, &mh) {
674
675 if (cmsg->cmsg_level == IPPROTO_IPV6) {
676 assert(p->family == AF_INET6);
677
678 switch (cmsg->cmsg_type) {
679
680 case IPV6_PKTINFO: {
681 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
682
683 if (p->ifindex <= 0)
684 p->ifindex = i->ipi6_ifindex;
685
686 p->destination.in6 = i->ipi6_addr;
687 break;
688 }
689
690 case IPV6_HOPLIMIT:
691 p->ttl = *(int *) CMSG_DATA(cmsg);
692 break;
693
694 }
695 } else if (cmsg->cmsg_level == IPPROTO_IP) {
696 assert(p->family == AF_INET);
697
698 switch (cmsg->cmsg_type) {
699
700 case IP_PKTINFO: {
701 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
702
703 if (p->ifindex <= 0)
704 p->ifindex = i->ipi_ifindex;
705
706 p->destination.in = i->ipi_addr;
707 break;
708 }
709
710 case IP_TTL:
711 p->ttl = *(int *) CMSG_DATA(cmsg);
712 break;
713 }
714 }
715 }
716
717 /* The Linux kernel sets the interface index to the loopback
718 * device if the packet came from the local host since it
719 * avoids the routing table in such a case. Let's unset the
720 * interface index in such a case. */
721 if (p->ifindex == LOOPBACK_IFINDEX)
722 p->ifindex = 0;
723
724 if (protocol != DNS_PROTOCOL_DNS) {
725 /* If we don't know the interface index still, we look for the
726 * first local interface with a matching address. Yuck! */
727 if (p->ifindex <= 0)
728 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
729 }
730
731 *ret = p;
732 p = NULL;
733
734 return 1;
735}
736
737static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
738 int r;
739
740 assert(fd >= 0);
741 assert(mh);
742
743 for (;;) {
744 if (sendmsg(fd, mh, flags) >= 0)
745 return 0;
746
747 if (errno == EINTR)
748 continue;
749
750 if (errno != EAGAIN)
751 return -errno;
752
753 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
754 if (r < 0)
755 return r;
756 if (r == 0)
757 return -ETIMEDOUT;
758 }
759}
760
761static int write_loop(int fd, void *message, size_t length) {
762 int r;
763
764 assert(fd >= 0);
765 assert(message);
766
767 for (;;) {
768 if (write(fd, message, length) >= 0)
769 return 0;
770
771 if (errno == EINTR)
772 continue;
773
774 if (errno != EAGAIN)
775 return -errno;
776
777 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
778 if (r < 0)
779 return r;
780 if (r == 0)
781 return -ETIMEDOUT;
782 }
783}
784
785int manager_write(Manager *m, int fd, DnsPacket *p) {
786 int r;
787
788 log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
789
790 r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
791 if (r < 0)
792 return r;
793
794 return 0;
795}
796
797static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
798 union sockaddr_union sa = {
799 .in.sin_family = AF_INET,
800 };
801 union {
802 struct cmsghdr header; /* For alignment */
803 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
804 } control;
805 struct msghdr mh = {};
806 struct iovec iov;
807
808 assert(m);
809 assert(fd >= 0);
810 assert(addr);
811 assert(port > 0);
812 assert(p);
813
814 iov.iov_base = DNS_PACKET_DATA(p);
815 iov.iov_len = p->size;
816
817 sa.in.sin_addr = *addr;
818 sa.in.sin_port = htobe16(port),
819
820 mh.msg_iov = &iov;
821 mh.msg_iovlen = 1;
822 mh.msg_name = &sa.sa;
823 mh.msg_namelen = sizeof(sa.in);
824
825 if (ifindex > 0) {
826 struct cmsghdr *cmsg;
827 struct in_pktinfo *pi;
828
829 zero(control);
830
831 mh.msg_control = &control;
832 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
833
834 cmsg = CMSG_FIRSTHDR(&mh);
835 cmsg->cmsg_len = mh.msg_controllen;
836 cmsg->cmsg_level = IPPROTO_IP;
837 cmsg->cmsg_type = IP_PKTINFO;
838
839 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
840 pi->ipi_ifindex = ifindex;
841 }
842
843 return sendmsg_loop(fd, &mh, 0);
844}
845
846static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
847 union sockaddr_union sa = {
848 .in6.sin6_family = AF_INET6,
849 };
850 union {
851 struct cmsghdr header; /* For alignment */
852 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
853 } control;
854 struct msghdr mh = {};
855 struct iovec iov;
856
857 assert(m);
858 assert(fd >= 0);
859 assert(addr);
860 assert(port > 0);
861 assert(p);
862
863 iov.iov_base = DNS_PACKET_DATA(p);
864 iov.iov_len = p->size;
865
866 sa.in6.sin6_addr = *addr;
867 sa.in6.sin6_port = htobe16(port),
868 sa.in6.sin6_scope_id = ifindex;
869
870 mh.msg_iov = &iov;
871 mh.msg_iovlen = 1;
872 mh.msg_name = &sa.sa;
873 mh.msg_namelen = sizeof(sa.in6);
874
875 if (ifindex > 0) {
876 struct cmsghdr *cmsg;
877 struct in6_pktinfo *pi;
878
879 zero(control);
880
881 mh.msg_control = &control;
882 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
883
884 cmsg = CMSG_FIRSTHDR(&mh);
885 cmsg->cmsg_len = mh.msg_controllen;
886 cmsg->cmsg_level = IPPROTO_IPV6;
887 cmsg->cmsg_type = IPV6_PKTINFO;
888
889 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
890 pi->ipi6_ifindex = ifindex;
891 }
892
893 return sendmsg_loop(fd, &mh, 0);
894}
895
896int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
897 assert(m);
898 assert(fd >= 0);
899 assert(addr);
900 assert(port > 0);
901 assert(p);
902
903 log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
904
905 if (family == AF_INET)
906 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
907 else if (family == AF_INET6)
908 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
909
910 return -EAFNOSUPPORT;
911}
912
913uint32_t manager_find_mtu(Manager *m) {
914 uint32_t mtu = 0;
915 Link *l;
916 Iterator i;
917
918 /* If we don't know on which link a DNS packet would be
919 * delivered, let's find the largest MTU that works on all
920 * interfaces we know of */
921
922 HASHMAP_FOREACH(l, m->links, i) {
923 if (l->mtu <= 0)
924 continue;
925
926 if (mtu <= 0 || l->mtu < mtu)
927 mtu = l->mtu;
928 }
929
930 return mtu;
931}
932
933int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
934 LinkAddress *a;
935
936 assert(m);
937
938 a = manager_find_link_address(m, family, in_addr);
939 if (a)
940 return a->link->ifindex;
941
942 return 0;
943}
944
945void manager_refresh_rrs(Manager *m) {
946 Iterator i;
947 Link *l;
948
949 assert(m);
950
951 m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
952 m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
953
954 HASHMAP_FOREACH(l, m->links, i) {
955 link_add_rrs(l, true);
956 link_add_rrs(l, false);
957 }
958}
959
960int manager_next_hostname(Manager *m) {
961 const char *p;
962 uint64_t u, a;
963 char *h, *k;
964 int r;
965
966 assert(m);
967
968 p = strchr(m->llmnr_hostname, 0);
969 assert(p);
970
971 while (p > m->llmnr_hostname) {
972 if (!strchr("0123456789", p[-1]))
973 break;
974
975 p--;
976 }
977
978 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
979 u = 1;
980
981 /* Add a random number to the old value. This way we can avoid
982 * that two hosts pick the same hostname, win on IPv4 and lose
983 * on IPv6 (or vice versa), and pick the same hostname
984 * replacement hostname, ad infinitum. We still want the
985 * numbers to go up monotonically, hence we just add a random
986 * value 1..10 */
987
988 random_bytes(&a, sizeof(a));
989 u += 1 + a % 10;
990
991 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
992 return -ENOMEM;
993
994 r = dns_name_concat(h, "local", &k);
995 if (r < 0) {
996 free(h);
997 return r;
998 }
999
1000 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
1001
1002 free(m->llmnr_hostname);
1003 m->llmnr_hostname = h;
1004
1005 free(m->mdns_hostname);
1006 m->mdns_hostname = k;
1007
1008 manager_refresh_rrs(m);
1009
1010 return 0;
1011}
1012
1013LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
1014 Iterator i;
1015 Link *l;
1016
1017 assert(m);
1018
1019 HASHMAP_FOREACH(l, m->links, i) {
1020 LinkAddress *a;
1021
1022 a = link_find_address(l, family, in_addr);
1023 if (a)
1024 return a;
1025 }
1026
1027 return NULL;
1028}
1029
1030bool manager_our_packet(Manager *m, DnsPacket *p) {
1031 assert(m);
1032 assert(p);
1033
1034 return !!manager_find_link_address(m, p->family, &p->sender);
1035}
1036
1037DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
1038 Link *l;
1039
1040 assert(m);
1041 assert(p);
1042
1043 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1044 if (!l)
1045 return NULL;
1046
1047 switch (p->protocol) {
1048 case DNS_PROTOCOL_LLMNR:
1049 if (p->family == AF_INET)
1050 return l->llmnr_ipv4_scope;
1051 else if (p->family == AF_INET6)
1052 return l->llmnr_ipv6_scope;
1053
1054 break;
1055
1056 case DNS_PROTOCOL_MDNS:
1057 if (p->family == AF_INET)
1058 return l->mdns_ipv4_scope;
1059 else if (p->family == AF_INET6)
1060 return l->mdns_ipv6_scope;
1061
1062 break;
1063
1064 default:
1065 break;
1066 }
1067
1068 return NULL;
1069}
1070
1071void manager_verify_all(Manager *m) {
1072 DnsScope *s;
1073
1074 assert(m);
1075
1076 LIST_FOREACH(scopes, s, m->dns_scopes)
1077 dns_zone_verify_all(&s->zone);
1078}
1079
1080int manager_is_own_hostname(Manager *m, const char *name) {
1081 int r;
1082
1083 assert(m);
1084 assert(name);
1085
1086 if (m->llmnr_hostname) {
1087 r = dns_name_equal(name, m->llmnr_hostname);
1088 if (r != 0)
1089 return r;
1090 }
1091
1092 if (m->mdns_hostname)
1093 return dns_name_equal(name, m->mdns_hostname);
1094
1095 return 0;
1096}
1097
1098int manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
1099 DnsServer *s;
1100 Iterator i;
1101 Link *l;
1102 int r;
1103
1104 assert(m);
1105 assert(dns);
1106
1107 r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
1108 if (r < 0)
1109 return r;
1110
1111 /* First add the system-wide servers and domains */
1112 LIST_FOREACH(servers, s, m->dns_servers) {
1113 r = ordered_set_put(*dns, s);
1114 if (r == -EEXIST)
1115 continue;
1116 if (r < 0)
1117 return r;
1118 }
1119
1120 /* Then, add the per-link servers */
1121 HASHMAP_FOREACH(l, m->links, i) {
1122 LIST_FOREACH(servers, s, l->dns_servers) {
1123 r = ordered_set_put(*dns, s);
1124 if (r == -EEXIST)
1125 continue;
1126 if (r < 0)
1127 return r;
1128 }
1129 }
1130
1131 /* If we found nothing, add the fallback servers */
1132 if (ordered_set_isempty(*dns)) {
1133 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1134 r = ordered_set_put(*dns, s);
1135 if (r == -EEXIST)
1136 continue;
1137 if (r < 0)
1138 return r;
1139 }
1140 }
1141
1142 return 0;
1143}
1144
1145int manager_compile_search_domains(Manager *m, OrderedSet **domains) {
1146 DnsSearchDomain *d;
1147 Iterator i;
1148 Link *l;
1149 int r;
1150
1151 assert(m);
1152 assert(domains);
1153
1154 r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops);
1155 if (r < 0)
1156 return r;
1157
1158 LIST_FOREACH(domains, d, m->search_domains) {
1159 r = ordered_set_put(*domains, d->name);
1160 if (r == -EEXIST)
1161 continue;
1162 if (r < 0)
1163 return r;
1164 }
1165
1166 HASHMAP_FOREACH(l, m->links, i) {
1167
1168 LIST_FOREACH(domains, d, l->search_domains) {
1169 r = ordered_set_put(*domains, d->name);
1170 if (r == -EEXIST)
1171 continue;
1172 if (r < 0)
1173 return r;
1174 }
1175 }
1176
1177 return 0;
1178}
1179
1180DnssecMode manager_get_dnssec_mode(Manager *m) {
1181 assert(m);
1182
1183 if (m->dnssec_mode != _DNSSEC_MODE_INVALID)
1184 return m->dnssec_mode;
1185
1186 return DNSSEC_NO;
1187}
1188
1189bool manager_dnssec_supported(Manager *m) {
1190 DnsServer *server;
1191 Iterator i;
1192 Link *l;
1193
1194 assert(m);
1195
1196 if (manager_get_dnssec_mode(m) == DNSSEC_NO)
1197 return false;
1198
1199 server = manager_get_dns_server(m);
1200 if (server && !dns_server_dnssec_supported(server))
1201 return false;
1202
1203 HASHMAP_FOREACH(l, m->links, i)
1204 if (!link_dnssec_supported(l))
1205 return false;
1206
1207 return true;
1208}
1209
1210void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) {
1211
1212 assert(verdict >= 0);
1213 assert(verdict < _DNSSEC_VERDICT_MAX);
1214
1215 if (log_get_max_level() >= LOG_DEBUG) {
1216 _cleanup_free_ char *s = NULL;
1217
1218 (void) dns_resource_key_to_string(key, &s);
1219
1220 log_debug("Found verdict for lookup %s: %s", s ? strstrip(s) : "n/a", dnssec_verdict_to_string(verdict));
1221 }
1222
1223 m->n_dnssec_verdict[verdict]++;
1224}