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