chg: usr: Reduce the number of outgoing queries

Reduces the number of outgoing queries when resolving the nameservers
for delegation points.  This helps the DNS resolver with cold cache
resolve client queries with complex delegation chains and redirections.

Merge branch 'ondrej/fctx_getaddresses' into 'main'

See merge request isc-projects/bind9!11148
This commit is contained in:
Ondřej Surý 2025-11-20 13:32:42 +01:00
commit 37d851df37
2 changed files with 355 additions and 257 deletions

View file

@ -240,9 +240,9 @@ for nscount in 1 2 3 4 5 6 7 8 9 10; do
test "${sourcerecs}" -eq "${nscount}" || ret=1
test "${sourcerecs}" -eq "${nscount}" || echo_i "NS count incorrect for target${nscount}.sourcens"
# Expected queries = 2 * number of NS records, up to a maximum of 10.
# Expected queries = 2 * number of NS records allowed at the first level, up to a maximum of 6.
expected=$((nscount * 2))
if [ "$expected" -gt 10 ]; then expected=10; fi
if [ "$expected" -gt 6 ]; then expected=6; fi
# Count the number of logged fetches
nextpart ns5/named.run >/dev/null
dig_with_opts @10.53.0.5 target${nscount}.sourcens A >dig.ns5.out.${nscount}.${n} || ret=1

View file

