From: Mark Andrews Date: Fri, 19 Dec 2025 07:12:06 +0000 (+1100) Subject: Remove determinist selection of nameserver X-Git-Tag: v9.21.19~5^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b78052119ab3f0355eeb9fb9a9ec199084fc186a;p=thirdparty%2Fbind9.git Remove determinist selection of nameserver 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. --- diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 38e4411820e..5240817c0f4 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -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; + } } }