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