barrier: fix race in test-code
[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
LP
392 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
393
394 m->use_llmnr = true;
091a364c 395
faa133f3 396 r = parse_dns_server_string(m, DNS_SERVERS);
091a364c
TG
397 if (r < 0)
398 return r;
399
400 r = sd_event_default(&m->event);
401 if (r < 0)
402 return r;
403
404 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
405 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
406
407 sd_event_set_watchdog(m->event, true);
408
1716f6dc 409 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
410 if (r < 0)
411 return r;
412
413 r = manager_network_monitor_listen(m);
414 if (r < 0)
415 return r;
416
417 r = manager_rtnl_listen(m);
418 if (r < 0)
419 return r;
420
421 r = manager_connect_bus(m);
422 if (r < 0)
423 return r;
424
091a364c
TG
425 *ret = m;
426 m = NULL;
427
428 return 0;
429}
430
74b2466e
LP
431Manager *manager_free(Manager *m) {
432 Link *l;
091a364c
TG
433
434 if (!m)
74b2466e
LP
435 return NULL;
436
437 while (m->dns_queries)
438 dns_query_free(m->dns_queries);
439
440 hashmap_free(m->dns_query_transactions);
441
442 while ((l = hashmap_first(m->links)))
443 link_free(l);
444 hashmap_free(m->links);
445
446 dns_scope_free(m->unicast_scope);
447
448 while (m->dns_servers)
449 dns_server_free(m->dns_servers);
091a364c 450
096b6773
LP
451 sd_event_source_unref(m->network_event_source);
452 sd_network_monitor_unref(m->network_monitor);
091a364c 453
74b2466e
LP
454 sd_event_source_unref(m->dns_ipv4_event_source);
455 sd_event_source_unref(m->dns_ipv6_event_source);
74b2466e
LP
456 safe_close(m->dns_ipv4_fd);
457 safe_close(m->dns_ipv6_fd);
458
1716f6dc
LP
459 sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
460 sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
461 safe_close(m->llmnr_ipv4_udp_fd);
462 safe_close(m->llmnr_ipv6_udp_fd);
463
74b2466e
LP
464 sd_event_source_unref(m->bus_retry_event_source);
465 sd_bus_unref(m->bus);
091a364c 466
74b2466e 467 sd_event_unref(m->event);
091a364c 468 free(m);
74b2466e
LP
469
470 return NULL;
091a364c
TG
471}
472
74b2466e
LP
473static void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
474 _cleanup_free_ char *t = NULL;
475 int r;
091a364c 476
74b2466e 477 assert(s);
091a364c 478 assert(f);
091a364c
TG
479 assert(count);
480
74b2466e 481 r = in_addr_to_string(s->family, &s->address, &t);
1716f6dc 482 if (r < 0) {
091a364c
TG
483 log_warning("Invalid DNS address. Ignoring.");
484 return;
485 }
486
487 if (*count == MAXNS)
74b2466e 488 fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
091a364c 489
74b2466e 490 fprintf(f, "nameserver %s\n", t);
091a364c
TG
491 (*count) ++;
492}
493
74b2466e 494int manager_write_resolv_conf(Manager *m) {
b686acb2 495 const char *path = "/run/systemd/resolve/resolv.conf";
091a364c
TG
496 _cleanup_free_ char *temp_path = NULL;
497 _cleanup_fclose_ FILE *f = NULL;
091a364c 498 unsigned count = 0;
74b2466e
LP
499 DnsServer *s;
500 Iterator i;
501 Link *l;
502 int r;
091a364c
TG
503
504 assert(m);
505
b686acb2 506 r = fopen_temporary(path, &f, &temp_path);
091a364c
TG
507 if (r < 0)
508 return r;
509
510 fchmod(fileno(f), 0644);
511
512 fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
513 "# Third party programs must not access this file directly, but\n"
514 "# only through the symlink at /etc/resolv.conf. To manage\n"
515 "# resolv.conf(5) in a different way, replace the symlink by a\n"
516 "# static file or a different symlink.\n\n", f);
517
6073b6f2
TG
518 HASHMAP_FOREACH(l, m->links, i)
519 LIST_FOREACH(servers, s, l->dns_servers)
74b2466e 520 write_resolve_conf_server(s, f, &count);
091a364c 521
74b2466e
LP
522 LIST_FOREACH(servers, s, m->dns_servers)
523 write_resolve_conf_server(s, f, &count);
091a364c 524
74b2466e
LP
525 r = fflush_and_check(f);
526 if (r < 0)
527 goto fail;
528
529 if (rename(temp_path, path) < 0) {
530 r = -errno;
531 goto fail;
532 }
091a364c 533
74b2466e 534 return 0;
091a364c 535
74b2466e
LP
536fail:
537 unlink(path);
538 unlink(temp_path);
539 return r;
540}
091a364c 541
1716f6dc 542int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 543 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
544 union {
545 struct cmsghdr header; /* For alignment */
546 uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
547 + CMSG_SPACE(int) /* ttl/hoplimit */
548 + 1024 /* kernel appears to require extra buffer space */];
549 } control;
550 union sockaddr_union sa;
74b2466e 551 struct msghdr mh = {};
1716f6dc 552 struct cmsghdr *cmsg;
74b2466e 553 struct iovec iov;
1716f6dc 554 int ms = 0, r;
74b2466e
LP
555 ssize_t l;
556
557 assert(m);
1716f6dc 558 assert(fd >= 0);
74b2466e
LP
559 assert(ret);
560
74b2466e
LP
561 r = ioctl(fd, FIONREAD, &ms);
562 if (r < 0)
563 return -errno;
564 if (ms < 0)
565 return -EIO;
566
1716f6dc 567 r = dns_packet_new(&p, protocol, ms);
74b2466e
LP
568 if (r < 0)
569 return r;
570
571 iov.iov_base = DNS_PACKET_DATA(p);
572 iov.iov_len = p->allocated;
573
1716f6dc
LP
574 mh.msg_name = &sa.sa;
575 mh.msg_namelen = sizeof(sa);
74b2466e
LP
576 mh.msg_iov = &iov;
577 mh.msg_iovlen = 1;
1716f6dc
LP
578 mh.msg_control = &control;
579 mh.msg_controllen = sizeof(control);
74b2466e
LP
580
581 l = recvmsg(fd, &mh, 0);
582 if (l < 0) {
ad867662 583 if (errno == EAGAIN || errno == EINTR)
74b2466e
LP
584 return 0;
585
586 return -errno;
091a364c
TG
587 }
588
74b2466e
LP
589 if (l <= 0)
590 return -EIO;
091a364c 591
1716f6dc
LP
592 assert(!(mh.msg_flags & MSG_CTRUNC));
593 assert(!(mh.msg_flags & MSG_TRUNC));
594
74b2466e 595 p->size = (size_t) l;
091a364c 596
1716f6dc
LP
597 p->family = sa.sa.sa_family;
598 if (p->family == AF_INET)
599 p->sender.in = sa.in.sin_addr;
600 else if (p->family == AF_INET6)
601 p->sender.in6 = sa.in6.sin6_addr;
602 else
603 return -EAFNOSUPPORT;
74b2466e 604
1716f6dc 605 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
74b2466e 606
1716f6dc
LP
607 if (cmsg->cmsg_level == IPPROTO_IPV6) {
608 assert(p->family == AF_INET6);
74b2466e 609
1716f6dc 610 switch (cmsg->cmsg_type) {
74b2466e 611
1716f6dc
LP
612 case IPV6_PKTINFO: {
613 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 614
1716f6dc
LP
615 p->ifindex = i->ipi6_ifindex;
616 p->destination.in6 = i->ipi6_addr;
617 break;
618 }
74b2466e 619
1716f6dc
LP
620 case IPV6_HOPLIMIT:
621 p->ttl = *(int *) CMSG_DATA(cmsg);
622 break;
74b2466e 623
1716f6dc
LP
624 }
625 } else if (cmsg->cmsg_level == IPPROTO_IP) {
626 assert(p->family == AF_INET);
74b2466e 627
1716f6dc 628 switch (cmsg->cmsg_type) {
74b2466e 629
1716f6dc
LP
630 case IP_PKTINFO: {
631 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 632
1716f6dc
LP
633 p->ifindex = i->ipi_ifindex;
634 p->destination.in = i->ipi_addr;
635 break;
636 }
74b2466e 637
1716f6dc
LP
638 case IP_RECVTTL:
639 p->ttl = *(int *) CMSG_DATA(cmsg);
640 break;
641 }
642 }
643 }
74b2466e
LP
644
645 *ret = p;
646 p = NULL;
647
648 return 1;
649}
650
1716f6dc 651static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e
LP
652 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
653 DnsQueryTransaction *t = NULL;
654 Manager *m = userdata;
655 int r;
656
1716f6dc 657 r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
74b2466e
LP
658 if (r <= 0)
659 return r;
660
1716f6dc
LP
661 if (dns_packet_validate_reply(p) >= 0) {
662 t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
663 if (!t)
664 return 0;
74b2466e 665
faa133f3 666 dns_query_transaction_process_reply(t, p);
1716f6dc
LP
667 } else
668 log_debug("Invalid reply packet.");
74b2466e 669
ad867662 670 return 0;
74b2466e
LP
671}
672
673int manager_dns_ipv4_fd(Manager *m) {
1716f6dc 674 const int one = 1;
74b2466e
LP
675 int r;
676
091a364c
TG
677 assert(m);
678
74b2466e
LP
679 if (m->dns_ipv4_fd >= 0)
680 return m->dns_ipv4_fd;
091a364c 681
74b2466e
LP
682 m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
683 if (m->dns_ipv4_fd < 0)
684 return -errno;
091a364c 685
1716f6dc
LP
686 r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
687 if (r < 0) {
688 r = -errno;
689 goto fail;
690 }
691
692 r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
74b2466e 693 if (r < 0)
1716f6dc 694 goto fail;
74b2466e
LP
695
696 return m->dns_ipv4_fd;
1716f6dc
LP
697
698fail:
699 m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
700 return r;
091a364c
TG
701}
702
74b2466e 703int manager_dns_ipv6_fd(Manager *m) {
1716f6dc 704 const int one = 1;
74b2466e
LP
705 int r;
706
707 assert(m);
091a364c 708
74b2466e
LP
709 if (m->dns_ipv6_fd >= 0)
710 return m->dns_ipv6_fd;
711
712 m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
713 if (m->dns_ipv6_fd < 0)
714 return -errno;
715
1716f6dc
LP
716 r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
717 if (r < 0) {
718 r = -errno;
719 goto fail;
720 }
721
722 r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
091a364c 723 if (r < 0)
1716f6dc 724 goto fail;
091a364c 725
74b2466e 726 return m->dns_ipv6_fd;
1716f6dc
LP
727
728fail:
729 m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
730 return r;
74b2466e
LP
731}
732
733static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
734 int r;
735
736 assert(fd >= 0);
737 assert(mh);
738
739 for (;;) {
740 if (sendmsg(fd, mh, flags) >= 0)
741 return 0;
742
743 if (errno == EINTR)
744 continue;
745
746 if (errno != EAGAIN)
747 return -errno;
748
749 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
750 if (r < 0)
751 return r;
752 if (r == 0)
753 return -ETIMEDOUT;
754 }
755}
756
1716f6dc 757static int manager_ipv4_send(Manager *m, int fd, int ifindex, struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
758 union sockaddr_union sa = {
759 .in.sin_family = AF_INET,
74b2466e 760 };
1716f6dc
LP
761 union {
762 struct cmsghdr header; /* For alignment */
763 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
764 } control;
74b2466e
LP
765 struct msghdr mh = {};
766 struct iovec iov;
74b2466e
LP
767
768 assert(m);
1716f6dc
LP
769 assert(fd >= 0);
770 assert(addr);
771 assert(port > 0);
74b2466e
LP
772 assert(p);
773
74b2466e
LP
774 iov.iov_base = DNS_PACKET_DATA(p);
775 iov.iov_len = p->size;
091a364c 776
1716f6dc
LP
777 sa.in.sin_addr = *addr;
778 sa.in.sin_port = htobe16(port),
091a364c 779
74b2466e
LP
780 mh.msg_iov = &iov;
781 mh.msg_iovlen = 1;
782 mh.msg_name = &sa.sa;
783 mh.msg_namelen = sizeof(sa.in);
091a364c 784
74b2466e
LP
785 if (ifindex > 0) {
786 struct cmsghdr *cmsg;
787 struct in_pktinfo *pi;
788
789 zero(control);
790
1716f6dc 791 mh.msg_control = &control;
74b2466e
LP
792 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
793
794 cmsg = CMSG_FIRSTHDR(&mh);
795 cmsg->cmsg_len = mh.msg_controllen;
796 cmsg->cmsg_level = IPPROTO_IP;
797 cmsg->cmsg_type = IP_PKTINFO;
798
799 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
800 pi->ipi_ifindex = ifindex;
801 }
802
803 return sendmsg_loop(fd, &mh, 0);
804}
805
1716f6dc 806static int manager_ipv6_send(Manager *m, int fd, int ifindex, struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
807 union sockaddr_union sa = {
808 .in6.sin6_family = AF_INET6,
74b2466e 809 };
1716f6dc
LP
810 union {
811 struct cmsghdr header; /* For alignment */
812 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
813 } control;
74b2466e
LP
814 struct msghdr mh = {};
815 struct iovec iov;
74b2466e
LP
816
817 assert(m);
1716f6dc
LP
818 assert(fd >= 0);
819 assert(addr);
820 assert(port > 0);
74b2466e
LP
821 assert(p);
822
74b2466e
LP
823 iov.iov_base = DNS_PACKET_DATA(p);
824 iov.iov_len = p->size;
825
1716f6dc
LP
826 sa.in6.sin6_addr = *addr;
827 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
828 sa.in6.sin6_scope_id = ifindex;
829
830 mh.msg_iov = &iov;
831 mh.msg_iovlen = 1;
832 mh.msg_name = &sa.sa;
833 mh.msg_namelen = sizeof(sa.in6);
834
835 if (ifindex > 0) {
836 struct cmsghdr *cmsg;
837 struct in6_pktinfo *pi;
838
839 zero(control);
840
1716f6dc 841 mh.msg_control = &control;
74b2466e
LP
842 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
843
844 cmsg = CMSG_FIRSTHDR(&mh);
845 cmsg->cmsg_len = mh.msg_controllen;
846 cmsg->cmsg_level = IPPROTO_IPV6;
847 cmsg->cmsg_type = IPV6_PKTINFO;
848
849 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
850 pi->ipi6_ifindex = ifindex;
851 }
852
853 return sendmsg_loop(fd, &mh, 0);
854}
855
0dd25fb9 856int manager_send(Manager *m, int fd, int ifindex, int family, union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dc
LP
857 assert(m);
858 assert(fd >= 0);
859 assert(addr);
860 assert(port > 0);
861 assert(p);
862
863 if (family == AF_INET)
864 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
865 else if (family == AF_INET6)
866 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
867
868 return -EAFNOSUPPORT;
869}
870
871
0dd25fb9 872DnsServer* manager_find_dns_server(Manager *m, int family, union in_addr_union *in_addr) {
74b2466e
LP
873 DnsServer *s;
874
875 assert(m);
876 assert(in_addr);
877
878 LIST_FOREACH(servers, s, m->dns_servers) {
879
880 if (s->family == family &&
881 in_addr_equal(family, &s->address, in_addr))
882 return s;
883 }
884
885 return NULL;
886}
887
888DnsServer *manager_get_dns_server(Manager *m) {
889 assert(m);
890
891 if (!m->current_dns_server)
892 m->current_dns_server = m->dns_servers;
893
894 return m->current_dns_server;
895}
896
897void manager_next_dns_server(Manager *m) {
898 assert(m);
899
900 if (!m->current_dns_server) {
901 m->current_dns_server = m->dns_servers;
902 return;
903 }
904
905 if (!m->current_dns_server)
906 return;
907
908 if (m->current_dns_server->servers_next) {
909 m->current_dns_server = m->current_dns_server->servers_next;
910 return;
911 }
912
913 m->current_dns_server = m->dns_servers;
091a364c 914}
e1c95994
LP
915
916uint32_t manager_find_mtu(Manager *m) {
917 uint32_t mtu = 0;
918 Link *l;
919 Iterator i;
920
921 /* If we don't know on which link a DNS packet would be
922 * delivered, let's find the largest MTU that works on all
923 * interfaces we know of */
924
925 HASHMAP_FOREACH(l, m->links, i) {
926 if (l->mtu <= 0)
927 continue;
928
929 if (mtu <= 0 || l->mtu < mtu)
930 mtu = l->mtu;
931 }
932
933 return mtu;
934}
1716f6dc
LP
935
936static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
937 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
938 DnsQueryTransaction *t = NULL;
939 Manager *m = userdata;
940 int r;
941
942 r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
943 if (r <= 0)
944 return r;
945
946 if (dns_packet_validate_reply(p) >= 0) {
947 t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
948 if (!t)
949 return 0;
950
faa133f3 951 dns_query_transaction_process_reply(t, p);
1716f6dc
LP
952 }
953
954 return 0;
955}
956
957int manager_llmnr_ipv4_udp_fd(Manager *m) {
958 union sockaddr_union sa = {
959 .in.sin_family = AF_INET,
960 .in.sin_port = htobe16(5355),
961 };
962 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
963 int r;
964
965 assert(m);
966
967 if (m->llmnr_ipv4_udp_fd >= 0)
968 return m->llmnr_ipv4_udp_fd;
969
970 m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
971 if (m->llmnr_ipv4_udp_fd < 0)
972 return -errno;
973
974 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
975 if (r < 0) {
976 r = -errno;
977 goto fail;
978 }
979
980 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &one, sizeof(one));
981 if (r < 0) {
982 r = -errno;
983 goto fail;
984 }
985
986 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
987 if (r < 0) {
988 r = -errno;
989 goto fail;
990 }
991
992 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
993 if (r < 0) {
994 r = -errno;
995 goto fail;
996 }
997
998 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
999 if (r < 0) {
1000 r = -errno;
1001 goto fail;
1002 }
1003
1004 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1005 if (r < 0) {
1006 r = -errno;
1007 goto fail;
1008 }
1009
1010 /* Disable Don't-Fragment bit in the IP header */
1011 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1012 if (r < 0) {
1013 r = -errno;
1014 goto fail;
1015 }
1016
1017 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
1018 if (r < 0) {
1019 r = -errno;
1020 goto fail;
1021 }
1022
1023 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
1024 if (r < 0)
1025 goto fail;
1026
1027 return m->llmnr_ipv4_udp_fd;
1028
1029fail:
1030 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
1031 return r;
1032}
1033
1034int manager_llmnr_ipv6_udp_fd(Manager *m) {
1035 union sockaddr_union sa = {
1036 .in6.sin6_family = AF_INET6,
1037 .in6.sin6_port = htobe16(5355),
1038 };
1039 static const int one = 1;
1040 int r;
1041
1042 assert(m);
1043
1044 if (m->llmnr_ipv6_udp_fd >= 0)
1045 return m->llmnr_ipv6_udp_fd;
1046
1047 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1048 if (m->llmnr_ipv6_udp_fd < 0)
1049 return -errno;
1050
1051 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
1052 if (r < 0) {
1053 r = -errno;
1054 goto fail;
1055 }
1056
1057 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &one, sizeof(one));
1058 if (r < 0) {
1059 r = -errno;
1060 goto fail;
1061 }
1062
1063 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
1064 if (r < 0) {
1065 r = -errno;
1066 goto fail;
1067 }
1068
1069 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1070 if (r < 0) {
1071 r = -errno;
1072 goto fail;
1073 }
1074
1075 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1076 if (r < 0) {
1077 r = -errno;
1078 goto fail;
1079 }
1080
1081 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1082 if (r < 0) {
1083 r = -errno;
1084 goto fail;
1085 }
1086
1087 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1088 if (r < 0) {
1089 r = -errno;
1090 goto fail;
1091 }
1092
1093 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
1094 if (r < 0) {
1095 r = -errno;
1096 goto fail;
1097 }
1098
1099 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
1100 if (r < 0) {
1101 r = -errno;
1102 goto fail;
1103 }
1104
1105 return m->llmnr_ipv6_udp_fd;
1106
1107fail:
1108 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
1109 return r;
1110}