mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
rename and refactor cache_name() and related functions
- renamed cache_message() to rctx_cachemessage() - renamed cache_name() to rctx_cachename() - merged ncache_message() into rctx_ncache() - split out a new function, rctx_cacherdataset(), which is called by rctx_cachename() in a loop to process each of the rdatasets associated with the name.
This commit is contained in:
@@ -842,6 +842,9 @@ typedef struct respctx {
|
|||||||
* response */
|
* response */
|
||||||
|
|
||||||
dns_rdataset_t *opt; /* OPT rdataset */
|
dns_rdataset_t *opt; /* OPT rdataset */
|
||||||
|
|
||||||
|
dns_rdataset_t *vrdataset;
|
||||||
|
dns_rdataset_t *vsigrdataset;
|
||||||
} respctx_t;
|
} respctx_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -958,7 +961,7 @@ set_stats(dns_resolver_t *res, isc_statscounter_t counter, uint64_t val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static void
|
||||||
valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
||||||
dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset,
|
dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *rdataset,
|
||||||
dns_rdataset_t *sigrdataset) {
|
dns_rdataset_t *sigrdataset) {
|
||||||
@@ -985,8 +988,6 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
|||||||
|
|
||||||
if (!ISC_LIST_EMPTY(fctx->validators)) {
|
if (!ISC_LIST_EMPTY(fctx->validators)) {
|
||||||
valoptions |= DNS_VALIDATOR_DEFER;
|
valoptions |= DNS_VALIDATOR_DEFER;
|
||||||
} else {
|
|
||||||
valoptions &= ~DNS_VALIDATOR_DEFER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_validator_create(
|
result = dns_validator_create(
|
||||||
@@ -996,7 +997,6 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
|||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
inc_stats(fctx->res, dns_resstatscounter_val);
|
inc_stats(fctx->res, dns_resstatscounter_val);
|
||||||
ISC_LIST_APPEND(fctx->validators, validator, link);
|
ISC_LIST_APPEND(fctx->validators, validator, link);
|
||||||
return ISC_R_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2248,8 +2248,8 @@ compute_cc(const resquery_t *query, uint8_t *cookie, const size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
issecuredomain(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
|
issecuredomain(fetchctx_t *fctx, const dns_name_t *name, dns_rdatatype_t type,
|
||||||
isc_stdtime_t now, bool checknta, bool *ntap) {
|
isc_stdtime_t now, bool *ntap) {
|
||||||
dns_name_t suffix;
|
dns_name_t suffix;
|
||||||
unsigned int labels;
|
unsigned int labels;
|
||||||
|
|
||||||
@@ -2266,7 +2266,8 @@ issecuredomain(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
|
|||||||
name = &suffix;
|
name = &suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dns_view_issecuredomain(view, name, now, checknta, ntap);
|
return dns_view_issecuredomain(fctx->res->view, name, now,
|
||||||
|
CHECKNTA(fctx), ntap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
@@ -5184,7 +5185,7 @@ validated(void *arg) {
|
|||||||
dns_adbaddrinfo_t *addrinfo = NULL;
|
dns_adbaddrinfo_t *addrinfo = NULL;
|
||||||
dns_dbnode_t *node = NULL;
|
dns_dbnode_t *node = NULL;
|
||||||
dns_dbnode_t *nsnode = NULL;
|
dns_dbnode_t *nsnode = NULL;
|
||||||
dns_fetchresponse_t *hresp = NULL;
|
dns_fetchresponse_t *resp = NULL;
|
||||||
dns_rdataset_t *ardataset = NULL;
|
dns_rdataset_t *ardataset = NULL;
|
||||||
dns_rdataset_t *asigrdataset = NULL;
|
dns_rdataset_t *asigrdataset = NULL;
|
||||||
dns_resolver_t *res = NULL;
|
dns_resolver_t *res = NULL;
|
||||||
@@ -5196,7 +5197,7 @@ validated(void *arg) {
|
|||||||
isc_result_t eresult = ISC_R_SUCCESS;
|
isc_result_t eresult = ISC_R_SUCCESS;
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
isc_stdtime_t now;
|
isc_stdtime_t now;
|
||||||
unsigned int options;
|
unsigned int options = 0;
|
||||||
dns_fixedname_t fwild;
|
dns_fixedname_t fwild;
|
||||||
dns_name_t *wild = NULL;
|
dns_name_t *wild = NULL;
|
||||||
dns_message_t *message = NULL;
|
dns_message_t *message = NULL;
|
||||||
@@ -5276,8 +5277,8 @@ validated(void *arg) {
|
|||||||
* started by a query with cd set)
|
* started by a query with cd set)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
hresp = ISC_LIST_HEAD(fctx->resps);
|
resp = ISC_LIST_HEAD(fctx->resps);
|
||||||
if (hresp != NULL) {
|
if (resp != NULL) {
|
||||||
if (!negative && !chaining && dns_rdatatype_ismulti(fctx->type))
|
if (!negative && !chaining && dns_rdatatype_ismulti(fctx->type))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -5285,8 +5286,8 @@ validated(void *arg) {
|
|||||||
* will iterate the node.
|
* will iterate the node.
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
ardataset = hresp->rdataset;
|
ardataset = resp->rdataset;
|
||||||
asigrdataset = hresp->sigrdataset;
|
asigrdataset = resp->sigrdataset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5406,21 +5407,18 @@ validated(void *arg) {
|
|||||||
goto noanswer_response;
|
goto noanswer_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
options = 0;
|
|
||||||
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
|
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
|
||||||
options = DNS_DBADD_PREFETCH;
|
options = DNS_DBADD_PREFETCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_db_addrdataset(fctx->cache, node, NULL, now, val->rdataset,
|
result = dns_db_addrdataset(fctx->cache, node, NULL, now, val->rdataset,
|
||||||
options, ardataset);
|
options, ardataset);
|
||||||
if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
|
if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
|
||||||
goto noanswer_response;
|
goto noanswer_response;
|
||||||
}
|
}
|
||||||
if (ardataset != NULL && NEGATIVE(ardataset)) {
|
if (ardataset != NULL && NEGATIVE(ardataset)) {
|
||||||
if (NXDOMAIN(ardataset)) {
|
eresult = NXDOMAIN(ardataset) ? DNS_R_NCACHENXDOMAIN
|
||||||
eresult = DNS_R_NCACHENXDOMAIN;
|
: DNS_R_NCACHENXRRSET;
|
||||||
} else {
|
|
||||||
eresult = DNS_R_NCACHENXRRSET;
|
|
||||||
}
|
|
||||||
} else if (val->sigrdataset != NULL) {
|
} else if (val->sigrdataset != NULL) {
|
||||||
result = dns_db_addrdataset(fctx->cache, node, NULL, now,
|
result = dns_db_addrdataset(fctx->cache, node, NULL, now,
|
||||||
val->sigrdataset, options,
|
val->sigrdataset, options,
|
||||||
@@ -5446,10 +5444,10 @@ validated(void *arg) {
|
|||||||
if (!ISC_LIST_EMPTY(fctx->validators)) {
|
if (!ISC_LIST_EMPTY(fctx->validators)) {
|
||||||
INSIST(!negative);
|
INSIST(!negative);
|
||||||
INSIST(dns_rdatatype_ismulti(fctx->type));
|
INSIST(dns_rdatatype_ismulti(fctx->type));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't send a response yet - we have
|
* Don't send a response yet - we have more rdatasets
|
||||||
* more rdatasets that still need to
|
* that still need to be validated.
|
||||||
* be validated.
|
|
||||||
*/
|
*/
|
||||||
dns_db_detachnode(fctx->cache, &node);
|
dns_db_detachnode(fctx->cache, &node);
|
||||||
UNLOCK(&fctx->lock);
|
UNLOCK(&fctx->lock);
|
||||||
@@ -5576,6 +5574,10 @@ answer_response:
|
|||||||
|
|
||||||
result = ISC_R_SUCCESS;
|
result = ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
if (HAVE_ANSWER(fctx) || resp == NULL) {
|
||||||
|
goto noanswer_response;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Respond with an answer, positive or negative,
|
* Respond with an answer, positive or negative,
|
||||||
* as opposed to an error. 'node' must be non-NULL.
|
* as opposed to an error. 'node' must be non-NULL.
|
||||||
@@ -5583,19 +5585,15 @@ answer_response:
|
|||||||
|
|
||||||
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
|
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
|
||||||
|
|
||||||
if (hresp != NULL) {
|
INSIST(resp->rdataset != NULL);
|
||||||
/*
|
if (dns_rdataset_isassociated(resp->rdataset)) {
|
||||||
* Negative results must be indicated in val->result.
|
if (NEGATIVE(resp->rdataset)) {
|
||||||
*/
|
|
||||||
INSIST(hresp->rdataset != NULL);
|
|
||||||
if (dns_rdataset_isassociated(hresp->rdataset)) {
|
|
||||||
if (NEGATIVE(hresp->rdataset)) {
|
|
||||||
INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
|
INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
|
||||||
eresult == DNS_R_NCACHENXRRSET);
|
eresult == DNS_R_NCACHENXRRSET);
|
||||||
} else if (eresult == ISC_R_SUCCESS &&
|
} else if (eresult == ISC_R_SUCCESS &&
|
||||||
hresp->rdataset->type != fctx->type)
|
resp->rdataset->type != fctx->type)
|
||||||
{
|
{
|
||||||
switch (hresp->rdataset->type) {
|
switch (resp->rdataset->type) {
|
||||||
case dns_rdatatype_cname:
|
case dns_rdatatype_cname:
|
||||||
eresult = DNS_R_CNAME;
|
eresult = DNS_R_CNAME;
|
||||||
break;
|
break;
|
||||||
@@ -5608,12 +5606,11 @@ answer_response:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hresp->result = eresult;
|
resp->result = eresult;
|
||||||
dns_name_copy(val->name, hresp->foundname);
|
dns_name_copy(val->name, resp->foundname);
|
||||||
dns_db_attach(fctx->cache, &hresp->db);
|
dns_db_attach(fctx->cache, &resp->db);
|
||||||
dns_db_transfernode(fctx->cache, &node, &hresp->node);
|
dns_db_transfernode(fctx->cache, &node, &resp->node);
|
||||||
clone_results(fctx);
|
clone_results(fctx);
|
||||||
}
|
|
||||||
|
|
||||||
noanswer_response:
|
noanswer_response:
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
@@ -5847,19 +5844,203 @@ fixttls(dns_view_t *view, dns_rdataset_t *rdataset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
rctx_cacherdataset(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
|
||||||
dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) {
|
dns_dbnode_t *node, dns_rdataset_t *rdataset,
|
||||||
|
dns_rdataset_t *sigrdataset, bool secure_domain,
|
||||||
|
bool need_validation) {
|
||||||
|
isc_result_t result;
|
||||||
|
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);
|
||||||
|
unsigned int options = 0;
|
||||||
|
|
||||||
|
if (secure_domain && rdataset->trust != dns_trust_glue) {
|
||||||
|
/*
|
||||||
|
* RRSIGs are validated as part of validating
|
||||||
|
* the type they cover.
|
||||||
|
*/
|
||||||
|
if (rdataset->type == dns_rdatatype_rrsig) {
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore unrelated non-answer rdatasets that are
|
||||||
|
* missing signatures.
|
||||||
|
*/
|
||||||
|
if (sigrdataset == NULL && need_validation && !ANSWER(rdataset))
|
||||||
|
{
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark this rdataset/sigrdataset pair as pending data.
|
||||||
|
* Track whether it was additional or not.
|
||||||
|
*/
|
||||||
|
if (rdataset->trust == dns_trust_additional) {
|
||||||
|
rdataset->trust = dns_trust_pending_additional;
|
||||||
|
} else {
|
||||||
|
rdataset->trust = dns_trust_pending_answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sigrdataset != NULL) {
|
||||||
|
sigrdataset->trust = rdataset->trust;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ANSWER(rdataset) && need_validation) {
|
||||||
|
if (!dns_rdatatype_ismulti(fctx->type)) {
|
||||||
|
/*
|
||||||
|
* This is The Answer. We will validate
|
||||||
|
* it, but first we cache the rest of the
|
||||||
|
* response - it may contain useful keys.
|
||||||
|
*/
|
||||||
|
INSIST(rctx->vrdataset == NULL &&
|
||||||
|
rctx->vsigrdataset == NULL);
|
||||||
|
rctx->vrdataset = rdataset;
|
||||||
|
rctx->vsigrdataset = sigrdataset;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is one of (potentially) multiple
|
||||||
|
* answers to an ANY query. To keep things
|
||||||
|
* simple, we just start the validator
|
||||||
|
* right away rather than caching first and
|
||||||
|
* having to remember which rdatasets
|
||||||
|
* needed validation.
|
||||||
|
*/
|
||||||
|
valcreate(fctx, message, query->addrinfo, name,
|
||||||
|
rdataset->type, rdataset,
|
||||||
|
sigrdataset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ANSWER(rdataset)) {
|
||||||
|
/*
|
||||||
|
* We're not validating, but the client might
|
||||||
|
* be, so look for the NOQNAME proof.
|
||||||
|
*/
|
||||||
|
findnoqname(fctx, message, name, rdataset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this was not an ANY/RRSIG/SIG query,
|
||||||
|
* or if it was but we got a CNAME/DNAME,
|
||||||
|
* then we need to set up rdatasets to
|
||||||
|
* send back to the caller.
|
||||||
|
*/
|
||||||
|
if (!dns_rdatatype_ismulti(fctx->type) ||
|
||||||
|
CHAINING(rdataset))
|
||||||
|
{
|
||||||
|
ardataset = resp->rdataset;
|
||||||
|
asigset = resp->sigrdataset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
|
||||||
|
options = DNS_DBADD_PREFETCH;
|
||||||
|
}
|
||||||
|
if ((fctx->options & DNS_FETCHOPT_NOCACHED) != 0) {
|
||||||
|
options |= DNS_DBADD_FORCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dns_db_addrdataset(fctx->cache, node, NULL,
|
||||||
|
rctx->now, rdataset,
|
||||||
|
options, ardataset);
|
||||||
|
if (result != DNS_R_UNCHANGED &&
|
||||||
|
result != ISC_R_SUCCESS)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sigrdataset == NULL) {
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == DNS_R_UNCHANGED && !need_validation &&
|
||||||
|
ardataset != NULL &&
|
||||||
|
!dns_rdataset_equals(rdataset, ardataset))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The cache wasn't updated because
|
||||||
|
* something was already there. If the data
|
||||||
|
* was the same as what we were trying to
|
||||||
|
* add, then sigrdataset might still be
|
||||||
|
* useful, and we should carry on caching
|
||||||
|
* it. Otherwise, move on.
|
||||||
|
*/
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dns_db_addrdataset(fctx->cache, node, NULL,
|
||||||
|
rctx->now, sigrdataset,
|
||||||
|
options, asigset);
|
||||||
|
if (result != DNS_R_UNCHANGED &&
|
||||||
|
result != ISC_R_SUCCESS)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're not in a secure domain, or this is glue,
|
||||||
|
* so we can cache right away.
|
||||||
|
*
|
||||||
|
* If this wasn't an ANY/RRSIG/SIG query then send
|
||||||
|
* an answer back to the caller.
|
||||||
|
*/
|
||||||
dns_rdataset_t *added = NULL;
|
dns_rdataset_t *added = NULL;
|
||||||
dns_rdataset_t *sigrdataset = NULL;
|
if (!dns_rdatatype_ismulti(fctx->type)) {
|
||||||
dns_rdataset_t *ardataset = NULL, *asigrdataset = NULL;
|
if (ANSWER(rdataset)) {
|
||||||
dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
|
added = resp->rdataset;
|
||||||
dns_dbnode_t *node = NULL;
|
} else if (ANSWERSIG(rdataset)) {
|
||||||
|
added = resp->sigrdataset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdataset->trust == dns_trust_glue &&
|
||||||
|
dns_rdataset_matchestype(rdataset, dns_rdatatype_ns))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If the trust level is glue, then we are adding data from
|
||||||
|
* a referral we got while executing the search algorithm.
|
||||||
|
* New referral data always takes precedence over the
|
||||||
|
* existing cache contents.
|
||||||
|
*/
|
||||||
|
options = DNS_DBADD_FORCE;
|
||||||
|
} else if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
|
||||||
|
options = DNS_DBADD_PREFETCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for the NOQNAME proof.
|
||||||
|
*/
|
||||||
|
if (ANSWER(rdataset)) {
|
||||||
|
findnoqname(fctx, message, name, rdataset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we can add the rdataset.
|
||||||
|
*/
|
||||||
|
result = dns_db_addrdataset(fctx->cache, node, NULL, rctx->now,
|
||||||
|
rdataset, options, added);
|
||||||
|
if (result == DNS_R_UNCHANGED) {
|
||||||
|
result = ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
rctx_cachename(respctx_t *rctx, dns_message_t *message, dns_name_t *name) {
|
||||||
|
isc_result_t result;
|
||||||
|
fetchctx_t *fctx = rctx->fctx;
|
||||||
|
resquery_t *query = rctx->query;
|
||||||
dns_resolver_t *res = fctx->res;
|
dns_resolver_t *res = fctx->res;
|
||||||
bool have_answer = false;
|
dns_rdataset_t *sigrdataset = NULL;
|
||||||
isc_result_t result, eresult = ISC_R_SUCCESS;
|
dns_dbnode_t *node = NULL;
|
||||||
dns_fetchresponse_t *resp = NULL;
|
dns_fetchresponse_t *resp = NULL;
|
||||||
|
|
||||||
FCTXTRACE("cache_name");
|
FCTXTRACE("rctx_cachename");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The appropriate bucket lock must be held.
|
* The appropriate bucket lock must be held.
|
||||||
@@ -5868,33 +6049,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
|||||||
/*
|
/*
|
||||||
* Is DNSSEC validation required for this name?
|
* Is DNSSEC validation required for this name?
|
||||||
*/
|
*/
|
||||||
bool checknta = ((fctx->options & DNS_FETCHOPT_NONTA) == 0);
|
bool secure_domain = issecuredomain(fctx, name, fctx->type, rctx->now,
|
||||||
bool secure_domain = issecuredomain(res->view, name, fctx->type, now,
|
NULL);
|
||||||
checknta, NULL);
|
|
||||||
bool need_validation = secure_domain &&
|
bool need_validation = secure_domain &&
|
||||||
((fctx->options & DNS_FETCHOPT_NOVALIDATE) == 0);
|
((fctx->options & DNS_FETCHOPT_NOVALIDATE) == 0);
|
||||||
|
|
||||||
if (name->attributes.answer && !need_validation) {
|
|
||||||
have_answer = true;
|
|
||||||
resp = ISC_LIST_HEAD(fctx->resps);
|
|
||||||
if (resp != NULL) {
|
|
||||||
/*
|
|
||||||
* If this is an ANY, SIG or RRSIG query, we're
|
|
||||||
* not going to return any rdatasets, unless we
|
|
||||||
* encountered a CNAME or DNAME as "the answer".
|
|
||||||
* In this case, we're going to return
|
|
||||||
* DNS_R_CNAME or DNS_R_DNAME and we must set up
|
|
||||||
* the rdatasets.
|
|
||||||
*/
|
|
||||||
if (!dns_rdatatype_ismulti(fctx->type) ||
|
|
||||||
name->attributes.chaining)
|
|
||||||
{
|
|
||||||
ardataset = resp->rdataset;
|
|
||||||
asigrdataset = resp->sigrdataset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find or create the cache node.
|
* Find or create the cache node.
|
||||||
*/
|
*/
|
||||||
@@ -5906,10 +6065,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
|||||||
/*
|
/*
|
||||||
* Cache or validate each cacheable rdataset.
|
* Cache or validate each cacheable rdataset.
|
||||||
*/
|
*/
|
||||||
bool fail = ((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
|
bool fail = ((res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
|
||||||
ISC_LIST_FOREACH (name->list, rdataset, link) {
|
ISC_LIST_FOREACH (name->list, rdataset, link) {
|
||||||
unsigned int options = 0;
|
|
||||||
|
|
||||||
result = check_cacheable(name, rdataset, fail);
|
result = check_cacheable(name, rdataset, fail);
|
||||||
if (result == DNS_R_CONTINUE) {
|
if (result == DNS_R_CONTINUE) {
|
||||||
result = ISC_R_SUCCESS;
|
result = ISC_R_SUCCESS;
|
||||||
@@ -5934,288 +6091,50 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
|||||||
*/
|
*/
|
||||||
fixttls(res->view, rdataset, sigrdataset);
|
fixttls(res->view, rdataset, sigrdataset);
|
||||||
|
|
||||||
/*
|
/* Try to cache the rdataset */
|
||||||
* If this RRset is in a secure domain, is in bailiwick,
|
result = rctx_cacherdataset(rctx, message, name, node, rdataset,
|
||||||
* and is not glue, attempt DNSSEC validation.
|
sigrdataset, secure_domain,
|
||||||
*
|
need_validation);
|
||||||
* We do not attempt to validate glue or out-of-bailiwick
|
|
||||||
* data - even though there might be some performance
|
|
||||||
* benefit to doing so - because it makes it simpler and
|
|
||||||
* safer to ensure that records from a secure domain are
|
|
||||||
* only cached if validated within the context of a query
|
|
||||||
* to the domain that owns them.
|
|
||||||
*/
|
|
||||||
if (secure_domain && rdataset->trust != dns_trust_glue) {
|
|
||||||
/*
|
|
||||||
* RRSIGs are validated as part of validating
|
|
||||||
* the type they cover.
|
|
||||||
*/
|
|
||||||
if (rdataset->type == dns_rdatatype_rrsig) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ignore unrelated non-answer rdatasets that are
|
|
||||||
* missing signatures.
|
|
||||||
*/
|
|
||||||
if (sigrdataset == NULL && need_validation &&
|
|
||||||
!ANSWER(rdataset))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normalize the rdataset and sigrdataset TTLs.
|
|
||||||
*/
|
|
||||||
if (sigrdataset != NULL) {
|
|
||||||
rdataset->ttl = ISC_MIN(rdataset->ttl,
|
|
||||||
sigrdataset->ttl);
|
|
||||||
sigrdataset->ttl = rdataset->ttl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark the rdataset as being prefetch eligible.
|
|
||||||
*/
|
|
||||||
if (rdataset->ttl >= fctx->res->view->prefetch_eligible)
|
|
||||||
{
|
|
||||||
rdataset->attributes.prefetch = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cache this rdataset/sigrdataset pair as
|
|
||||||
* pending data. Track whether it was
|
|
||||||
* additional or not. If this was a priming
|
|
||||||
* query, additional should be cached as glue.
|
|
||||||
*/
|
|
||||||
if (rdataset->trust == dns_trust_additional) {
|
|
||||||
rdataset->trust = dns_trust_pending_additional;
|
|
||||||
} else {
|
|
||||||
rdataset->trust = dns_trust_pending_answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sigrdataset != NULL) {
|
|
||||||
sigrdataset->trust = rdataset->trust;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ANSWER(rdataset) && need_validation) {
|
|
||||||
if (!dns_rdatatype_ismulti(fctx->type)) {
|
|
||||||
/*
|
|
||||||
* This is The Answer. We will
|
|
||||||
* validate it, but first we
|
|
||||||
* cache the rest of the
|
|
||||||
* response - it may contain
|
|
||||||
* useful keys.
|
|
||||||
*/
|
|
||||||
INSIST(valrdataset == NULL &&
|
|
||||||
valsigrdataset == NULL);
|
|
||||||
valrdataset = rdataset;
|
|
||||||
valsigrdataset = sigrdataset;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* This is one of (potentially)
|
|
||||||
* multiple answers to an ANY
|
|
||||||
* or SIG query. To keep things
|
|
||||||
* simple, we just start the
|
|
||||||
* validator right away rather
|
|
||||||
* than caching first and
|
|
||||||
* having to remember which
|
|
||||||
* rdatasets needed validation.
|
|
||||||
*/
|
|
||||||
result = valcreate(
|
|
||||||
fctx, message, addrinfo, name,
|
|
||||||
rdataset->type, rdataset,
|
|
||||||
sigrdataset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ANSWER(rdataset)) {
|
|
||||||
findnoqname(fctx, message, name,
|
|
||||||
rdataset);
|
|
||||||
}
|
|
||||||
if ((fctx->options & DNS_FETCHOPT_PREFETCH) !=
|
|
||||||
0)
|
|
||||||
{
|
|
||||||
options = DNS_DBADD_PREFETCH;
|
|
||||||
}
|
|
||||||
if ((fctx->options & DNS_FETCHOPT_NOCACHED) !=
|
|
||||||
0)
|
|
||||||
{
|
|
||||||
options |= DNS_DBADD_FORCE;
|
|
||||||
}
|
|
||||||
added = ardataset;
|
|
||||||
result = dns_db_addrdataset(fctx->cache, node,
|
|
||||||
NULL, now, rdataset,
|
|
||||||
options, added);
|
|
||||||
if (result == DNS_R_UNCHANGED) {
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
if (!need_validation && added != NULL &&
|
|
||||||
NEGATIVE(added))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The answer in the
|
|
||||||
* cache is better than
|
|
||||||
* the answer we found.
|
|
||||||
* If it's a negative
|
|
||||||
* cache entry, we
|
|
||||||
* must set eresult
|
|
||||||
* appropriately.
|
|
||||||
*/
|
|
||||||
if (NXDOMAIN(added)) {
|
|
||||||
eresult =
|
|
||||||
DNS_R_NCACHENXDOMAIN;
|
|
||||||
} else {
|
|
||||||
eresult =
|
|
||||||
DNS_R_NCACHENXRRSET;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (!need_validation &&
|
|
||||||
added != NULL &&
|
|
||||||
sigrdataset != NULL &&
|
|
||||||
!dns_rdataset_equals(
|
|
||||||
rdataset, added))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The cache wasn't updated
|
|
||||||
* because something was
|
|
||||||
* already there. If the
|
|
||||||
* data was the same as what
|
|
||||||
* we were trying to add,
|
|
||||||
* then sigrdataset might
|
|
||||||
* still be useful, and we
|
|
||||||
* should carry on caching
|
|
||||||
* it. Otherwise, move on.
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
break;
|
goto cleanup;
|
||||||
}
|
|
||||||
if (sigrdataset != NULL) {
|
|
||||||
added = asigrdataset;
|
|
||||||
result = dns_db_addrdataset(
|
|
||||||
fctx->cache, node, NULL, now,
|
|
||||||
sigrdataset, options, added);
|
|
||||||
if (result == DNS_R_UNCHANGED) {
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (!ANSWER(rdataset)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CHAINING(rdataset)) {
|
|
||||||
if (rdataset->type ==
|
|
||||||
dns_rdatatype_cname)
|
|
||||||
{
|
|
||||||
eresult = DNS_R_CNAME;
|
|
||||||
} else {
|
|
||||||
INSIST(rdataset->type ==
|
|
||||||
dns_rdatatype_dname);
|
|
||||||
eresult = DNS_R_DNAME;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* It's OK to cache this rdataset now.
|
|
||||||
*/
|
|
||||||
if (ANSWER(rdataset)) {
|
|
||||||
added = ardataset;
|
|
||||||
} else if (ANSWERSIG(rdataset)) {
|
|
||||||
added = asigrdataset;
|
|
||||||
} else {
|
|
||||||
added = NULL;
|
|
||||||
}
|
|
||||||
if (rdataset->trust == dns_trust_glue &&
|
|
||||||
dns_rdataset_matchestype(rdataset,
|
|
||||||
dns_rdatatype_ns))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If the trust level is
|
|
||||||
* 'dns_trust_glue' then we are adding
|
|
||||||
* data from a referral we got while
|
|
||||||
* executing the search algorithm. New
|
|
||||||
* referral data always takes precedence
|
|
||||||
* over the existing cache contents.
|
|
||||||
*/
|
|
||||||
options = DNS_DBADD_FORCE;
|
|
||||||
} else if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
|
|
||||||
{
|
|
||||||
options = DNS_DBADD_PREFETCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ANSWER(rdataset)) {
|
|
||||||
findnoqname(fctx, message, name, rdataset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now we can add the rdataset.
|
|
||||||
*/
|
|
||||||
result = dns_db_addrdataset(fctx->cache, node, NULL,
|
|
||||||
now, rdataset, options,
|
|
||||||
added);
|
|
||||||
|
|
||||||
if (result == DNS_R_UNCHANGED) {
|
|
||||||
if (ANSWER(rdataset) && added != NULL &&
|
|
||||||
NEGATIVE(added))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The answer in the cache is
|
|
||||||
* better than the answer we
|
|
||||||
* found, and is a negative
|
|
||||||
* cache entry, so we must set
|
|
||||||
* eresult appropriately.
|
|
||||||
*/
|
|
||||||
if (NXDOMAIN(added)) {
|
|
||||||
eresult = DNS_R_NCACHENXDOMAIN;
|
|
||||||
} else {
|
|
||||||
eresult = DNS_R_NCACHENXRRSET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
} else if (result != ISC_R_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valrdataset != NULL) {
|
if (rctx->vrdataset != NULL) {
|
||||||
dns_rdatatype_t vtype = fctx->type;
|
dns_rdatatype_t vtype = fctx->type;
|
||||||
if (CHAINING(valrdataset)) {
|
if (CHAINING(rctx->vrdataset)) {
|
||||||
if (valrdataset->type == dns_rdatatype_cname) {
|
vtype = rctx->vrdataset->type;
|
||||||
vtype = dns_rdatatype_cname;
|
INSIST(dns_rdatatype_isalias(vtype));
|
||||||
} else {
|
|
||||||
vtype = dns_rdatatype_dname;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = valcreate(fctx, message, addrinfo, name, vtype,
|
valcreate(fctx, message, query->addrinfo, name, vtype,
|
||||||
valrdataset, valsigrdataset);
|
rctx->vrdataset, rctx->vsigrdataset);
|
||||||
|
rctx->vrdataset = NULL;
|
||||||
|
rctx->vsigrdataset = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == ISC_R_SUCCESS && have_answer) {
|
if (result == ISC_R_SUCCESS && name->attributes.answer &&
|
||||||
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
|
!need_validation && !HAVE_ANSWER(fctx))
|
||||||
|
{
|
||||||
|
resp = ISC_LIST_HEAD(fctx->resps);
|
||||||
if (resp != NULL) {
|
if (resp != NULL) {
|
||||||
/*
|
/*
|
||||||
* Negative results must be indicated in
|
* Negative results must be indicated in
|
||||||
* resp->result.
|
* resp->result.
|
||||||
*/
|
*/
|
||||||
|
resp->result = ISC_R_SUCCESS;
|
||||||
if (dns_rdataset_isassociated(resp->rdataset)) {
|
if (dns_rdataset_isassociated(resp->rdataset)) {
|
||||||
if (NEGATIVE(resp->rdataset)) {
|
if (NXDOMAIN(resp->rdataset)) {
|
||||||
INSIST(eresult ==
|
resp->result = DNS_R_NCACHENXDOMAIN;
|
||||||
DNS_R_NCACHENXDOMAIN ||
|
} else if (NEGATIVE(resp->rdataset)) {
|
||||||
eresult == DNS_R_NCACHENXRRSET);
|
resp->result = DNS_R_NCACHENXRRSET;
|
||||||
} else if (eresult == ISC_R_SUCCESS &&
|
} else if (resp->rdataset->type != fctx->type) {
|
||||||
resp->rdataset->type != fctx->type)
|
|
||||||
{
|
|
||||||
switch (resp->rdataset->type) {
|
switch (resp->rdataset->type) {
|
||||||
case dns_rdatatype_cname:
|
case dns_rdatatype_cname:
|
||||||
eresult = DNS_R_CNAME;
|
resp->result = DNS_R_CNAME;
|
||||||
break;
|
break;
|
||||||
case dns_rdatatype_dname:
|
case dns_rdatatype_dname:
|
||||||
eresult = DNS_R_DNAME;
|
resp->result = DNS_R_DNAME;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -6223,12 +6142,13 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp->result = eresult;
|
|
||||||
dns_name_copy(name, resp->foundname);
|
dns_name_copy(name, resp->foundname);
|
||||||
dns_db_attach(fctx->cache, &resp->db);
|
dns_db_attach(fctx->cache, &resp->db);
|
||||||
dns_db_transfernode(fctx->cache, &node, &resp->node);
|
dns_db_transfernode(fctx->cache, &node, &resp->node);
|
||||||
clone_results(fctx);
|
clone_results(fctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -6240,22 +6160,24 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
cache_message(fetchctx_t *fctx, dns_message_t *message,
|
rctx_cachemessage(respctx_t *rctx) {
|
||||||
dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) {
|
isc_result_t result;
|
||||||
FCTXTRACE("cache_message");
|
fetchctx_t *fctx = rctx->fctx;
|
||||||
|
resquery_t *query = rctx->query;
|
||||||
|
dns_message_t *message = query->rmessage;
|
||||||
|
|
||||||
|
FCTXTRACE("rctx_cachemessage");
|
||||||
|
|
||||||
FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTCACHE);
|
FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTCACHE);
|
||||||
|
|
||||||
LOCK(&fctx->lock);
|
LOCK(&fctx->lock);
|
||||||
|
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
|
||||||
for (dns_section_t section = DNS_SECTION_ANSWER;
|
for (dns_section_t section = DNS_SECTION_ANSWER;
|
||||||
section <= DNS_SECTION_ADDITIONAL; section++)
|
section <= DNS_SECTION_ADDITIONAL; section++)
|
||||||
{
|
{
|
||||||
MSG_SECTION_FOREACH (message, section, name) {
|
MSG_SECTION_FOREACH (message, section, name) {
|
||||||
if (name->attributes.cache) {
|
if (name->attributes.cache) {
|
||||||
result = cache_name(fctx, name, message,
|
result = rctx_cachename(rctx, message, name);
|
||||||
addrinfo, now);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@@ -6358,17 +6280,28 @@ negcache(dns_message_t *message, fetchctx_t *fctx, const dns_name_t *name,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
/*
|
||||||
ncache_message(fetchctx_t *fctx, dns_message_t *message,
|
* rctx_ncache():
|
||||||
dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) {
|
* Cache the negatively cacheable parts of the message. This may
|
||||||
isc_result_t result, eresult = ISC_R_SUCCESS;
|
* also cause work to be queued to the DNSSEC validator.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
rctx_ncache(respctx_t *rctx) {
|
||||||
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
|
isc_result_t eresult = ISC_R_SUCCESS;
|
||||||
|
fetchctx_t *fctx = rctx->fctx;
|
||||||
dns_name_t *name = fctx->name;
|
dns_name_t *name = fctx->name;
|
||||||
dns_resolver_t *res = fctx->res;
|
dns_message_t *message = rctx->query->rmessage;
|
||||||
|
dns_adbaddrinfo_t *addrinfo = rctx->query->addrinfo;
|
||||||
dns_dbnode_t *node = NULL;
|
dns_dbnode_t *node = NULL;
|
||||||
dns_fetchresponse_t *resp = NULL;
|
dns_fetchresponse_t *resp = NULL;
|
||||||
dns_rdataset_t *added = NULL;
|
dns_rdataset_t *added = NULL;
|
||||||
|
|
||||||
FCTXTRACE("ncache_message");
|
FCTXTRACE("rctx_ncache");
|
||||||
|
|
||||||
|
if (!WANTNCACHE(fctx)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTNCACHE);
|
FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTNCACHE);
|
||||||
|
|
||||||
@@ -6381,15 +6314,16 @@ ncache_message(fetchctx_t *fctx, dns_message_t *message,
|
|||||||
/*
|
/*
|
||||||
* Is DNSSEC validation required for this name?
|
* Is DNSSEC validation required for this name?
|
||||||
*/
|
*/
|
||||||
bool checknta = ((fctx->options & DNS_FETCHOPT_NONTA) == 0);
|
bool secure_domain = issecuredomain(fctx, name, fctx->type, rctx->now,
|
||||||
bool secure_domain = issecuredomain(res->view, name, fctx->type, now,
|
NULL);
|
||||||
checknta, NULL);
|
|
||||||
bool need_validation = secure_domain &&
|
bool need_validation = secure_domain &&
|
||||||
((fctx->options & DNS_FETCHOPT_NOVALIDATE) == 0);
|
((fctx->options & DNS_FETCHOPT_NOVALIDATE) == 0);
|
||||||
|
|
||||||
if (secure_domain) {
|
if (secure_domain) {
|
||||||
/*
|
/*
|
||||||
* Mark all rdatasets as pending.
|
* Mark all rdatasets as pending. (We do this for
|
||||||
|
* any domain under a trust anchor, regardless
|
||||||
|
* of whether we're actually validating.)
|
||||||
*/
|
*/
|
||||||
MSG_SECTION_FOREACH (message, DNS_SECTION_AUTHORITY, tname) {
|
MSG_SECTION_FOREACH (message, DNS_SECTION_AUTHORITY, tname) {
|
||||||
ISC_LIST_FOREACH (tname->list, trdataset, link) {
|
ISC_LIST_FOREACH (tname->list, trdataset, link) {
|
||||||
@@ -6400,37 +6334,31 @@ ncache_message(fetchctx_t *fctx, dns_message_t *message,
|
|||||||
|
|
||||||
if (need_validation) {
|
if (need_validation) {
|
||||||
/*
|
/*
|
||||||
* Do negative response validation.
|
* Start the validator for the negative response. It
|
||||||
|
* will call validated() on completion; the caching of
|
||||||
|
* negative answers will be done then.
|
||||||
*/
|
*/
|
||||||
result = valcreate(fctx, message, addrinfo, name, fctx->type,
|
valcreate(fctx, message, addrinfo, name, fctx->type, NULL,
|
||||||
NULL, NULL);
|
NULL);
|
||||||
/*
|
goto done;
|
||||||
* If validation is necessary, return now. Otherwise
|
|
||||||
* continue to process the message, letting the
|
|
||||||
* validation complete in its own good time.
|
|
||||||
*/
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache the negative answer, and copy it into the fetch response.
|
||||||
|
*/
|
||||||
LOCK(&fctx->lock);
|
LOCK(&fctx->lock);
|
||||||
|
|
||||||
if (!HAVE_ANSWER(fctx)) {
|
|
||||||
resp = ISC_LIST_HEAD(fctx->resps);
|
resp = ISC_LIST_HEAD(fctx->resps);
|
||||||
if (resp != NULL) {
|
if (!HAVE_ANSWER(fctx) && resp != NULL) {
|
||||||
added = resp->rdataset;
|
added = resp->rdataset;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
result = negcache(message, fctx, name, now, false, false, added, &node,
|
result = negcache(message, fctx, name, rctx->now, false, false, added,
|
||||||
&eresult);
|
&node, &eresult);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS || HAVE_ANSWER(fctx)) {
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HAVE_ANSWER(fctx)) {
|
|
||||||
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
|
FCTX_ATTR_SET(fctx, FCTX_ATTR_HAVEANSWER);
|
||||||
}
|
|
||||||
|
|
||||||
if (resp != NULL) {
|
if (resp != NULL) {
|
||||||
resp->result = eresult;
|
resp->result = eresult;
|
||||||
dns_name_copy(name, resp->foundname);
|
dns_name_copy(name, resp->foundname);
|
||||||
@@ -6446,7 +6374,10 @@ unlock:
|
|||||||
dns_db_detachnode(fctx->cache, &node);
|
dns_db_detachnode(fctx->cache, &node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
done:
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
FCTXTRACE3("rctx_ncache complete", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -6465,6 +6396,7 @@ mark_related(dns_name_t *name, dns_rdataset_t *rdataset, bool external,
|
|||||||
} else {
|
} else {
|
||||||
rdataset->trust = dns_trust_additional;
|
rdataset->trust = dns_trust_additional;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Avoid infinite loops by only marking new rdatasets.
|
* Avoid infinite loops by only marking new rdatasets.
|
||||||
*/
|
*/
|
||||||
@@ -7696,10 +7628,9 @@ resquery_response_continue(void *arg, isc_result_t result) {
|
|||||||
*/
|
*/
|
||||||
if (WANTCACHE(fctx)) {
|
if (WANTCACHE(fctx)) {
|
||||||
isc_result_t tresult;
|
isc_result_t tresult;
|
||||||
tresult = cache_message(fctx, query->rmessage, query->addrinfo,
|
tresult = rctx_cachemessage(rctx);
|
||||||
rctx->now);
|
|
||||||
if (tresult != ISC_R_SUCCESS) {
|
if (tresult != ISC_R_SUCCESS) {
|
||||||
FCTXTRACE3("cache_message complete", tresult);
|
FCTXTRACE3("rctx_cachemessage complete", tresult);
|
||||||
rctx_done(rctx, tresult);
|
rctx_done(rctx, tresult);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@@ -7794,6 +7725,9 @@ rctx_answer_init(respctx_t *rctx) {
|
|||||||
rctx->soa_name = NULL;
|
rctx->soa_name = NULL;
|
||||||
rctx->ds_name = NULL;
|
rctx->ds_name = NULL;
|
||||||
rctx->found_name = NULL;
|
rctx->found_name = NULL;
|
||||||
|
|
||||||
|
rctx->vrdataset = NULL;
|
||||||
|
rctx->vsigrdataset = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -8882,30 +8816,6 @@ rctx_authority_negative(respctx_t *rctx) {
|
|||||||
return ISC_R_SUCCESS;
|
return ISC_R_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* rctx_ncache():
|
|
||||||
* Cache the negatively cacheable parts of the message. This may
|
|
||||||
* also cause work to be queued to the DNSSEC validator.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
rctx_ncache(respctx_t *rctx) {
|
|
||||||
isc_result_t result;
|
|
||||||
fetchctx_t *fctx = rctx->fctx;
|
|
||||||
|
|
||||||
if (!WANTNCACHE(fctx)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cache any negative cache entries in the message.
|
|
||||||
*/
|
|
||||||
result = ncache_message(fctx, rctx->query->rmessage,
|
|
||||||
rctx->query->addrinfo, rctx->now);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
FCTXTRACE3("ncache_message complete", result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rctx_authority_dnssec():
|
* rctx_authority_dnssec():
|
||||||
*
|
*
|
||||||
@@ -8929,7 +8839,6 @@ rctx_authority_dnssec(respctx_t *rctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ISC_LIST_FOREACH (name->list, rdataset, link) {
|
ISC_LIST_FOREACH (name->list, rdataset, link) {
|
||||||
bool checknta = true;
|
|
||||||
bool secure_domain = false;
|
bool secure_domain = false;
|
||||||
dns_rdatatype_t type = rdataset->type;
|
dns_rdatatype_t type = rdataset->type;
|
||||||
|
|
||||||
@@ -8993,12 +8902,9 @@ rctx_authority_dnssec(respctx_t *rctx) {
|
|||||||
name->attributes.cache = true;
|
name->attributes.cache = true;
|
||||||
rdataset->attributes.cache = true;
|
rdataset->attributes.cache = true;
|
||||||
|
|
||||||
if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
|
secure_domain = issecuredomain(fctx, name,
|
||||||
checknta = false;
|
dns_rdatatype_ds,
|
||||||
}
|
fctx->now, NULL);
|
||||||
secure_domain = issecuredomain(
|
|
||||||
fctx->res->view, name, dns_rdatatype_ds,
|
|
||||||
fctx->now, checknta, NULL);
|
|
||||||
if (secure_domain) {
|
if (secure_domain) {
|
||||||
rdataset->trust =
|
rdataset->trust =
|
||||||
dns_trust_pending_answer;
|
dns_trust_pending_answer;
|
||||||
|
Reference in New Issue
Block a user