1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
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.
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.
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/>.
22 #include <sd-messages.h>
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"
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)
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)
39 /* The number of times we will attempt a certain feature set before degrading */
40 #define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3
48 const union in_addr_union
*in_addr
) {
53 assert((type
== DNS_SERVER_LINK
) == !!l
);
56 if (!IN_SET(family
, AF_INET
, AF_INET6
))
60 if (l
->n_dns_servers
>= LINK_DNS_SERVERS_MAX
)
63 if (m
->n_dns_servers
>= MANAGER_DNS_SERVERS_MAX
)
67 s
= new0(DnsServer
, 1);
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
;
79 s
->address
= *in_addr
;
80 s
->resend_timeout
= DNS_TIMEOUT_MIN_USEC
;
86 LIST_APPEND(servers
, l
->dns_servers
, s
);
90 case DNS_SERVER_SYSTEM
:
91 LIST_APPEND(servers
, m
->dns_servers
, s
);
95 case DNS_SERVER_FALLBACK
:
96 LIST_APPEND(servers
, m
->fallback_dns_servers
, s
);
101 assert_not_reached("Unknown server type");
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
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
);
120 DnsServer
* dns_server_ref(DnsServer
*s
) {
124 assert(s
->n_ref
> 0);
130 DnsServer
* dns_server_unref(DnsServer
*s
) {
134 assert(s
->n_ref
> 0);
140 free(s
->server_string
);
145 void dns_server_unlink(DnsServer
*s
) {
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. */
158 case DNS_SERVER_LINK
:
160 assert(s
->link
->n_dns_servers
> 0);
161 LIST_REMOVE(servers
, s
->link
->dns_servers
, s
);
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
--;
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
--;
179 if (s
->link
&& s
->link
->current_dns_server
== s
)
180 link_set_dns_server(s
->link
, NULL
);
182 if (s
->manager
->current_dns_server
== s
)
183 manager_set_dns_server(s
->manager
, NULL
);
188 void dns_server_move_back_and_unmark(DnsServer
*s
) {
198 if (!s
->linked
|| !s
->servers_next
)
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. */
206 case DNS_SERVER_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
);
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
);
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
);
226 assert_not_reached("Unknown server type");
230 static void dns_server_verified(DnsServer
*s
, DnsServerFeatureLevel level
) {
233 if (s
->verified_feature_level
> level
)
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
;
243 assert_se(sd_event_now(s
->manager
->event
, clock_boottime_or_monotonic(), &s
->verified_usec
) >= 0);
246 void dns_server_packet_received(DnsServer
*s
, int protocol
, DnsServerFeatureLevel level
, usec_t rtt
, size_t size
) {
249 if (protocol
== IPPROTO_UDP
) {
250 if (s
->possible_feature_level
== level
)
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;
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;
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;
266 } else if (protocol
== IPPROTO_TCP
) {
268 if (s
->possible_feature_level
== level
)
271 /* Successful TCP connections are only useful to verify the TCP feature level. */
272 level
= DNS_SERVER_FEATURE_LEVEL_TCP
;
275 dns_server_verified(s
, level
);
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
280 if (protocol
== IPPROTO_UDP
&& s
->received_udp_packet_max
< size
)
281 s
->received_udp_packet_max
= size
;
283 if (s
->max_rtt
< rtt
) {
285 s
->resend_timeout
= CLAMP(s
->max_rtt
* 2, DNS_TIMEOUT_MIN_USEC
, DNS_TIMEOUT_MAX_USEC
);
289 void dns_server_packet_lost(DnsServer
*s
, int protocol
, DnsServerFeatureLevel level
, usec_t usec
) {
293 if (s
->possible_feature_level
== level
) {
294 if (protocol
== IPPROTO_UDP
)
296 else if (protocol
== IPPROTO_TCP
)
300 if (s
->resend_timeout
> usec
)
303 s
->resend_timeout
= MIN(s
->resend_timeout
* 2, DNS_TIMEOUT_MAX_USEC
);
306 void dns_server_packet_failed(DnsServer
*s
, DnsServerFeatureLevel level
) {
309 /* Invoked whenever we get a FORMERR, SERVFAIL or NOTIMP rcode from a server. */
311 if (s
->possible_feature_level
!= level
)
314 s
->packet_failed
= true;
317 void dns_server_packet_truncated(DnsServer
*s
, DnsServerFeatureLevel level
) {
320 /* Invoked whenever we get a packet with TC bit set. */
322 if (s
->possible_feature_level
!= level
)
325 s
->packet_truncated
= true;
328 void dns_server_packet_rrsig_missing(DnsServer
*s
, DnsServerFeatureLevel level
) {
331 if (level
< DNS_SERVER_FEATURE_LEVEL_DO
)
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;
338 s
->packet_rrsig_missing
= true;
341 void dns_server_packet_bad_opt(DnsServer
*s
, DnsServerFeatureLevel level
) {
344 if (level
< DNS_SERVER_FEATURE_LEVEL_EDNS0
)
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;
351 s
->packet_bad_opt
= true;
354 static bool dns_server_grace_period_expired(DnsServer
*s
) {
360 if (s
->verified_usec
== 0)
363 assert_se(sd_event_now(s
->manager
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
365 if (s
->verified_usec
+ s
->features_grace_period_usec
> ts
)
368 s
->features_grace_period_usec
= MIN(s
->features_grace_period_usec
* 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC
);
373 static void dns_server_reset_counters(DnsServer
*s
) {
378 s
->packet_failed
= false;
379 s
->packet_truncated
= false;
380 s
->verified_usec
= 0;
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
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
394 DnsServerFeatureLevel
dns_server_possible_feature_level(DnsServer
*s
) {
397 if (s
->possible_feature_level
!= DNS_SERVER_FEATURE_LEVEL_BEST
&&
398 dns_server_grace_period_expired(s
)) {
400 s
->possible_feature_level
= DNS_SERVER_FEATURE_LEVEL_BEST
;
402 dns_server_reset_counters(s
);
404 s
->packet_bad_opt
= false;
405 s
->packet_rrsig_missing
= false;
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
));
411 } else if (s
->possible_feature_level
<= s
->verified_feature_level
)
412 s
->possible_feature_level
= s
->verified_feature_level
;
414 DnsServerFeatureLevel p
= s
->possible_feature_level
;
416 if (s
->n_failed_tcp
>= DNS_SERVER_FEATURE_RETRY_ATTEMPTS
&&
417 s
->possible_feature_level
== DNS_SERVER_FEATURE_LEVEL_TCP
) {
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
;
424 } else if (s
->packet_bad_opt
&&
425 s
->possible_feature_level
>= DNS_SERVER_FEATURE_LEVEL_EDNS0
) {
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 */
432 log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
433 s
->possible_feature_level
= DNS_SERVER_FEATURE_LEVEL_UDP
;
435 } else if (s
->packet_rrsig_missing
&&
436 s
->possible_feature_level
>= DNS_SERVER_FEATURE_LEVEL_DO
) {
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
443 log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
444 s
->possible_feature_level
= DNS_SERVER_FEATURE_LEVEL_EDNS0
;
446 } else if (s
->n_failed_udp
>= DNS_SERVER_FEATURE_RETRY_ATTEMPTS
&&
447 s
->possible_feature_level
>= DNS_SERVER_FEATURE_LEVEL_UDP
) {
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. */
453 log_debug("Lost too many UDP packets, downgrading feature level...");
454 s
->possible_feature_level
--;
456 } else if (s
->packet_failed
&&
457 s
->possible_feature_level
> DNS_SERVER_FEATURE_LEVEL_UDP
) {
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. */
463 log_debug("Got server failure, downgrading feature level...");
464 s
->possible_feature_level
--;
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
) {
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. */
476 log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
477 s
->possible_feature_level
--;
480 if (p
!= s
->possible_feature_level
) {
482 /* We changed the feature level, reset the counting */
483 dns_server_reset_counters(s
);
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
));
491 return s
->possible_feature_level
;
494 int dns_server_adjust_opt(DnsServer
*server
, DnsPacket
*packet
, DnsServerFeatureLevel level
) {
501 assert(packet
->protocol
== DNS_PROTOCOL_DNS
);
503 /* Fix the OPT field in the packet to match our current feature level. */
505 r
= dns_packet_truncate_opt(packet
);
509 if (level
< DNS_SERVER_FEATURE_LEVEL_EDNS0
)
512 edns_do
= level
>= DNS_SERVER_FEATURE_LEVEL_DO
;
514 if (level
>= DNS_SERVER_FEATURE_LEVEL_LARGE
)
515 packet_size
= DNS_PACKET_UNICAST_SIZE_LARGE_MAX
;
517 packet_size
= server
->received_udp_packet_max
;
519 return dns_packet_append_opt(packet
, packet_size
, edns_do
, NULL
);
522 const char *dns_server_string(DnsServer
*server
) {
525 if (!server
->server_string
)
526 (void) in_addr_to_string(server
->family
, &server
->address
, &server
->server_string
);
528 return strna(server
->server_string
);
531 bool dns_server_dnssec_supported(DnsServer
*server
) {
534 /* Returns whether the server supports DNSSEC according to what we know about it */
536 if (server
->possible_feature_level
< DNS_SERVER_FEATURE_LEVEL_DO
)
539 if (server
->packet_bad_opt
)
542 if (server
->packet_rrsig_missing
)
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
)
552 void dns_server_warn_downgrade(DnsServer
*server
) {
555 if (server
->warned_downgrade
)
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
),
565 server
->warned_downgrade
= true;
568 static void dns_server_hash_func(const void *p
, struct siphash
*state
) {
569 const DnsServer
*s
= p
;
573 siphash24_compress(&s
->family
, sizeof(s
->family
), state
);
574 siphash24_compress(&s
->address
, FAMILY_ADDRESS_SIZE(s
->family
), state
);
577 static int dns_server_compare_func(const void *a
, const void *b
) {
578 const DnsServer
*x
= a
, *y
= b
;
580 if (x
->family
< y
->family
)
582 if (x
->family
> y
->family
)
585 return memcmp(&x
->address
, &y
->address
, FAMILY_ADDRESS_SIZE(x
->family
));
588 const struct hash_ops dns_server_hash_ops
= {
589 .hash
= dns_server_hash_func
,
590 .compare
= dns_server_compare_func
593 void dns_server_unlink_all(DnsServer
*first
) {
599 next
= first
->servers_next
;
600 dns_server_unlink(first
);
602 dns_server_unlink_all(next
);
605 void dns_server_unlink_marked(DnsServer
*first
) {
611 next
= first
->servers_next
;
614 dns_server_unlink(first
);
616 dns_server_unlink_marked(next
);
619 void dns_server_mark_all(DnsServer
*first
) {
623 first
->marked
= true;
624 dns_server_mark_all(first
->servers_next
);
627 DnsServer
*dns_server_find(DnsServer
*first
, int family
, const union in_addr_union
*in_addr
) {
630 LIST_FOREACH(servers
, s
, first
)
631 if (s
->family
== family
&& in_addr_equal(family
, &s
->address
, in_addr
) > 0)
637 DnsServer
*manager_get_first_dns_server(Manager
*m
, DnsServerType t
) {
642 case DNS_SERVER_SYSTEM
:
643 return m
->dns_servers
;
645 case DNS_SERVER_FALLBACK
:
646 return m
->fallback_dns_servers
;
653 DnsServer
*manager_set_dns_server(Manager
*m
, DnsServer
*s
) {
656 if (m
->current_dns_server
== s
)
660 log_info("Switching to system DNS server %s.", dns_server_string(s
));
662 dns_server_unref(m
->current_dns_server
);
663 m
->current_dns_server
= dns_server_ref(s
);
665 if (m
->unicast_scope
)
666 dns_cache_flush(&m
->unicast_scope
->cache
);
671 DnsServer
*manager_get_dns_server(Manager
*m
) {
675 /* Try to read updates resolv.conf */
676 manager_read_resolv_conf(m
);
678 /* If no DNS server was chose so far, pick the first one */
679 if (!m
->current_dns_server
)
680 manager_set_dns_server(m
, m
->dns_servers
);
682 if (!m
->current_dns_server
) {
686 /* No DNS servers configured, let's see if there are
687 * any on any links. If not, we use the fallback
690 HASHMAP_FOREACH(l
, m
->links
, i
)
691 if (l
->dns_servers
) {
697 manager_set_dns_server(m
, m
->fallback_dns_servers
);
700 return m
->current_dns_server
;
703 void manager_next_dns_server(Manager
*m
) {
706 /* If there's currently no DNS server set, then the next
707 * manager_get_dns_server() will find one */
708 if (!m
->current_dns_server
)
711 /* Change to the next one, but make sure to follow the linked
712 * list only if the server is still linked. */
713 if (m
->current_dns_server
->linked
&& m
->current_dns_server
->servers_next
) {
714 manager_set_dns_server(m
, m
->current_dns_server
->servers_next
);
718 /* If there was no next one, then start from the beginning of
720 if (m
->current_dns_server
->type
== DNS_SERVER_FALLBACK
)
721 manager_set_dns_server(m
, m
->fallback_dns_servers
);
723 manager_set_dns_server(m
, m
->dns_servers
);
726 static const char* const dns_server_feature_level_table
[_DNS_SERVER_FEATURE_LEVEL_MAX
] = {
727 [DNS_SERVER_FEATURE_LEVEL_TCP
] = "TCP",
728 [DNS_SERVER_FEATURE_LEVEL_UDP
] = "UDP",
729 [DNS_SERVER_FEATURE_LEVEL_EDNS0
] = "UDP+EDNS0",
730 [DNS_SERVER_FEATURE_LEVEL_DO
] = "UDP+EDNS0+DO",
731 [DNS_SERVER_FEATURE_LEVEL_LARGE
] = "UDP+EDNS0+DO+LARGE",
733 DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level
, DnsServerFeatureLevel
);