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