Merge pull request #7591 from poettering/retry-on-servfail

resolved: retry with a different server on SERVFAIL
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2017-12-12 22:22:06 +01:00
committed by GitHub
4 changed files with 47 additions and 4 deletions
+20
View File
@@ -143,6 +143,26 @@ DnsServer *dns_scope_get_dns_server(DnsScope *s) {
return manager_get_dns_server(s->manager);
}
unsigned dns_scope_get_n_dns_servers(DnsScope *s) {
unsigned n = 0;
DnsServer *i;
assert(s);
if (s->protocol != DNS_PROTOCOL_DNS)
return 0;
if (s->link)
i = s->link->dns_servers;
else
i = s->manager->dns_servers;
for (; i; i = i->servers_next)
n++;
return n;
}
void dns_scope_next_dns_server(DnsScope *s) {
assert(s);
+1
View File
@@ -95,6 +95,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key);
DnsServer *dns_scope_get_dns_server(DnsScope *s);
unsigned dns_scope_get_n_dns_servers(DnsScope *s);
void dns_scope_next_dns_server(DnsScope *s);
int dns_scope_llmnr_membership(DnsScope *s, bool b);
+24 -4
View File
@@ -408,6 +408,8 @@ static int dns_transaction_pick_server(DnsTransaction *t) {
dns_server_unref(t->server);
t->server = dns_server_ref(server);
t->n_picked_servers ++;
log_debug("Using DNS server %s for transaction %u.", dns_server_string(t->server), t->id);
return 1;
@@ -737,8 +739,17 @@ static void dns_transaction_process_dnssec(DnsTransaction *t) {
if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER &&
t->scope->dnssec_mode == DNSSEC_YES) {
/* We are not in automatic downgrade mode, and the
* server is bad, refuse operation. */
/* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe
* that works. */
if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
/* We tried fewer servers on this transaction than we know, let's try another one then */
dns_transaction_retry(t, true);
return;
}
/* OK, let's give up, apparently all servers we tried didn't work. */
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
return;
}
@@ -913,12 +924,21 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
/* Request failed, immediately try again with reduced features */
if (t->current_feature_level <= DNS_SERVER_FEATURE_LEVEL_UDP) {
/* This was already at UDP feature level? If so, it doesn't make sense to downgrade
* this transaction anymore, hence let's process the response, and accept the
* this transaction anymore, but let's see if it might make sense to send the request
* to a different DNS server instead. If not let's process the response, and accept the
* rcode. Note that we don't retry on TCP, since that's a suitable way to mitigate
* packet loss, but is not going to give us better rcodes should we actually have
* managed to get them already at UDP level. */
if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
/* We tried fewer servers on this transaction than we know, let's try another one then */
dns_transaction_retry(t, true);
return;
}
/* Give up, accept the rcode */
log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
break;
}
@@ -1351,7 +1371,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
/* Before trying the cache, let's make sure we figured out a
* server to use. Should this cause a change of server this
* might flush the cache. */
dns_scope_get_dns_server(t->scope);
(void) dns_scope_get_dns_server(t->scope);
/* Let's then prune all outdated entries */
dns_cache_prune(&t->scope->cache);
+2
View File
@@ -109,6 +109,8 @@ struct DnsTransaction {
sd_event_source *timeout_event_source;
unsigned n_attempts;
unsigned n_picked_servers;
/* UDP connection logic, if we need it */
int dns_udp_fd;
sd_event_source *dns_udp_event_source;