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