]> 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 08:27:03 +0000 (09:27 +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.

lib/dns/resolver.c

index 38e4411820eb64216c8136186fda72f4114d0086..5240817c0f4943cdddfaf08ac1050e362cacf3d8 100644 (file)
@@ -3673,49 +3673,65 @@ fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
        dns_rdata_ns_t ns;
        bool have_address = false;
        unsigned int ns_processed = 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);
+
+       for (size_t pass = 0; pass < 2; pass++) {
+               size_t curns = 0;
+
+               DNS_RDATASET_FOREACH(&fctx->nameservers) {
+                       isc_result_t result = ISC_R_SUCCESS;
+                       dns_rdata_t rdata = DNS_RDATA_INIT;
+                       bool overquota = false;
+                       unsigned int static_stub = 0;
+                       unsigned int no_fetch = 0;
+
+                       if (pass == 0 && curns++ < startns) {
+                               continue;
+                       }
+                       if (pass == 1 && curns++ >= startns) {
+                               break;
+                       }
 
-       DNS_RDATASET_FOREACH(&fctx->nameservers) {
-               isc_result_t result = ISC_R_SUCCESS;
-               dns_rdata_t rdata = DNS_RDATA_INIT;
-               bool overquota = false;
-               unsigned int static_stub = 0;
-               unsigned int no_fetch = 0;
-
-               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;
-               }
+                       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;
+                       }
 
-               if (STATICSTUB(&fctx->nameservers) &&
-                   dns_name_equal(&ns.name, fctx->domain))
-               {
-                       static_stub = DNS_ADBFIND_STATICSTUB;
-               }
+                       if (STATICSTUB(&fctx->nameservers) &&
+                           dns_name_equal(&ns.name, fctx->domain))
+                       {
+                               static_stub = DNS_ADBFIND_STATICSTUB;
+                       }
 
-               /*
-                * Make sure we only launch a limited number of
-                * outgoing fetches.
-                */
-               if (fctx->pending_running >= fetches_allowed) {
-                       no_fetch = DNS_ADBFIND_NOFETCH;
-               }
+                       /*
+                        * Make sure we only launch a limited number of
+                        * outgoing fetches.
+                        */
+                       if (fctx->pending_running >= fetches_allowed) {
+                               no_fetch = DNS_ADBFIND_NOFETCH;
+                       }
 
-               findname(fctx, &ns.name, 0, stdoptions | static_stub | no_fetch,
-                        0, now, &overquota, need_alternatep, &have_address);
+                       findname(fctx, &ns.name, 0,
+                                stdoptions | static_stub | no_fetch, 0, now,
+                                &overquota, need_alternatep, &have_address);
 
-               if (!overquota) {
-                       *all_spilledp = false;
-               }
+                       if (!overquota) {
+                               *all_spilledp = false;
+                       }
 
-               dns_rdata_reset(&rdata);
-               dns_rdata_freestruct(&ns);
+                       dns_rdata_reset(&rdata);
+                       dns_rdata_freestruct(&ns);
 
-               if (++ns_processed >= NS_PROCESSING_LIMIT) {
-                       break;
+                       if (++ns_processed >= NS_PROCESSING_LIMIT) {
+                               break;
+                       }
                }
        }