chiark / gitweb /
fed9a7797359020bb2c30d62289a7a494f257637
[elogind.git] / src / resolve / resolved-manager.c
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>
25 #include <sys/ioctl.h>
26 #include <sys/poll.h>
27 #include <netinet/in.h>
28
29 #include "rtnl-util.h"
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"
36 #include "socket-util.h"
37 #include "resolved.h"
38
39 #define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
40
41 static 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
89 fail:
90         log_warning("Failed to process RTNL link message: %s", strerror(-r));
91         return 0;
92 }
93
94 static 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
175 fail:
176         log_warning("Failed to process RTNL address message: %s", strerror(-r));
177         return 0;
178 }
179
180
181 static 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;
208
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
257 static 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
280 static int manager_network_monitor_listen(Manager *m) {
281         int r, fd, events;
282
283         assert(m);
284
285         r = sd_network_monitor_new(&m->network_monitor, NULL);
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
304 static int parse_dns_server_string(Manager *m, const char *string) {
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) {
313                 char buffer[length+1];
314                 unsigned family;
315                 union in_addr_union addr;
316
317                 memcpy(buffer, word, length);
318                 buffer[length] = 0;
319
320                 r = in_addr_from_string_auto(buffer, &family, &addr);
321                 if (r < 0) {
322                         log_warning("Ignoring invalid DNS address '%s'", buffer);
323                         continue;
324                 }
325
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;
333         }
334
335         return 0;
336 }
337
338 int 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;
351         int r;
352
353         assert(filename);
354         assert(lvalue);
355         assert(rvalue);
356         assert(m);
357
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;
364         }
365
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         }
371
372         return 0;
373 }
374
375 int manager_parse_config_file(Manager *m) {
376         assert(m);
377
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);
382 }
383
384 int manager_new(Manager **ret) {
385         _cleanup_(manager_freep) Manager *m = NULL;
386         int r;
387
388         assert(ret);
389
390         m = new0(Manager, 1);
391         if (!m)
392                 return -ENOMEM;
393
394         m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
395
396         r = parse_dns_server_string(m, /* "172.31.0.125 2001:4860:4860::8888 2001:4860:4860::8889" */ DNS_SERVERS);
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
409         r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_DNS);
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
425         *ret = m;
426         m = NULL;
427
428         return 0;
429 }
430
431 Manager *manager_free(Manager *m) {
432         Link *l;
433
434         if (!m)
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);
450
451         sd_event_source_unref(m->network_event_source);
452         sd_network_monitor_unref(m->network_monitor);
453
454         sd_event_source_unref(m->dns_ipv4_event_source);
455         sd_event_source_unref(m->dns_ipv6_event_source);
456
457         safe_close(m->dns_ipv4_fd);
458         safe_close(m->dns_ipv6_fd);
459
460         sd_event_source_unref(m->bus_retry_event_source);
461         sd_bus_unref(m->bus);
462
463         sd_event_unref(m->event);
464         free(m);
465
466         return NULL;
467 }
468
469 static void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
470         _cleanup_free_ char *t  = NULL;
471         int r;
472
473         assert(s);
474         assert(f);
475         assert(count);
476
477         r = in_addr_to_string(s->family, &s->address, &t);
478         if (r < 0) {
479                 log_warning("Invalid DNS address. Ignoring.");
480                 return;
481         }
482
483         if (*count == MAXNS)
484                 fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
485
486         fprintf(f, "nameserver %s\n", t);
487         (*count) ++;
488 }
489
490 int manager_write_resolv_conf(Manager *m) {
491         const char *path = "/run/systemd/resolve/resolv.conf";
492         _cleanup_free_ char *temp_path = NULL;
493         _cleanup_fclose_ FILE *f = NULL;
494         unsigned count = 0;
495         DnsServer *s;
496         Iterator i;
497         Link *l;
498         int r;
499
500         assert(m);
501
502         r = fopen_temporary(path, &f, &temp_path);
503         if (r < 0)
504                 return r;
505
506         fchmod(fileno(f), 0644);
507
508         fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
509               "# Third party programs must not access this file directly, but\n"
510               "# only through the symlink at /etc/resolv.conf. To manage\n"
511               "# resolv.conf(5) in a different way, replace the symlink by a\n"
512               "# static file or a different symlink.\n\n", f);
513
514         HASHMAP_FOREACH(l, m->links, i) {
515                 LIST_FOREACH(servers, s, l->link_dns_servers)
516                         write_resolve_conf_server(s, f, &count);
517
518                 LIST_FOREACH(servers, s, l->dhcp_dns_servers)
519                         write_resolve_conf_server(s, f, &count);
520         }
521
522         LIST_FOREACH(servers, s, m->dns_servers)
523                 write_resolve_conf_server(s, f, &count);
524
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         }
533
534         return 0;
535
536 fail:
537         unlink(path);
538         unlink(temp_path);
539         return r;
540 }
541
542 int manager_dns_ipv4_recv(Manager *m, DnsPacket **ret) {
543         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
544         struct msghdr mh = {};
545         int fd, ms = 0, r;
546         struct iovec iov;
547         ssize_t l;
548
549         assert(m);
550         assert(ret);
551
552         fd = manager_dns_ipv4_fd(m);
553         if (fd < 0)
554                 return fd;
555
556         r = ioctl(fd, FIONREAD, &ms);
557         if (r < 0)
558                 return -errno;
559         if (ms < 0)
560                 return -EIO;
561
562         r = dns_packet_new(&p, ms);
563         if (r < 0)
564                 return r;
565
566         iov.iov_base = DNS_PACKET_DATA(p);
567         iov.iov_len = p->allocated;
568
569         mh.msg_iov = &iov;
570         mh.msg_iovlen = 1;
571
572         l = recvmsg(fd, &mh, 0);
573         if (l < 0) {
574                 if (errno == EAGAIN || errno == EINTR)
575                         return 0;
576
577                 return -errno;
578         }
579
580         if (l <= 0)
581                 return -EIO;
582
583         p->size = (size_t) l;
584
585         *ret = p;
586         p = NULL;
587
588         return 1;
589 }
590
591 int manager_dns_ipv6_recv(Manager *m, DnsPacket **ret) {
592         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
593         struct msghdr mh = {};
594         struct iovec iov;
595         int fd, ms = 0, r;
596         ssize_t l;
597
598         assert(m);
599         assert(ret);
600
601         fd = manager_dns_ipv6_fd(m);
602         if (fd < 0)
603                 return fd;
604
605         r = ioctl(fd, FIONREAD, &ms);
606         if (r < 0)
607                 return -errno;
608         if (ms < 0)
609                 return -EIO;
610
611         r = dns_packet_new(&p, ms);
612         if (r < 0)
613                 return r;
614
615         iov.iov_base = DNS_PACKET_DATA(p);
616         iov.iov_len = p->allocated;
617
618         mh.msg_iov = &iov;
619         mh.msg_iovlen = 1;
620
621         l = recvmsg(fd, &mh, 0);
622         if (l < 0) {
623                 if (errno == EAGAIN || errno == EINTR)
624                         return 0;
625
626                 return -errno;
627         }
628
629         if (l <= 0)
630                 return -EIO;
631
632         p->size = (size_t) l;
633
634         *ret = p;
635         p = NULL;
636
637         return 1;
638 }
639
640 static int on_dns_ipv4_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
641         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
642         DnsQueryTransaction *t = NULL;
643         Manager *m = userdata;
644         int r;
645
646         r = manager_dns_ipv4_recv(m, &p);
647         if (r <= 0)
648                 return r;
649
650         t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
651         if (!t)
652                 return 0;
653
654         dns_query_transaction_reply(t, p);
655         return 0;
656 }
657
658 static int on_dns_ipv6_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
659         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
660         DnsQueryTransaction *t = NULL;
661         Manager *m = userdata;
662         int r;
663
664         r = manager_dns_ipv6_recv(m, &p);
665         if (r <= 0)
666                 return r;
667
668         t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
669         if (!t)
670                 return 0;
671
672         dns_query_transaction_reply(t, p);
673         return 0;
674 }
675
676 int manager_dns_ipv4_fd(Manager *m) {
677         int r;
678
679         assert(m);
680
681         if (m->dns_ipv4_fd >= 0)
682                 return m->dns_ipv4_fd;
683
684         m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
685         if (m->dns_ipv4_fd < 0)
686                 return -errno;
687
688         r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_ipv4_packet, m);
689         if (r < 0)
690                 return r;
691
692         return m->dns_ipv4_fd;
693 }
694
695 int manager_dns_ipv6_fd(Manager *m) {
696         int r;
697
698         assert(m);
699
700         if (m->dns_ipv6_fd >= 0)
701                 return m->dns_ipv6_fd;
702
703         m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
704         if (m->dns_ipv6_fd < 0)
705                 return -errno;
706
707         r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_ipv6_packet, m);
708         if (r < 0)
709                 return r;
710
711         return m->dns_ipv6_fd;
712 }
713
714 static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
715         int r;
716
717         assert(fd >= 0);
718         assert(mh);
719
720         for (;;) {
721                 if (sendmsg(fd, mh, flags) >= 0)
722                         return 0;
723
724                 if (errno == EINTR)
725                         continue;
726
727                 if (errno != EAGAIN)
728                         return -errno;
729
730                 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
731                 if (r < 0)
732                         return r;
733                 if (r == 0)
734                         return -ETIMEDOUT;
735         }
736 }
737
738 int manager_dns_ipv4_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p) {
739         union sockaddr_union sa = {
740                 .in.sin_family = AF_INET,
741                 .in.sin_port = htobe16(53),
742         };
743         struct msghdr mh = {};
744         struct iovec iov;
745         uint8_t control[CMSG_SPACE(sizeof(struct in_pktinfo))];
746         int fd;
747
748         assert(m);
749         assert(srv);
750         assert(p);
751
752         fd = manager_dns_ipv4_fd(m);
753         if (fd < 0)
754                 return fd;
755
756         iov.iov_base = DNS_PACKET_DATA(p);
757         iov.iov_len = p->size;
758
759         sa.in.sin_addr = srv->address.in;
760
761         mh.msg_iov = &iov;
762         mh.msg_iovlen = 1;
763         mh.msg_name = &sa.sa;
764         mh.msg_namelen = sizeof(sa.in);
765
766         if (ifindex > 0) {
767                 struct cmsghdr *cmsg;
768                 struct in_pktinfo *pi;
769
770                 zero(control);
771
772                 mh.msg_control = control;
773                 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
774
775                 cmsg = CMSG_FIRSTHDR(&mh);
776                 cmsg->cmsg_len = mh.msg_controllen;
777                 cmsg->cmsg_level = IPPROTO_IP;
778                 cmsg->cmsg_type = IP_PKTINFO;
779
780                 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
781                 pi->ipi_ifindex = ifindex;
782         }
783
784         return sendmsg_loop(fd, &mh, 0);
785 }
786
787 int manager_dns_ipv6_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p) {
788         union sockaddr_union sa = {
789                 .in6.sin6_family = AF_INET6,
790                 .in6.sin6_port = htobe16(53),
791         };
792
793         struct msghdr mh = {};
794         struct iovec iov;
795         uint8_t control[CMSG_SPACE(sizeof(struct in6_pktinfo))];
796         int fd;
797
798         assert(m);
799         assert(srv);
800         assert(p);
801
802         fd = manager_dns_ipv6_fd(m);
803         if (fd < 0)
804                 return fd;
805
806         iov.iov_base = DNS_PACKET_DATA(p);
807         iov.iov_len = p->size;
808
809         sa.in6.sin6_addr = srv->address.in6;
810         sa.in6.sin6_scope_id = ifindex;
811
812         mh.msg_iov = &iov;
813         mh.msg_iovlen = 1;
814         mh.msg_name = &sa.sa;
815         mh.msg_namelen = sizeof(sa.in6);
816
817         if (ifindex > 0) {
818                 struct cmsghdr *cmsg;
819                 struct in6_pktinfo *pi;
820
821                 zero(control);
822
823                 mh.msg_control = control;
824                 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
825
826                 cmsg = CMSG_FIRSTHDR(&mh);
827                 cmsg->cmsg_len = mh.msg_controllen;
828                 cmsg->cmsg_level = IPPROTO_IPV6;
829                 cmsg->cmsg_type = IPV6_PKTINFO;
830
831                 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
832                 pi->ipi6_ifindex = ifindex;
833         }
834
835         return sendmsg_loop(fd, &mh, 0);
836 }
837
838 DnsServer* manager_find_dns_server(Manager *m, unsigned char family, union in_addr_union *in_addr) {
839         DnsServer *s;
840
841         assert(m);
842         assert(in_addr);
843
844         LIST_FOREACH(servers, s, m->dns_servers) {
845
846                 if (s->family == family &&
847                     in_addr_equal(family, &s->address, in_addr))
848                         return s;
849         }
850
851         return NULL;
852 }
853
854 DnsServer *manager_get_dns_server(Manager *m) {
855         assert(m);
856
857         if (!m->current_dns_server)
858                 m->current_dns_server = m->dns_servers;
859
860         return m->current_dns_server;
861 }
862
863 void manager_next_dns_server(Manager *m) {
864         assert(m);
865
866         if (!m->current_dns_server) {
867                 m->current_dns_server = m->dns_servers;
868                 return;
869         }
870
871         if (!m->current_dns_server)
872                 return;
873
874         if (m->current_dns_server->servers_next) {
875                 m->current_dns_server = m->current_dns_server->servers_next;
876                 return;
877         }
878
879         m->current_dns_server = m->dns_servers;
880 }
881
882 uint32_t manager_find_mtu(Manager *m) {
883         uint32_t mtu = 0;
884         Link *l;
885         Iterator i;
886
887         /* If we don't know on which link a DNS packet would be
888          * delivered, let's find the largest MTU that works on all
889          * interfaces we know of */
890
891         HASHMAP_FOREACH(l, m->links, i) {
892                 if (l->mtu <= 0)
893                         continue;
894
895                 if (mtu <= 0 || l->mtu < mtu)
896                         mtu = l->mtu;
897         }
898
899         return mtu;
900 }