]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Remove determinist selection of nameserver
authorMark Andrews <marka@isc.org>
Fri, 19 Dec 2025 07:12:06 +0000 (18:12 +1100)
committerColin Vidal <colin@isc.org>
Wed, 25 Feb 2026 09:18:46 +0000 (10:18 +0100)
When selecting nameserver addresses to be looked up we where
always selecting them in dnssec name order from the start of
the nameserver rrset.  This could lead to resolution failure
despite there being address that could be resolved for the
other names.  Use a random starting point when selecting which
names to lookup.

(cherry picked from commit b78052119ab3f0355eeb9fb9a9ec199084fc186a)

lib/dns/resolver.c

index 7d244792b629c9956b10414e9c79e810460b43d8..1557aef2e8a06323c2eb10ed0a5ac0bf6b23e554 100644 (file)
@@ -3658,58 +3658,74 @@ normal_nses:
        }
 
        for (;;) {
-               for (result = dns_rdataset_first(&fctx->nameservers);
-                    result == ISC_R_SUCCESS;
-                    result = dns_rdataset_next(&fctx->nameservers))
-               {
-                       dns_rdata_t rdata = DNS_RDATA_INIT;
-                       bool overquota = false;
-                       unsigned int static_stub = 0;
-                       unsigned int no_fetch = 0;
+               size_t nscount = dns_rdataset_count(&fctx->nameservers);
+               size_t maxstartns = nscount > NS_PROCESSING_LIMIT
+                                           ? NS_PROCESSING_LIMIT
+                                           : nscount;
+               size_t startns = isc_random_uniform(maxstartns);
 
-                       dns_rdataset_current(&fctx->nameservers, &rdata);
-                       /*
-                        * Extract the name from the NS record.
-                        */
-                       result = dns_rdata_tostruct(&rdata, &ns, NULL);
-                       if (result != ISC_R_SUCCESS) {
-                               continue;
-                       }
+               for (size_t pass = 0; pass < 2; pass++) {
+                       size_t curns = 0;
 
-                       if (STATICSTUB(&fctx->nameservers) &&
-                           dns_name_equal(&ns.name, fctx->domain))
+                       for (result = dns_rdataset_first(&fctx->nameservers);
+                            result == ISC_R_SUCCESS;
+                            result = dns_rdataset_next(&fctx->nameservers))
                        {
-                               static_stub = DNS_ADBFIND_STATICSTUB;
-                       }
+                               dns_rdata_t rdata = DNS_RDATA_INIT;
+                               bool overquota = false;
+                               unsigned int static_stub = 0;
+                               unsigned int no_fetch = 0;
 
-                       /*
-                        * Make sure we only launch a limited number of
-                        * outgoing fetches.
-                        */
-                       if (fctx->pending_running >= fetches_allowed) {
-                               no_fetch = DNS_ADBFIND_NOFETCH;
-                       }
+                               if (pass == 0 && curns++ < startns) {
+                                       continue;
+                               }
+                               if (pass == 1 && curns++ >= startns) {
+                                       break;
+                               }
+
+                               dns_rdataset_current(&fctx->nameservers,
+                                                    &rdata);
+                               /*
+                                * Extract the name from the NS record.
+                                */
+                               result = dns_rdata_tostruct(&rdata, &ns, NULL);
+                               if (result != ISC_R_SUCCESS) {
+                                       continue;
+                               }
 
-                       findname(fctx, &ns.name, 0,
-                                stdoptions | static_stub | no_fetch, 0, now,
-                                &overquota, &need_alternate, &have_address);
+                               if (STATICSTUB(&fctx->nameservers) &&
+                                   dns_name_equal(&ns.name, fctx->domain))
+                               {
+                                       static_stub = DNS_ADBFIND_STATICSTUB;
+                               }
 
-                       if (!overquota) {
-                               all_spilled = false;
-                       }
+                               /*
+                                * Make sure we only launch a limited number of
+                                * outgoing fetches.
+                                */
+                               if (fctx->pending_running >= fetches_allowed) {
+                                       no_fetch = DNS_ADBFIND_NOFETCH;
+                               }
 
-                       dns_rdata_reset(&rdata);
-                       dns_rdata_freestruct(&ns);
+                               findname(fctx, &ns.name, 0,
+                                        stdoptions | static_stub | no_fetch, 0,
+                                        now, &overquota, &need_alternate,
+                                        &have_address);
 
-                       if (++ns_processed >= NS_PROCESSING_LIMIT) {
-                               result = ISC_R_NOMORE;
-                               break;
+                               if (!overquota) {
+                                       all_spilled = false;
+                               }
+
+                               dns_rdata_reset(&rdata);
+                               dns_rdata_freestruct(&ns);
+
+                               if (++ns_processed >= NS_PROCESSING_LIMIT) {
+                                       result = ISC_R_NOMORE;
+                                       break;
+                               }
                        }
                }
 
-               /*
-                * Don't start alternate fetch if we just started one above.
-                */
                /*
                 * Don't start alternate fetch if we just started one above.
                 */