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

Remove the negative type logic from qpcache

Previously, when a negative header was stored in the cache, it would be
stored in the dns_typepair_t as .type = 0, .covers = <negative type>.
When searching the cache internally, we would have to look for both
positive and negative typepair and the slabheader .down list could be a
mix of positive and negative types.

Remove the extra representation of the negative type and simply use the
negative attribute on the slabheader.  Other units (namely dns_ncache)
can still insert the (0, type) negative rdatasets into the cache, but
internally, those will be converted into (type, 0) slabheaders, and vice
versa - when binding the rdatasets, the negative (type, 0) slabheader
will be converted to (0, type) rdataset.  Simple DNS_TYPEPAIR() helper
macro was added to simplify converting single rdatatype to typepair
value.

As a side-effect, the search logic in all places can exit early if
there's a negative header for the type we are looking for, f.e. when
searching for the zone cut, we don't have to walk through all the
slabheaders, if there's a stored negative slabheader.
This commit is contained in:
Ondřej Surý 2025-08-11 09:39:13 +02:00 committed by Ondřej Surý
parent 3445362918
commit 6e2ca5e0d7
No known key found for this signature in database
GPG Key ID: 2820F37E873DEA41
5 changed files with 163 additions and 103 deletions

View File

@ -19,8 +19,6 @@
#include <dns/nsec3.h> #include <dns/nsec3.h>
#include <dns/types.h> #include <dns/types.h>
#define RDATATYPE_NCACHEANY DNS_TYPEPAIR_VALUE(0, dns_rdatatype_any)
#ifdef STRONG_RWLOCK_CHECK #ifdef STRONG_RWLOCK_CHECK
#define STRONG_RWLOCK_CHECK(cond) REQUIRE(cond) #define STRONG_RWLOCK_CHECK(cond) REQUIRE(cond)
#else #else

View File

