resolved: if strict DNSSEC mode is selected never downgrade below DNSSEC server feature level due to packet loss

Fixes: #4315
This commit is contained in:
Lennart Poettering 2017-02-08 20:35:32 +01:00
parent e96de0ce47
commit 12bf233175
2 changed files with 18 additions and 3 deletions

View file

@ -451,18 +451,22 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
} else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_UDP) {
s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
/* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the
* packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good
* idea. We might downgrade all the way down to TCP this way. */
* idea. We might downgrade all the way down to TCP this way.
*
* If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss
* might have many reasons, a broken DNSSEC implementation being only one reason. And if the
* user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */
log_debug("Lost too many UDP packets, downgrading feature level...");
s->possible_feature_level--;
} else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
s->packet_truncated &&
s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) {
s->possible_feature_level > (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
/* We got too many TCP connection failures in a row, we had at least one truncated packet, and
* are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0
@ -779,6 +783,15 @@ bool dns_server_address_valid(int family, const union in_addr_union *sa) {
return true;
}
DnssecMode dns_server_get_dnssec_mode(DnsServer *s) {
assert(s);
if (s->link)
return link_get_dnssec_mode(s->link);
return manager_get_dnssec_mode(s->manager);
}
static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
[DNS_SERVER_SYSTEM] = "system",
[DNS_SERVER_FALLBACK] = "fallback",

View file

@ -144,6 +144,8 @@ void manager_next_dns_server(Manager *m);
bool dns_server_address_valid(int family, const union in_addr_union *sa);
DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
extern const struct hash_ops dns_server_hash_ops;