]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: degrade the feature level on explicit failure
authorTom Gundersen <teg@jklm.no>
Thu, 16 Jul 2015 12:39:55 +0000 (14:39 +0200)
committerTom Gundersen <teg@jklm.no>
Fri, 27 Nov 2015 00:35:33 +0000 (01:35 +0100)
Previously, we would only degrade on packet loss, but when adding EDNS0 support,
we also have to handle the case where the server replies with an explicit error.

src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-server.h
src/resolve/resolved-dns-transaction.c

index 5fc7c3187f36d224095f7190e633edcd3d7a14d6..c5396a03c82db32bebe2213a41cec921826f69e4 100644 (file)
@@ -253,6 +253,16 @@ void dns_server_packet_lost(DnsServer *s, DnsServerFeatureLevel features, usec_t
         s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
 }
 
+void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel features) {
+        assert(s);
+        assert(s->manager);
+
+        if (s->possible_features != features)
+                return;
+
+        s->n_failed_attempts  = (unsigned) -1;
+}
+
 static bool dns_server_grace_period_expired(DnsServer *s) {
         usec_t ts;
 
index f82b14e8fb0718c4b41580249c272fa09fe2759d..a3e8cbcc52c5ebd789ff5047e2d41657d5c4c326 100644 (file)
@@ -89,6 +89,7 @@ void dns_server_move_back_and_unmark(DnsServer *s);
 
 void dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, usec_t rtt);
 void dns_server_packet_lost(DnsServer *s, DnsServerFeatureLevel features, usec_t usec);
+void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel features);
 
 DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr);
 
index 0e09a339aa40812c767b4aa57de0ed90ab12b6d9..4398c2cb9908cf43dc3fe256115d6aae97b8be06 100644 (file)
@@ -418,7 +418,22 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
         case DNS_PROTOCOL_DNS:
                 assert(t->server);
 
-                dns_server_packet_received(t->server, t->current_features, ts - t->start_usec);
+                if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
+
+                        /* request failed, immediately try again with reduced features */
+                        log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
+
+                        dns_server_packet_failed(t->server, t->current_features);
+
+                        r = dns_transaction_go(t);
+                        if (r < 0) {
+                                dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+                                return;
+                        }
+
+                        return;
+                } else
+                        dns_server_packet_received(t->server, t->current_features, ts - t->start_usec);
 
                 break;
         case DNS_PROTOCOL_LLMNR: