dns_rdatalist_t ncrdatalist;
unsigned char data[65536];
unsigned int next = 0;
- isc_result_t result;
/*
* Convert the authority data from 'message' into a negative cache
ncrdataset.attributes.optout = true;
}
- result = dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0,
- addedrdataset);
- if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
- return result;
- }
-
- return ISC_R_SUCCESS;
+ return dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0,
+ addedrdataset);
}
isc_result_t
trust = newheader->trust;
}
+ /*
+ * An unvalidated negative entry covering all types (NXDOMAIN or
+ * NODATA(QTYPE=ANY)) must not purge secure data. Check for it in a
+ * separate pass first: evicting as we go and bailing out later would
+ * destroy lower-trust siblings before we found the secure header.
+ */
+ if (EXISTS(newheader) && NEGATIVE(newheader) &&
+ rdtype == dns_rdatatype_any && trust < dns_trust_secure)
+ {
+ DNS_SLABHEADER_FOREACH(header, &qpnode->headers) {
+ if (header->trust >= dns_trust_secure) {
+ qpcache_hit(qpdb, header);
+ bindrdataset(qpdb, qpnode, header, now,
+ nlocktype, tlocktype,
+ addedrdataset DNS__DB_FLARG_PASS);
+ return DNS_R_UNCHANGED;
+ }
+ }
+ }
+
DNS_SLABHEADER_FOREACH(header, &qpnode->headers) {
if (EXISTS(newheader) && NEGATIVE(newheader)) {
if (rdtype == dns_rdatatype_any) {
static isc_result_t
rctx_timedout(respctx_t *rctx);
-static void
+static isc_result_t
rctx_ncache(respctx_t *rctx);
/*%
result = dns_ncache_add(message, cache, node, covers, now, minttl,
maxttl, optout, secure, added);
+ /*
+ * We failed to add the negative cache entry and some rdataset was
+ * returned. If we were adding dns_rdatatype_any, this could be of a
+ * different type than was originally requested.
+ */
+ if (result == DNS_R_UNCHANGED) {
+ /*
+ * We got the same negative type that we were adding, everything
+ * is fine, continue.
+ */
+ if (NEGATIVE(added) && added->covers == covers) {
+ result = ISC_R_SUCCESS;
+ } else {
+ dns_rdataset_disassociate(added);
+ dns_db_detachnode(&node);
+ return DNS_R_SERVFAIL;
+ }
+ }
+
if (added == &rdataset) {
dns_rdataset_cleanup(added);
}
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(&node);
+ return result;
+ }
+
*nodep = node;
return result;
}
* Cache the negatively cacheable parts of the message. This may
* also cause work to be queued to the DNSSEC validator.
*/
-static void
+static isc_result_t
rctx_ncache(respctx_t *rctx) {
isc_result_t result = ISC_R_SUCCESS;
fetchctx_t *fctx = rctx->fctx;
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("rctx_ncache complete", result);
}
+ return result;
}
static void
/*
* Negative caching
*/
- rctx_ncache(rctx);
+ isc_result_t nresult = rctx_ncache(rctx);
+ if (nresult != ISC_R_SUCCESS) {
+ result = nresult;
+ }
FCTXTRACE("resquery_response done");
rctx_done(rctx, result);