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