chg: dev: resolver: refactoring of the dns_fetchresponse_t handling

Instead of cloning fetch responses immediately after inserting them at the head of the `fetch_response` list, defer cloning until the events are actually sent.

This enables to:
- Remove the `fctx->cloned` state;
- Simplify the code by eliminating explicit calls to `clone_result()`;
- Remove the logic that enforced having a fetch response with a `sigrdataset` at the head of the list;
- Remove (just a bit of) locking in some places.

The fetch result is stored directly in new `fctx` properties, but there is no memory increase as those are grouped in an anonymous struct used in a union besides another (bigger) anonymous struct wrapping properties used by qmin fetch only (and, in the case of qmin fetch, those fetch result properties are not needed).

Merge branch 'colin/resolver-cloneresults' into 'main'

See merge request isc-projects/bind9!11458
This commit is contained in:
Colin Vidal 2026-02-10 09:25:09 +01:00
commit a36853d7fd
9 changed files with 229 additions and 294 deletions

View file

@ -6461,8 +6461,8 @@ tat_done(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_resolver_freefresp(&resp);

View file

@ -2586,8 +2586,8 @@ fetch_callback(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
if (atomic_load(&adb->shuttingdown)) {

View file

@ -531,7 +531,7 @@ client_resfind(resctx_t *rctx, dns_fetchresponse_t *resp) {
INSIST(resp != NULL);
INSIST(resp->fetch == rctx->fetch);
dns_resolver_destroyfetch(&rctx->fetch);
db = resp->db;
db = resp->cache;
node = resp->node;
result = resp->result;
vresult = resp->vresult;

View file

@ -82,7 +82,7 @@ struct dns_fetchresponse {
isc_result_t vresult;
dns_edectx_t *edectx;
dns_rdatatype_t qtype;
dns_db_t *db;
dns_db_t *cache;
dns_dbnode_t *node;
dns_rdataset_t *rdataset;
dns_rdataset_t *sigrdataset;

View file

@ -163,8 +163,8 @@ fetch_done(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_resolver_freefresp(&resp);

View file

@ -350,7 +350,6 @@ struct fetchctx {
/*% Locked by lock. */
isc_mutex_t lock;
fetchstate_t state;
bool cloned;
bool spilled;
uint_fast32_t allowed;
uint_fast32_t dropped;
@ -390,21 +389,49 @@ struct fetchctx {
isc_counter_t *qc;
isc_counter_t *gqc;
bool minimized;
dns_fixedname_t fwdfname;
dns_name_t *fwdname;
bool forwarding;
/*%
* These hold state information regarding QNAME minimization.
*/
unsigned int qmin_labels;
isc_result_t qmin_warning;
bool force_qmin_warning;
bool ip6arpaskip;
bool forwarding;
dns_fixedname_t qminfname;
dns_name_t *qminname;
dns_rdatatype_t qmintype;
dns_fetch_t *qminfetch;
dns_rdataset_t qminrrset;
dns_rdataset_t qminsigrrset;
dns_fixedname_t qmindcfname;
dns_name_t *qmindcname;
dns_fixedname_t fwdfname;
dns_name_t *fwdname;
/*%
* These are results from the query that need to be copied to the
* response objects (dns_fetchresponse_t).
*/
isc_result_t resp_result;
dns_dbnode_t *resp_node;
/*%
* These are used both during the QNAME minimization process, and
* also to store final query results to be copied into the fetch
* response. These uses never occur at the same time, so we can
* save space in the fetchctx object by making them a union.
*/
union {
struct {
dns_rdataset_t rdataset;
dns_rdataset_t sigrdataset;
dns_fixedname_t fname;
dns_name_t *name;
dns_fixedname_t dcfname;
dns_name_t *dcname;
} qmin;
struct {
dns_rdataset_t rdataset;
dns_rdataset_t sigrdataset;
dns_fixedname_t fname;
dns_name_t *foundname;
} resp;
};
/*%
* Used to track started ADB finds with event.
@ -806,9 +833,6 @@ fctx__done(fetchctx_t *fctx, isc_result_t result, const char *func,
static void
resume_qmin(void *arg);
static void
clone_results(fetchctx_t *fctx);
static isc_result_t
get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
@ -1615,6 +1639,42 @@ fcount_decr(fetchctx_t *fctx) {
static void
spillattimer_countdown(void *arg);
static void
copy_to_resp(fetchctx_t *fctx, dns_fetchresponse_t *resp) {
resp->result = fctx->resp_result;
dns_name_copy(fctx->resp.foundname, resp->foundname);
dns_db_attach(fctx->cache, &resp->cache);
dns_db_attachnode(fctx->resp_node, &resp->node);
if (dns_rdataset_isassociated(&fctx->resp.rdataset)) {
dns_rdataset_clone(&fctx->resp.rdataset, resp->rdataset);
}
if (resp->sigrdataset != NULL &&
dns_rdataset_isassociated(&fctx->resp.sigrdataset))
{
dns_rdataset_clone(&fctx->resp.sigrdataset, resp->sigrdataset);
}
}
static void
pull_from_resp(dns_fetchresponse_t *resp, fetchctx_t *fctx) {
if (dns_rdataset_isassociated(resp->rdataset)) {
dns_rdataset_clone(resp->rdataset, &fctx->resp.rdataset);
}
if (dns_rdataset_isassociated(resp->sigrdataset)) {
dns_rdataset_clone(resp->sigrdataset, &fctx->resp.sigrdataset);
}
if (resp->cache != NULL) {
INSIST(resp->cache == fctx->cache);
}
if (resp->node != NULL) {
dns_db_attachnode(resp->node, &fctx->resp_node);
}
dns_name_copy(resp->foundname, fctx->resp.foundname);
}
static void
fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
unsigned int count = 0;
@ -1640,6 +1700,9 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
ISC_LIST_FOREACH(fctx->resps, resp, link) {
ISC_LIST_UNLINK(fctx->resps, resp, link);
if (result == ISC_R_SUCCESS) {
copy_to_resp(fctx, resp);
}
count++;
resp->vresult = fctx->vresult;
@ -4200,7 +4263,7 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
char namebuf[DNS_NAME_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
dns_name_format(fctx->qminname, namebuf,
dns_name_format(fctx->qmin.name, namebuf,
sizeof(namebuf));
dns_rdatatype_format(fctx->qmintype, typebuf,
sizeof(typebuf));
@ -4231,12 +4294,12 @@ fctx_try(fetchctx_t *fctx, bool retrying) {
fetchctx_ref(fctx);
result = dns_resolver_createfetch(
fctx->res, fctx->qminname, fctx->qmintype, fctx->domain,
&fctx->nameservers, NULL, NULL, 0,
fctx->res, fctx->qmin.name, fctx->qmintype,
fctx->domain, &fctx->nameservers, NULL, NULL, 0,
options | DNS_FETCHOPT_QMINFETCH, 0, fctx->qc,
fctx->gqc, fctx, fctx->loop, resume_qmin, fctx,
&fctx->edectx, &fctx->qminrrset, &fctx->qminsigrrset,
&fctx->qminfetch);
&fctx->edectx, &fctx->qmin.rdataset,
&fctx->qmin.sigrdataset, &fctx->qminfetch);
if (result != ISC_R_SUCCESS) {
fetchctx_unref(fctx);
goto done;
@ -4288,6 +4351,26 @@ done:
}
}
static void
clear_resp(dns_fetchresponse_t **respp) {
dns_fetchresponse_t *resp = *respp;
if (resp == NULL) {
return;
}
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_rdataset_cleanup(resp->rdataset);
dns_rdataset_cleanup(resp->sigrdataset);
dns_resolver_freefresp(respp);
}
static void
resume_qmin(void *arg) {
dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
@ -4297,10 +4380,6 @@ resume_qmin(void *arg) {
unsigned int findoptions = 0;
dns_name_t *fname = NULL, *dcname = NULL;
dns_fixedname_t ffixed, dcfixed;
dns_rdataset_t rdataset;
dns_rdataset_t sigrdataset;
dns_db_t *db = NULL;
dns_dbnode_t *node = NULL;
REQUIRE(VALID_FCTX(fctx));
@ -4313,32 +4392,8 @@ resume_qmin(void *arg) {
fname = dns_fixedname_initname(&ffixed);
dcname = dns_fixedname_initname(&dcfixed);
dns_rdataset_init(&rdataset);
dns_rdataset_init(&sigrdataset);
if (resp->node != NULL) {
dns_db_attachnode(resp->node, &node);
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_attach(resp->db, &db);
dns_db_detach(&resp->db);
}
if (dns_rdataset_isassociated(resp->rdataset)) {
dns_rdataset_clone(resp->rdataset, &rdataset);
dns_rdataset_disassociate(resp->rdataset);
}
if (dns_rdataset_isassociated(resp->sigrdataset)) {
dns_rdataset_clone(resp->sigrdataset, &sigrdataset);
dns_rdataset_disassociate(resp->sigrdataset);
}
dns_name_copy(resp->foundname, fname);
result = resp->result;
dns_resolver_freefresp(&resp);
LOCK(&fctx->lock);
if (SHUTTINGDOWN(fctx)) {
result = ISC_R_SHUTTINGDOWN;
@ -4370,31 +4425,8 @@ resume_qmin(void *arg) {
if (result == DNS_R_NXDOMAIN &&
fctx->qmin_labels == dns_name_countlabels(fctx->name))
{
LOCK(&fctx->lock);
resp = ISC_LIST_HEAD(fctx->resps);
if (resp != NULL) {
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_clone(&rdataset,
resp->rdataset);
}
if (dns_rdataset_isassociated(&sigrdataset) &&
resp->sigrdataset != NULL)
{
dns_rdataset_clone(&sigrdataset,
resp->sigrdataset);
}
if (db != NULL) {
dns_db_attach(db, &resp->db);
}
if (node != NULL) {
dns_db_attachnode(node, &resp->node);
}
dns_name_copy(fname, resp->foundname);
clone_results(fctx);
UNLOCK(&fctx->lock);
goto cleanup;
}
UNLOCK(&fctx->lock);
pull_from_resp(resp, fctx);
goto cleanup;
}
/* ...or disable minimization in relaxed mode */
@ -4437,39 +4469,23 @@ resume_qmin(void *arg) {
fctx->type != dns_rdatatype_sig &&
fctx->type != dns_rdatatype_rrsig)
{
LOCK(&fctx->lock);
resp = ISC_LIST_HEAD(fctx->resps);
if (resp != NULL) {
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_clone(&rdataset,
resp->rdataset);
}
if (dns_rdataset_isassociated(&sigrdataset) &&
resp->sigrdataset != NULL)
{
dns_rdataset_clone(&sigrdataset,
resp->sigrdataset);
}
if (db != NULL) {
dns_db_attach(db, &resp->db);
}
if (node != NULL) {
dns_db_attachnode(node, &resp->node);
}
dns_name_copy(fname, resp->foundname);
clone_results(fctx);
if (result == DNS_R_CNAME &&
dns_rdataset_isassociated(&rdataset) &&
fctx->type == dns_rdatatype_cname)
{
fctx_success_unref(fctx);
result = ISC_R_SUCCESS;
} else {
UNLOCK(&fctx->lock);
}
goto cleanup;
pull_from_resp(resp, fctx);
if (result == DNS_R_CNAME &&
dns_rdataset_isassociated(resp->rdataset) &&
fctx->type == dns_rdatatype_cname)
{
LOCK(&fctx->lock);
fctx_success_unref(fctx);
result = ISC_R_SUCCESS;
/*
* `fctx_success_unref()` directly goes into the
* `fctx__done()` flow which expect fctx to be
* locked in case of success.
*/
}
UNLOCK(&fctx->lock);
goto cleanup;
}
/*
@ -4491,6 +4507,7 @@ resume_qmin(void *arg) {
break;
}
clear_resp(&resp);
dns_rdataset_cleanup(&fctx->nameservers);
if (dns_rdatatype_atparent(fctx->type)) {
@ -4510,7 +4527,7 @@ resume_qmin(void *arg) {
CHECK(fcount_incr(fctx, false));
dns_name_copy(dcname, fctx->qmindcname);
dns_name_copy(dcname, fctx->qmin.dcname);
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = true;
@ -4530,14 +4547,8 @@ resume_qmin(void *arg) {
fctx_try(fctx, true);
cleanup:
if (node != NULL) {
dns_db_detachnode(&node);
}
if (db != NULL) {
dns_db_detach(&db);
}
dns_rdataset_cleanup(&rdataset);
dns_rdataset_cleanup(&sigrdataset);
clear_resp(&resp);
if (result != ISC_R_SUCCESS) {
/* An error occurred, tear down whole fctx */
fctx_failure_unref(fctx, result);
@ -4623,6 +4634,12 @@ fctx__destroy(fetchctx_t *fctx, const char *func, const char *file,
dns_ede_invalidate(&fctx->edectx);
if (fctx->resp_node != NULL) {
dns_db_detachnode(&fctx->resp_node);
}
dns_rdataset_cleanup(&fctx->resp.rdataset);
dns_rdataset_cleanup(&fctx->resp.sigrdataset);
isc_mem_free(fctx->mctx, fctx->info);
call_rcu(&fctx->rcu_head, fctx_destroy_rcu);
@ -4719,16 +4736,7 @@ fctx_add_event(fetchctx_t *fctx, isc_loop_t *loop, const isc_sockaddr_t *client,
isc_mem_attach(fctx->mctx, &resp->mctx);
resp->foundname = dns_fixedname_initname(&resp->fname);
/*
* Store the sigrdataset in the first resp in case it is needed
* by any of the events.
*/
if (resp->sigrdataset != NULL) {
ISC_LIST_PREPEND(fctx->resps, resp, link);
} else {
ISC_LIST_APPEND(fctx->resps, resp, link);
}
ISC_LIST_APPEND(fctx->resps, resp, link);
}
static void
@ -4789,31 +4797,30 @@ fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
REQUIRE(fctxp != NULL && *fctxp == NULL);
fctx = isc_mem_get(mctx, sizeof(*fctx));
*fctx = (fetchctx_t){
.type = type,
.qmintype = type,
.options = options,
.tid = isc_tid(),
.state = fetchstate_active,
.depth = depth,
.qmin_labels = 1,
.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,
};
*fctx = (fetchctx_t){ .type = type,
.qmintype = type,
.options = options,
.tid = isc_tid(),
.state = fetchstate_active,
.depth = depth,
.qmin_labels = 1,
.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,
.nsrrset = DNS_RDATASET_INIT,
.resp_result = DNS_R_SERVFAIL,
.qmin.rdataset = DNS_RDATASET_INIT,
.qmin.sigrdataset = DNS_RDATASET_INIT };
isc_mem_attach(mctx, &fctx->mctx);
dns_resolver_attach(res, &fctx->res);
@ -4825,12 +4832,12 @@ fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
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->qmin.name = dns_fixedname_initname(&fctx->qmin.fname);
fctx->qmin.dcname = dns_fixedname_initname(&fctx->qmin.dcfname);
fctx->fwdname = dns_fixedname_initname(&fctx->fwdfname);
dns_name_copy(name, fctx->name);
dns_name_copy(name, fctx->qminname);
dns_name_copy(name, fctx->qmin.name);
fctx->start = isc_time_now();
fctx->now = (isc_stdtime_t)fctx->start.seconds;
@ -4926,7 +4933,7 @@ fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
* domain.
*/
dns_name_copy(fctx->fwdname, fctx->domain);
dns_name_copy(fctx->fwdname, fctx->qmindcname);
dns_name_copy(fctx->fwdname, fctx->qmin.dcname);
/*
* Disable query minimization
*/
@ -4952,14 +4959,14 @@ fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
}
dns_name_copy(fctx->fwdname, fctx->domain);
dns_name_copy(dcname, fctx->qmindcname);
dns_name_copy(dcname, fctx->qmin.dcname);
fctx->ns_ttl = fctx->nameservers.ttl;
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_name_copy(domain, fctx->qmin.dcname);
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = true;
}
@ -5243,50 +5250,6 @@ same_question(fetchctx_t *fctx, dns_message_t *message) {
return ISC_R_SUCCESS;
}
static void
clone_results(fetchctx_t *fctx) {
dns_fetchresponse_t *hresp = NULL;
REQUIRE(!ISC_LIST_EMPTY(fctx->resps));
/*
* Set up any other resps to have the same data as the first.
* Caller must be holding the appropriate lock.
*/
FCTXTRACE("clone_results");
ISC_LIST_FOREACH(fctx->resps, resp, link) {
/* This is the head resp; keep a pointer and move on */
if (hresp == NULL) {
hresp = ISC_LIST_HEAD(fctx->resps);
FCTXTRACEN("clone_results", hresp->foundname,
hresp->result);
continue;
}
resp->result = hresp->result;
dns_name_copy(hresp->foundname, resp->foundname);
dns_db_attach(hresp->db, &resp->db);
dns_db_attachnode(hresp->node, &resp->node);
INSIST(hresp->rdataset != NULL && resp->rdataset != NULL);
if (dns_rdataset_isassociated(hresp->rdataset)) {
dns_rdataset_clone(hresp->rdataset, resp->rdataset);
}
INSIST(hresp->sigrdataset != NULL || resp->sigrdataset == NULL);
if (resp->sigrdataset != NULL && hresp->sigrdataset != NULL &&
dns_rdataset_isassociated(hresp->sigrdataset))
{
dns_rdataset_clone(hresp->sigrdataset,
resp->sigrdataset);
}
}
fctx->cloned = true;
}
#define CACHE(r) (((r)->attributes.cache))
#define ANSWER(r) (((r)->attributes.answer))
#define ANSWERSIG(r) (((r)->attributes.answersig))
@ -5382,27 +5345,28 @@ has_000_label(dns_rdataset_t *nsecset) {
return false;
}
static isc_result_t
fctx_setresult(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
isc_result_t eresult = ISC_R_SUCCESS;
static void
fctx_setresult(fetchctx_t *fctx) {
isc_result_t result = ISC_R_SUCCESS;
dns_rdataset_t *rdataset = &fctx->resp.rdataset;
if (NEGATIVE(rdataset)) {
eresult = NXDOMAIN(rdataset) ? DNS_R_NCACHENXDOMAIN
: DNS_R_NCACHENXRRSET;
} else if (eresult == ISC_R_SUCCESS && rdataset->type != fctx->type) {
result = NXDOMAIN(rdataset) ? DNS_R_NCACHENXDOMAIN
: DNS_R_NCACHENXRRSET;
} else if (result == ISC_R_SUCCESS && rdataset->type != fctx->type) {
switch (rdataset->type) {
case dns_rdatatype_cname:
eresult = DNS_R_CNAME;
result = DNS_R_CNAME;
break;
case dns_rdatatype_dname:
eresult = DNS_R_DNAME;
result = DNS_R_DNAME;
break;
default:
break;
}
}
return eresult;
fctx->resp_result = result;
}
static inline dns_trust_t
@ -5617,7 +5581,6 @@ validated(void *arg) {
dns_validator_t *nextval = NULL;
dns_adbaddrinfo_t *addrinfo = NULL;
dns_dbnode_t *node = NULL;
dns_fetchresponse_t *resp = NULL;
dns_rdataset_t *ardataset = NULL, *asigrdataset = NULL;
dns_message_t *message = NULL;
fetchctx_t *fctx = NULL;
@ -5698,12 +5661,9 @@ validated(void *arg) {
* we pass an rdataset back to the caller. Otherwise the caller
* iterates the node.
*/
resp = ISC_LIST_HEAD(fctx->resps);
if (resp != NULL &&
(negative || chaining || !dns_rdatatype_ismulti(fctx->type)))
{
ardataset = resp->rdataset;
asigrdataset = resp->sigrdataset;
if (negative || chaining || !dns_rdatatype_ismulti(fctx->type)) {
ardataset = &fctx->resp.rdataset;
asigrdataset = &fctx->resp.sigrdataset;
}
/*
@ -5787,15 +5747,11 @@ answer_response:
* We're responding with an answer, positive or negative,
* not an error.
*/
if (resp != NULL) {
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
resp->result = fctx_setresult(fctx, resp->rdataset);
dns_name_copy(val->name, resp->foundname);
dns_db_attach(fctx->cache, &resp->db);
dns_db_transfernode(fctx->cache, &node, &resp->node);
clone_results(fctx);
}
fctx_setresult(fctx);
dns_name_copy(val->name, fctx->resp.foundname);
dns_db_transfernode(fctx->cache, &node, &fctx->resp_node);
done = true;
@ -6021,7 +5977,6 @@ rctx_cache_secure(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
fetchctx_t *fctx = rctx->fctx;
resquery_t *query = rctx->query;
dns_rdataset_t *ardataset = NULL, *asigset = NULL;
dns_fetchresponse_t *resp = ISC_LIST_HEAD(fctx->resps);
/*
* RRSIGs are validated as part of validating the type they cover.
@ -6086,12 +6041,11 @@ rctx_cache_secure(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
* but we got a CNAME/DNAME - then we need to
* set up rdatasets to send back to the caller.
*/
if (resp != NULL &&
(!dns_rdatatype_ismulti(fctx->type) ||
CHAINING(rdataset)))
if (!dns_rdatatype_ismulti(fctx->type) ||
CHAINING(rdataset))
{
ardataset = resp->rdataset;
asigset = resp->sigrdataset;
ardataset = &fctx->resp.rdataset;
asigset = &fctx->resp.sigrdataset;
}
}
@ -6114,7 +6068,6 @@ rctx_cache_insecure(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
dns_rdataset_t *sigrdataset) {
isc_result_t result;
fetchctx_t *fctx = rctx->fctx;
dns_fetchresponse_t *resp = ISC_LIST_HEAD(fctx->resps);
dns_rdataset_t *added = NULL;
/*
@ -6122,13 +6075,11 @@ rctx_cache_insecure(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
* CNAME/DNAME - then we need to set up an rdataset to send
* back to the caller.
*/
if (resp != NULL &&
(!dns_rdatatype_ismulti(fctx->type) || CHAINING(rdataset)))
{
if (!dns_rdatatype_ismulti(fctx->type) || CHAINING(rdataset)) {
if (ANSWER(rdataset)) {
added = resp->rdataset;
added = &fctx->resp.rdataset;
} else if (ANSWERSIG(rdataset)) {
added = resp->sigrdataset;
added = &fctx->resp.sigrdataset;
}
}
@ -6238,22 +6189,14 @@ rctx_cachename(respctx_t *rctx, dns_message_t *message, dns_name_t *name) {
* it back to the caller.
*/
if (!need_validation && name->attributes.answer && !HAVE_ANSWER(fctx)) {
dns_fetchresponse_t *resp = ISC_LIST_HEAD(fctx->resps);
if (resp != NULL) {
isc_result_t eresult = ISC_R_SUCCESS;
fctx->resp_result = ISC_R_SUCCESS;
if (dns_rdataset_isassociated(resp->rdataset)) {
eresult = fctx_setresult(fctx, resp->rdataset);
}
resp->result = eresult;
dns_name_copy(name, resp->foundname);
dns_db_attach(fctx->cache, &resp->db);
dns_db_transfernode(fctx->cache, &node, &resp->node);
clone_results(fctx);
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
if (dns_rdataset_isassociated(&fctx->resp.rdataset)) {
fctx_setresult(fctx);
}
dns_name_copy(name, fctx->resp.foundname);
dns_db_transfernode(fctx->cache, &node, &fctx->resp_node);
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
}
cleanup:
@ -6372,7 +6315,6 @@ rctx_ncache(respctx_t *rctx) {
dns_message_t *message = rctx->query->rmessage;
dns_adbaddrinfo_t *addrinfo = rctx->query->addrinfo;
dns_dbnode_t *node = NULL;
dns_fetchresponse_t *resp = NULL;
dns_rdataset_t *added = NULL;
FCTXTRACE("rctx_ncache");
@ -6425,9 +6367,8 @@ rctx_ncache(respctx_t *rctx) {
* Cache the negative answer, and copy it into the fetch response.
*/
LOCK(&fctx->lock);
resp = ISC_LIST_HEAD(fctx->resps);
if (!HAVE_ANSWER(fctx) && resp != NULL) {
added = resp->rdataset;
if (!HAVE_ANSWER(fctx)) {
added = &fctx->resp.rdataset;
}
result = negcache(message, fctx, name, rctx->now, false, false, added,
@ -6437,13 +6378,9 @@ rctx_ncache(respctx_t *rctx) {
}
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
if (resp != NULL) {
resp->result = fctx_setresult(fctx, resp->rdataset);
dns_name_copy(name, resp->foundname);
dns_db_attach(fctx->cache, &resp->db);
dns_db_transfernode(fctx->cache, &node, &resp->node);
clone_results(fctx);
}
fctx_setresult(fctx);
dns_name_copy(name, fctx->resp.foundname);
dns_db_transfernode(fctx->cache, &node, &fctx->resp_node);
unlock:
UNLOCK(&fctx->lock);
@ -6890,8 +6827,8 @@ resume_dslookup(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
/* Preserve data from resp before freeing it. */
@ -9103,7 +9040,7 @@ rctx_referral(respctx_t *rctx) {
dns_name_copy(rctx->ns_name, fctx->domain);
if ((fctx->options & DNS_FETCHOPT_QMINIMIZE) != 0) {
dns_name_copy(rctx->ns_name, fctx->qmindcname);
dns_name_copy(rctx->ns_name, fctx->qmin.dcname);
fctx_minimize_qname(fctx);
}
@ -9243,7 +9180,7 @@ rctx_nextserver(respctx_t *rctx, dns_message_t *message,
fcount_decr(fctx);
dns_name_copy(fname, fctx->domain);
dns_name_copy(dcname, fctx->qmindcname);
dns_name_copy(dcname, fctx->qmin.dcname);
result = fcount_incr(fctx, true);
if (result != ISC_R_SUCCESS) {
@ -9867,8 +9804,8 @@ prime_done(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_rdataset_cleanup(resp->rdataset);
INSIST(resp->sigrdataset == NULL);
@ -10000,7 +9937,7 @@ fctx_minimize_qname(fetchctx_t *fctx) {
dns_name_init(&name);
dlabels = dns_name_countlabels(fctx->qmindcname);
dlabels = dns_name_countlabels(fctx->qmin.dcname);
nlabels = dns_name_countlabels(fctx->name);
if (dlabels > fctx->qmin_labels) {
@ -10073,18 +10010,18 @@ fctx_minimize_qname(fetchctx_t *fctx) {
}
if (fctx->qmin_labels < nlabels) {
dns_name_copy(&name, fctx->qminname);
dns_name_copy(&name, fctx->qmin.name);
fctx->qmintype = dns_rdatatype_ns;
fctx->minimized = true;
} else {
/* Minimization is done, we'll ask for whole qname */
dns_name_copy(fctx->name, fctx->qminname);
dns_name_copy(fctx->name, fctx->qmin.name);
fctx->qmintype = fctx->type;
fctx->minimized = false;
}
char domainbuf[DNS_NAME_FORMATSIZE];
dns_name_format(fctx->qminname, domainbuf, sizeof(domainbuf));
dns_name_format(fctx->qmin.name, domainbuf, sizeof(domainbuf));
isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
ISC_LOG_DEBUG(5),
"QNAME minimization - %s minimized, qmintype %d "
@ -10164,7 +10101,7 @@ get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
goto create;
}
if (SHUTTINGDOWN(fctx) || fctx->cloned) {
if (SHUTTINGDOWN(fctx)) {
/* The fctx will get deleted either here or in fctx__done() */
cds_lfht_del(res->fctxs_ht, &fctx->ht_node);
@ -10419,7 +10356,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
* Sanity check: the caller should have gotten its event before
* trying to destroy the fetch.
*/
if (fctx->state != fetchstate_done) {
if (!SHUTTINGDOWN(fctx)) {
ISC_LIST_FOREACH(fctx->resps, resp, link) {
RUNTIME_CHECK(resp->fetch != fetch);
}
@ -10731,9 +10668,7 @@ dns_resolver_dumpfetches(dns_resolver_t *res, isc_statsformat_t format,
dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
fprintf(fp, "/%s (%s), 0x%x: started %s, ", typebuf,
fctx->state == fetchstate_done ? "done"
: fctx->cloned ? "cloned"
: "active",
fctx->state == fetchstate_done ? "done" : "active",
fctx->options, timebuf);
ISC_LIST_FOREACH(fctx->resps, resp, link) {
@ -10892,7 +10827,7 @@ dns_resolver_freefresp(dns_fetchresponse_t **frespp) {
}
dns_fetchresponse_t *fresp = *frespp;
*frespp = NULL;
isc_mem_putanddetach(&fresp->mctx, fresp, sizeof(*fresp));
}

View file

@ -427,8 +427,8 @@ fetch_callback_dnskey(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_rdataset_cleanup(&val->fsigrdataset);
@ -520,8 +520,8 @@ fetch_callback_ds(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_rdataset_cleanup(&val->fsigrdataset);

View file

@ -148,8 +148,8 @@ dns_zonefetch_done(void *arg) {
if (resp->node != NULL) {
dns_db_detachnode(&resp->node);
}
if (resp->db != NULL) {
dns_db_detach(&resp->db);
if (resp->cache != NULL) {
dns_db_detach(&resp->cache);
}
dns_resolver_destroyfetch(&fetch->fetch);

View file

@ -2591,8 +2591,8 @@ free_fresp(ns_client_t *client, dns_fetchresponse_t **frespp) {
if (fresp->node != NULL) {
dns_db_detachnode(&fresp->node);
}
if (fresp->db != NULL) {
dns_db_detach(&fresp->db);
if (fresp->cache != NULL) {
dns_db_detach(&fresp->cache);
}
if (fresp->rdataset != NULL) {
ns_client_putrdataset(client, &fresp->rdataset);
@ -6385,7 +6385,7 @@ query_resume(query_ctx_t *qctx) {
if (qctx->fresp->node != NULL) {
dns_db_detachnode(&qctx->fresp->node);
}
SAVE(qctx->rpz_st->r.db, qctx->fresp->db);
SAVE(qctx->rpz_st->r.db, qctx->fresp->cache);
qctx->rpz_st->r.r_type = qctx->fresp->qtype;
SAVE(qctx->rpz_st->r.r_rdataset, qctx->fresp->rdataset);
ns_client_putrdataset(qctx->client, &qctx->fresp->sigrdataset);
@ -6423,15 +6423,15 @@ query_resume(query_ctx_t *qctx) {
if (qctx->fresp->node != NULL) {
dns_db_detachnode(&qctx->fresp->node);
}
if (qctx->fresp->db != NULL) {
dns_db_detach(&qctx->fresp->db);
if (qctx->fresp->cache != NULL) {
dns_db_detach(&qctx->fresp->cache);
}
} else {
CCTRACE(ISC_LOG_DEBUG(3), "resume from normal recursion");
qctx->authoritative = false;
qctx->qtype = qctx->fresp->qtype;
SAVE(qctx->db, qctx->fresp->db);
SAVE(qctx->db, qctx->fresp->cache);
SAVE(qctx->node, qctx->fresp->node);
SAVE(qctx->rdataset, qctx->fresp->rdataset);
SAVE(qctx->sigrdataset, qctx->fresp->sigrdataset);