]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: when a server consistently returns SERVFAIL, try another one
authorLennart Poettering <lennart@poettering.net>
Fri, 8 Dec 2017 18:48:15 +0000 (19:48 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 12 Dec 2017 11:10:08 +0000 (12:10 +0100)
Currently, we accept SERVFAIL after downgrading fully, cache it and move
on. Let's extend this a bit: after downgrading fully, if the SERVFAIL
logic continues to be an issue, then use a different DNS server if there
are any.

Fixes: #7147
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-scope.h
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-transaction.h

index 0a644f42525a209d43ce0aeb8e6acf2c48618eab..0f9c4fa47abf7f2d33bf17ef0b841390363fa4a2 100644 (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);
 
index d46ccd884ce7873988f12bd33d23ab9732c0e48c..6f58c3c25702757a2f9803f1fb8a880e29585105 100644 (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);
index 792a16d6930d7f3ae03dde741a90aa336aeb6470..e930dd9c93b487cac5d1cfc89007dc9a1badc128 100644 (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;
@@ -913,12 +915,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;
                         }
index 4ae93c78138c9027a652789938da49b306966f69..31dcd7627a7351b4b3c9d0444ca6be5d2b7b2f50 100644 (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;