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