From: Ondřej Surý Date: Tue, 23 Sep 2025 07:54:52 +0000 (+0200) Subject: Refactor find headers to make use of related X-Git-Tag: v9.21.14~31^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3e05958a42400d6f88674ae3ed4f232e61d2d69a;p=thirdparty%2Fbind9.git Refactor find headers to make use of related Change the code of finding headers to make use of the related circular reference. Co-authored-by: Matthijs Mekking --- diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 62ad3e0775f..4702ff05d86 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -1234,7 +1234,8 @@ check_stale_header(dns_slabheader_t *header, qpc_search_t *search) { static bool check_header(dns_slabheader_t *header, qpc_search_t *search) { - return header == NULL || check_stale_header(header, search); + return header == NULL || check_stale_header(header, search) || + !EXISTS(header) || ANCIENT(header); } /* @@ -1243,78 +1244,121 @@ check_header(dns_slabheader_t *header, qpc_search_t *search) { * negative header covering either 'negtype' or ANY. */ static bool -related_headers(dns_slabheader_t *header, dns_typepair_t typepair, - dns_typepair_t sigpair, dns_slabheader_t **foundp, - dns_slabheader_t **foundsigp, bool *matchp) { - if (!EXISTS(header) || ANCIENT(header)) { - return false; +related_headers(dns_slabheader_t *header, dns_slabheader_t *sigheader, + dns_typepair_t typepair, dns_slabheader_t **foundp, + dns_slabheader_t **foundsigp) { + if (header != NULL) { + REQUIRE(DNS_TYPEPAIR_TYPE(header->typepair) != + dns_rdatatype_rrsig); + REQUIRE(DNS_TYPEPAIR_COVERS(header->typepair) == + dns_rdatatype_none); + } + if (sigheader != NULL) { + REQUIRE(DNS_TYPEPAIR_TYPE(sigheader->typepair) == + dns_rdatatype_rrsig); + REQUIRE(DNS_TYPEPAIR_COVERS(sigheader->typepair) != + dns_rdatatype_none || + NEGATIVE(sigheader)); } - 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; - SET_IF_NOT_NULL(matchp, true); - if (*foundsigp != NULL) { - return true; - } - } else if (header->typepair == sigpair) { - INSIST(!NEGATIVE(header)); - *foundsigp = header; - SET_IF_NOT_NULL(matchp, true); - if (*foundp != NULL) { - return true; - } - } else if (header->typepair == dns_typepair_any) { + /* + * Nothing exists if there's a NEGATIVE(dns_typepair_any). + */ + if (header != NULL && header->typepair == dns_typepair_any) { INSIST(NEGATIVE(header)); + INSIST(sigheader == NULL); *foundp = header; *foundsigp = NULL; - SET_IF_NOT_NULL(matchp, true); return true; } - return false; -} + /* + * Use the sigheader if we are looking for RRSIG. + */ + if (DNS_TYPEPAIR_TYPE(typepair) == dns_rdatatype_rrsig) { + if (sigheader == NULL) { + return false; + } -/* - * Return true if we've found headers for both 'type' and RRSIG('type'). - */ -static bool -both_headers(dns_slabheader_t *header, dns_rdatatype_t type, - dns_slabheader_t **foundp, dns_slabheader_t **foundsigp) { - dns_typepair_t typepair = DNS_TYPEPAIR_VALUE(type, 0); - dns_typepair_t sigpair = DNS_SIGTYPEPAIR(type); + REQUIRE(EXISTS(sigheader) && !ANCIENT(sigheader)); + if (sigheader->typepair == typepair) { + *foundp = sigheader; + *foundsigp = NULL; + return true; + } + return false; + } else { + if (header == NULL) { + return false; + } - bool done = related_headers(header, typepair, sigpair, foundp, - foundsigp, NULL); - if (done && NEGATIVE(*foundp)) { - *foundp = NULL; + REQUIRE(EXISTS(header) && !ANCIENT(header)); + REQUIRE(!NEGATIVE(header) || sigheader == NULL); + + if (header->typepair == typepair) { + *foundp = header; + *foundsigp = sigheader; + return true; + } } - return done; + return false; } static void find_headers(qpcnode_t *node, qpc_search_t *search, dns_rdatatype_t type, - dns_slabheader_t **found, dns_slabheader_t **foundsig) { + dns_slabheader_t **foundp, dns_slabheader_t **foundsigp) { DNS_SLABTOP_FOREACH(top, node->data) { - dns_slabheader_t *header = first_header(top); - if (check_header(header, search)) { + dns_slabheader_t *header = NULL, *sigheader = NULL; + dns_slabtop_t *related = top->related; + + if (top->typepair == dns_typepair_any) { + INSIST(top->related == NULL); + header = first_header(top); + INSIST(NEGATIVE(header)); + if (check_header(header, search)) { + /* + * NEGATIVE(ANY), but it is no longer valid. + */ + header = NULL; + continue; + } + *foundp = NULL; + *foundsigp = NULL; + return; + } + + if (top->typepair == DNS_TYPEPAIR(type)) { + header = first_header(top); + if (related != NULL) { + sigheader = first_header(related); + } + } else if (top->typepair == DNS_SIGTYPEPAIR(type)) { + sigheader = first_header(top); + if (related != NULL) { + header = first_header(related); + } + } else { + /* Not our type; continue with next slabtop */ continue; } - if (both_headers(header, type, found, foundsig)) { - break; + + if (check_header(header, search)) { + header = NULL; + } + if (check_header(sigheader, search)) { + sigheader = NULL; } + + /* + * This function only sets positive headers. + */ + if (header != NULL && !NEGATIVE(header)) { + *foundp = header; + *foundsigp = sigheader; + } + + return; } } @@ -1555,10 +1599,10 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, isc_rwlock_t *nlock = NULL; isc_rwlocktype_t tlocktype = isc_rwlocktype_none; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; - dns_slabheader_t *found = NULL, *nsheader = NULL; - dns_slabheader_t *foundsig = NULL, *nssig = NULL, *cnamesig = NULL; + dns_slabheader_t *found = NULL, *foundsig = NULL; + dns_slabheader_t *nsheader = NULL, *nssig = NULL; dns_slabheader_t *nsecheader = NULL, *nsecsig = NULL; - dns_typepair_t typepair, sigpair; + dns_typepair_t typepair; if (type == dns_rdatatype_none) { /* We can't search negative cache directly */ @@ -1670,20 +1714,35 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, found = NULL; foundsig = NULL; typepair = DNS_TYPEPAIR(type); - sigpair = (type != dns_rdatatype_rrsig) ? DNS_SIGTYPEPAIR(type) : 0; nsheader = NULL; nsecheader = NULL; nssig = NULL; nsecsig = NULL; - cnamesig = NULL; empty_node = true; + DNS_SLABTOP_FOREACH(top, node->data) { - dns_slabheader_t *header = first_header(top); + dns_slabheader_t *header = NULL, *sigheader = NULL; + if (DNS_TYPEPAIR_TYPE(top->typepair) == dns_rdatatype_rrsig) { + sigheader = first_header(top); + if (top->related != NULL) { + header = first_header(top->related); + } + } else { + header = first_header(top); + if (top->related != NULL) { + sigheader = first_header(top->related); + } + } + if (check_header(header, &search)) { - continue; + header = NULL; } - if (!EXISTS(header) || ANCIENT(header)) { + if (check_header(sigheader, &search)) { + sigheader = NULL; + } + + if (header == NULL && sigheader == NULL) { continue; } @@ -1693,20 +1752,22 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, */ empty_node = false; - if (header->noqname != NULL && + if (header != NULL && header->noqname != NULL && atomic_load(&header->trust) == dns_trust_secure) { found_noqname = true; } - if (!NEGATIVE(header)) { + if (header != NULL && !NEGATIVE(header)) { all_negative = false; } - bool match = false; - if (related_headers(header, typepair, sigpair, &found, - &foundsig, &match) && - !missing_answer(found, options)) + if (sigheader != NULL && !NEGATIVE(sigheader)) { + all_negative = false; + } + + if (related_headers(header, sigheader, typepair, &found, + &foundsig)) { /* * We can't exit early until we have an answer with @@ -1714,63 +1775,42 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, * for details - because we might need NS or NSEC * records. */ - break; - } + if (missing_answer(found, options)) { + continue; + } - if (match) { /* We found something, continue with next header */ - continue; + break; } - if (NEGATIVE(header)) { + if (header == NULL || 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. + * We are not interested in the negative headers for the + * auxiliary types, only for the main type we are + * looking for. */ continue; } switch (top->typepair) { case dns_rdatatype_cname: - if (!cname_ok) { - break; - } - - found = header; - if (cnamesig != NULL) { - /* We already have CNAME signature */ - foundsig = cnamesig; - } else { - /* Look for CNAME signature instead */ - sigpair = DNS_SIGTYPEPAIR(dns_rdatatype_cname); - foundsig = NULL; - } - break; case DNS_SIGTYPEPAIR(dns_rdatatype_cname): - if (!cname_ok) { - break; + if (cname_ok) { + found = header; + foundsig = sigheader; } - - cnamesig = header; break; + case dns_rdatatype_ns: - /* Remember the NS rdataset */ - nsheader = header; - break; case DNS_SIGTYPEPAIR(dns_rdatatype_ns): - /* ...and its signature */ - nssig = header; + nsheader = header; + nssig = sigheader; break; case dns_rdatatype_nsec: - nsecheader = header; - break; case DNS_SIGTYPEPAIR(dns_rdatatype_nsec): - nsecsig = header; + nsecheader = header; + nsecsig = sigheader; break; default: @@ -1780,6 +1820,10 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, break; } } + + if (!missing_answer(found, options)) { + break; + } } if (empty_node) { @@ -2091,16 +2135,37 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, : dns_typepair_none; DNS_SLABTOP_FOREACH(top, qpnode->data) { - dns_slabheader_t *header = first_header(top); - if (check_header(header, &search)) { + dns_slabheader_t *header = NULL, *sigheader = NULL; + + if (top->typepair != typepair && top->typepair != sigpair && + top->typepair != dns_typepair_any) + { continue; } - if (related_headers(header, typepair, sigpair, &found, - &foundsig, NULL)) - { - break; + if (DNS_TYPEPAIR_TYPE(top->typepair) == dns_rdatatype_rrsig) { + sigheader = first_header(top); + if (top->related != NULL) { + header = first_header(top->related); + } + } else { + header = first_header(top); + if (top->related != NULL) { + sigheader = first_header(top->related); + } } + + if (check_header(header, &search)) { + header = NULL; + } + + if (check_header(sigheader, &search)) { + sigheader = NULL; + } + + (void)related_headers(header, sigheader, typepair, &found, + &foundsig); + break; } if (found != NULL) {