]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/resolve/resolved-manager.c
nss: always explicitly reset all error variables
[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 <arpa/inet.h>
23#include <resolv.h>
24#include <net/if.h>
25#include <sys/ioctl.h>
26#include <sys/poll.h>
27#include <netinet/in.h>
28
29#include "rtnl-util.h"
30#include "event-util.h"
31#include "network-util.h"
32#include "network-internal.h"
33#include "conf-parser.h"
34#include "socket-util.h"
35#include "af-list.h"
36#include "resolved.h"
37#include "utf8.h"
38#include "resolved-dns-domain.h"
39
40#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
41
42static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
43 Manager *m = userdata;
44 uint16_t type;
45 Link *l;
46 int ifindex, r;
47
48 assert(rtnl);
49 assert(m);
50 assert(mm);
51
52 r = sd_rtnl_message_get_type(mm, &type);
53 if (r < 0)
54 goto fail;
55
56 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
57 if (r < 0)
58 goto fail;
59
60 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
61
62 switch (type) {
63
64 case RTM_NEWLINK:{
65 bool is_new = !l;
66
67 if (!l) {
68 r = link_new(m, &l, ifindex);
69 if (r < 0)
70 goto fail;
71 }
72
73 r = link_update_rtnl(l, mm);
74 if (r < 0)
75 goto fail;
76
77 if (is_new)
78 log_debug("Found new link %i/%s", ifindex, l->name);
79
80 break;
81 }
82
83 case RTM_DELLINK:
84 if (l) {
85 log_debug("Removing link %i/%s", l->ifindex, l->name);
86 link_free(l);
87 }
88
89 break;
90 }
91
92 return 0;
93
94fail:
95 log_warning("Failed to process RTNL link message: %s", strerror(-r));
96 return 0;
97}
98
99static int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
100 Manager *m = userdata;
101 union in_addr_union address;
102 uint16_t type;
103 int r, ifindex, family;
104 LinkAddress *a;
105 Link *l;
106
107 assert(rtnl);
108 assert(mm);
109 assert(m);
110
111 r = sd_rtnl_message_get_type(mm, &type);
112 if (r < 0)
113 goto fail;
114
115 r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
116 if (r < 0)
117 goto fail;
118
119 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
120 if (!l)
121 return 0;
122
123 r = sd_rtnl_message_addr_get_family(mm, &family);
124 if (r < 0)
125 goto fail;
126
127 switch (family) {
128
129 case AF_INET:
130 r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
131 if (r < 0) {
132 r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
133 if (r < 0)
134 goto fail;
135 }
136
137 break;
138
139 case AF_INET6:
140 r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
141 if (r < 0) {
142 r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
143 if (r < 0)
144 goto fail;
145 }
146
147 break;
148
149 default:
150 return 0;
151 }
152
153 a = link_find_address(l, family, &address);
154
155 switch (type) {
156
157 case RTM_NEWADDR:
158
159 if (!a) {
160 r = link_address_new(l, &a, family, &address);
161 if (r < 0)
162 return r;
163 }
164
165 r = link_address_update_rtnl(a, mm);
166 if (r < 0)
167 return r;
168
169 break;
170
171 case RTM_DELADDR:
172 if (a)
173 link_address_free(a);
174 break;
175 }
176
177 return 0;
178
179fail:
180 log_warning("Failed to process RTNL address message: %s", strerror(-r));
181 return 0;
182}
183
184
185static int manager_rtnl_listen(Manager *m) {
186 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
187 sd_rtnl_message *i;
188 int r;
189
190 assert(m);
191
192 /* First, subscibe to interfaces coming and going */
193 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
194 if (r < 0)
195 return r;
196
197 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
198 if (r < 0)
199 return r;
200
201 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
202 if (r < 0)
203 return r;
204
205 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
206 if (r < 0)
207 return r;
208
209 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
210 if (r < 0)
211 return r;
212
213 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
214 if (r < 0)
215 return r;
216
217 /* Then, enumerate all links */
218 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
219 if (r < 0)
220 return r;
221
222 r = sd_rtnl_message_request_dump(req, true);
223 if (r < 0)
224 return r;
225
226 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
227 if (r < 0)
228 return r;
229
230 for (i = reply; i; i = sd_rtnl_message_next(i)) {
231 r = manager_process_link(m->rtnl, i, m);
232 if (r < 0)
233 return r;
234 }
235
236 req = sd_rtnl_message_unref(req);
237 reply = sd_rtnl_message_unref(reply);
238
239 /* Finally, enumerate all addresses, too */
240 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
241 if (r < 0)
242 return r;
243
244 r = sd_rtnl_message_request_dump(req, true);
245 if (r < 0)
246 return r;
247
248 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
249 if (r < 0)
250 return r;
251
252 for (i = reply; i; i = sd_rtnl_message_next(i)) {
253 r = manager_process_address(m->rtnl, i, m);
254 if (r < 0)
255 return r;
256 }
257
258 return r;
259}
260
261static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
262 Manager *m = userdata;
263 Iterator i;
264 Link *l;
265 int r;
266
267 assert(m);
268
269 sd_network_monitor_flush(m->network_monitor);
270
271 HASHMAP_FOREACH(l, m->links, i) {
272 r = link_update_monitor(l);
273 if (r < 0)
274 log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
275 }
276
277 r = manager_write_resolv_conf(m);
278 if (r < 0)
279 log_warning("Could not update resolv.conf: %s", strerror(-r));
280
281 return 0;
282}
283
284static int manager_network_monitor_listen(Manager *m) {
285 int r, fd, events;
286
287 assert(m);
288
289 r = sd_network_monitor_new(&m->network_monitor, NULL);
290 if (r < 0)
291 return r;
292
293 fd = sd_network_monitor_get_fd(m->network_monitor);
294 if (fd < 0)
295 return fd;
296
297 events = sd_network_monitor_get_events(m->network_monitor);
298 if (events < 0)
299 return events;
300
301 r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
302 if (r < 0)
303 return r;
304
305 return 0;
306}
307
308static int parse_dns_server_string(Manager *m, const char *string) {
309 const char *word, *state;
310 size_t length;
311 int r;
312
313 assert(m);
314 assert(string);
315
316 FOREACH_WORD_QUOTED(word, length, string, state) {
317 char buffer[length+1];
318 int family;
319 union in_addr_union addr;
320
321 memcpy(buffer, word, length);
322 buffer[length] = 0;
323
324 r = in_addr_from_string_auto(buffer, &family, &addr);
325 if (r < 0) {
326 log_warning("Ignoring invalid DNS address '%s'", buffer);
327 continue;
328 }
329
330 /* filter out duplicates */
331 if (manager_find_dns_server(m, family, &addr))
332 continue;
333
334 r = dns_server_new(m, NULL, NULL, family, &addr);
335 if (r < 0)
336 return r;
337 }
338 /* do not warn about state here, since probably systemd already did */
339
340 return 0;
341}
342
343int config_parse_dnsv(
344 const char *unit,
345 const char *filename,
346 unsigned line,
347 const char *section,
348 unsigned section_line,
349 const char *lvalue,
350 int ltype,
351 const char *rvalue,
352 void *data,
353 void *userdata) {
354
355 Manager *m = userdata;
356 int r;
357
358 assert(filename);
359 assert(lvalue);
360 assert(rvalue);
361 assert(m);
362
363 /* Empty assignment means clear the list */
364 if (isempty(rvalue)) {
365 while (m->dns_servers)
366 dns_server_free(m->dns_servers);
367
368 return 0;
369 }
370
371 r = parse_dns_server_string(m, rvalue);
372 if (r < 0) {
373 log_error("Failed to parse DNS server string");
374 return r;
375 }
376
377 return 0;
378}
379
380int manager_parse_config_file(Manager *m) {
381 assert(m);
382
383 return config_parse(NULL, "/etc/systemd/resolved.conf", NULL,
384 "Resolve\0",
385 config_item_perf_lookup, resolved_gperf_lookup,
386 false, false, true, m);
387}
388
389static int determine_hostname(char **ret) {
390 _cleanup_free_ char *h = NULL, *n = NULL;
391 int r;
392
393 assert(ret);
394
395 h = gethostname_malloc();
396 if (!h)
397 return log_oom();
398
399 if (!utf8_is_valid(h)) {
400 log_error("System hostname is not UTF-8 clean.");
401 return -EINVAL;
402 }
403
404 r = dns_name_normalize(h, &n);
405 if (r < 0) {
406 log_error("System hostname '%s' cannot be normalized.", h);
407 return r;
408 }
409
410 *ret = n;
411 n = NULL;
412
413 return 0;
414}
415
416static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
417 _cleanup_free_ char *h = NULL;
418 Manager *m = userdata;
419 int r;
420
421 assert(m);
422
423 r = determine_hostname(&h);
424 if (r < 0)
425 return 0; /* ignore invalid hostnames */
426
427 if (streq(h, m->hostname))
428 return 0;
429
430 log_info("System hostname changed to '%s'.", h);
431 free(m->hostname);
432 m->hostname = h;
433 h = NULL;
434
435 manager_refresh_rrs(m);
436
437 return 0;
438}
439
440static int manager_watch_hostname(Manager *m) {
441 _cleanup_free_ char *h = NULL;
442 int r;
443
444 assert(m);
445
446 m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
447 if (m->hostname_fd < 0) {
448 log_warning("Failed to watch hostname: %m");
449 return 0;
450 }
451
452 r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
453 if (r < 0) {
454 if (r == -EPERM)
455 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
456 m->hostname_fd = safe_close(m->hostname_fd);
457 else {
458 log_error("Failed to add hostname event source: %s", strerror(-r));
459 return r;
460 }
461 }
462
463 r = determine_hostname(&m->hostname);
464 if (r < 0) {
465 log_info("Defaulting to hostname 'linux'.");
466 m->hostname = strdup("linux");
467 if (!m->hostname)
468 return log_oom();
469 } else
470 log_info("Using system hostname '%s'.", m->hostname);
471
472 return 0;
473}
474
475int manager_new(Manager **ret) {
476 _cleanup_(manager_freep) Manager *m = NULL;
477 int r;
478
479 assert(ret);
480
481 m = new0(Manager, 1);
482 if (!m)
483 return -ENOMEM;
484
485 m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
486 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
487 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
488 m->hostname_fd = -1;
489
490 m->use_llmnr = true;
491
492 r = parse_dns_server_string(m, DNS_SERVERS);
493 if (r < 0)
494 return r;
495
496 r = sd_event_default(&m->event);
497 if (r < 0)
498 return r;
499
500 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
501 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
502
503 sd_event_set_watchdog(m->event, true);
504
505 r = manager_watch_hostname(m);
506 if (r < 0)
507 return r;
508
509 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
510 if (r < 0)
511 return r;
512
513 r = manager_network_monitor_listen(m);
514 if (r < 0)
515 return r;
516
517 r = manager_rtnl_listen(m);
518 if (r < 0)
519 return r;
520
521 r = manager_connect_bus(m);
522 if (r < 0)
523 return r;
524
525 r = manager_llmnr_ipv4_udp_fd(m);
526 if (r < 0)
527 return r;
528 r = manager_llmnr_ipv6_udp_fd(m);
529 if (r < 0)
530 return r;
531 r = manager_llmnr_ipv4_tcp_fd(m);
532 if (r < 0)
533 return r;
534 r = manager_llmnr_ipv6_tcp_fd(m);
535 if (r < 0)
536 return r;
537
538 *ret = m;
539 m = NULL;
540
541 return 0;
542}
543
544Manager *manager_free(Manager *m) {
545 Link *l;
546
547 if (!m)
548 return NULL;
549
550 while (m->dns_queries)
551 dns_query_free(m->dns_queries);
552
553 hashmap_free(m->dns_transactions);
554
555 while ((l = hashmap_first(m->links)))
556 link_free(l);
557 hashmap_free(m->links);
558
559 dns_scope_free(m->unicast_scope);
560
561 while (m->dns_servers)
562 dns_server_free(m->dns_servers);
563
564 sd_event_source_unref(m->network_event_source);
565 sd_network_monitor_unref(m->network_monitor);
566
567 sd_event_source_unref(m->dns_ipv4_event_source);
568 sd_event_source_unref(m->dns_ipv6_event_source);
569 safe_close(m->dns_ipv4_fd);
570 safe_close(m->dns_ipv6_fd);
571
572 sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
573 sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
574 safe_close(m->llmnr_ipv4_udp_fd);
575 safe_close(m->llmnr_ipv6_udp_fd);
576
577 sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
578 sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
579 safe_close(m->llmnr_ipv4_tcp_fd);
580 safe_close(m->llmnr_ipv6_tcp_fd);
581
582 sd_event_source_unref(m->bus_retry_event_source);
583 sd_bus_unref(m->bus);
584
585 sd_event_unref(m->event);
586
587 dns_resource_key_unref(m->host_ipv4_key);
588 dns_resource_key_unref(m->host_ipv6_key);
589
590 safe_close(m->hostname_fd);
591 sd_event_source_unref(m->hostname_event_source);
592 free(m->hostname);
593
594 free(m);
595
596 return NULL;
597}
598
599static void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
600 _cleanup_free_ char *t = NULL;
601 int r;
602
603 assert(s);
604 assert(f);
605 assert(count);
606
607 r = in_addr_to_string(s->family, &s->address, &t);
608 if (r < 0) {
609 log_warning("Invalid DNS address. Ignoring.");
610 return;
611 }
612
613 if (*count == MAXNS)
614 fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
615
616 fprintf(f, "nameserver %s\n", t);
617 (*count) ++;
618}
619
620int manager_write_resolv_conf(Manager *m) {
621 const char *path = "/run/systemd/resolve/resolv.conf";
622 _cleanup_free_ char *temp_path = NULL;
623 _cleanup_fclose_ FILE *f = NULL;
624 unsigned count = 0;
625 DnsServer *s;
626 Iterator i;
627 Link *l;
628 int r;
629
630 assert(m);
631
632 r = fopen_temporary(path, &f, &temp_path);
633 if (r < 0)
634 return r;
635
636 fchmod(fileno(f), 0644);
637
638 fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
639 "# Third party programs must not access this file directly, but\n"
640 "# only through the symlink at /etc/resolv.conf. To manage\n"
641 "# resolv.conf(5) in a different way, replace the symlink by a\n"
642 "# static file or a different symlink.\n\n", f);
643
644 HASHMAP_FOREACH(l, m->links, i)
645 LIST_FOREACH(servers, s, l->dns_servers)
646 write_resolve_conf_server(s, f, &count);
647
648 LIST_FOREACH(servers, s, m->dns_servers)
649 write_resolve_conf_server(s, f, &count);
650
651 r = fflush_and_check(f);
652 if (r < 0)
653 goto fail;
654
655 if (rename(temp_path, path) < 0) {
656 r = -errno;
657 goto fail;
658 }
659
660 return 0;
661
662fail:
663 unlink(path);
664 unlink(temp_path);
665 return r;
666}
667
668int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
669 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
670 union {
671 struct cmsghdr header; /* For alignment */
672 uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
673 + CMSG_SPACE(int) /* ttl/hoplimit */
674 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
675 } control;
676 union sockaddr_union sa;
677 struct msghdr mh = {};
678 struct cmsghdr *cmsg;
679 struct iovec iov;
680 int ms = 0, r;
681 ssize_t l;
682
683 assert(m);
684 assert(fd >= 0);
685 assert(ret);
686
687 r = ioctl(fd, FIONREAD, &ms);
688 if (r < 0)
689 return -errno;
690 if (ms < 0)
691 return -EIO;
692
693 r = dns_packet_new(&p, protocol, ms);
694 if (r < 0)
695 return r;
696
697 iov.iov_base = DNS_PACKET_DATA(p);
698 iov.iov_len = p->allocated;
699
700 mh.msg_name = &sa.sa;
701 mh.msg_namelen = sizeof(sa);
702 mh.msg_iov = &iov;
703 mh.msg_iovlen = 1;
704 mh.msg_control = &control;
705 mh.msg_controllen = sizeof(control);
706
707 l = recvmsg(fd, &mh, 0);
708 if (l < 0) {
709 if (errno == EAGAIN || errno == EINTR)
710 return 0;
711
712 return -errno;
713 }
714
715 if (l <= 0)
716 return -EIO;
717
718 assert(!(mh.msg_flags & MSG_CTRUNC));
719 assert(!(mh.msg_flags & MSG_TRUNC));
720
721 p->size = (size_t) l;
722
723 p->family = sa.sa.sa_family;
724 p->ipproto = IPPROTO_UDP;
725 if (p->family == AF_INET) {
726 p->sender.in = sa.in.sin_addr;
727 p->sender_port = be16toh(sa.in.sin_port);
728 } else if (p->family == AF_INET6) {
729 p->sender.in6 = sa.in6.sin6_addr;
730 p->sender_port = be16toh(sa.in6.sin6_port);
731 p->ifindex = sa.in6.sin6_scope_id;
732 } else
733 return -EAFNOSUPPORT;
734
735 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
736
737 if (cmsg->cmsg_level == IPPROTO_IPV6) {
738 assert(p->family == AF_INET6);
739
740 switch (cmsg->cmsg_type) {
741
742 case IPV6_PKTINFO: {
743 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
744
745 if (p->ifindex <= 0)
746 p->ifindex = i->ipi6_ifindex;
747
748 p->destination.in6 = i->ipi6_addr;
749 break;
750 }
751
752 case IPV6_HOPLIMIT:
753 p->ttl = *(int *) CMSG_DATA(cmsg);
754 break;
755
756 }
757 } else if (cmsg->cmsg_level == IPPROTO_IP) {
758 assert(p->family == AF_INET);
759
760 switch (cmsg->cmsg_type) {
761
762 case IP_PKTINFO: {
763 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
764
765 if (p->ifindex <= 0)
766 p->ifindex = i->ipi_ifindex;
767
768 p->destination.in = i->ipi_addr;
769 break;
770 }
771
772 case IP_TTL:
773 p->ttl = *(int *) CMSG_DATA(cmsg);
774 break;
775 }
776 }
777 }
778
779 /* The Linux kernel sets the interface index to the loopback
780 * device if the packet came from the local host since it
781 * avoids the routing table in such a case. Let's unset the
782 * interface index in such a case. */
783 if (p->ifindex > 0 && manager_ifindex_is_loopback(m, p->ifindex) != 0)
784 p->ifindex = 0;
785
786 /* If we don't know the interface index still, we look for the
787 * first local interface with a matching address. Yuck! */
788 if (p->ifindex <= 0)
789 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
790
791 *ret = p;
792 p = NULL;
793
794 return 1;
795}
796
797static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
798 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
799 DnsTransaction *t = NULL;
800 Manager *m = userdata;
801 int r;
802
803 r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
804 if (r <= 0)
805 return r;
806
807 if (dns_packet_validate_reply(p) > 0) {
808 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
809 if (!t)
810 return 0;
811
812 dns_transaction_process_reply(t, p);
813
814 } else
815 log_debug("Invalid DNS packet.");
816
817 return 0;
818}
819
820int manager_dns_ipv4_fd(Manager *m) {
821 const int one = 1;
822 int r;
823
824 assert(m);
825
826 if (m->dns_ipv4_fd >= 0)
827 return m->dns_ipv4_fd;
828
829 m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
830 if (m->dns_ipv4_fd < 0)
831 return -errno;
832
833 r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
834 if (r < 0) {
835 r = -errno;
836 goto fail;
837 }
838
839 r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
840 if (r < 0)
841 goto fail;
842
843 return m->dns_ipv4_fd;
844
845fail:
846 m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
847 return r;
848}
849
850int manager_dns_ipv6_fd(Manager *m) {
851 const int one = 1;
852 int r;
853
854 assert(m);
855
856 if (m->dns_ipv6_fd >= 0)
857 return m->dns_ipv6_fd;
858
859 m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
860 if (m->dns_ipv6_fd < 0)
861 return -errno;
862
863 r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
864 if (r < 0) {
865 r = -errno;
866 goto fail;
867 }
868
869 r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
870 if (r < 0)
871 goto fail;
872
873 return m->dns_ipv6_fd;
874
875fail:
876 m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
877 return r;
878}
879
880static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
881 int r;
882
883 assert(fd >= 0);
884 assert(mh);
885
886 for (;;) {
887 if (sendmsg(fd, mh, flags) >= 0)
888 return 0;
889
890 if (errno == EINTR)
891 continue;
892
893 if (errno != EAGAIN)
894 return -errno;
895
896 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
897 if (r < 0)
898 return r;
899 if (r == 0)
900 return -ETIMEDOUT;
901 }
902}
903
904static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
905 union sockaddr_union sa = {
906 .in.sin_family = AF_INET,
907 };
908 union {
909 struct cmsghdr header; /* For alignment */
910 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
911 } control;
912 struct msghdr mh = {};
913 struct iovec iov;
914
915 assert(m);
916 assert(fd >= 0);
917 assert(addr);
918 assert(port > 0);
919 assert(p);
920
921 iov.iov_base = DNS_PACKET_DATA(p);
922 iov.iov_len = p->size;
923
924 sa.in.sin_addr = *addr;
925 sa.in.sin_port = htobe16(port),
926
927 mh.msg_iov = &iov;
928 mh.msg_iovlen = 1;
929 mh.msg_name = &sa.sa;
930 mh.msg_namelen = sizeof(sa.in);
931
932 if (ifindex > 0) {
933 struct cmsghdr *cmsg;
934 struct in_pktinfo *pi;
935
936 zero(control);
937
938 mh.msg_control = &control;
939 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
940
941 cmsg = CMSG_FIRSTHDR(&mh);
942 cmsg->cmsg_len = mh.msg_controllen;
943 cmsg->cmsg_level = IPPROTO_IP;
944 cmsg->cmsg_type = IP_PKTINFO;
945
946 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
947 pi->ipi_ifindex = ifindex;
948 }
949
950 return sendmsg_loop(fd, &mh, 0);
951}
952
953static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
954 union sockaddr_union sa = {
955 .in6.sin6_family = AF_INET6,
956 };
957 union {
958 struct cmsghdr header; /* For alignment */
959 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
960 } control;
961 struct msghdr mh = {};
962 struct iovec iov;
963
964 assert(m);
965 assert(fd >= 0);
966 assert(addr);
967 assert(port > 0);
968 assert(p);
969
970 iov.iov_base = DNS_PACKET_DATA(p);
971 iov.iov_len = p->size;
972
973 sa.in6.sin6_addr = *addr;
974 sa.in6.sin6_port = htobe16(port),
975 sa.in6.sin6_scope_id = ifindex;
976
977 mh.msg_iov = &iov;
978 mh.msg_iovlen = 1;
979 mh.msg_name = &sa.sa;
980 mh.msg_namelen = sizeof(sa.in6);
981
982 if (ifindex > 0) {
983 struct cmsghdr *cmsg;
984 struct in6_pktinfo *pi;
985
986 zero(control);
987
988 mh.msg_control = &control;
989 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
990
991 cmsg = CMSG_FIRSTHDR(&mh);
992 cmsg->cmsg_len = mh.msg_controllen;
993 cmsg->cmsg_level = IPPROTO_IPV6;
994 cmsg->cmsg_type = IPV6_PKTINFO;
995
996 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
997 pi->ipi6_ifindex = ifindex;
998 }
999
1000 return sendmsg_loop(fd, &mh, 0);
1001}
1002
1003int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1004 assert(m);
1005 assert(fd >= 0);
1006 assert(addr);
1007 assert(port > 0);
1008 assert(p);
1009
1010 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));
1011
1012 if (family == AF_INET)
1013 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1014 else if (family == AF_INET6)
1015 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
1016
1017 return -EAFNOSUPPORT;
1018}
1019
1020DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
1021 DnsServer *s;
1022
1023 assert(m);
1024 assert(in_addr);
1025
1026 LIST_FOREACH(servers, s, m->dns_servers) {
1027
1028 if (s->family == family &&
1029 in_addr_equal(family, &s->address, in_addr))
1030 return s;
1031 }
1032
1033 return NULL;
1034}
1035
1036DnsServer *manager_get_dns_server(Manager *m) {
1037 assert(m);
1038
1039 if (!m->current_dns_server)
1040 m->current_dns_server = m->dns_servers;
1041
1042 return m->current_dns_server;
1043}
1044
1045void manager_next_dns_server(Manager *m) {
1046 assert(m);
1047
1048 if (!m->current_dns_server) {
1049 m->current_dns_server = m->dns_servers;
1050 return;
1051 }
1052
1053 if (!m->current_dns_server)
1054 return;
1055
1056 if (m->current_dns_server->servers_next) {
1057 m->current_dns_server = m->current_dns_server->servers_next;
1058 return;
1059 }
1060
1061 m->current_dns_server = m->dns_servers;
1062}
1063
1064uint32_t manager_find_mtu(Manager *m) {
1065 uint32_t mtu = 0;
1066 Link *l;
1067 Iterator i;
1068
1069 /* If we don't know on which link a DNS packet would be
1070 * delivered, let's find the largest MTU that works on all
1071 * interfaces we know of */
1072
1073 HASHMAP_FOREACH(l, m->links, i) {
1074 if (l->mtu <= 0)
1075 continue;
1076
1077 if (mtu <= 0 || l->mtu < mtu)
1078 mtu = l->mtu;
1079 }
1080
1081 return mtu;
1082}
1083
1084static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1085 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1086 DnsTransaction *t = NULL;
1087 Manager *m = userdata;
1088 int r;
1089
1090 r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
1091 if (r <= 0)
1092 return r;
1093
1094 if (dns_packet_validate_reply(p) > 0) {
1095 log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
1096
1097 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
1098 if (!t)
1099 return 0;
1100
1101 dns_transaction_process_reply(t, p);
1102
1103 } else if (dns_packet_validate_query(p) > 0) {
1104 Link *l;
1105
1106 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1107 if (l) {
1108 DnsScope *scope = NULL;
1109
1110 if (p->family == AF_INET)
1111 scope = l->llmnr_ipv4_scope;
1112 else if (p->family == AF_INET6)
1113 scope = l->llmnr_ipv6_scope;
1114
1115 if (scope)
1116 dns_scope_process_query(scope, NULL, p);
1117 }
1118 } else
1119 log_debug("Invalid LLMNR packet.");
1120
1121 return 0;
1122}
1123
1124int manager_llmnr_ipv4_udp_fd(Manager *m) {
1125 union sockaddr_union sa = {
1126 .in.sin_family = AF_INET,
1127 .in.sin_port = htobe16(5355),
1128 };
1129 static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
1130 int r;
1131
1132 assert(m);
1133
1134 if (m->llmnr_ipv4_udp_fd >= 0)
1135 return m->llmnr_ipv4_udp_fd;
1136
1137 m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1138 if (m->llmnr_ipv4_udp_fd < 0)
1139 return -errno;
1140
1141 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
1142 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
1143 if (r < 0) {
1144 r = -errno;
1145 goto fail;
1146 }
1147
1148 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
1149 if (r < 0) {
1150 r = -errno;
1151 goto fail;
1152 }
1153
1154 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
1155 if (r < 0) {
1156 r = -errno;
1157 goto fail;
1158 }
1159
1160 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1161 if (r < 0) {
1162 r = -errno;
1163 goto fail;
1164 }
1165
1166 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1167 if (r < 0) {
1168 r = -errno;
1169 goto fail;
1170 }
1171
1172 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1173 if (r < 0) {
1174 r = -errno;
1175 goto fail;
1176 }
1177
1178 /* Disable Don't-Fragment bit in the IP header */
1179 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1180 if (r < 0) {
1181 r = -errno;
1182 goto fail;
1183 }
1184
1185 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
1186 if (r < 0) {
1187 r = -errno;
1188 goto fail;
1189 }
1190
1191 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
1192 if (r < 0)
1193 goto fail;
1194
1195 return m->llmnr_ipv4_udp_fd;
1196
1197fail:
1198 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
1199 return r;
1200}
1201
1202int manager_llmnr_ipv6_udp_fd(Manager *m) {
1203 union sockaddr_union sa = {
1204 .in6.sin6_family = AF_INET6,
1205 .in6.sin6_port = htobe16(5355),
1206 };
1207 static const int one = 1, ttl = 255;
1208 int r;
1209
1210 assert(m);
1211
1212 if (m->llmnr_ipv6_udp_fd >= 0)
1213 return m->llmnr_ipv6_udp_fd;
1214
1215 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1216 if (m->llmnr_ipv6_udp_fd < 0)
1217 return -errno;
1218
1219 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
1220 if (r < 0) {
1221 r = -errno;
1222 goto fail;
1223 }
1224
1225 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
1226 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
1227 if (r < 0) {
1228 r = -errno;
1229 goto fail;
1230 }
1231
1232 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
1233 if (r < 0) {
1234 r = -errno;
1235 goto fail;
1236 }
1237
1238 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1239 if (r < 0) {
1240 r = -errno;
1241 goto fail;
1242 }
1243
1244 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1245 if (r < 0) {
1246 r = -errno;
1247 goto fail;
1248 }
1249
1250 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1251 if (r < 0) {
1252 r = -errno;
1253 goto fail;
1254 }
1255
1256 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1257 if (r < 0) {
1258 r = -errno;
1259 goto fail;
1260 }
1261
1262 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
1263 if (r < 0) {
1264 r = -errno;
1265 goto fail;
1266 }
1267
1268 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
1269 if (r < 0) {
1270 r = -errno;
1271 goto fail;
1272 }
1273
1274 return m->llmnr_ipv6_udp_fd;
1275
1276fail:
1277 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
1278 return r;
1279}
1280
1281static int on_llmnr_stream_packet(DnsStream *s) {
1282 assert(s);
1283
1284 if (dns_packet_validate_query(s->read_packet) > 0) {
1285 Link *l;
1286
1287 l = hashmap_get(s->manager->links, INT_TO_PTR(s->read_packet->ifindex));
1288 if (l) {
1289 DnsScope *scope = NULL;
1290
1291 if (s->read_packet->family == AF_INET)
1292 scope = l->llmnr_ipv4_scope;
1293 else if (s->read_packet->family == AF_INET6)
1294 scope = l->llmnr_ipv6_scope;
1295
1296 if (scope) {
1297 dns_scope_process_query(scope, s, s->read_packet);
1298
1299 /* If no reply packet was set, we free the stream */
1300 if (s->write_packet)
1301 return 0;
1302 }
1303 }
1304 }
1305
1306 dns_stream_free(s);
1307 return 0;
1308}
1309
1310static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1311 DnsStream *stream;
1312 Manager *m = userdata;
1313 int cfd, r;
1314
1315 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
1316 if (cfd < 0) {
1317 if (errno == EAGAIN || errno == EINTR)
1318 return 0;
1319
1320 return -errno;
1321 }
1322
1323 r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
1324 if (r < 0) {
1325 safe_close(cfd);
1326 return r;
1327 }
1328
1329 stream->on_packet = on_llmnr_stream_packet;
1330 return 0;
1331}
1332
1333int manager_llmnr_ipv4_tcp_fd(Manager *m) {
1334 union sockaddr_union sa = {
1335 .in.sin_family = AF_INET,
1336 .in.sin_port = htobe16(5355),
1337 };
1338 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
1339 int r;
1340
1341 assert(m);
1342
1343 if (m->llmnr_ipv4_tcp_fd >= 0)
1344 return m->llmnr_ipv4_tcp_fd;
1345
1346 m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1347 if (m->llmnr_ipv4_tcp_fd < 0)
1348 return -errno;
1349
1350 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
1351 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
1352 if (r < 0) {
1353 r = -errno;
1354 goto fail;
1355 }
1356
1357 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1358 if (r < 0) {
1359 r = -errno;
1360 goto fail;
1361 }
1362
1363 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1364 if (r < 0) {
1365 r = -errno;
1366 goto fail;
1367 }
1368
1369 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1370 if (r < 0) {
1371 r = -errno;
1372 goto fail;
1373 }
1374
1375 /* Disable Don't-Fragment bit in the IP header */
1376 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1377 if (r < 0) {
1378 r = -errno;
1379 goto fail;
1380 }
1381
1382 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
1383 if (r < 0) {
1384 r = -errno;
1385 goto fail;
1386 }
1387
1388 r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
1389 if (r < 0) {
1390 r = -errno;
1391 goto fail;
1392 }
1393
1394 r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
1395 if (r < 0)
1396 goto fail;
1397
1398 return m->llmnr_ipv4_tcp_fd;
1399
1400fail:
1401 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
1402 return r;
1403}
1404
1405int manager_llmnr_ipv6_tcp_fd(Manager *m) {
1406 union sockaddr_union sa = {
1407 .in6.sin6_family = AF_INET6,
1408 .in6.sin6_port = htobe16(5355),
1409 };
1410 static const int one = 1;
1411 int r;
1412
1413 assert(m);
1414
1415 if (m->llmnr_ipv6_tcp_fd >= 0)
1416 return m->llmnr_ipv6_tcp_fd;
1417
1418 m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1419 if (m->llmnr_ipv6_tcp_fd < 0)
1420 return -errno;
1421
1422 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
1423 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
1424 if (r < 0) {
1425 r = -errno;
1426 goto fail;
1427 }
1428
1429 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1430 if (r < 0) {
1431 r = -errno;
1432 goto fail;
1433 }
1434
1435 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1436 if (r < 0) {
1437 r = -errno;
1438 goto fail;
1439 }
1440
1441 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1442 if (r < 0) {
1443 r = -errno;
1444 goto fail;
1445 }
1446
1447 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1448 if (r < 0) {
1449 r = -errno;
1450 goto fail;
1451 }
1452
1453 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
1454 if (r < 0) {
1455 r = -errno;
1456 goto fail;
1457 }
1458
1459 r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
1460 if (r < 0) {
1461 r = -errno;
1462 goto fail;
1463 }
1464
1465 r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
1466 if (r < 0) {
1467 r = -errno;
1468 goto fail;
1469 }
1470
1471 return m->llmnr_ipv6_tcp_fd;
1472
1473fail:
1474 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
1475 return r;
1476}
1477
1478int manager_ifindex_is_loopback(Manager *m, int ifindex) {
1479 Link *l;
1480 assert(m);
1481
1482 if (ifindex <= 0)
1483 return -EINVAL;
1484
1485 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1486 if (l->flags & IFF_LOOPBACK)
1487 return 1;
1488
1489 return 0;
1490}
1491
1492int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
1493 LinkAddress *a;
1494
1495 assert(m);
1496
1497 a = manager_find_address(m, family, in_addr);
1498 if (a)
1499 return a->link->ifindex;
1500
1501 return 0;
1502}
1503
1504void manager_refresh_rrs(Manager *m) {
1505 Iterator i;
1506 Link *l;
1507
1508 assert(m);
1509
1510 m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
1511 m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
1512
1513 HASHMAP_FOREACH(l, m->links, i) {
1514 link_add_rrs(l, true);
1515 link_add_rrs(l, false);
1516 }
1517}
1518
1519int manager_next_hostname(Manager *m) {
1520 const char *p;
1521 uint64_t u;
1522 char *h;
1523
1524 assert(m);
1525
1526 p = strchr(m->hostname, 0);
1527 assert(p);
1528
1529 while (p > m->hostname) {
1530 if (!strchr("0123456789", p[-1]))
1531 break;
1532
1533 p--;
1534 }
1535
1536 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
1537 u = 1;
1538
1539 u++;
1540
1541 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
1542 return -ENOMEM;
1543
1544 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
1545
1546 free(m->hostname);
1547 m->hostname = h;
1548
1549 manager_refresh_rrs(m);
1550
1551 return 0;
1552}
1553
1554LinkAddress* manager_find_address(Manager *m, int family, const union in_addr_union *in_addr) {
1555 Iterator i;
1556 Link *l;
1557
1558 assert(m);
1559
1560 HASHMAP_FOREACH(l, m->links, i) {
1561 LinkAddress *a;
1562
1563 a = link_find_address(l, family, in_addr);
1564 if (a)
1565 return a;
1566 }
1567
1568 return NULL;
1569}
1570
1571int manager_our_packet(Manager *m, DnsPacket *p) {
1572 assert(m);
1573 assert(p);
1574
1575 return !!manager_find_address(m, p->family, &p->sender);
1576}