2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Merge branch 'ondrej-further-dns_validator-refactoring' into 'main'

additional refactoring of dns_validator

See merge request isc-projects/bind9!7546
This commit is contained in:
Ondřej Surý
2023-02-17 06:22:03 +00:00
4 changed files with 320 additions and 417 deletions

View File

@@ -1,3 +1,7 @@
6103. [func] All uses of the isc_task and isc_event APIs have
been refactored to use isc_loop instead, and the
original APIs have been removed. [GL #3797]
6102. [cleanup] Several nugatory headers have been removed from libisc.
[GL !7464]

View File

@@ -48,8 +48,9 @@
#include <stdbool.h>
#include <isc/job.h>
#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/refcount.h>
#include <dns/fixedname.h>
#include <dns/rdataset.h>
@@ -58,31 +59,44 @@
#include <dst/dst.h>
#define DNS_VALIDATOR_NOQNAMEPROOF 0
#define DNS_VALIDATOR_NODATAPROOF 1
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
#define DNS_VALIDATOR_CLOSESTENCLOSER 3
/*%
* A dns_valstatus_t is sent when a 'validation' completes.
* A validator object represents a validation in progress.
* \brief
* 'name', 'rdataset', 'sigrdataset', and 'message' are the values that were
* supplied when dns_validator_create() was called. They are returned to the
* caller so that they may be freed.
*
* If the RESULT is ISC_R_SUCCESS and the answer is secure then
* proofs[] will contain the names of the NSEC records that hold the
* various proofs. Note the same name may appear multiple times.
*
* The structure is freed by dns_validator_destroy().
* Clients are strongly discouraged from using this type directly, with
* the exception of the 'link' field, which may be used directly for
* whatever purpose the client desires.
*/
typedef struct dns_valstatus {
dns_validator_t *validator;
isc_result_t result;
struct dns_validator {
unsigned int magic;
dns_view_t *view;
isc_loopmgr_t *loopmgr;
uint32_t tid;
isc_refcount_t references;
isc_mem_t *mctx;
/*
* Name and type of the response to be validated.
*/
dns_fixedname_t fname;
/* Name and type of the response to be validated. */
dns_name_t *name;
dns_rdatatype_t type;
/*
* Callback and argument to use to inform the caller
* that validation is complete.
*/
isc_job_cb cb;
void *arg;
/* Validation options (_DEFER, _NONTA, etc). */
unsigned int options;
/*
* Results of a completed validation.
*/
isc_result_t result;
/*
* Rdata and RRSIG (if any) for positive responses.
*/
@@ -105,40 +119,17 @@ typedef struct dns_valstatus {
* Answer is secure.
*/
bool secure;
} dns_valstatus_t;
#define DNS_VALIDATOR_NOQNAMEPROOF 0
#define DNS_VALIDATOR_NODATAPROOF 1
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
#define DNS_VALIDATOR_CLOSESTENCLOSER 3
/*%
* A validator object represents a validation in progress.
* \brief
* Clients are strongly discouraged from using this type directly, with
* the exception of the 'link' field, which may be used directly for
* whatever purpose the client desires.
*/
struct dns_validator {
/* Unlocked. */
unsigned int magic;
isc_mutex_t lock;
dns_view_t *view;
/* Locked by lock. */
unsigned int options;
/* Internal validator state */
unsigned int attributes;
dns_valstatus_t *vstat;
dns_fetch_t *fetch;
dns_validator_t *subvalidator;
dns_validator_t *parent;
dns_keytable_t *keytable;
dst_key_t *key;
dns_rdata_rrsig_t *siginfo;
isc_loop_t *loop;
isc_job_cb cb;
void *arg;
unsigned int labels;
dns_rdataset_t *currentset;
dns_rdataset_t *nxset;
dns_rdataset_t *keyset;
dns_rdataset_t *dsset;
dns_rdataset_t fdsset;
@@ -169,7 +160,7 @@ isc_result_t
dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_message_t *message, unsigned int options,
isc_loop_t *loop, isc_job_cb cb, void *arg,
isc_loopmgr_t *loop, isc_job_cb cb, void *arg,
dns_validator_t **validatorp);
/*%<
* Start a DNSSEC validation.
@@ -238,10 +229,24 @@ dns_validator_destroy(dns_validator_t **validatorp);
* Requires:
*\li '*validatorp' points to a valid DNSSEC validator.
* \li The validator must have completed and sent its completion
* event.
* event.
*
* Ensures:
*\li All resources used by the validator are freed.
*/
#if DNS_VALIDATOR_TRACE
#define dns_validator_ref(ptr) \
dns_validator__ref(ptr, __func__, __FILE__, __LINE__)
#define dns_validator_unref(ptr) \
dns_validator__unref(ptr, __func__, __FILE__, __LINE__)
#define dns_validator_attach(ptr, ptrp) \
dns_validator__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
#define dns_validator_detach(ptrp) \
dns_validator__detach(ptrp, __func__, __FILE__, __LINE__)
ISC_REFCOUNT_TRACE_DECL(dns_validator);
#else
ISC_REFCOUNT_DECL(dns_validator);
#endif
ISC_LANG_ENDDECLS

View File

@@ -961,8 +961,7 @@ set_stats(dns_resolver_t *res, isc_statscounter_t counter, uint64_t val) {
static isc_result_t
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_rdataset_t *sigrdataset, unsigned int valoptions,
isc_loop_t *loop) {
dns_rdataset_t *sigrdataset, unsigned int valoptions) {
dns_validator_t *validator = NULL;
dns_valarg_t *valarg = NULL;
isc_result_t result;
@@ -980,9 +979,9 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
valoptions &= ~DNS_VALIDATOR_DEFER;
}
result = dns_validator_create(fctx->res->view, name, type, rdataset,
sigrdataset, message, valoptions, loop,
validated, valarg, &validator);
result = dns_validator_create(
fctx->res->view, name, type, rdataset, sigrdataset, message,
valoptions, fctx->res->loopmgr, validated, valarg, &validator);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
inc_stats(fctx->res, dns_resstatscounter_val);
if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
@@ -5312,8 +5311,7 @@ has_000_label(dns_rdataset_t *nsecset) {
*/
static void
validated(void *arg) {
dns_valstatus_t *vstat = (dns_valstatus_t *)arg;
dns_validator_t *val = vstat->validator;
dns_validator_t *val = (dns_validator_t *)arg;
dns_adbaddrinfo_t *addrinfo = NULL;
dns_dbnode_t *node = NULL;
dns_dbnode_t *nsnode = NULL;
@@ -5354,8 +5352,8 @@ validated(void *arg) {
res = fctx->res;
addrinfo = valarg->addrinfo;
message = vstat->message;
fctx->vresult = vstat->result;
message = val->message;
fctx->vresult = val->result;
LOCK(&fctx->lock);
ISC_LIST_UNLINK(fctx->validators, val, link);
@@ -5366,14 +5364,14 @@ validated(void *arg) {
* Destroy the validator early so that we can
* destroy the fctx if necessary. Save the wildcard name.
*/
if (vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
if (val->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
wild = dns_fixedname_initname(&fwild);
dns_name_copy(dns_fixedname_name(&val->wild), wild);
}
isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
negative = (vstat->rdataset == NULL);
negative = (val->rdataset == NULL);
LOCK(&fctx->lock);
sentresponse = ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
@@ -5394,13 +5392,13 @@ validated(void *arg) {
* If chaining, we need to make sure that the right result code
* is returned, and that the rdatasets are bound.
*/
if (vstat->result == ISC_R_SUCCESS && !negative &&
vstat->rdataset != NULL && CHAINING(vstat->rdataset))
if (val->result == ISC_R_SUCCESS && !negative &&
val->rdataset != NULL && CHAINING(val->rdataset))
{
if (vstat->rdataset->type == dns_rdatatype_cname) {
if (val->rdataset->type == dns_rdatatype_cname) {
eresult = DNS_R_CNAME;
} else {
INSIST(vstat->rdataset->type == dns_rdatatype_dname);
INSIST(val->rdataset->type == dns_rdatatype_dname);
eresult = DNS_R_DNAME;
}
chaining = true;
@@ -5431,28 +5429,26 @@ validated(void *arg) {
}
}
if (vstat->result != ISC_R_SUCCESS) {
if (val->result != ISC_R_SUCCESS) {
FCTXTRACE("validation failed");
inc_stats(res, dns_resstatscounter_valfail);
fctx->valfail++;
fctx->vresult = vstat->result;
fctx->vresult = val->result;
if (fctx->vresult != DNS_R_BROKENCHAIN) {
result = ISC_R_NOTFOUND;
if (vstat->rdataset != NULL) {
result = dns_db_findnode(
fctx->cache, vstat->name, true, &node);
if (val->rdataset != NULL) {
result = dns_db_findnode(fctx->cache, val->name,
true, &node);
}
if (result == ISC_R_SUCCESS) {
(void)dns_db_deleterdataset(fctx->cache, node,
NULL, vstat->type,
0);
NULL, val->type, 0);
}
if (result == ISC_R_SUCCESS &&
vstat->sigrdataset != NULL)
if (result == ISC_R_SUCCESS && val->sigrdataset != NULL)
{
(void)dns_db_deleterdataset(
fctx->cache, node, NULL,
dns_rdatatype_rrsig, vstat->type);
dns_rdatatype_rrsig, val->type);
}
if (result == ISC_R_SUCCESS) {
dns_db_detachnode(fctx->cache, &node);
@@ -5464,21 +5460,20 @@ validated(void *arg) {
* validation.
*/
result = ISC_R_NOTFOUND;
if (vstat->rdataset != NULL) {
result = dns_db_findnode(
fctx->cache, vstat->name, true, &node);
if (val->rdataset != NULL) {
result = dns_db_findnode(fctx->cache, val->name,
true, &node);
}
if (result == ISC_R_SUCCESS) {
(void)dns_db_addrdataset(
fctx->cache, node, NULL, now,
vstat->rdataset, 0, NULL);
val->rdataset, 0, NULL);
}
if (result == ISC_R_SUCCESS &&
vstat->sigrdataset != NULL)
if (result == ISC_R_SUCCESS && val->sigrdataset != NULL)
{
(void)dns_db_addrdataset(
fctx->cache, node, NULL, now,
vstat->sigrdataset, 0, NULL);
val->sigrdataset, 0, NULL);
}
if (result == ISC_R_SUCCESS) {
dns_db_detachnode(fctx->cache, &node);
@@ -5539,7 +5534,7 @@ validated(void *arg) {
covers = fctx->type;
}
result = dns_db_findnode(fctx->cache, vstat->name, true, &node);
result = dns_db_findnode(fctx->cache, val->name, true, &node);
if (result != ISC_R_SUCCESS) {
/* fctx->lock unlocked in noanswer_response */
goto noanswer_response;
@@ -5559,7 +5554,7 @@ validated(void *arg) {
result = ncache_adderesult(message, fctx->cache, node, covers,
now, fctx->res->view->minncachettl,
ttl, vstat->optout, vstat->secure,
ttl, val->optout, val->secure,
ardataset, &eresult);
if (result != ISC_R_SUCCESS) {
goto noanswer_response;
@@ -5571,28 +5566,27 @@ validated(void *arg) {
FCTXTRACE("validation OK");
if (vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
if (val->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
result = dns_rdataset_addnoqname(
vstat->rdataset,
vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
val->rdataset, val->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
INSIST(vstat->sigrdataset != NULL);
vstat->sigrdataset->ttl = vstat->rdataset->ttl;
if (vstat->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
INSIST(val->sigrdataset != NULL);
val->sigrdataset->ttl = val->rdataset->ttl;
if (val->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
result = dns_rdataset_addclosest(
vstat->rdataset,
vstat->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
val->rdataset,
val->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
} else if (vstat->rdataset->trust == dns_trust_answer &&
vstat->rdataset->type != dns_rdatatype_rrsig)
} else if (val->rdataset->trust == dns_trust_answer &&
val->rdataset->type != dns_rdatatype_rrsig)
{
isc_result_t tresult;
dns_name_t *noqname = NULL;
tresult = findnoqname(fctx, message, vstat->name,
vstat->rdataset->type, &noqname);
tresult = findnoqname(fctx, message, val->name,
val->rdataset->type, &noqname);
if (tresult == ISC_R_SUCCESS && noqname != NULL) {
tresult = dns_rdataset_addnoqname(vstat->rdataset,
tresult = dns_rdataset_addnoqname(val->rdataset,
noqname);
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
}
@@ -5604,7 +5598,7 @@ validated(void *arg) {
* rdatasets to the first event on the fetch
* event list.
*/
result = dns_db_findnode(fctx->cache, vstat->name, true, &node);
result = dns_db_findnode(fctx->cache, val->name, true, &node);
if (result != ISC_R_SUCCESS) {
goto noanswer_response;
}
@@ -5613,8 +5607,8 @@ validated(void *arg) {
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
options = DNS_DBADD_PREFETCH;
}
result = dns_db_addrdataset(fctx->cache, node, NULL, now,
vstat->rdataset, options, ardataset);
result = dns_db_addrdataset(fctx->cache, node, NULL, now, val->rdataset,
options, ardataset);
if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
goto noanswer_response;
}
@@ -5624,9 +5618,9 @@ validated(void *arg) {
} else {
eresult = DNS_R_NCACHENXRRSET;
}
} else if (vstat->sigrdataset != NULL) {
} else if (val->sigrdataset != NULL) {
result = dns_db_addrdataset(fctx->cache, node, NULL, now,
vstat->sigrdataset, options,
val->sigrdataset, options,
asigrdataset);
if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
goto noanswer_response;
@@ -5760,25 +5754,24 @@ answer_response:
/*
* Add the wild card entry.
*/
if (vstat->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL &&
vstat->rdataset != NULL &&
dns_rdataset_isassociated(vstat->rdataset) &&
vstat->rdataset->trust == dns_trust_secure &&
vstat->sigrdataset != NULL &&
dns_rdataset_isassociated(vstat->sigrdataset) &&
vstat->sigrdataset->trust == dns_trust_secure && wild != NULL)
if (val->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL &&
val->rdataset != NULL && dns_rdataset_isassociated(val->rdataset) &&
val->rdataset->trust == dns_trust_secure &&
val->sigrdataset != NULL &&
dns_rdataset_isassociated(val->sigrdataset) &&
val->sigrdataset->trust == dns_trust_secure && wild != NULL)
{
dns_dbnode_t *wnode = NULL;
result = dns_db_findnode(fctx->cache, wild, true, &wnode);
if (result == ISC_R_SUCCESS) {
result = dns_db_addrdataset(fctx->cache, wnode, NULL,
now, vstat->rdataset, 0,
now, val->rdataset, 0,
NULL);
}
if (result == ISC_R_SUCCESS) {
(void)dns_db_addrdataset(fctx->cache, wnode, NULL, now,
vstat->sigrdataset, 0, NULL);
val->sigrdataset, 0, NULL);
}
if (wnode != NULL) {
dns_db_detachnode(fctx->cache, &wnode);
@@ -5796,7 +5789,7 @@ answer_response:
if (hresp != NULL) {
/*
* Negative results must be indicated in vstat->result.
* Negative results must be indicated in val->result.
*/
INSIST(hresp->rdataset != NULL);
if (dns_rdataset_isassociated(hresp->rdataset) &&
@@ -5807,7 +5800,7 @@ answer_response:
}
hresp->result = eresult;
dns_name_copy(vstat->name, hresp->foundname);
dns_name_copy(val->name, hresp->foundname);
dns_db_attach(fctx->cache, &hresp->db);
dns_db_transfernode(fctx->cache, &node, &hresp->node);
clone_results(fctx);
@@ -6320,8 +6313,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
result = valcreate(
fctx, message, addrinfo, name,
rdataset->type, rdataset,
sigrdataset, valoptions,
fctx->loop);
sigrdataset, valoptions);
}
} else if (CHAINING(rdataset)) {
if (rdataset->type == dns_rdatatype_cname) {
@@ -6429,8 +6421,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
}
result = valcreate(fctx, message, addrinfo, name, vtype,
valrdataset, valsigrdataset, valoptions,
fctx->loop);
valrdataset, valsigrdataset, valoptions);
}
if (result == ISC_R_SUCCESS && have_answer) {
@@ -6652,7 +6643,7 @@ ncache_message(fetchctx_t *fctx, dns_message_t *message,
* Do negative response validation.
*/
result = valcreate(fctx, message, addrinfo, name, fctx->type,
NULL, NULL, valoptions, fctx->loop);
NULL, NULL, valoptions);
/*
* If validation is necessary, return now. Otherwise
* continue to process the message, letting the

File diff suppressed because it is too large Load Diff