]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-server.c
Merge pull request #2509 from bengal/dhcp-nak-delay-v4
[thirdparty/systemd.git] / src / resolve / resolved-dns-server.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 Lennart Poettering
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 <sd-messages.h>
23
24 #include "alloc-util.h"
25 #include "resolved-dns-server.h"
26 #include "resolved-resolv-conf.h"
27 #include "siphash24.h"
28 #include "string-table.h"
29 #include "string-util.h"
30
31 /* After how much time to repeat classic DNS requests */
32 #define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC)
33 #define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC)
34
35 /* The amount of time to wait before retrying with a full feature set */
36 #define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR)
37 #define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE)
38
39 /* The number of times we will attempt a certain feature set before degrading */
40 #define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3
41
42 int dns_server_new(
43 Manager *m,
44 DnsServer **ret,
45 DnsServerType type,
46 Link *l,
47 int family,
48 const union in_addr_union *in_addr) {
49
50 DnsServer *s;
51
52 assert(m);
53 assert((type == DNS_SERVER_LINK) == !!l);
54 assert(in_addr);
55
56 if (!IN_SET(family, AF_INET, AF_INET6))
57 return -EAFNOSUPPORT;
58
59 if (l) {
60 if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX)
61 return -E2BIG;
62 } else {
63 if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX)
64 return -E2BIG;
65 }
66
67 s = new0(DnsServer, 1);
68 if (!s)
69 return -ENOMEM;
70
71 s->n_ref = 1;
72 s->manager = m;
73 s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
74 s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
75 s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
76 s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX;
77 s->type = type;
78 s->family = family;
79 s->address = *in_addr;
80 s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
81
82 switch (type) {
83
84 case DNS_SERVER_LINK:
85 s->link = l;
86 LIST_APPEND(servers, l->dns_servers, s);
87 l->n_dns_servers++;
88 break;
89
90 case DNS_SERVER_SYSTEM:
91 LIST_APPEND(servers, m->dns_servers, s);
92 m->n_dns_servers++;
93 break;
94
95 case DNS_SERVER_FALLBACK:
96 LIST_APPEND(servers, m->fallback_dns_servers, s);
97 m->n_dns_servers++;
98 break;
99
100 default:
101 assert_not_reached("Unknown server type");
102 }
103
104 s->linked = true;
105
106 /* A new DNS server that isn't fallback is added and the one
107 * we used so far was a fallback one? Then let's try to pick
108 * the new one */
109 if (type != DNS_SERVER_FALLBACK &&
110 m->current_dns_server &&
111 m->current_dns_server->type == DNS_SERVER_FALLBACK)
112 manager_set_dns_server(m, NULL);
113
114 if (ret)
115 *ret = s;
116
117 return 0;
118 }
119
120 DnsServer* dns_server_ref(DnsServer *s) {
121 if (!s)
122 return NULL;
123
124 assert(s->n_ref > 0);
125 s->n_ref ++;
126
127 return s;
128 }
129
130 DnsServer* dns_server_unref(DnsServer *s) {
131 if (!s)
132 return NULL;
133
134 assert(s->n_ref > 0);
135 s->n_ref --;
136
137 if (s->n_ref > 0)
138 return NULL;
139
140 free(s->server_string);
141 free(s);
142 return NULL;
143 }
144
145 void dns_server_unlink(DnsServer *s) {
146 assert(s);
147 assert(s->manager);
148
149 /* This removes the specified server from the linked list of
150 * servers, but any server might still stay around if it has
151 * refs, for example from an ongoing transaction. */
152
153 if (!s->linked)
154 return;
155
156 switch (s->type) {
157
158 case DNS_SERVER_LINK:
159 assert(s->link);
160 assert(s->link->n_dns_servers > 0);
161 LIST_REMOVE(servers, s->link->dns_servers, s);
162 break;
163
164 case DNS_SERVER_SYSTEM:
165 assert(s->manager->n_dns_servers > 0);
166 LIST_REMOVE(servers, s->manager->dns_servers, s);
167 s->manager->n_dns_servers--;
168 break;
169
170 case DNS_SERVER_FALLBACK:
171 assert(s->manager->n_dns_servers > 0);
172 LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
173 s->manager->n_dns_servers--;
174 break;
175 }
176
177 s->linked = false;
178
179 if (s->link && s->link->current_dns_server == s)
180 link_set_dns_server(s->link, NULL);
181
182 if (s->manager->current_dns_server == s)
183 manager_set_dns_server(s->manager, NULL);
184
185 dns_server_unref(s);
186 }
187
188 void dns_server_move_back_and_unmark(DnsServer *s) {
189 DnsServer *tail;
190
191 assert(s);
192
193 if (!s->marked)
194 return;
195
196 s->marked = false;
197
198 if (!s->linked || !s->servers_next)
199 return;
200
201 /* Move us to the end of the list, so that the order is
202 * strictly kept, if we are not at the end anyway. */
203
204 switch (s->type) {
205
206 case DNS_SERVER_LINK:
207 assert(s->link);
208 LIST_FIND_TAIL(servers, s, tail);
209 LIST_REMOVE(servers, s->link->dns_servers, s);
210 LIST_INSERT_AFTER(servers, s->link->dns_servers, tail, s);
211 break;
212
213 case DNS_SERVER_SYSTEM:
214 LIST_FIND_TAIL(servers, s, tail);
215 LIST_REMOVE(servers, s->manager->dns_servers, s);
216 LIST_INSERT_AFTER(servers, s->manager->dns_servers, tail, s);
217 break;
218
219 case DNS_SERVER_FALLBACK:
220 LIST_FIND_TAIL(servers, s, tail);
221 LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
222 LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s);
223 break;
224
225 default:
226 assert_not_reached("Unknown server type");
227 }
228 }
229
230 static void dns_server_verified(DnsServer *s, DnsServerFeatureLevel level) {
231 assert(s);
232
233 if (s->verified_feature_level > level)
234 return;
235
236 if (s->verified_feature_level != level) {
237 log_debug("Verified we get a response at feature level %s from DNS server %s.",
238 dns_server_feature_level_to_string(level),
239 dns_server_string(s));
240 s->verified_feature_level = level;
241 }
242
243 assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0);
244 }
245
246 void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size) {
247 assert(s);
248
249 if (protocol == IPPROTO_UDP) {
250 if (s->possible_feature_level == level)
251 s->n_failed_udp = 0;
252
253 /* If the RRSIG data is missing, then we can only validate EDNS0 at max */
254 if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO)
255 level = DNS_SERVER_FEATURE_LEVEL_DO - 1;
256
257 /* If the OPT RR got lost, then we can only validate UDP at max */
258 if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
259 level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1;
260
261 /* Even if we successfully receive a reply to a request announcing support for large packets,
262 that does not mean we can necessarily receive large packets. */
263 if (level == DNS_SERVER_FEATURE_LEVEL_LARGE)
264 level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1;
265
266 } else if (protocol == IPPROTO_TCP) {
267
268 if (s->possible_feature_level == level)
269 s->n_failed_tcp = 0;
270
271 /* Successful TCP connections are only useful to verify the TCP feature level. */
272 level = DNS_SERVER_FEATURE_LEVEL_TCP;
273 }
274
275 dns_server_verified(s, level);
276
277 /* Remember the size of the largest UDP packet we received from a server,
278 we know that we can always announce support for packets with at least
279 this size. */
280 if (protocol == IPPROTO_UDP && s->received_udp_packet_max < size)
281 s->received_udp_packet_max = size;
282
283 if (s->max_rtt < rtt) {
284 s->max_rtt = rtt;
285 s->resend_timeout = CLAMP(s->max_rtt * 2, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
286 }
287 }
288
289 void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec) {
290 assert(s);
291 assert(s->manager);
292
293 if (s->possible_feature_level == level) {
294 if (protocol == IPPROTO_UDP)
295 s->n_failed_udp ++;
296 else if (protocol == IPPROTO_TCP)
297 s->n_failed_tcp ++;
298 }
299
300 if (s->resend_timeout > usec)
301 return;
302
303 s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
304 }
305
306 void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel level) {
307 assert(s);
308
309 /* Invoked whenever we get a FORMERR, SERVFAIL or NOTIMP rcode from a server. */
310
311 if (s->possible_feature_level != level)
312 return;
313
314 s->packet_failed = true;
315 }
316
317 void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level) {
318 assert(s);
319
320 /* Invoked whenever we get a packet with TC bit set. */
321
322 if (s->possible_feature_level != level)
323 return;
324
325 s->packet_truncated = true;
326 }
327
328 void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level) {
329 assert(s);
330
331 if (level < DNS_SERVER_FEATURE_LEVEL_DO)
332 return;
333
334 /* If the RRSIG RRs are missing, we have to downgrade what we previously verified */
335 if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO)
336 s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_DO-1;
337
338 s->packet_rrsig_missing = true;
339 }
340
341 void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level) {
342 assert(s);
343
344 if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
345 return;
346
347 /* If the OPT RR got lost, we have to downgrade what we previously verified */
348 if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
349 s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0-1;
350
351 s->packet_bad_opt = true;
352 }
353
354 static bool dns_server_grace_period_expired(DnsServer *s) {
355 usec_t ts;
356
357 assert(s);
358 assert(s->manager);
359
360 if (s->verified_usec == 0)
361 return false;
362
363 assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
364
365 if (s->verified_usec + s->features_grace_period_usec > ts)
366 return false;
367
368 s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC);
369
370 return true;
371 }
372
373 static void dns_server_reset_counters(DnsServer *s) {
374 assert(s);
375
376 s->n_failed_udp = 0;
377 s->n_failed_tcp = 0;
378 s->packet_failed = false;
379 s->packet_truncated = false;
380 s->verified_usec = 0;
381
382 /* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the
383 * grace period ends, but not when lowering the possible feature level, as a lower level feature level should
384 * not make RRSIGs appear or OPT appear, but rather make them disappear. If the reappear anyway, then that's
385 * indication for a differently broken OPT/RRSIG implementation, and we really don't want to support that
386 * either.
387 *
388 * This is particularly important to deal with certain Belkin routers which break OPT for certain lookups (A),
389 * but pass traffic through for others (AAAA). If we detect the broken behaviour on one lookup we should not
390 * reenable it for another, because we cannot validate things anyway, given that the RRSIG/OPT data will be
391 * incomplete. */
392 }
393
394 DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
395 assert(s);
396
397 if (s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_BEST &&
398 dns_server_grace_period_expired(s)) {
399
400 s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
401
402 dns_server_reset_counters(s);
403
404 s->packet_bad_opt = false;
405 s->packet_rrsig_missing = false;
406
407 log_info("Grace period over, resuming full feature set (%s) for DNS server %s.",
408 dns_server_feature_level_to_string(s->possible_feature_level),
409 dns_server_string(s));
410
411 } else if (s->possible_feature_level <= s->verified_feature_level)
412 s->possible_feature_level = s->verified_feature_level;
413 else {
414 DnsServerFeatureLevel p = s->possible_feature_level;
415
416 if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
417 s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TCP) {
418
419 /* We are at the TCP (lowest) level, and we tried a couple of TCP connections, and it didn't
420 * work. Upgrade back to UDP again. */
421 log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
422 s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
423
424 } else if (s->packet_bad_opt &&
425 s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
426
427 /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below
428 * EDNS0 levels. After all, some records generate different responses with and without OPT RR
429 * in the request. Example:
430 * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
431
432 log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
433 s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
434
435 } else if (s->packet_rrsig_missing &&
436 s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) {
437
438 /* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't
439 * augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore,
440 * after all some servers generate different replies depending if an OPT RR is in the query or
441 * not. */
442
443 log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
444 s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
445
446 } else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
447 s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_UDP) {
448
449 /* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the
450 * packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good
451 * idea. We might downgrade all the way down to TCP this way. */
452
453 log_debug("Lost too many UDP packets, downgrading feature level...");
454 s->possible_feature_level--;
455
456 } else if (s->packet_failed &&
457 s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) {
458
459 /* We got a failure packet, and are at a feature level above UDP. Note that in this case we
460 * downgrade no further than UDP, under the assumption that a failure packet indicates an
461 * incompatible packet contents, but not a problem with the transport. */
462
463 log_debug("Got server failure, downgrading feature level...");
464 s->possible_feature_level--;
465
466 } else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
467 s->packet_truncated &&
468 s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) {
469
470 /* We got too many TCP connection failures in a row, we had at least one truncated packet, and
471 * are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0
472 * data we hope to make the packet smaller, so that it still works via UDP given that TCP
473 * appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't
474 * go further down, since that's TCP, and TCP failed too often after all. */
475
476 log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
477 s->possible_feature_level--;
478 }
479
480 if (p != s->possible_feature_level) {
481
482 /* We changed the feature level, reset the counting */
483 dns_server_reset_counters(s);
484
485 log_warning("Using degraded feature set (%s) for DNS server %s.",
486 dns_server_feature_level_to_string(s->possible_feature_level),
487 dns_server_string(s));
488 }
489 }
490
491 return s->possible_feature_level;
492 }
493
494 int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level) {
495 size_t packet_size;
496 bool edns_do;
497 int r;
498
499 assert(server);
500 assert(packet);
501 assert(packet->protocol == DNS_PROTOCOL_DNS);
502
503 /* Fix the OPT field in the packet to match our current feature level. */
504
505 r = dns_packet_truncate_opt(packet);
506 if (r < 0)
507 return r;
508
509 if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
510 return 0;
511
512 edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO;
513
514 if (level >= DNS_SERVER_FEATURE_LEVEL_LARGE)
515 packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX;
516 else
517 packet_size = server->received_udp_packet_max;
518
519 return dns_packet_append_opt(packet, packet_size, edns_do, NULL);
520 }
521
522 const char *dns_server_string(DnsServer *server) {
523 assert(server);
524
525 if (!server->server_string)
526 (void) in_addr_to_string(server->family, &server->address, &server->server_string);
527
528 return strna(server->server_string);
529 }
530
531 bool dns_server_dnssec_supported(DnsServer *server) {
532 assert(server);
533
534 /* Returns whether the server supports DNSSEC according to what we know about it */
535
536 if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO)
537 return false;
538
539 if (server->packet_bad_opt)
540 return false;
541
542 if (server->packet_rrsig_missing)
543 return false;
544
545 /* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */
546 if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS)
547 return false;
548
549 return true;
550 }
551
552 void dns_server_warn_downgrade(DnsServer *server) {
553 assert(server);
554
555 if (server->warned_downgrade)
556 return;
557
558 log_struct(LOG_NOTICE,
559 LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_DOWNGRADE),
560 LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.", dns_server_string(server)),
561 "DNS_SERVER=%s", dns_server_string(server),
562 "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level),
563 NULL);
564
565 server->warned_downgrade = true;
566 }
567
568 static void dns_server_hash_func(const void *p, struct siphash *state) {
569 const DnsServer *s = p;
570
571 assert(s);
572
573 siphash24_compress(&s->family, sizeof(s->family), state);
574 siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state);
575 }
576
577 static int dns_server_compare_func(const void *a, const void *b) {
578 const DnsServer *x = a, *y = b;
579
580 if (x->family < y->family)
581 return -1;
582 if (x->family > y->family)
583 return 1;
584
585 return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
586 }
587
588 const struct hash_ops dns_server_hash_ops = {
589 .hash = dns_server_hash_func,
590 .compare = dns_server_compare_func
591 };
592
593 void dns_server_unlink_all(DnsServer *first) {
594 DnsServer *next;
595
596 if (!first)
597 return;
598
599 next = first->servers_next;
600 dns_server_unlink(first);
601
602 dns_server_unlink_all(next);
603 }
604
605 void dns_server_unlink_marked(DnsServer *first) {
606 DnsServer *next;
607
608 if (!first)
609 return;
610
611 next = first->servers_next;
612
613 if (first->marked)
614 dns_server_unlink(first);
615
616 dns_server_unlink_marked(next);
617 }
618
619 void dns_server_mark_all(DnsServer *first) {
620 if (!first)
621 return;
622
623 first->marked = true;
624 dns_server_mark_all(first->servers_next);
625 }
626
627 DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr) {
628 DnsServer *s;
629
630 LIST_FOREACH(servers, s, first)
631 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
632 return s;
633
634 return NULL;
635 }
636
637 DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t) {
638 assert(m);
639
640 switch (t) {
641
642 case DNS_SERVER_SYSTEM:
643 return m->dns_servers;
644
645 case DNS_SERVER_FALLBACK:
646 return m->fallback_dns_servers;
647
648 default:
649 return NULL;
650 }
651 }
652
653 DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
654 assert(m);
655
656 if (m->current_dns_server == s)
657 return s;
658
659 if (s)
660 log_info("Switching to %s DNS server %s.",
661 dns_server_type_to_string(s->type),
662 dns_server_string(s));
663
664 dns_server_unref(m->current_dns_server);
665 m->current_dns_server = dns_server_ref(s);
666
667 if (m->unicast_scope)
668 dns_cache_flush(&m->unicast_scope->cache);
669
670 return s;
671 }
672
673 DnsServer *manager_get_dns_server(Manager *m) {
674 Link *l;
675 assert(m);
676
677 /* Try to read updates resolv.conf */
678 manager_read_resolv_conf(m);
679
680 /* If no DNS server was chosen so far, pick the first one */
681 if (!m->current_dns_server)
682 manager_set_dns_server(m, m->dns_servers);
683
684 if (!m->current_dns_server) {
685 bool found = false;
686 Iterator i;
687
688 /* No DNS servers configured, let's see if there are
689 * any on any links. If not, we use the fallback
690 * servers */
691
692 HASHMAP_FOREACH(l, m->links, i)
693 if (l->dns_servers) {
694 found = true;
695 break;
696 }
697
698 if (!found)
699 manager_set_dns_server(m, m->fallback_dns_servers);
700 }
701
702 return m->current_dns_server;
703 }
704
705 void manager_next_dns_server(Manager *m) {
706 assert(m);
707
708 /* If there's currently no DNS server set, then the next
709 * manager_get_dns_server() will find one */
710 if (!m->current_dns_server)
711 return;
712
713 /* Change to the next one, but make sure to follow the linked
714 * list only if the server is still linked. */
715 if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
716 manager_set_dns_server(m, m->current_dns_server->servers_next);
717 return;
718 }
719
720 /* If there was no next one, then start from the beginning of
721 * the list */
722 if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
723 manager_set_dns_server(m, m->fallback_dns_servers);
724 else
725 manager_set_dns_server(m, m->dns_servers);
726 }
727
728 static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
729 [DNS_SERVER_SYSTEM] = "system",
730 [DNS_SERVER_FALLBACK] = "fallback",
731 [DNS_SERVER_LINK] = "link",
732 };
733 DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType);
734
735 static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
736 [DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
737 [DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
738 [DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0",
739 [DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO",
740 [DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE",
741 };
742 DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);