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

Fix the foundname vs dcname madness in qpcache_findzonecut()

The qpcache_findzonecut() accepts two "foundnames": 'foundname' and
'dcname' could be NULL.  Originally, when 'dcname' would be NULL, the
'dcname' would be set to 'foundname'.  Then code like this was present:

    result = find_deepest_zonecut(&search, node, nodep, foundname,
                                  rdataset,
                                  sigrdataset DNS__DB_FLARG_PASS);
    dns_name_copy(foundname, dcname);

Which basically means that we are copying the .ndata over itself for no
apparent reason.  Cleanup the dcname vs foundname usage.

Co-authored-by: Evan Hunt <each@isc.org>
Co-authored-by: Ondřej Surý <ondrej@isc.org>
This commit is contained in:
Ondřej Surý
2025-02-02 15:50:15 +01:00
parent d388063466
commit 303c20caf8

View File

@@ -1997,78 +1997,23 @@ tree_exit:
}
static isc_result_t
qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
isc_stdtime_t __now, dns_dbnode_t **nodep,
dns_name_t *foundname, dns_name_t *dcname,
dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
qpcnode_t *node = NULL;
isc_rwlock_t *nlock = NULL;
isc_result_t result;
seek_ns_headers(qpc_search_t *search, qpcnode_t *node, dns_dbnode_t **nodep,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_name_t *foundname, dns_name_t *dcname,
isc_rwlocktype_t *tlocktype) {
dns_slabheader_t *header = NULL;
dns_slabheader_t *header_prev = NULL, *header_next = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
bool dcnull = (dcname == NULL);
qpc_search_t search = (qpc_search_t){
.qpdb = (qpcache_t *)db,
.options = options,
.now = __now ? __now : isc_stdtime_now(),
};
isc_rwlock_t *nlock = &search->qpdb->buckets[node->locknum].lock;
dns_slabheader_t *found = NULL, *foundsig = NULL;
REQUIRE(VALID_QPDB((qpcache_t *)db));
if (dcnull) {
dcname = foundname;
}
TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype);
/*
* Search down from the root of the tree.
*/
result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL,
&search.chain, (void **)&node, NULL);
if (result != ISC_R_NOTFOUND) {
dns_name_copy(&node->name, dcname);
}
if ((options & DNS_DBFIND_NOEXACT) != 0 && result == ISC_R_SUCCESS) {
int len = dns_qpchain_length(&search.chain);
if (len >= 2) {
node = NULL;
dns_qpchain_node(&search.chain, len - 2, NULL,
(void **)&node, NULL);
search.chain.len = len - 1;
result = DNS_R_PARTIALMATCH;
} else {
result = ISC_R_NOTFOUND;
}
}
if (result == DNS_R_PARTIALMATCH) {
result = find_deepest_zonecut(&search, node, nodep, foundname,
rdataset,
sigrdataset DNS__DB_FLARG_PASS);
goto tree_exit;
} else if (result != ISC_R_SUCCESS) {
goto tree_exit;
} else if (!dcnull) {
dns_name_copy(dcname, foundname);
}
/*
* We now go looking for an NS rdataset at the node.
*/
nlock = &search.qpdb->buckets[node->locknum].lock;
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
bool ns = (header->type == dns_rdatatype_ns ||
header->type == DNS_SIGTYPE(dns_rdatatype_ns));
if (check_stale_header(node, header, &nlocktype, nlock, &search,
if (check_stale_header(node, header, &nlocktype, nlock, search,
&header_prev))
{
if (ns) {
@@ -2091,32 +2036,108 @@ qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
}
if (found == NULL) {
isc_result_t result;
/*
* No active NS records found. Call find_deepest_zonecut()
* to look for them in nodes above this one.
*/
NODE_UNLOCK(nlock, &nlocktype);
result = find_deepest_zonecut(&search, node, nodep, foundname,
result = find_deepest_zonecut(search, node, nodep, foundname,
rdataset,
sigrdataset DNS__DB_FLARG_PASS);
dns_name_copy(foundname, dcname);
goto tree_exit;
if (dcname != NULL) {
dns_name_copy(foundname, dcname);
}
return result;
}
if (nodep != NULL) {
qpcnode_acquire(search.qpdb, node, nlocktype,
tlocktype DNS__DB_FLARG_PASS);
qpcnode_acquire(search->qpdb, node, nlocktype,
*tlocktype DNS__DB_FLARG_PASS);
*nodep = (dns_dbnode_t *)node;
}
bindrdatasets(search.qpdb, node, found, foundsig, search.now, nlocktype,
tlocktype, rdataset, sigrdataset DNS__DB_FLARG_PASS);
maybe_update_headers(search.qpdb, found, foundsig, nlock, &nlocktype,
search.now);
bindrdatasets(search->qpdb, node, found, foundsig, search->now,
nlocktype, *tlocktype, rdataset,
sigrdataset DNS__DB_FLARG_PASS);
maybe_update_headers(search->qpdb, found, foundsig, nlock, &nlocktype,
search->now);
NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
return ISC_R_SUCCESS;
}
static isc_result_t
qpcache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
isc_stdtime_t __now, dns_dbnode_t **nodep,
dns_name_t *foundname, dns_name_t *dcname,
dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
qpcnode_t *node = NULL;
isc_result_t result;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
qpc_search_t search = (qpc_search_t){
.qpdb = (qpcache_t *)db,
.options = options,
.now = __now ? __now : isc_stdtime_now(),
};
unsigned int len = 0;
REQUIRE(VALID_QPDB((qpcache_t *)db));
TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype);
/*
* Search down from the root of the tree.
*/
result = dns_qp_lookup(search.qpdb->tree, name, NULL, NULL,
&search.chain, (void **)&node, NULL);
switch (result) {
case ISC_R_SUCCESS:
if ((options & DNS_DBFIND_NOEXACT) == 0) {
if (dcname != NULL) {
dns_name_copy(&node->name, dcname);
}
dns_name_copy(&node->name, foundname);
result = seek_ns_headers(&search, node, nodep, rdataset,
sigrdataset, foundname, dcname,
&tlocktype);
break;
}
len = dns_qpchain_length(&search.chain);
if (len < 2) {
result = ISC_R_NOTFOUND;
break;
}
FALLTHROUGH;
case DNS_R_PARTIALMATCH:
if (dcname != NULL) {
dns_name_copy(&node->name, dcname);
}
if (result == ISC_R_SUCCESS) {
/* Fell through from the previous case */
INSIST(len >= 2);
node = NULL;
dns_qpchain_node(&search.chain, len - 2, NULL,
(void **)&node, NULL);
search.chain.len = len - 1;
}
result = find_deepest_zonecut(&search, node, nodep, foundname,
rdataset,
sigrdataset DNS__DB_FLARG_PASS);
break;
default:
break;
}
TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
INSIST(!search.need_cleanup);