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