]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
try other servers when receiving FORMERR
authorEvan Hunt <each@isc.org>
Fri, 1 Jul 2022 21:23:33 +0000 (14:23 -0700)
committerEvan Hunt <each@isc.org>
Wed, 6 Jul 2022 21:15:32 +0000 (14:15 -0700)
previously, when an iterative query returned FORMERR, resolution
would be stopped under the assumption that other servers for
the same domain would likely have the same capabilities. this
assumption is not correct; some domains have been reported for
which some but not all servers will return FORMERR to a given
query; retrying allows recursion to succeed.

bin/tests/system/qmin/clean.sh
bin/tests/system/qmin/tests.sh
bin/tests/system/resolver/ans2/ans.pl
bin/tests/system/resolver/ans3/ans.pl
bin/tests/system/resolver/ns4/root.db
bin/tests/system/resolver/tests.sh
lib/dns/resolver.c

index 172a4230840909c8b8224d4a87ac85a046e46f7e..52c38e68baee734c32ec8f88772bd392e663bb1f 100644 (file)
@@ -13,7 +13,7 @@
 
 rm -f ns*/named.conf
 rm -f */named.memstats
-rm -f */named.run
+rm -f */named.run */named.run.prev
 rm -f dig.out.*
 rm -f ns*/named.lock
 rm -f ans*/query.log*
index f2b2d4c3adc9f8b11f6f792023899fb42030ffe9..26d3cb8946c4eb94473b8c3f645946ebdd695b6c 100755 (executable)
@@ -272,7 +272,7 @@ $RNDCCMD 10.53.0.7 flush
 n=$((n+1))
 echo_i "information that minimization was unsuccessful for .ugly is logged ($n)"
 ret=0
-grep "success resolving 'icky.icky.icky.ptang.zoop.boing.ugly/A' after disabling qname minimization due to 'FORMERR'" ns7/named.run > /dev/null || ret=1
+wait_for_log 5 "success resolving 'icky.icky.icky.ptang.zoop.boing.ugly/A' after disabling qname minimization" ns7/named.run > /dev/null || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status+ret))
 
index dd6775fc5cd8ddb7eae09a02d516f3266a015ba7..94f645151f1545446d5781cfde118d359372aef6 100644 (file)
@@ -122,6 +122,8 @@ for (;;) {
                # Delegation to broken TLD.
                $packet->push("authority", new Net::DNS::RR("broken 300 NS ns.broken"));
                $packet->push("additional", new Net::DNS::RR("ns.broken 300 A 10.53.0.4"));
+       } elsif ($qname =~ /\.partial-formerr/) {
+               $packet->header->rcode("FORMERR");
        } else {
                # Data for the "bogus referrals" test
                $packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com"));
index eb41f5fcb3730c88be42a608f48588ce6ccd03c0..dbd10d944d81ffda3f0b3b5b8d2ff01ec29ced21 100644 (file)
@@ -125,6 +125,9 @@ for (;;) {
                $packet->push("answer",
                              new Net::DNS::RR($qname .
                                       " 300 A 10.53.0.3"));
+       } elsif ($qname =~ /\.partial-formerr/) {
+               $packet->push("answer",
+                             new Net::DNS::RR($qname .  " 1 A 10.53.0.3"));
        } else {
                $packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
        }
index 71d90e32e564a0d4b8356b94268d8f14570eb329..df6c29b926d77deb3026705f6df58e3d8846153f 100644 (file)
@@ -32,3 +32,6 @@ sourcens.             NS      ns.sourcens.
 ns.sourcens.           A       10.53.0.4
 targetns.              NS      ns.targetns.
 ns.targetns.           A       10.53.0.6
+partial-formerr.       NS      ns.partial-formerr.
+ns.partial-formerr.    A       10.53.0.2
+ns.partial-formerr.    A       10.53.0.3
index 0d649784383eb005750ba4049056699494939450..3ff957675615fe7f36541ed952d4eb47f1037169 100755 (executable)
@@ -862,6 +862,14 @@ grep "status: SERVFAIL" dig.ns5.out.${n} > /dev/null || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status + ret))
 
+n=$((n+1))
+echo_i "checking SERVFAIL is not returned if only some authoritative servers return FORMERR ($n)"
+ret=0
+dig_with_opts @10.53.0.5 ns.partial-formerr. a > dig.ns5.out.${n} || ret=1
+grep "status: SERVFAIL" dig.ns5.out.${n} > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
 n=$((n+1))
 echo_i "check logged command line ($n)"
 ret=0
index 7392e2bf6d7effa89b8f11abe3250d80ca10d81b..ba258a82feba335150c4840ec6962e606f509dc1 100644 (file)
@@ -9890,25 +9890,13 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
                add_bad_edns(fctx, &query->addrinfo->sockaddr);
                inc_stats(fctx->res, dns_resstatscounter_edns0fail);
        } else if (rcode == dns_rcode_formerr) {
-               if (ISFORWARDER(query->addrinfo)) {
-                       /*
-                        * This forwarder doesn't understand us,
-                        * but other forwarders might.  Keep trying.
-                        */
-                       rctx->broken_server = DNS_R_REMOTEFORMERR;
-                       rctx->next_server = true;
-               } else {
-                       /*
-                        * The server doesn't understand us.  Since
-                        * all servers for a zone need similar
-                        * capabilities, we assume that we will get
-                        * FORMERR from all servers, and thus we
-                        * cannot make any more progress with this
-                        * fetch.
-                        */
-                       log_formerr(fctx, "server sent FORMERR");
-                       result = DNS_R_FORMERR;
-               }
+               /*
+                * The server (or forwarder) doesn't understand us,
+                * but others might.
+                */
+               rctx->next_server = true;
+               rctx->broken_server = DNS_R_REMOTEFORMERR;
+               log_formerr(fctx, "server sent FORMERR");
        } else if (rcode == dns_rcode_badvers) {
                unsigned int version;
 #if DNS_EDNS_VERSION > 0