]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
update TODO
[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>
24#include <linux/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
285 r = sd_network_monitor_new(NULL, &m->network_monitor);
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 int r;
377
378 assert(m);
379
e9f3d2d5 380 r = config_parse(NULL, "/etc/systemd/resolved.conf", NULL,
74b2466e 381 "Resolve\0",
e9f3d2d5 382 config_item_perf_lookup, resolved_gperf_lookup,
987d561f 383 false, false, m);
091a364c
TG
384 if (r < 0)
385 log_warning("Failed to parse configuration file: %s", strerror(-r));
386
74b2466e 387 return 0;
091a364c
TG
388}
389
390int manager_new(Manager **ret) {
74b2466e 391 _cleanup_(manager_freep) Manager *m = NULL;
091a364c
TG
392 int r;
393
c92e531c
LP
394 assert(ret);
395
091a364c
TG
396 m = new0(Manager, 1);
397 if (!m)
398 return -ENOMEM;
399
74b2466e 400 m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
091a364c 401
74b2466e 402 r = parse_dns_server_string(m, /* "172.31.0.125 2001:4860:4860::8888 2001:4860:4860::8889" */ DNS_SERVERS);
091a364c
TG
403 if (r < 0)
404 return r;
405
406 r = sd_event_default(&m->event);
407 if (r < 0)
408 return r;
409
410 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
411 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
412
413 sd_event_set_watchdog(m->event, true);
414
74b2466e
LP
415 r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_DNS);
416 if (r < 0)
417 return r;
418
419 r = manager_network_monitor_listen(m);
420 if (r < 0)
421 return r;
422
423 r = manager_rtnl_listen(m);
424 if (r < 0)
425 return r;
426
427 r = manager_connect_bus(m);
428 if (r < 0)
429 return r;
430
091a364c
TG
431 *ret = m;
432 m = NULL;
433
434 return 0;
435}
436
74b2466e
LP
437Manager *manager_free(Manager *m) {
438 Link *l;
091a364c
TG
439
440 if (!m)
74b2466e
LP
441 return NULL;
442
443 while (m->dns_queries)
444 dns_query_free(m->dns_queries);
445
446 hashmap_free(m->dns_query_transactions);
447
448 while ((l = hashmap_first(m->links)))
449 link_free(l);
450 hashmap_free(m->links);
451
452 dns_scope_free(m->unicast_scope);
453
454 while (m->dns_servers)
455 dns_server_free(m->dns_servers);
091a364c 456
096b6773
LP
457 sd_event_source_unref(m->network_event_source);
458 sd_network_monitor_unref(m->network_monitor);
091a364c 459
74b2466e
LP
460 sd_event_source_unref(m->dns_ipv4_event_source);
461 sd_event_source_unref(m->dns_ipv6_event_source);
462
463 safe_close(m->dns_ipv4_fd);
464 safe_close(m->dns_ipv6_fd);
465
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
LP
483 r = in_addr_to_string(s->family, &s->address, &t);
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
74b2466e
LP
548int manager_dns_ipv4_recv(Manager *m, DnsPacket **ret) {
549 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
550 struct msghdr mh = {};
551 int fd, ms = 0, r;
552 struct iovec iov;
553 ssize_t l;
554
555 assert(m);
556 assert(ret);
557
558 fd = manager_dns_ipv4_fd(m);
559 if (fd < 0)
560 return fd;
561
562 r = ioctl(fd, FIONREAD, &ms);
563 if (r < 0)
564 return -errno;
565 if (ms < 0)
566 return -EIO;
567
568 r = dns_packet_new(&p, ms);
569 if (r < 0)
570 return r;
571
572 iov.iov_base = DNS_PACKET_DATA(p);
573 iov.iov_len = p->allocated;
574
575 mh.msg_iov = &iov;
576 mh.msg_iovlen = 1;
577
578 l = recvmsg(fd, &mh, 0);
579 if (l < 0) {
580 if (errno == EAGAIN)
581 return 0;
582
583 return -errno;
091a364c
TG
584 }
585
74b2466e
LP
586 if (l <= 0)
587 return -EIO;
091a364c 588
74b2466e 589 p->size = (size_t) l;
091a364c 590
74b2466e
LP
591 *ret = p;
592 p = NULL;
593
594 return 1;
595}
596
597int manager_dns_ipv6_recv(Manager *m, DnsPacket **ret) {
598 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
599 struct msghdr mh = {};
600 struct iovec iov;
601 int fd, ms = 0, r;
602 ssize_t l;
603
604 assert(m);
605 assert(ret);
606
607 fd = manager_dns_ipv6_fd(m);
608 if (fd < 0)
609 return fd;
610
611 r = ioctl(fd, FIONREAD, &ms);
612 if (r < 0)
613 return -errno;
614 if (ms < 0)
615 return -EIO;
616
617 r = dns_packet_new(&p, ms);
618 if (r < 0)
091a364c 619 return r;
74b2466e
LP
620
621 iov.iov_base = DNS_PACKET_DATA(p);
622 iov.iov_len = p->allocated;
623
624 mh.msg_iov = &iov;
625 mh.msg_iovlen = 1;
626
627 l = recvmsg(fd, &mh, 0);
628 if (l < 0) {
629 if (errno == EAGAIN)
630 return 0;
631
632 return -errno;
091a364c
TG
633 }
634
74b2466e
LP
635 if (l <= 0)
636 return -EIO;
637
638 p->size = (size_t) l;
639
640 *ret = p;
641 p = NULL;
642
643 return 1;
644}
645
646static int on_dns_ipv4_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
647 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
648 DnsQueryTransaction *t = NULL;
649 Manager *m = userdata;
650 int r;
651
652 r = manager_dns_ipv4_recv(m, &p);
653 if (r <= 0)
654 return r;
655
656 t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_HEADER(p)->id));
657 if (!t)
658 return 0;
659
660 return dns_query_transaction_reply(t, p);
091a364c
TG
661}
662
74b2466e
LP
663static int on_dns_ipv6_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
664 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
665 DnsQueryTransaction *t = NULL;
091a364c
TG
666 Manager *m = userdata;
667 int r;
668
74b2466e
LP
669 r = manager_dns_ipv6_recv(m, &p);
670 if (r <= 0)
671 return r;
672
673 t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_HEADER(p)->id));
674 if (!t)
675 return 0;
676
677 return dns_query_transaction_reply(t, p);
678}
679
680int manager_dns_ipv4_fd(Manager *m) {
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
74b2466e
LP
692 r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_ipv4_packet, m);
693 if (r < 0)
694 return r;
695
696 return m->dns_ipv4_fd;
091a364c
TG
697}
698
74b2466e
LP
699int manager_dns_ipv6_fd(Manager *m) {
700 int r;
701
702 assert(m);
091a364c 703
74b2466e
LP
704 if (m->dns_ipv6_fd >= 0)
705 return m->dns_ipv6_fd;
706
707 m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
708 if (m->dns_ipv6_fd < 0)
709 return -errno;
710
711 r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_ipv6_packet, m);
091a364c
TG
712 if (r < 0)
713 return r;
714
74b2466e
LP
715 return m->dns_ipv6_fd;
716}
717
718static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
719 int r;
720
721 assert(fd >= 0);
722 assert(mh);
723
724 for (;;) {
725 if (sendmsg(fd, mh, flags) >= 0)
726 return 0;
727
728 if (errno == EINTR)
729 continue;
730
731 if (errno != EAGAIN)
732 return -errno;
733
734 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
735 if (r < 0)
736 return r;
737 if (r == 0)
738 return -ETIMEDOUT;
739 }
740}
741
742int manager_dns_ipv4_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p) {
743 union sockaddr_union sa = {
744 .in.sin_family = AF_INET,
745 .in.sin_port = htobe16(53),
746 };
747 struct msghdr mh = {};
748 struct iovec iov;
749 uint8_t control[CMSG_SPACE(sizeof(struct in_pktinfo))];
750 int fd;
751
752 assert(m);
753 assert(srv);
754 assert(p);
755
756 fd = manager_dns_ipv4_fd(m);
091a364c
TG
757 if (fd < 0)
758 return fd;
759
74b2466e
LP
760 iov.iov_base = DNS_PACKET_DATA(p);
761 iov.iov_len = p->size;
091a364c 762
74b2466e 763 sa.in.sin_addr = srv->address.in;
091a364c 764
74b2466e
LP
765 mh.msg_iov = &iov;
766 mh.msg_iovlen = 1;
767 mh.msg_name = &sa.sa;
768 mh.msg_namelen = sizeof(sa.in);
091a364c 769
74b2466e
LP
770 if (ifindex > 0) {
771 struct cmsghdr *cmsg;
772 struct in_pktinfo *pi;
773
774 zero(control);
775
776 mh.msg_control = control;
777 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
778
779 cmsg = CMSG_FIRSTHDR(&mh);
780 cmsg->cmsg_len = mh.msg_controllen;
781 cmsg->cmsg_level = IPPROTO_IP;
782 cmsg->cmsg_type = IP_PKTINFO;
783
784 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
785 pi->ipi_ifindex = ifindex;
786 }
787
788 return sendmsg_loop(fd, &mh, 0);
789}
790
791int manager_dns_ipv6_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p) {
792 union sockaddr_union sa = {
793 .in6.sin6_family = AF_INET6,
794 .in6.sin6_port = htobe16(53),
795 };
796
797 struct msghdr mh = {};
798 struct iovec iov;
799 uint8_t control[CMSG_SPACE(sizeof(struct in6_pktinfo))];
800 int fd;
801
802 assert(m);
803 assert(srv);
804 assert(p);
805
806 fd = manager_dns_ipv6_fd(m);
807 if (fd < 0)
808 return fd;
809
810 iov.iov_base = DNS_PACKET_DATA(p);
811 iov.iov_len = p->size;
812
813 sa.in6.sin6_addr = srv->address.in6;
814 sa.in6.sin6_scope_id = ifindex;
815
816 mh.msg_iov = &iov;
817 mh.msg_iovlen = 1;
818 mh.msg_name = &sa.sa;
819 mh.msg_namelen = sizeof(sa.in6);
820
821 if (ifindex > 0) {
822 struct cmsghdr *cmsg;
823 struct in6_pktinfo *pi;
824
825 zero(control);
826
827 mh.msg_control = control;
828 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
829
830 cmsg = CMSG_FIRSTHDR(&mh);
831 cmsg->cmsg_len = mh.msg_controllen;
832 cmsg->cmsg_level = IPPROTO_IPV6;
833 cmsg->cmsg_type = IPV6_PKTINFO;
834
835 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
836 pi->ipi6_ifindex = ifindex;
837 }
838
839 return sendmsg_loop(fd, &mh, 0);
840}
841
842DnsServer* manager_find_dns_server(Manager *m, unsigned char family, union in_addr_union *in_addr) {
843 DnsServer *s;
844
845 assert(m);
846 assert(in_addr);
847
848 LIST_FOREACH(servers, s, m->dns_servers) {
849
850 if (s->family == family &&
851 in_addr_equal(family, &s->address, in_addr))
852 return s;
853 }
854
855 return NULL;
856}
857
858DnsServer *manager_get_dns_server(Manager *m) {
859 assert(m);
860
861 if (!m->current_dns_server)
862 m->current_dns_server = m->dns_servers;
863
864 return m->current_dns_server;
865}
866
867void manager_next_dns_server(Manager *m) {
868 assert(m);
869
870 if (!m->current_dns_server) {
871 m->current_dns_server = m->dns_servers;
872 return;
873 }
874
875 if (!m->current_dns_server)
876 return;
877
878 if (m->current_dns_server->servers_next) {
879 m->current_dns_server = m->current_dns_server->servers_next;
880 return;
881 }
882
883 m->current_dns_server = m->dns_servers;
091a364c 884}