@ -49,8 +49,12 @@
DNS__TYPEPAIR_VALUE(base, covers); \ DNS__TYPEPAIR_VALUE(base, covers); \
}) })
#define DNS_TYPEPAIR(type) DNS__TYPEPAIR_VALUE(type, dns_rdatatype_none)
#define DNS_SIGTYPE(type) DNS__TYPEPAIR_VALUE(dns_rdatatype_rrsig, type) #define DNS_SIGTYPE(type) DNS__TYPEPAIR_VALUE(dns_rdatatype_rrsig, type)
constexpr dns_typepair_t dns_typepair_none = DNS_TYPEPAIR(dns_rdatatype_none);
constexpr dns_typepair_t dns_typepair_any = DNS_TYPEPAIR(dns_rdatatype_any);
isc_result_t isc_result_t
dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source); dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source);
/*%< /*%<

View File

@ -52,6 +52,7 @@
#include <dns/rdatasetiter.h> #include <dns/rdatasetiter.h>
#include <dns/rdataslab.h> #include <dns/rdataslab.h>
#include <dns/rdatastruct.h> #include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/stats.h> #include <dns/stats.h>
#include <dns/time.h> #include <dns/time.h>
#include <dns/view.h> #include <dns/view.h>
@ -845,7 +846,7 @@ update_rrsetstats(dns_stats_t *stats, const dns_typepair_t typepair,
statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN; statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
} else { } else {
statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET; statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET;
base = DNS_TYPEPAIR_COVERS(header->typepair); base = DNS_TYPEPAIR_TYPE(header->typepair);
} }
} else { } else {
base = DNS_TYPEPAIR_TYPE(header->typepair); base = DNS_TYPEPAIR_TYPE(header->typepair);
@ -1038,8 +1039,15 @@ bindrdataset(qpcache_t *qpdb, qpcnode_t *node, dns_slabheader_t *header,
rdataset->methods = &dns_rdataslab_rdatasetmethods; rdataset->methods = &dns_rdataslab_rdatasetmethods;
rdataset->rdclass = qpdb->common.rdclass; rdataset->rdclass = qpdb->common.rdclass;
if (NEGATIVE(header)) {
rdataset->type = dns_rdatatype_none;
rdataset->covers = DNS_TYPEPAIR_TYPE(header->typepair);
INSIST(DNS_TYPEPAIR_COVERS(header->typepair) ==
dns_rdatatype_none);
} else {
rdataset->type = DNS_TYPEPAIR_TYPE(header->typepair); rdataset->type = DNS_TYPEPAIR_TYPE(header->typepair);
rdataset->covers = DNS_TYPEPAIR_COVERS(header->typepair); rdataset->covers = DNS_TYPEPAIR_COVERS(header->typepair);
}
rdataset->ttl = !ZEROTTL(header) ? header->expire - now : 0; rdataset->ttl = !ZEROTTL(header) ? header->expire - now : 0;
rdataset->trust = header->trust; rdataset->trust = header->trust;
rdataset->resign = 0; rdataset->resign = 0;
@ -1150,7 +1158,7 @@ setup_delegation(qpc_search_t *search, dns_dbnode_t **nodep,
NODE_UNLOCK(nlock, &nlocktype); NODE_UNLOCK(nlock, &nlocktype);
} }
if (typepair == dns_rdatatype_dname) { if (typepair == DNS_TYPEPAIR_VALUE(dns_rdatatype_dname, 0)) {
return DNS_R_DNAME; return DNS_R_DNAME;
} }
return DNS_R_DELEGATION; return DNS_R_DELEGATION;
@ -1222,28 +1230,39 @@ check_stale_header(dns_slabheader_t *header, qpc_search_t *search,
*/ */
static bool static bool
related_headers(dns_slabheader_t *header, dns_typepair_t typepair, related_headers(dns_slabheader_t *header, dns_typepair_t typepair,
dns_typepair_t sigpair, dns_typepair_t negpair, dns_typepair_t sigpair, dns_slabheader_t **foundp,
dns_slabheader_t **foundp, dns_slabheader_t **foundsigp, dns_slabheader_t **foundsigp, bool *matchp) {
bool *matchp) {
if (!EXISTS(header) || ANCIENT(header)) { if (!EXISTS(header) || ANCIENT(header)) {
return false; return false;
} }
if (header->typepair == typepair) { if (header->typepair == typepair && NEGATIVE(header)) {
/*
* In theory, the RRSIG(type) should not exist, but in reality,
* both the LRU and TTL based cleaning can delete one, but not
* the other. The INSIST below should be restored when we add
* a more strict synchronization between the type and its
* signature.
*/
/* INSIST(*foundsigp == NULL); */
*foundp = header;
SET_IF_NOT_NULL(matchp, true);
return true;
} else if (header->typepair == typepair) {
*foundp = header; *foundp = header;
SET_IF_NOT_NULL(matchp, true); SET_IF_NOT_NULL(matchp, true);
if (*foundsigp != NULL) { if (*foundsigp != NULL) {
return true; return true;
} }
} else if (header->typepair == sigpair) { } else if (header->typepair == sigpair) {
INSIST(!NEGATIVE(header));
*foundsigp = header; *foundsigp = header;
SET_IF_NOT_NULL(matchp, true); SET_IF_NOT_NULL(matchp, true);
if (*foundp != NULL) { if (*foundp != NULL) {
return true; return true;
} }
} else if (negpair != 0 && (header->typepair == RDATATYPE_NCACHEANY || } else if (header->typepair == dns_typepair_any) {
header->typepair == negpair)) INSIST(NEGATIVE(header));
{
*foundp = header; *foundp = header;
*foundsigp = NULL; *foundsigp = NULL;
SET_IF_NOT_NULL(matchp, true); SET_IF_NOT_NULL(matchp, true);
@ -1262,8 +1281,13 @@ both_headers(dns_slabheader_t *header, dns_rdatatype_t type,
dns_typepair_t typepair = DNS_TYPEPAIR_VALUE(type, 0); dns_typepair_t typepair = DNS_TYPEPAIR_VALUE(type, 0);
dns_typepair_t sigpair = DNS_SIGTYPE(type); dns_typepair_t sigpair = DNS_SIGTYPE(type);
return related_headers(header, typepair, sigpair, 0, foundp, foundsigp, bool done = related_headers(header, typepair, sigpair, foundp,
NULL); foundsigp, NULL);
if (done && NEGATIVE(*foundp)) {
*foundp = NULL;
}
return done;
} }
static isc_result_t static isc_result_t
@ -1271,7 +1295,7 @@ check_zonecut(qpcnode_t *node, void *arg DNS__DB_FLARG) {
qpc_search_t *search = arg; qpc_search_t *search = arg;
dns_slabheader_t *header = NULL; dns_slabheader_t *header = NULL;
dns_slabheader_t *header_prev = NULL, *header_next = NULL; dns_slabheader_t *header_prev = NULL, *header_next = NULL;
dns_slabheader_t *dname_header = NULL, *sigdname_header = NULL; dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_result_t result; isc_result_t result;
isc_rwlock_t *nlock = NULL; isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none; isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
@ -1290,15 +1314,14 @@ check_zonecut(qpcnode_t *node, void *arg DNS__DB_FLARG) {
continue; continue;
} }
if (both_headers(header, dns_rdatatype_dname, &dname_header, if (both_headers(header, dns_rdatatype_dname, &found,
&sigdname_header)) &foundsig))
{ {
break; break;
} }
} }
if (dname_header != NULL && if (found != NULL && (!DNS_TRUST_PENDING(found->trust) ||
(!DNS_TRUST_PENDING(dname_header->trust) ||
(search->options & DNS_DBFIND_PENDINGOK) != 0)) (search->options & DNS_DBFIND_PENDINGOK) != 0))
{ {
/* /*
@ -1308,8 +1331,8 @@ check_zonecut(qpcnode_t *node, void *arg DNS__DB_FLARG) {
qpcnode_acquire(search->qpdb, node, nlocktype, qpcnode_acquire(search->qpdb, node, nlocktype,
isc_rwlocktype_none DNS__DB_FLARG_PASS); isc_rwlocktype_none DNS__DB_FLARG_PASS);
search->zonecut = node; search->zonecut = node;
search->zonecut_header = dname_header; search->zonecut_header = found;
search->zonecut_sigheader = sigdname_header; search->zonecut_sigheader = foundsig;
search->need_cleanup = true; search->need_cleanup = true;
result = DNS_R_PARTIALMATCH; result = DNS_R_PARTIALMATCH;
} else { } else {
@ -1463,15 +1486,12 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name,
continue; continue;
} }
if (DNS_TYPEPAIR_TYPE(header->typepair) == 0) {
continue;
}
if (both_headers(header, dns_rdatatype_nsec, &found, &foundsig)) if (both_headers(header, dns_rdatatype_nsec, &found, &foundsig))
{ {
break; break;
} }
} }
if (found != NULL) { if (found != NULL) {
if (nodep != NULL) { if (nodep != NULL) {
qpcnode_acquire(search->qpdb, node, nlocktype, qpcnode_acquire(search->qpdb, node, nlocktype,
@ -1543,7 +1563,7 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
dns_slabheader_t *found = NULL, *nsheader = NULL; dns_slabheader_t *found = NULL, *nsheader = NULL;
dns_slabheader_t *foundsig = NULL, *nssig = NULL, *cnamesig = NULL; dns_slabheader_t *foundsig = NULL, *nssig = NULL, *cnamesig = NULL;
dns_slabheader_t *nsecheader = NULL, *nsecsig = NULL; dns_slabheader_t *nsecheader = NULL, *nsecsig = NULL;
dns_typepair_t typepair, sigpair, negpair; dns_typepair_t typepair, sigpair;
qpc_search_t search; qpc_search_t search;
qpc_search_init(&search, (qpcache_t *)db, options, __now); qpc_search_init(&search, (qpcache_t *)db, options, __now);
@ -1650,9 +1670,8 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
*/ */
found = NULL; found = NULL;
foundsig = NULL; foundsig = NULL;
typepair = DNS_TYPEPAIR_VALUE(type, 0); typepair = DNS_TYPEPAIR(type);
sigpair = DNS_SIGTYPE(type); sigpair = DNS_SIGTYPE(type);
negpair = DNS_TYPEPAIR_VALUE(0, type);
nsheader = NULL; nsheader = NULL;
nsecheader = NULL; nsecheader = NULL;
nssig = NULL; nssig = NULL;
@ -1687,7 +1706,7 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
} }
bool match = false; bool match = false;
if (related_headers(header, typepair, sigpair, negpair, &found, if (related_headers(header, typepair, sigpair, &found,
&foundsig, &match) && &foundsig, &match) &&
!MISSING_ANSWER(found, options)) !MISSING_ANSWER(found, options))
{ {
@ -1706,6 +1725,18 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
continue; continue;
} }
if (NEGATIVE(header)) {
/*
* FIXME: As of now, we are not interested in
* the negative headers. This could be
* improved and we can bail out early if we've
* seen all the types below (positive or
* negative), but the code is not yet ready
* for this.
*/
continue;
}
switch (header->typepair) { switch (header->typepair) {
case dns_rdatatype_cname: case dns_rdatatype_cname:
if (!cname_ok) { if (!cname_ok) {
@ -1746,9 +1777,7 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
break; break;
default: default:
if (typepair == dns_rdatatype_any && if (typepair == dns_typepair_any) {
DNS_TYPEPAIR_TYPE(header->typepair) != 0)
{
/* QTYPE==ANY, so any anwers will do */ /* QTYPE==ANY, so any anwers will do */
found = header; found = header;
break; break;
@ -1856,8 +1885,8 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
result = DNS_R_NCACHENXRRSET; result = DNS_R_NCACHENXRRSET;
} }
} else if (typepair != found->typepair && } else if (typepair != found->typepair &&
typepair != dns_rdatatype_any && typepair != dns_typepair_any &&
found->typepair == dns_rdatatype_cname) found->typepair == DNS_TYPEPAIR(dns_rdatatype_cname))
{ {
/* /*
* We weren't doing an ANY query and we found a CNAME instead * We weren't doing an ANY query and we found a CNAME instead
@ -1872,7 +1901,7 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
result = ISC_R_SUCCESS; result = ISC_R_SUCCESS;
} }
if (typepair != dns_rdatatype_any || result == DNS_R_NCACHENXDOMAIN || if (typepair != dns_typepair_any || result == DNS_R_NCACHENXDOMAIN ||
result == DNS_R_NCACHENXRRSET) result == DNS_R_NCACHENXRRSET)
{ {
bindrdatasets(search.qpdb, node, found, foundsig, search.now, bindrdatasets(search.qpdb, node, found, foundsig, search.now,
@ -1921,8 +1950,8 @@ seek_ns_headers(qpc_search_t *search, qpcnode_t *node, dns_dbnode_t **nodep,
for (header = node->data; header != NULL; header = header_next) { for (header = node->data; header != NULL; header = header_next) {
header_next = header->next; header_next = header->next;
bool ns = (header->typepair == dns_rdatatype_ns || bool ns = header->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) ||
header->typepair == DNS_SIGTYPE(dns_rdatatype_ns)); header->typepair == DNS_SIGTYPE(dns_rdatatype_ns);
if (check_stale_header(header, search, &header_prev)) { if (check_stale_header(header, search, &header_prev)) {
if (ns) { if (ns) {
/* /*
@ -2065,7 +2094,7 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_slabheader_t *header = NULL; dns_slabheader_t *header = NULL;
dns_slabheader_t *header_prev = NULL, *header_next = NULL; dns_slabheader_t *header_prev = NULL, *header_next = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL; dns_slabheader_t *found = NULL, *foundsig = NULL;
dns_typepair_t typepair, sigpair, negpair; dns_typepair_t typepair, sigpair;
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
isc_rwlock_t *nlock = NULL; isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none; isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
@ -2078,7 +2107,11 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
REQUIRE(version == NULL); REQUIRE(version == NULL);
REQUIRE(type != dns_rdatatype_any); REQUIRE(type != dns_rdatatype_any);
if (type == dns_rdatatype_none && covers == dns_rdatatype_none) { if (type == dns_rdatatype_none) {
/* We can't search negative cache directly */
return ISC_R_NOTFOUND;
}
if (dns_rdatatype_issig(type) && covers == dns_rdatatype_none) {
return ISC_R_NOTFOUND; return ISC_R_NOTFOUND;
} }
@ -2086,9 +2119,8 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
NODE_RDLOCK(nlock, &nlocktype); NODE_RDLOCK(nlock, &nlocktype);
typepair = DNS_TYPEPAIR_VALUE(type, covers); typepair = DNS_TYPEPAIR_VALUE(type, covers);
negpair = DNS_TYPEPAIR_VALUE(0, type); sigpair = !dns_rdatatype_issig(type) ? DNS_SIGTYPE(type)
sigpair = (covers == dns_rdatatype_none) ? DNS_SIGTYPE(type) : dns_typepair_none;
: dns_rdatatype_none;
for (header = qpnode->data; header != NULL; header = header_next) { for (header = qpnode->data; header != NULL; header = header_next) {
header_next = header->next; header_next = header->next;
@ -2097,12 +2129,13 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
continue; continue;
} }
if (related_headers(header, typepair, sigpair, negpair, &found, if (related_headers(header, typepair, sigpair, &found,
&foundsig, NULL)) &foundsig, NULL))
{ {
break; break;
} }
} }
if (found != NULL) { if (found != NULL) {
bindrdatasets(qpdb, qpnode, found, foundsig, search.now, bindrdatasets(qpdb, qpnode, found, foundsig, search.now,
nlocktype, isc_rwlocktype_none, rdataset, nlocktype, isc_rwlocktype_none, rdataset,
@ -2487,12 +2520,6 @@ overmaxtype(qpcache_t *qpdb, uint32_t ntypes) {
static bool static bool
prio_header(dns_slabheader_t *header) { prio_header(dns_slabheader_t *header) {
if (NEGATIVE(header) &&
prio_type(DNS_TYPEPAIR_COVERS(header->typepair)))
{
return true;
}
return prio_type(header->typepair); return prio_type(header->typepair);
} }
@ -2550,9 +2577,25 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
dns_slabheader_t *topheader = NULL, *topheader_prev = NULL; dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
dns_slabheader_t *header = NULL, *sigheader = NULL; dns_slabheader_t *header = NULL, *sigheader = NULL;
dns_slabheader_t *prioheader = NULL, *expireheader = NULL; dns_slabheader_t *prioheader = NULL, *expireheader = NULL;
dns_typepair_t negpair = 0;
dns_trust_t trust; dns_trust_t trust;
uint32_t ntypes = 0; uint32_t ntypes = 0;
dns_rdatatype_t rdtype = DNS_TYPEPAIR_TYPE(newheader->typepair);
dns_rdatatype_t covers = DNS_TYPEPAIR_COVERS(newheader->typepair);
dns_typepair_t sigpair = !dns_rdatatype_issig(rdtype)
? DNS_SIGTYPE(rdtype)
: dns_typepair_none;
REQUIRE(rdtype != dns_rdatatype_none);
if (dns_rdatatype_issig(rdtype)) {
/* signature must be positive, and cover a type */
REQUIRE(!NEGATIVE(newheader));
REQUIRE(covers != dns_rdatatype_none);
} else {
/* otherwise, it must cover nothing */
REQUIRE(covers == dns_rdatatype_none);
}
/* positive header can't be ANY */
REQUIRE(rdtype != dns_rdatatype_any || NEGATIVE(newheader));
if ((options & DNS_DBADD_FORCE) != 0) { if ((options & DNS_DBADD_FORCE) != 0) {
trust = dns_trust_ultimate; trust = dns_trust_ultimate;
@ -2561,15 +2604,11 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
} }
if (EXISTS(newheader)) { if (EXISTS(newheader)) {
dns_rdatatype_t rdtype = DNS_TYPEPAIR_TYPE(newheader->typepair);
dns_rdatatype_t covers =
DNS_TYPEPAIR_COVERS(newheader->typepair);
dns_typepair_t sigpair = DNS_SIGTYPE(covers);
if (NEGATIVE(newheader)) { if (NEGATIVE(newheader)) {
/* /*
* We're adding a negative cache entry. * We're adding a negative cache entry.
*/ */
if (covers == dns_rdatatype_any) { if (rdtype == dns_rdatatype_any) {
/* /*
* If we're adding an negative cache entry * If we're adding an negative cache entry
* which covers all types (NXDOMAIN, * which covers all types (NXDOMAIN,
@ -2599,27 +2638,37 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
break; break;
} }
} }
negpair = DNS_TYPEPAIR_VALUE(covers,
dns_rdatatype_none);
} else { } else {
/* /*
* We're adding something that isn't a * We're adding something that isn't a
* negative cache entry. Look for an extant * negative cache entry.
* non-ancient NXDOMAIN/NODATA(QTYPE=ANY) negative
* cache entry. If we're adding an RRSIG, also
* check for an extant non-ancient NODATA ncache
* entry which covers the same type as the RRSIG.
*/ */
for (topheader = qpnode->data; topheader != NULL; for (topheader = qpnode->data; topheader != NULL;
topheader = topheader->next) topheader = topheader->next)
{ {
if ((topheader->typepair == /*
RDATATYPE_NCACHEANY) || * Look for any existing negative cache
(newheader->typepair == sigpair && * entries.
topheader->typepair == */
DNS_TYPEPAIR_VALUE( if (!NEGATIVE(topheader)) {
dns_rdatatype_none, continue;
covers))) }
/*
* If we find a cached NXDOMAIN, don't
* cache anything else.
*/
if (topheader->typepair == dns_typepair_any) {
break;
}
/*
* Don't cache an RRSIG if it cover a type
* for which we have a cached NODATA record.
*/
if (newheader->typepair == sigpair &&
DNS_TYPEPAIR_TYPE(topheader->typepair) ==
covers)
{ {
break; break;
} }
@ -2654,7 +2703,6 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
topheader = NULL; topheader = NULL;
goto find_header; goto find_header;
} }
negpair = DNS_TYPEPAIR_VALUE(0, rdtype);
} }
} }
@ -2669,9 +2717,7 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
prioheader = topheader; prioheader = topheader;
} }
if (topheader->typepair == newheader->typepair || if (topheader->typepair == newheader->typepair) {
topheader->typepair == negpair)
{
break; break;
} }
topheader_prev = topheader; topheader_prev = topheader;
@ -2719,8 +2765,9 @@ find_header:
* normally further down. * normally further down.
*/ */
if (ACTIVE(header, now) && if (ACTIVE(header, now) &&
header->typepair == dns_rdatatype_ns && EXISTS(header) && header->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
EXISTS(newheader) && header->trust >= newheader->trust && EXISTS(header) && EXISTS(newheader) &&
header->trust >= newheader->trust &&
dns_rdataslab_equalx(header, newheader, dns_rdataslab_equalx(header, newheader,
qpdb->common.rdclass, qpdb->common.rdclass,
DNS_TYPEPAIR_TYPE(header->typepair))) DNS_TYPEPAIR_TYPE(header->typepair)))
@ -2762,8 +2809,9 @@ find_header:
* ensures the delegations that are withdrawn are honoured. * ensures the delegations that are withdrawn are honoured.
*/ */
if (ACTIVE(header, now) && if (ACTIVE(header, now) &&
header->typepair == dns_rdatatype_ns && EXISTS(header) && header->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
EXISTS(newheader) && header->trust <= newheader->trust) EXISTS(header) && EXISTS(newheader) &&
header->trust <= newheader->trust)
{ {
if (newheader->expire > header->expire) { if (newheader->expire > header->expire) {
newheader->expire = header->expire; newheader->expire = header->expire;
@ -2771,9 +2819,9 @@ find_header:
} }
if (ACTIVE(header, now) && if (ACTIVE(header, now) &&
(options & DNS_DBADD_PREFETCH) == 0 && (options & DNS_DBADD_PREFETCH) == 0 &&
(header->typepair == dns_rdatatype_a || (header->typepair == DNS_TYPEPAIR(dns_rdatatype_a) ||
header->typepair == dns_rdatatype_aaaa || header->typepair == DNS_TYPEPAIR(dns_rdatatype_aaaa) ||
header->typepair == dns_rdatatype_ds || header->typepair == DNS_TYPEPAIR(dns_rdatatype_ds) ||
header->typepair == DNS_SIGTYPE(dns_rdatatype_ds)) && header->typepair == DNS_SIGTYPE(dns_rdatatype_ds)) &&
EXISTS(header) && EXISTS(newheader) && EXISTS(header) && EXISTS(newheader) &&
header->trust >= newheader->trust && header->trust >= newheader->trust &&
@ -3132,13 +3180,24 @@ qpcache_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
dns_slabheader_t *newheader = NULL; dns_slabheader_t *newheader = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none; isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL; isc_rwlock_t *nlock = NULL;
uint16_t attributes = DNS_SLABHEADERATTR_NONEXISTENT;
REQUIRE(VALID_QPDB(qpdb)); REQUIRE(VALID_QPDB(qpdb));
REQUIRE(version == NULL); REQUIRE(version == NULL);
/* Positive ANY type can't be in the cache. */
if (type == dns_rdatatype_any) { if (type == dns_rdatatype_any) {
return ISC_R_NOTIMPLEMENTED; return ISC_R_NOTIMPLEMENTED;
} }
/* Convert the negative type into positive type. */
if (type == dns_rdatatype_none && covers != dns_rdatatype_none) {
type = covers;
covers = dns_rdatatype_none;
attributes |= DNS_SLABHEADERATTR_NEGATIVE;
}
/* RRSIG must have covered type */
if (type == dns_rdatatype_rrsig && covers == dns_rdatatype_none) { if (type == dns_rdatatype_rrsig && covers == dns_rdatatype_none) {
return ISC_R_NOTIMPLEMENTED; return ISC_R_NOTIMPLEMENTED;
} }
@ -3146,7 +3205,7 @@ qpcache_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
newheader = dns_slabheader_new(db, node); newheader = dns_slabheader_new(db, node);
newheader->typepair = DNS_TYPEPAIR_VALUE(type, covers); newheader->typepair = DNS_TYPEPAIR_VALUE(type, covers);
setttl(newheader, 0); setttl(newheader, 0);
atomic_init(&newheader->attributes, DNS_SLABHEADERATTR_NONEXISTENT); atomic_init(&newheader->attributes, attributes);
nlock = &qpdb->buckets[qpnode->locknum].lock; nlock = &qpdb->buckets[qpnode->locknum].lock;
NODE_WRLOCK(nlock, &nlocktype); NODE_WRLOCK(nlock, &nlocktype);

View File

@ -1648,7 +1648,7 @@ qpzone_findrdataset(dns_db_t *db, dns_dbnode_t *dbnode,
if (covers == dns_rdatatype_none) { if (covers == dns_rdatatype_none) {
sigpair = DNS_SIGTYPE(type); sigpair = DNS_SIGTYPE(type);
} else { } else {
sigpair = dns_rdatatype_none; sigpair = dns_typepair_none;
} }
for (header = node->data; header != NULL; header = header_next) { for (header = node->data; header != NULL; header = header_next) {
@ -3110,7 +3110,7 @@ find_closest_nsec(qpz_search_t *search, dns_dbnode_t **nodep,
dns_name_t *name = dns_fixedname_initname(&fname); dns_name_t *name = dns_fixedname_initname(&fname);
dns_rdatatype_t matchtype = nsec3 ? dns_rdatatype_nsec3 dns_rdatatype_t matchtype = nsec3 ? dns_rdatatype_nsec3
: dns_rdatatype_nsec; : dns_rdatatype_nsec;
dns_typepair_t typepair = DNS_TYPEPAIR_VALUE(matchtype, 0); dns_typepair_t typepair = DNS_TYPEPAIR(matchtype);
dns_typepair_t sigpair = DNS_SIGTYPE(matchtype); dns_typepair_t sigpair = DNS_SIGTYPE(matchtype);
bool wraps = nsec3; bool wraps = nsec3;
bool first = true; bool first = true;

View File

@ -350,10 +350,23 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
result = makeslab(rdataset, mctx, region, maxrrperset); result = makeslab(rdataset, mctx, region, maxrrperset);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
dns_slabheader_t *new = (dns_slabheader_t *)region->base; dns_slabheader_t *new = (dns_slabheader_t *)region->base;
dns_typepair_t typepair;
if (rdataset->attributes.negative) {
INSIST(rdataset->type == dns_rdatatype_none);
INSIST(rdataset->covers != dns_rdatatype_none);
typepair = DNS_TYPEPAIR_VALUE(rdataset->covers,
dns_rdatatype_none);
} else {
INSIST(rdataset->type != dns_rdatatype_none);
INSIST(dns_rdatatype_issig(rdataset->type) ||
rdataset->covers == dns_rdatatype_none);
typepair = DNS_TYPEPAIR_VALUE(rdataset->type,
rdataset->covers);
}
*new = (dns_slabheader_t){ *new = (dns_slabheader_t){
.typepair = DNS_TYPEPAIR_VALUE(rdataset->type, .typepair = typepair,
rdataset->covers),
.trust = rdataset->trust, .trust = rdataset->trust,
.ttl = rdataset->ttl, .ttl = rdataset->ttl,
.link = ISC_LINK_INITIALIZER, .link = ISC_LINK_INITIALIZER,
@ -940,25 +953,11 @@ dns_slabheader_freeproof(isc_mem_t *mctx, dns_slabheader_proof_t **proofp) {
dns_slabheader_t * dns_slabheader_t *
dns_slabheader_top(dns_slabheader_t *header) { dns_slabheader_top(dns_slabheader_t *header) {
dns_typepair_t typepair, negpair;
dns_rdatatype_t rdtype, covers;
typepair = header->typepair;
rdtype = DNS_TYPEPAIR_TYPE(header->typepair);
if (NEGATIVE(header)) {
covers = DNS_TYPEPAIR_COVERS(header->typepair);
negpair = DNS_TYPEPAIR_VALUE(covers, 0);
} else {
negpair = DNS_TYPEPAIR_VALUE(0, rdtype);
}
/* /*
* Find the start of the header chain for the next type * Find the start of the header chain for the next type
* by walking back up the list. * by walking back up the list.
*/ */
while (header->up != NULL && (header->up->typepair == typepair || while (header->up != NULL && header->up->typepair == header->typepair) {
header->up->typepair == negpair))
{
header = header->up; header = header->up;
} }