]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/resolve/resolved-manager.c
shared: rename PROTO_ADDRESS_SIZE() to FAMILY_ADDRESS_SIZE()
[thirdparty/systemd.git] / src / resolve / resolved-manager.c
... / ...
CommitLineData
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
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;
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
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(&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
304static 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
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;
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
375int 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
384int 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
431Manager *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
469static 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
490int 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
536fail:
537 unlink(path);
538 unlink(temp_path);
539 return r;
540}
541
542int 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
591int 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
640static 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
658static 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
676int 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
695int 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
714static 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
738int 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
787int 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
838DnsServer* 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
854DnsServer *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
863void 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
882uint32_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}