while (tresult == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter,
rctx->rdataset);
- if (rctx->rdataset->type != 0) {
+ if (!rctx->rdataset->attributes.negative) {
ISC_LIST_APPEND(ansname->list,
rctx->rdataset, link);
n++;
* Notes:
*
* \li In a cache database, a negative cache entry is stored under the
- * type it covers. Passing 'type' == dns_rdatatype_none with 'covers'
- * set (the shape in which rdataset iterators return negative entries)
- * deletes the cache entry for the covered type, whether it is positive
- * or negative.
+ * type whose nonexistence it proves (dns_rdatatype_any for NXDOMAIN
+ * and NODATA(QTYPE=ANY) entries), so deleting 'type' removes the
+ * cache entry for that type whether it is positive or negative.
*
* Requires:
*
isc_result_t
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
- dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
+ dns_rdatatype_t rdtype, isc_stdtime_t now, dns_ttl_t minttl,
dns_ttl_t maxttl, bool optout, bool secure,
dns_rdataset_t *addedrdataset);
/*%<
* \li If 'secure' is false, the negative cache entry's trust level
* will be capped at answer.
*
- * The 'covers' argument is the RR type whose nonexistence we are caching,
+ * The 'rdtype' argument is the RR type whose nonexistence we are caching,
* or dns_rdatatype_any when caching a NXDOMAIN response.
*
* 'optout' parameter indicates if 'optout' attribute should be set. This only
#include <dns/types.h>
#if DNS_TYPEPAIR_CHECK
-#define DNS__TYPEPAIR_CHECK(base, covers) \
- INSIST((dns_rdatatype_issig(base) && covers != dns_rdatatype_none) || \
- (base == dns_rdatatype_none && covers != dns_rdatatype_none) || \
+#define DNS__TYPEPAIR_CHECK(base, covers) \
+ INSIST((dns_rdatatype_issig(base) && covers != dns_rdatatype_none) || \
(base != dns_rdatatype_none && covers == dns_rdatatype_none))
#else
#define DNS__TYPEPAIR_CHECK(base, covers) (void)(base), (void)(covers)
bool first = true;
uint32_t current_ttl;
bool current_ttl_valid;
- dns_rdatatype_t type;
unsigned int type_start;
dns_fixedname_t fixed;
dns_name_t *name = NULL;
/*
* Type.
*/
-
- if (rdataset->attributes.negative) {
- type = rdataset->covers;
- } else {
- type = rdataset->type;
- }
-
INDENT_TO(type_column);
type_start = target->used;
if (rdataset->attributes.negative) {
RETERR(str_totext("\\-", target));
}
- switch (type) {
+ switch (rdataset->type) {
case dns_rdatatype_keydata:
#define KEYDATA "KEYDATA"
if ((ctx->style.flags & DNS_STYLEFLAG_KEYDATA) != 0) {
if ((ctx->style.flags & DNS_STYLEFLAG_UNKNOWNFORMAT) !=
0)
{
- result = dns_rdatatype_tounknowntext(type,
- target);
+ result = dns_rdatatype_tounknowntext(
+ rdataset->type, target);
} else {
- result = dns_rdatatype_totext(type, target);
+ result = dns_rdatatype_totext(rdataset->type,
+ target);
}
if (result != ISC_R_SUCCESS) {
return result;
isc_result_t
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
- dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
+ dns_rdatatype_t rdtype, isc_stdtime_t now, dns_ttl_t minttl,
dns_ttl_t maxttl, bool optout, bool secure,
dns_rdataset_t *addedrdataset) {
isc_buffer_t buffer;
*/
dns_rdatalist_init(&ncrdatalist);
ncrdatalist.rdclass = dns_db_class(cache);
- ncrdatalist.covers = covers;
+ ncrdatalist.type = rdtype;
+ ncrdatalist.covers = dns_rdatatype_none;
ncrdatalist.ttl = maxttl;
/*
*/
REQUIRE(rdataset != NULL);
- REQUIRE(rdataset->type == dns_rdatatype_none);
+ REQUIRE(rdataset->type != dns_rdatatype_none);
+ REQUIRE(rdataset->covers == dns_rdatatype_none);
REQUIRE(rdataset->attributes.negative);
savedbuffer = *target;
REQUIRE(ncacherdataset != NULL);
REQUIRE(DNS_RDATASET_VALID(ncacherdataset));
- REQUIRE(ncacherdataset->type == dns_rdatatype_none);
+ REQUIRE(ncacherdataset->type != dns_rdatatype_none);
+ REQUIRE(ncacherdataset->covers == dns_rdatatype_none);
REQUIRE(ncacherdataset->attributes.negative);
REQUIRE(name != NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
unsigned int count;
REQUIRE(ncacherdataset != NULL);
- REQUIRE(ncacherdataset->type == dns_rdatatype_none);
+ REQUIRE(ncacherdataset->type != dns_rdatatype_none);
+ REQUIRE(ncacherdataset->covers == dns_rdatatype_none);
REQUIRE(ncacherdataset->attributes.negative);
REQUIRE(name != NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
unsigned char *raw;
REQUIRE(ncacherdataset != NULL);
- REQUIRE(ncacherdataset->type == dns_rdatatype_none);
+ REQUIRE(ncacherdataset->type != dns_rdatatype_none);
+ REQUIRE(ncacherdataset->covers == dns_rdatatype_none);
REQUIRE(ncacherdataset->attributes.negative);
REQUIRE(found != NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
rdataset->methods = &dns_rdataslab_rdatasetmethods;
rdataset->rdclass = qpdb->common.rdclass;
- if (NEGATIVE(header)) {
- /*
- * Convert the internal represetation of a negative record
- * to the rdataset representation (type=0, covers=type).
- */
- 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->covers = DNS_TYPEPAIR_COVERS(header->typepair);
- }
+ rdataset->type = DNS_TYPEPAIR_TYPE(header->typepair);
+ rdataset->covers = DNS_TYPEPAIR_COVERS(header->typepair);
rdataset->ttl = !ZEROTTL(header) ? header->expire - now : 0;
rdataset->trust = header_trust(header);
rdataset->resign = 0;
dns_slabheader_t *nsecheader = NULL, *nsecsig = NULL;
dns_typepair_t typepair = DNS_TYPEPAIR(type);
- if (type == dns_rdatatype_none) {
- /* We can't search negative cache directly */
+ /*
+ * Meta-types can't exist in the cache, with the sole exception
+ * of ANY, which matches any type at the node (both ANY and
+ * RRSIG queries are looked up as ANY).
+ */
+ if (type == dns_rdatatype_none ||
+ (dns_rdatatype_ismeta(type) && type != dns_rdatatype_any))
+ {
return ISC_R_NOTFOUND;
}
qpcache_t *qpdb = (qpcache_t *)db;
qpcnode_t *qpnode = (qpcnode_t *)node;
dns_slabheader_t *found = NULL, *foundsig = NULL;
- dns_typepair_t typepair, sigpair;
+ dns_typepair_t typepair = DNS_TYPEPAIR_VALUE(type, covers);
+ dns_typepair_t sigpair = !dns_rdatatype_issig(type)
+ ? DNS_SIGTYPEPAIR(type)
+ : dns_typepair_none;
isc_result_t result = ISC_R_SUCCESS;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
REQUIRE(version == NULL);
REQUIRE(type != dns_rdatatype_any);
- if (type == dns_rdatatype_none) {
- /* We can't search negative cache directly */
+ /*
+ * Meta-types can't exist in the cache, with the sole
+ * exception of ANY, which records the nonexistence of all
+ * types at the node (NXDOMAIN or NODATA(QTYPE=ANY) proof),
+ * but can't be looked up using this function.
+ */
+ if (type == dns_rdatatype_none || dns_rdatatype_ismeta(type)) {
return ISC_R_NOTFOUND;
}
nlock = &qpdb->buckets[qpnode->locknum].lock;
NODE_RDLOCK(nlock, &nlocktype);
- typepair = DNS_TYPEPAIR_VALUE(type, covers);
- sigpair = (type != dns_rdatatype_rrsig) ? DNS_SIGTYPEPAIR(type)
- : dns_typepair_none;
-
DNS_SLABHEADER_FOREACH(tmp, &qpnode->headers) {
dns_slabheader_t *header = NULL, *sigheader = NULL;
REQUIRE(VALID_QPDB(qpdb));
REQUIRE(version == NULL);
+ /*
+ * Meta-types can't be added to the cache, with the sole
+ * exception of a negative ANY entry, which records the
+ * nonexistence of all types at the node (NXDOMAIN or
+ * NODATA(QTYPE=ANY) proof).
+ */
+ if (rdataset->type == dns_rdatatype_none ||
+ (dns_rdatatype_ismeta(rdataset->type) &&
+ !(rdataset->type == dns_rdatatype_any &&
+ rdataset->attributes.negative)))
+ {
+ return ISC_R_NOTIMPLEMENTED;
+ }
+
result = dns_rdataslab_fromrdataset(rdataset, qpnode->mctx, ®ion,
qpdb->maxrrperset);
if (result != ISC_R_SUCCESS) {
REQUIRE(VALID_QPDB(qpdb));
REQUIRE(version == NULL);
- /* Positive ANY type can't be in the cache. */
- if (type == dns_rdatatype_any) {
- return ISC_R_NOTIMPLEMENTED;
- }
-
/*
- * Convert the rdataset representation of a negative record
- * (type=0, covers=type) to the internal representation (the
- * other way around).
+ * Type none can't exist in the cache; note that type ANY is
+ * a valid argument here because it matches the negative cache
+ * entry left behind by an NXDOMAIN or NODATA(QTYPE=ANY) response.
*/
- if (type == dns_rdatatype_none && covers != dns_rdatatype_none) {
- type = covers;
- covers = dns_rdatatype_none;
+ if (type == dns_rdatatype_none ||
+ (dns_rdatatype_ismeta(type) && type != dns_rdatatype_any))
+ {
+ return ISC_R_NOTIMPLEMENTED;
}
typepair = DNS_TYPEPAIR_VALUE(type, covers);
/*
* If there are no rdata then we just need to allocate a header
- * with a zero record count.
+ * with a zero record count. Only a negative cache entry (e.g.
+ * an uncacheable NODATA proof) may be empty.
*/
nitems = dns_rdataset_count(rdataset);
if (nitems == 0) {
- if (rdataset->type != 0) {
+ if (!rdataset->attributes.negative) {
return ISC_R_FAILURE;
}
(void)newslab(rdataset, mctx, region, 0, buflen, func, file,
}
/*
- * Ensure that singleton types are actually singletons.
+ * Ensure that singleton types are actually singletons. The check
+ * doesn't apply to a negative cache entry: it stores ncache-encoded
+ * records rather than RRs of 'rdataset->type'.
*/
- if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
+ if (nitems > 1 && !rdataset->attributes.negative &&
+ dns_rdatatype_issingleton(rdataset->type))
+ {
/*
* We have a singleton type, but there's more than one
* RR in the rdataset.
}
dns_slabheader_t *header = (dns_slabheader_t *)region->base;
- if (rdataset->attributes.negative) {
- INSIST(rdataset->type == dns_rdatatype_none);
- INSIST(rdataset->covers != dns_rdatatype_none);
- header->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);
- header->typepair = DNS_TYPEPAIR_VALUE(rdataset->type,
- rdataset->covers);
- }
+ INSIST(rdataset->type != dns_rdatatype_none);
+ INSIST(dns_rdatatype_issig(rdataset->type) ||
+ rdataset->covers == dns_rdatatype_none);
+ header->typepair = DNS_TYPEPAIR_VALUE(rdataset->type, rdataset->covers);
return ISC_R_SUCCESS;
}
result = makevec(rdataset, mctx, region, maxrrperset);
if (result == ISC_R_SUCCESS) {
dns_vecheader_t *new = (dns_vecheader_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);
- }
+ INSIST(!rdataset->attributes.negative);
+ INSIST(rdataset->type != dns_rdatatype_none);
+ INSIST(dns_rdatatype_issig(rdataset->type) ||
+ rdataset->covers == dns_rdatatype_none);
/*
* Reset the vecheader content, but keep the refcount and mctx.
*/
*new = (dns_vecheader_t){
.next_header = ISC_SLINK_INITIALIZER,
- .typepair = typepair,
+ .typepair = DNS_TYPEPAIR_VALUE(rdataset->type,
+ rdataset->covers),
.trust = rdataset->trust,
.ttl = rdataset->ttl,
.references = atomic_load_acquire(&new->references),
isc_result_t result;
dns_ttl_t minttl = fctx->res->view->minncachettl;
dns_ttl_t maxttl = fctx->res->view->maxncachettl;
- dns_rdatatype_t covers = fctx->type;
+ dns_rdatatype_t rdtype = fctx->type;
dns_db_t *cache = fctx->cache;
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset = DNS_RDATASET_INIT;
if (message->rcode == dns_rcode_nxdomain &&
fctx->type != dns_rdatatype_ds)
{
- covers = dns_rdatatype_any;
+ rdtype = dns_rdatatype_any;
}
/*
* to zero to facilitate locating the containing zone of
* an arbitrary zone.
*/
- if (fctx->type == dns_rdatatype_soa && covers == dns_rdatatype_any &&
+ if (fctx->type == dns_rdatatype_soa && rdtype == dns_rdatatype_any &&
fctx->res->zero_no_soa_ttl)
{
maxttl = 0;
*/
RETERR(dns_db_findnode(fctx->cache, name, true, &node));
- result = dns_ncache_add(message, cache, node, covers, now, minttl,
+ result = dns_ncache_add(message, cache, node, rdtype, now, minttl,
maxttl, optout, secure, added);
/*
* We got the same negative type that we were adding, everything
* is fine, continue.
*/
- if (NEGATIVE(added) && added->covers == covers) {
+ if (NEGATIVE(added) && added->type == rdtype) {
result = ISC_R_SUCCESS;
} else {
dns_rdataset_disassociate(added);
}
switch (result) {
- case ISC_R_SUCCESS:
+ case ISC_R_SUCCESS: {
+ bool have_dsset = !NEGATIVE(&val->frdataset) &&
+ val->frdataset.type == dns_rdatatype_ds;
+ dns_name_t *name = dns_fixedname_name(&val->fname);
+
validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
- val->frdataset.type == dns_rdatatype_ds
- ? "dsset"
- : "ds non-existence",
+ have_dsset ? "dsset" : "ds non-existence",
dns_trust_totext(val->frdataset.trust));
- bool have_dsset = (val->frdataset.type == dns_rdatatype_ds);
- dns_name_t *name = dns_fixedname_name(&val->fname);
if ((val->attributes & VALATTR_INSECURITY) != 0) {
bool crossed = false;
bool insecure = false;
- if (val->frdataset.covers == dns_rdatatype_ds &&
- NEGATIVE(&val->frdataset))
+ if (NEGATIVE(&val->frdataset) &&
+ val->frdataset.type == dns_rdatatype_ds)
{
insecure = is_insecure_referral(
val, name, &val->frdataset,
result = validate_async_run(val, validate_dnskey);
}
break;
+ }
case ISC_R_CANCELED: /* Validation was canceled */
case ISC_R_SHUTTINGDOWN: /* Server shutting down */
case ISC_R_QUOTA: /* Validation fails quota reached */
default:
UNREACHABLE();
}
- } else if (val->rdataset != NULL && val->rdataset->type != 0) {
+ } else if (val->rdataset != NULL && !NEGATIVE(val->rdataset)) {
/*
* This is either an unsecure subdomain or a response
* from a broken server.
dns_rdataset_disassociate(qctx->rdataset);
} else if ((qctx->qtype == dns_rdatatype_any ||
qctx->rdataset->type == qctx->qtype) &&
- qctx->rdataset->type != 0)
+ !qctx->rdataset->attributes.negative)
{
if (qctx->rdataset->attributes.noqname &&
qctx->client->inner.wantdnssec)