From: Mark Andrews Date: Fri, 19 Dec 2025 07:12:06 +0000 (+1100) Subject: Remove determinist selection of nameserver X-Git-Tag: v9.20.20~7^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80316efdd2e6b2128cbb04dfa6eab51fba5e06f9;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. (cherry picked from commit b78052119ab3f0355eeb9fb9a9ec199084fc186a) --- diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 7d244792b62..1557aef2e8a 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -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. */