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);
}
/*
* 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;
}
}
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 */
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;
}
*/
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
* 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:
break;
}
}
+
+ if (!missing_answer(found, options)) {
+ break;
+ }
}
if (empty_node) {
: 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) {