@ -25,6 +25,7 @@
#include <isc/hash.h>
#include <isc/hashmap.h>
#include <isc/hex.h>
#include <isc/list.h>
#include <isc/log.h>
#include <isc/loop.h>
#include <isc/mutex.h>
@ -221,13 +222,6 @@
#define DEFAULT_MAX_QUERIES 50
#endif /* ifndef DEFAULT_MAX_QUERIES */
/*
* After NS_FAIL_LIMIT attempts to fetch a name server address,
* if the number of addresses in the NS RRset exceeds NS_RR_LIMIT,
* stop trying to fetch, in order to avoid wasting resources.
*/
#define NS_FAIL_LIMIT 4
#define NS_RR_LIMIT 5
/*
* IP address lookups are performed for at most NS_PROCESSING_LIMIT NS RRs in
* any NS RRset encountered, to avoid excessive resource use while processing
@ -235,11 +229,6 @@
*/
#define NS_PROCESSING_LIMIT 20
STATIC_ASSERT(NS_PROCESSING_LIMIT > NS_RR_LIMIT,
"The maximum number of NS RRs processed for each "
"delegation (NS_PROCESSING_LIMIT) must be larger than the large "
"delegation threshold (NS_RR_LIMIT).");
/* Hash table for zone counters */
#ifndef RES_DOMAIN_HASH_BITS
#define RES_DOMAIN_HASH_BITS 12
@ -418,9 +407,10 @@ struct fetchctx {
dns_name_t *fwdname;
/*%
* The number of events we're waiting for.
* Used to track started ADB finds with event.
*/
atomic_uint_fast32_t pending;
size_t pending_running;
dns_adbfindlist_t pending_finds;
/*%
* The number of times we've "restarted" the current
@ -1739,6 +1729,16 @@ fctx__done(fetchctx_t *fctx, isc_result_t result, const char *func,
fctx->qmin_warning = ISC_R_SUCCESS;
/*
* Cancel all pending ADB finds if we have not been successful
* or we are shutting down.
*/
if (result != ISC_R_SUCCESS) {
ISC_LIST_FOREACH(fctx->pending_finds, find, publink) {
dns_adb_cancelfind(find);
}
}
fctx_cancelqueries(fctx, no_response, age_untried);
fctx_stoptimer(fctx);
@ -2878,13 +2878,38 @@ detach:
resquery_detach(&query);
}
static isc_result_t
fctx_finddone_fail(fetchctx_t *fctx) {
fctx->findfail++;
/*
* There are still running ADB finds and these can be more successful.
*/
if (!ISC_LIST_EMPTY(fctx->pending_finds)) {
return DNS_R_WAIT;
}
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
/*
* There's something on the alternate list. Try that.
*/
if (!ISC_LIST_EMPTY(fctx->res->alternates)) {
return DNS_R_CONTINUE;
}
/*
* We've got nothing else to wait for and don't know the answer.
* There's nothing to do but fail the fctx.
*/
return ISC_R_FAILURE;
}
static void
fctx_finddone(void *arg) {
dns_adbfind_t *find = (dns_adbfind_t *)arg;
fetchctx_t *fctx = (fetchctx_t *)find->cbarg;
bool want_try = false;
bool want_done = false;
uint_fast32_t pending;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(VALID_FCTX(fctx));
@ -2893,8 +2918,15 @@ fctx_finddone(void *arg) {
REQUIRE(fctx->tid == isc_tid());
LOCK(&fctx->lock);
pending = atomic_fetch_sub_release(&fctx->pending, 1);
INSIST(pending > 0);
if (ISC_LINK_LINKED(find, publink)) {
/*
* If we canceled the find directly in findname(),
* it won't be linked here as dns_adb_cancelfind()
* is not idempotent.
*/
fctx->pending_running--;
ISC_LIST_UNLINK(fctx->pending_finds, find, publink);
}
if (ADDRWAIT(fctx)) {
/*
@ -2903,33 +2935,25 @@ fctx_finddone(void *arg) {
INSIST(!SHUTTINGDOWN(fctx));
if (dns_adb_findstatus(find) == DNS_ADB_MOREADDRESSES) {
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
want_try = true;
result = DNS_R_CONTINUE;
} else {
fctx->findfail++;
if (atomic_load_acquire(&fctx->pending) == 0) {
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
if (!ISC_LIST_EMPTY(fctx->res->alternates)) {
want_try = true;
} else {
/*
* We've got nothing else to wait for
* and don't know the answer. There's
* nothing to do but fail the fctx.
*/
want_done = true;
}
}
result = fctx_finddone_fail(fctx);
}
}
UNLOCK(&fctx->lock);
if (want_done) {
FCTXTRACE("fetch failed in finddone(); return "
"ISC_R_FAILURE");
fctx_failure_unref(fctx, ISC_R_FAILURE);
} else if (want_try) {
switch (result) {
case ISC_R_SUCCESS:
case DNS_R_WAIT:
break;
case DNS_R_CONTINUE:
fctx_try(fctx, true);
break;
default:
FCTXTRACE2("fetch failed in finddone()",
isc_result_totext(result));
fctx_failure_unref(fctx, result);
break;
}
dns_adb_destroyfind(&find);
@ -3216,7 +3240,7 @@ waiting_for(dns_adbfind_t *find, dns_rdatatype_t type) {
static void
findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
unsigned int options, unsigned int flags, isc_stdtime_t now,
bool *overquota, bool *need_alternate, unsigned int *no_addresses) {
bool *overquota, bool *need_alternate, bool *have_address) {
dns_adbfind_t *find = NULL;
dns_resolver_t *res = fctx->res;
bool unshared = ((fctx->options & DNS_FETCHOPT_UNSHARED) != 0);
@ -3304,6 +3328,7 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
} else {
ISC_LIST_APPEND(fctx->finds, find, publink);
}
SET_IF_NOT_NULL(have_address, true);
return;
}
@ -3322,7 +3347,6 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
fctx->info);
if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
atomic_fetch_add_relaxed(&fctx->pending, 1);
dns_adb_cancelfind(find);
} else {
dns_adb_destroyfind(&find);
@ -3336,7 +3360,8 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
* we'll get an event later when the find has what it needs.
*/
if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
atomic_fetch_add_relaxed(&fctx->pending, 1);
fctx->pending_running++;
ISC_LIST_APPEND(fctx->pending_finds, find, publink);
/*
* Bootstrap.
@ -3349,9 +3374,6 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
{
*need_alternate = true;
}
if (no_addresses != NULL) {
(*no_addresses)++;
}
return;
}
@ -3389,72 +3411,34 @@ isstrictsubdomain(const dns_name_t *name1, const dns_name_t *name2) {
return namereln == dns_namereln_subdomain;
}
static unsigned int
fctx_getaddresses_allowed(fetchctx_t *fctx) {
switch (fctx->depth) {
case 0:
return 3;
case 1:
return 2;
case 2:
return 1;
default:
return 0;
}
}
static isc_result_t
fctx_getaddresses(fetchctx_t *fctx) {
isc_result_t result;
dns_resolver_t *res;
isc_stdtime_t now;
unsigned int stdoptions = 0;
dns_forwarder_t *fwd;
dns_adbaddrinfo_t *ai;
bool all_bad;
dns_rdata_ns_t ns;
bool need_alternate = false;
bool all_spilled = false;
unsigned int no_addresses = 0;
unsigned int ns_processed = 0;
FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
/*
* Don't pound on remote servers. (Failsafe!)
*/
fctx->restarts++;
if (fctx->restarts > 100) {
FCTXTRACE("too many restarts");
return DNS_R_SERVFAIL;
}
res = fctx->res;
if (fctx->depth > res->maxdepth) {
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
ISC_LOG_DEBUG(3),
"too much NS indirection resolving '%s' "
"(depth=%u, maxdepth=%u)",
fctx->info, fctx->depth, res->maxdepth);
return DNS_R_SERVFAIL;
}
/*
* Forwarders.
*/
INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
/*
* If we have DNS_FETCHOPT_NOFORWARD set and forwarding policy
* allows us to not forward - skip forwarders and go straight
* to NSes. This is currently used to make sure that priming
* query gets root servers' IP addresses in ADDITIONAL section.
*/
if ((fctx->options & DNS_FETCHOPT_NOFORWARD) != 0 &&
(fctx->fwdpolicy != dns_fwdpolicy_only))
{
goto normal_nses;
}
fctx_getaddresses_forwarders(fetchctx_t *fctx) {
dns_resolver_t *res = fctx->res;
/*
* If this fctx has forwarders, use them; otherwise use any
* selective forwarders specified in the view; otherwise use the
* resolver's forwarders (if any).
*/
fwd = ISC_LIST_HEAD(fctx->forwarders);
dns_forwarder_t *fwd = ISC_LIST_HEAD(fctx->forwarders);
if (fwd == NULL) {
dns_forwarders_t *forwarders = NULL;
dns_name_t *name = fctx->name;
dns_name_t suffix;
isc_result_t result;
/*
* DS records are found in the parent server.
@ -3492,8 +3476,11 @@ fctx_getaddresses(fetchctx_t *fctx) {
}
while (fwd != NULL) {
isc_result_t result;
dns_adbaddrinfo_t *ai;
if ((isc_sockaddr_pf(&fwd->addr) == AF_INET &&
res->dispatches4 == NULL) ||
(isc_sockaddr_pf(&fwd->addr) == AF_INET6 &&
res->dispatches6 == NULL))
{
@ -3529,18 +3516,180 @@ fctx_getaddresses(fetchctx_t *fctx) {
fwd = ISC_LIST_NEXT(fwd, link);
}
return DNS_R_CONTINUE;
}
static isc_result_t
fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
unsigned int stdoptions,
unsigned int fetches_allowed,
bool *need_alternatep, bool *all_spilledp) {
dns_rdata_ns_t ns;
bool have_address = false;
unsigned int ns_processed = 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;
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;
}
/*
* 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);
if (!overquota) {
*all_spilledp = false;
}
dns_rdata_reset(&rdata);
dns_rdata_freestruct(&ns);
if (++ns_processed >= NS_PROCESSING_LIMIT) {
break;
}
}
if (fctx->pending_running == 0 && !have_address) {
/*
* We don't have any address and there are no
* pending fetches running, indicate that we
* need to continue looking.
*/
return DNS_R_CONTINUE;
}
return ISC_R_SUCCESS;
}
static void
fctx_getaddresses_alternate(fetchctx_t *fctx, isc_stdtime_t now,
unsigned int stdoptions) {
dns_resolver_t *res = fctx->res;
int family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
ISC_LIST_FOREACH(res->alternates, a, link) {
dns_adbaddrinfo_t *ai;
isc_result_t result;
if (!a->isaddress) {
findname(fctx, &a->_u._n.name, a->_u._n.port,
stdoptions, FCTX_ADDRINFO_DUALSTACK, now, NULL,
NULL, NULL);
continue;
}
if (isc_sockaddr_pf(&a->_u.addr) != family) {
continue;
}
ai = NULL;
result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr, &ai, 0);
if (result != ISC_R_SUCCESS) {
continue;
}
dns_adbaddrinfo_t *cur;
ai->flags |= FCTX_ADDRINFO_FORWARDER;
ai->flags |= FCTX_ADDRINFO_DUALSTACK;
cur = ISC_LIST_HEAD(fctx->altaddrs);
while (cur != NULL && cur->srtt < ai->srtt) {
cur = ISC_LIST_NEXT(cur, publink);
}
if (cur != NULL) {
ISC_LIST_INSERTBEFORE(fctx->altaddrs, cur, ai, publink);
} else {
ISC_LIST_APPEND(fctx->altaddrs, ai, publink);
}
}
}
static isc_result_t
fctx_getaddresses(fetchctx_t *fctx) {
isc_result_t result;
dns_resolver_t *res;
isc_stdtime_t now;
unsigned int stdoptions = 0;
bool all_bad;
bool need_alternate = false;
bool all_spilled = false;
unsigned int fetches_allowed = 0;
FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
/*
* If the forwarding policy is "only", we don't need the
* addresses of the nameservers.
* Don't pound on remote servers. (Failsafe!)
*/
if (fctx->fwdpolicy == dns_fwdpolicy_only) {
goto out;
fctx->restarts++;
if (fctx->restarts > 100) {
FCTXTRACE("too many restarts");
return DNS_R_SERVFAIL;
}
res = fctx->res;
if (fctx->depth > res->maxdepth) {
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
ISC_LOG_DEBUG(3),
"too much NS indirection resolving '%s' "
"(depth=%u, maxdepth=%u)",
fctx->info, fctx->depth, res->maxdepth);
return DNS_R_SERVFAIL;
}
/*
* Forwarders.
*/
INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
/*
* Skip forwarders only if DNS_FETCHOPT_NOFORWARD is not set or if the
* forwarding policy doesn't allow us to not forward.
*
* This is currently used to make sure that priming query gets root
* servers' IP addresses in ADDITIONAL section.
*/
if ((fctx->options & DNS_FETCHOPT_NOFORWARD) == 0 ||
(fctx->fwdpolicy == dns_fwdpolicy_only))
{
result = fctx_getaddresses_forwarders(fctx);
if (result != DNS_R_CONTINUE) {
return result;
}
/*
* If the forwarding policy is "only", we don't need the
* addresses of the nameservers.
*/
if (fctx->fwdpolicy == dns_fwdpolicy_only) {
goto out;
}
}
/*
* Normal nameservers.
*/
normal_nses:
stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
if (fctx->restarts == 1) {
/*
@ -3574,84 +3723,35 @@ normal_nses:
INSIST(ISC_LIST_EMPTY(fctx->finds));
INSIST(ISC_LIST_EMPTY(fctx->altfinds));
DNS_RDATASET_FOREACH(&fctx->nameservers) {
dns_rdata_t rdata = DNS_RDATA_INIT;
bool overquota = false;
unsigned int static_stub = 0;
fetches_allowed = fctx_getaddresses_allowed(fctx);
dns_rdataset_current(&fctx->nameservers, &rdata);
result = fctx_getaddresses_nameservers(fctx, now, stdoptions,
fetches_allowed, &need_alternate,
&all_spilled);
if (result == DNS_R_CONTINUE && fetches_allowed == 0) {
/*
* Extract the name from the NS record.
* We have no addresses and we haven't allowed any
* fetches to be started. Allow one extra fetch and try
* again.
*/
result = dns_rdata_tostruct(&rdata, &ns, NULL);
if (result != ISC_R_SUCCESS) {
continue;
}
(void)fctx_getaddresses_nameservers(fctx, now, stdoptions, 1,
&need_alternate,
&all_spilled);
}
if (STATICSTUB(&fctx->nameservers) &&
dns_name_equal(&ns.name, fctx->domain))
{
static_stub = DNS_ADBFIND_STATICSTUB;
}
if (no_addresses > NS_FAIL_LIMIT &&
dns_rdataset_count(&fctx->nameservers) > NS_RR_LIMIT)
{
stdoptions |= DNS_ADBFIND_NOFETCH;
}
findname(fctx, &ns.name, 0, stdoptions | static_stub, 0, now,
&overquota, &need_alternate, &no_addresses);
if (!overquota) {
all_spilled = false;
}
dns_rdata_reset(&rdata);
dns_rdata_freestruct(&ns);
if (++ns_processed >= NS_PROCESSING_LIMIT) {
break;
}
/*
* Don't start alternate fetch if we just started one above.
*/
if (fctx->pending_running > 0) {
stdoptions |= DNS_ADBFIND_NOFETCH;
}
/*
* Do we need to use 6 to 4?
*/
if (need_alternate) {
int family;
family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
ISC_LIST_FOREACH(res->alternates, a, link) {
if (!a->isaddress) {
findname(fctx, &a->_u._n.name, a->_u._n.port,
stdoptions, FCTX_ADDRINFO_DUALSTACK,
now, NULL, NULL, NULL);
continue;
}
if (isc_sockaddr_pf(&a->_u.addr) != family) {
continue;
}
ai = NULL;
result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
&ai, 0);
if (result == ISC_R_SUCCESS) {
dns_adbaddrinfo_t *cur;
ai->flags |= FCTX_ADDRINFO_FORWARDER;
ai->flags |= FCTX_ADDRINFO_DUALSTACK;
cur = ISC_LIST_HEAD(fctx->altaddrs);
while (cur != NULL && cur->srtt < ai->srtt) {
cur = ISC_LIST_NEXT(cur, publink);
}
if (cur != NULL) {
ISC_LIST_INSERTBEFORE(fctx->altaddrs,
cur, ai, publink);
} else {
ISC_LIST_APPEND(fctx->altaddrs, ai,
publink);
}
}
}
fctx_getaddresses_alternate(fctx, now, stdoptions);
}
out:
/*
* Mark all known bad servers.
@ -3661,55 +3761,54 @@ out:
/*
* How are we doing?
*/
if (all_bad) {
/*
* We've got no addresses.
*/
if (atomic_load_acquire(&fctx->pending) > 0) {
/*
* We're fetching the addresses, but don't have
* any yet. Tell the caller to wait for an
* answer.
*/
result = DNS_R_WAIT;
} else {
/*
* We've lost completely. We don't know any
* addresses, and the ADB has told us it can't
* get them.
*/
FCTXTRACE("no addresses");
result = ISC_R_FAILURE;
/*
* If all of the addresses found were over the
* fetches-per-server quota, increase the ServerQuota
* counter and return the configured response.
*/
if (all_spilled) {
result = res->quotaresp[dns_quotatype_server];
inc_stats(res, dns_resstatscounter_serverquota);
}
/*
* If we are using a 'forward only' policy, and all
* the forwarders are bad, increase the ForwardOnlyFail
* counter.
*/
if (fctx->fwdpolicy == dns_fwdpolicy_only) {
inc_stats(res,
dns_resstatscounter_forwardonlyfail);
}
}
} else {
if (!all_bad) {
/*
* We've found some addresses. We might still be
* looking for more addresses.
*/
sort_finds(&fctx->finds, res->view->v6bias);
sort_finds(&fctx->altfinds, 0);
result = ISC_R_SUCCESS;
return ISC_R_SUCCESS;
}
/*
* We've got no addresses.
*/
if (fctx->pending_running > 0) {
/*
* We're fetching the addresses, but don't have
* any yet. Tell the caller to wait for an
* answer.
*/
return DNS_R_WAIT;
}
/*
* We've lost completely. We don't know any
* addresses, and the ADB has told us it can't
* get them.
*/
FCTXTRACE("no addresses");
result = ISC_R_FAILURE;
/*
* If all of the addresses found were over the
* fetches-per-server quota, increase the ServerQuota
* counter and return the configured response.
*/
if (all_spilled) {
result = res->quotaresp[dns_quotatype_server];
inc_stats(res, dns_resstatscounter_serverquota);
}
/*
* If we are using a 'forward only' policy, and all
* the forwarders are bad, increase the ForwardOnlyFail
* counter.
*/
if (fctx->fwdpolicy == dns_fwdpolicy_only) {
inc_stats(res, dns_resstatscounter_forwardonlyfail);
}
return result;
@ -3939,11 +4038,6 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
dns_adbaddrinfo_t *addrinfo = NULL;
dns_resolver_t *res = NULL;
FCTXTRACE5("try", "fctx->qc=", isc_counter_used(fctx->qc));
if (fctx->gqc != NULL) {
FCTXTRACE5("try", "fctx->gqc=", isc_counter_used(fctx->gqc));
}
REQUIRE(!ADDRWAIT(fctx));
REQUIRE(fctx->tid == isc_tid());
@ -4079,6 +4173,10 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
}
result = isc_counter_increment(fctx->qc);
#if WANT_QUERYTRACE
FCTXTRACE5("query", "max-recursion-queries, querycount=",
isc_counter_used(fctx->qc));
#endif
if (result != ISC_R_SUCCESS) {
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
ISC_LOG_DEBUG(3),
@ -4090,6 +4188,10 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
if (fctx->gqc != NULL) {
result = isc_counter_increment(fctx->gqc);
#if WANT_QUERYTRACE
FCTXTRACE5("query", "max-query-count, querycount=",
isc_counter_used(fctx->gqc));
#endif
if (result != ISC_R_SUCCESS) {
isc_log_write(DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
@ -4348,7 +4450,6 @@ resume_qmin(void *arg) {
goto cleanup;
}
fcount_decr(fctx);
dns_name_copy(fname, fctx->domain);
result = fcount_incr(fctx, false);
@ -4413,9 +4514,10 @@ fctx_destroy(fetchctx_t *fctx) {
REQUIRE(ISC_LIST_EMPTY(fctx->queries));
REQUIRE(ISC_LIST_EMPTY(fctx->finds));
REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
REQUIRE(atomic_load_acquire(&fctx->pending) == 0);
REQUIRE(ISC_LIST_EMPTY(fctx->pending_finds));
REQUIRE(ISC_LIST_EMPTY(fctx->validators));
REQUIRE(fctx->state != fetchstate_active);
REQUIRE(fctx->timer == NULL);
FCTXTRACE("destroy");
@ -4630,6 +4732,19 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
.fwdpolicy = dns_fwdpolicy_none,
.result = ISC_R_FAILURE,
.loop = loop,
.queries = ISC_LIST_INITIALIZER,
.finds = ISC_LIST_INITIALIZER,
.altfinds = ISC_LIST_INITIALIZER,
.forwaddrs = ISC_LIST_INITIALIZER,
.altaddrs = ISC_LIST_INITIALIZER,
.forwarders = ISC_LIST_INITIALIZER,
.bad = ISC_LIST_INITIALIZER,
.edns = ISC_LIST_INITIALIZER,
.validators = ISC_LIST_INITIALIZER,
.nameservers = DNS_RDATASET_INIT,
.qminrrset = DNS_RDATASET_INIT,
.qminsigrrset = DNS_RDATASET_INIT,
.nsrrset = DNS_RDATASET_INIT,
};
isc_mem_attach(mctx, &fctx->mctx);
@ -4639,6 +4754,19 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
dns_ede_init(fctx->mctx, &fctx->edectx);
fctx->name = dns_fixedname_initname(&fctx->fname);
fctx->nsname = dns_fixedname_initname(&fctx->nsfname);
fctx->domain = dns_fixedname_initname(&fctx->dfname);
fctx->qminname = dns_fixedname_initname(&fctx->qminfname);
fctx->qmindcname = dns_fixedname_initname(&fctx->qmindcfname);
fctx->fwdname = dns_fixedname_initname(&fctx->fwdfname);
dns_name_copy(name, fctx->name);
dns_name_copy(name, fctx->qminname);
fctx->start = isc_time_now();
fctx->now = (isc_stdtime_t)fctx->start.seconds;
/*
* Make fctx->info point to a copy of a formatted string
* "name/type". FCTXTRACE won't work until this is done.
@ -4688,36 +4816,6 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
#endif
urcu_ref_set(&fctx->ref, 1);
ISC_LIST_INIT(fctx->queries);
ISC_LIST_INIT(fctx->finds);
ISC_LIST_INIT(fctx->altfinds);
ISC_LIST_INIT(fctx->forwaddrs);
ISC_LIST_INIT(fctx->altaddrs);
ISC_LIST_INIT(fctx->forwarders);
ISC_LIST_INIT(fctx->bad);
ISC_LIST_INIT(fctx->edns);
ISC_LIST_INIT(fctx->validators);
atomic_init(&fctx->attributes, 0);
fctx->name = dns_fixedname_initname(&fctx->fname);
fctx->nsname = dns_fixedname_initname(&fctx->nsfname);
fctx->domain = dns_fixedname_initname(&fctx->dfname);
fctx->qminname = dns_fixedname_initname(&fctx->qminfname);
fctx->qmindcname = dns_fixedname_initname(&fctx->qmindcfname);
fctx->fwdname = dns_fixedname_initname(&fctx->fwdfname);
dns_name_copy(name, fctx->name);
dns_name_copy(name, fctx->qminname);
dns_rdataset_init(&fctx->nameservers);
dns_rdataset_init(&fctx->qminrrset);
dns_rdataset_init(&fctx->qminsigrrset);
dns_rdataset_init(&fctx->nsrrset);
fctx->start = isc_time_now();
fctx->now = (isc_stdtime_t)fctx->start.seconds;
if (client != NULL) {
isc_sockaddr_format(client, fctx->clientstr,
sizeof(fctx->clientstr));
@ -4791,9 +4889,9 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
fctx->ns_ttl_ok = true;
}
} else {
dns_rdataset_clone(nameservers, &fctx->nameservers);
dns_name_copy(domain, fctx->domain);
dns_name_copy(domain, fctx->qmindcname);
dns_rdataset_clone(nameservers, &fctx->nameservers);
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = true;
}