]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
sd-network: make socket filter programs static const where possible
[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 };
1027 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
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
1039 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
1040 if (r < 0) {
1041 r = -errno;
1042 goto fail;
1043 }
1044
1045 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &one, sizeof(one));
1046 if (r < 0) {
1047 r = -errno;
1048 goto fail;
1049 }
1050
1051 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
1052 if (r < 0) {
1053 r = -errno;
1054 goto fail;
1055 }
1056
1057 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1058 if (r < 0) {
1059 r = -errno;
1060 goto fail;
1061 }
1062
1063 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1064 if (r < 0) {
1065 r = -errno;
1066 goto fail;
1067 }
1068
1069 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1070 if (r < 0) {
1071 r = -errno;
1072 goto fail;
1073 }
1074
1075 /* Disable Don't-Fragment bit in the IP header */
1076 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1077 if (r < 0) {
1078 r = -errno;
1079 goto fail;
1080 }
1081
1082 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
1083 if (r < 0) {
1084 r = -errno;
1085 goto fail;
1086 }
1087
1088 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
1089 if (r < 0)
1090 goto fail;
1091
1092 return m->llmnr_ipv4_udp_fd;
1093
1094fail:
1095 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
1096 return r;
1097}
1098
1099int manager_llmnr_ipv6_udp_fd(Manager *m) {
1100 union sockaddr_union sa = {
1101 .in6.sin6_family = AF_INET6,
1102 .in6.sin6_port = htobe16(5355),
1103 };
1104 static const int one = 1;
1105 int r;
1106
1107 assert(m);
1108
1109 if (m->llmnr_ipv6_udp_fd >= 0)
1110 return m->llmnr_ipv6_udp_fd;
1111
1112 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1113 if (m->llmnr_ipv6_udp_fd < 0)
1114 return -errno;
1115
1116 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
1117 if (r < 0) {
1118 r = -errno;
1119 goto fail;
1120 }
1121
1122 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &one, sizeof(one));
1123 if (r < 0) {
1124 r = -errno;
1125 goto fail;
1126 }
1127
1128 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
1129 if (r < 0) {
1130 r = -errno;
1131 goto fail;
1132 }
1133
1134 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1135 if (r < 0) {
1136 r = -errno;
1137 goto fail;
1138 }
1139
1140 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1141 if (r < 0) {
1142 r = -errno;
1143 goto fail;
1144 }
1145
1146 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1147 if (r < 0) {
1148 r = -errno;
1149 goto fail;
1150 }
1151
1152 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1153 if (r < 0) {
1154 r = -errno;
1155 goto fail;
1156 }
1157
1158 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
1159 if (r < 0) {
1160 r = -errno;
1161 goto fail;
1162 }
1163
1164 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
1165 if (r < 0) {
1166 r = -errno;
1167 goto fail;
1168 }
1169
1170 return m->llmnr_ipv6_udp_fd;
1171
1172fail:
1173 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
1174 return r;
1175}
623a4c97
LP
1176
1177static int on_llmnr_stream_packet(DnsStream *s) {
1178 assert(s);
1179
1180 if (dns_packet_validate_query(s->read_packet) > 0) {
1181 Link *l;
1182
1183 l = hashmap_get(s->manager->links, INT_TO_PTR(s->read_packet->ifindex));
1184 if (l) {
1185 DnsScope *scope = NULL;
1186
1187 if (s->read_packet->family == AF_INET)
1188 scope = l->llmnr_ipv4_scope;
1189 else if (s->read_packet->family == AF_INET6)
1190 scope = l->llmnr_ipv6_scope;
1191
1192 if (scope) {
1193 dns_scope_process_query(scope, s, s->read_packet);
1194
1195 /* If no reply packet was set, we free the stream */
1196 if (s->write_packet)
1197 return 0;
1198 }
1199 }
1200 }
1201
1202 dns_stream_free(s);
1203 return 0;
1204}
1205
1206static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1207 DnsStream *stream;
1208 Manager *m = userdata;
1209 int cfd, r;
1210
1211 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
1212 if (cfd < 0) {
1213 if (errno == EAGAIN || errno == EINTR)
1214 return 0;
1215
1216 return -errno;
1217 }
1218
1219 r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
1220 if (r < 0) {
1221 safe_close(cfd);
1222 return r;
1223 }
1224
1225 stream->on_packet = on_llmnr_stream_packet;
1226 return 0;
1227}
1228
1229int manager_llmnr_ipv4_tcp_fd(Manager *m) {
1230 union sockaddr_union sa = {
1231 .in.sin_family = AF_INET,
1232 .in.sin_port = htobe16(5355),
1233 };
1234 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
1235 int r;
1236
1237 assert(m);
1238
1239 if (m->llmnr_ipv4_tcp_fd >= 0)
1240 return m->llmnr_ipv4_tcp_fd;
1241
1242 m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1243 if (m->llmnr_ipv4_tcp_fd < 0)
1244 return -errno;
1245
1246 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
1247 if (r < 0) {
1248 r = -errno;
1249 goto fail;
1250 }
1251
1252 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1253 if (r < 0) {
1254 r = -errno;
1255 goto fail;
1256 }
1257
1258 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1259 if (r < 0) {
1260 r = -errno;
1261 goto fail;
1262 }
1263
1264 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1265 if (r < 0) {
1266 r = -errno;
1267 goto fail;
1268 }
1269
1270 /* Disable Don't-Fragment bit in the IP header */
1271 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1272 if (r < 0) {
1273 r = -errno;
1274 goto fail;
1275 }
1276
1277 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
1278 if (r < 0) {
1279 r = -errno;
1280 goto fail;
1281 }
1282
1283 r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
1284 if (r < 0) {
1285 r = -errno;
1286 goto fail;
1287 }
1288
1289 r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
1290 if (r < 0)
1291 goto fail;
1292
1293 return m->llmnr_ipv4_tcp_fd;
1294
1295fail:
1296 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
1297 return r;
1298}
1299
1300int manager_llmnr_ipv6_tcp_fd(Manager *m) {
1301 union sockaddr_union sa = {
1302 .in6.sin6_family = AF_INET6,
1303 .in6.sin6_port = htobe16(5355),
1304 };
1305 static const int one = 1;
1306 int r;
1307
1308 assert(m);
1309
1310 if (m->llmnr_ipv6_tcp_fd >= 0)
1311 return m->llmnr_ipv6_tcp_fd;
1312
1313 m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1314 if (m->llmnr_ipv6_tcp_fd < 0)
1315 return -errno;
1316
1317 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
1318 if (r < 0) {
1319 r = -errno;
1320 goto fail;
1321 }
1322
1323 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1324 if (r < 0) {
1325 r = -errno;
1326 goto fail;
1327 }
1328
1329 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1330 if (r < 0) {
1331 r = -errno;
1332 goto fail;
1333 }
1334
1335 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1336 if (r < 0) {
1337 r = -errno;
1338 goto fail;
1339 }
1340
1341 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1342 if (r < 0) {
1343 r = -errno;
1344 goto fail;
1345 }
1346
1347 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
1348 if (r < 0) {
1349 r = -errno;
1350 goto fail;
1351 }
1352
1353 r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
1354 if (r < 0) {
1355 r = -errno;
1356 goto fail;
1357 }
1358
1359 r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
1360 if (r < 0) {
1361 r = -errno;
1362 goto fail;
1363 }
1364
1365 return m->llmnr_ipv6_tcp_fd;
1366
1367fail:
1368 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
1369 return r;
1370}
1371
1372int manager_ifindex_is_loopback(Manager *m, int ifindex) {
1373 Link *l;
1374 assert(m);
1375
1376 if (ifindex <= 0)
1377 return -EINVAL;
1378
1379 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1380 if (l->flags & IFF_LOOPBACK)
1381 return 1;
1382
1383 return 0;
1384}
1385
1386int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
1387 Link *l;
1388 Iterator i;
1389
1390 assert(m);
1391
1392 HASHMAP_FOREACH(l, m->links, i)
1393 if (link_find_address(l, family, in_addr))
1394 return l->ifindex;
1395
1396 return 0;
1397}