]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Store negative cache entries under their natural type 12481/head
authorOndřej Surý <ondrej@isc.org>
Thu, 30 Jul 2026 15:42:26 +0000 (17:42 +0200)
committerEvan Hunt <each@isc.org>
Fri, 31 Jul 2026 19:13:19 +0000 (19:13 +0000)
Negative cache entries were exposed through dns_rdataset_t in an
inverted shape (type=none, covers=<qtype>) while the cache internally
stored them under (<qtype>, none) with a NEGATIVE flag, so every
consumer had to convert between the two representations, and several
places relied on type==0 as an implicit negativity test.

Expose negative entries in their natural shape instead: type holds the
RR type whose nonexistence is cached (dns_rdatatype_any for NXDOMAIN
and NODATA(QTYPE=ANY) proofs), covers stays none, and the negative
attribute marks the entry.  The implicit type==0 tests become explicit
attribute checks, and the cache database now rejects meta-types other
than ANY, which remains valid as a lookup type and as a negative
entry.

12 files changed:
lib/dns/client.c
lib/dns/include/dns/db.h
lib/dns/include/dns/ncache.h
lib/dns/include/dns/rdatatype.h
lib/dns/masterdump.c
lib/dns/ncache.c
lib/dns/qpcache.c
lib/dns/rdataslab.c
lib/dns/rdatavec.c
lib/dns/resolver.c
lib/dns/validator.c
lib/ns/query.c

index c50126895e4d63773a31b442e82889bb754b2041..2f3730767814ee90477b5e2d4c2d2ecb8ca4c95b 100644 (file)
@@ -677,7 +677,7 @@ client_resfind(resctx_t *rctx, dns_fetchresponse_t *resp) {
                        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++;
index f97eb3dd8c6c36b7db11b4d6d96411ff687e7ade..66c501d3323444377e206667a5267a155a7f0418 100644 (file)
@@ -1360,10 +1360,9 @@ dns__db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
  * 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:
  *
index ae187668c8f12a4999c8423cf1a6e78cf907c381..e6bc6be8f75729f978c068752b3372ff287e844a 100644 (file)
@@ -53,7 +53,7 @@
 
 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);
 /*%<
@@ -67,7 +67,7 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
  * \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
index 1822daef07225d349f259e8d72cbb3510aa11b2a..7623ad135cfe910da70e2f94088fc336e2631b17 100644 (file)
@@ -18,9 +18,8 @@
 #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)
index 2040a832d03d69c7bd4cc4d58b0af71d4b69b68b..5ad7c7c894d4e70f6302d7b0631f8c867e56d823 100644 (file)
@@ -571,7 +571,6 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
        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;
@@ -697,19 +696,12 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
                /*
                 * 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) {
@@ -726,10 +718,11 @@ rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
                        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;
index 942df43a7f26f1c2f803a43f848ee4d839dbffd4..344435974fd495e185989aafee346e8e2c9d92e6 100644 (file)
@@ -92,7 +92,7 @@ copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
 
 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;
@@ -126,7 +126,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
         */
        dns_rdatalist_init(&ncrdatalist);
        ncrdatalist.rdclass = dns_db_class(cache);
-       ncrdatalist.covers = covers;
+       ncrdatalist.type = rdtype;
+       ncrdatalist.covers = dns_rdatatype_none;
        ncrdatalist.ttl = maxttl;
 
        /*
@@ -257,7 +258,8 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
         */
 
        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;
@@ -474,7 +476,8 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
 
        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));
@@ -540,7 +543,8 @@ dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
        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));
@@ -625,7 +629,8 @@ dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
        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));
index c84039da891fbc79f0d57e523570e1b3a556db66..a1431ac3538fb153af692ade911913f1c15df33f 100644 (file)
@@ -920,19 +920,8 @@ bindrdataset(qpcache_t *qpdb, qpcnode_t *node, dns_slabheader_t *header,
 
        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;
@@ -1433,8 +1422,14 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
        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;
        }
 
@@ -1739,7 +1734,10 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        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;
@@ -1752,18 +1750,19 @@ qpcache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        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;
 
@@ -2649,6 +2648,20 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        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, &region,
                                            qpdb->maxrrperset);
        if (result != ISC_R_SUCCESS) {
@@ -2774,19 +2787,15 @@ qpcache_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
        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);
index 107a1df4e50beb6dbcfa82b095b7ba0e86996674..cf8302525a6683626fa90e235aada1266aa373fe 100644 (file)
@@ -196,11 +196,12 @@ makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region,
 
        /*
         * 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,
@@ -301,9 +302,13 @@ makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region,
        }
 
        /*
-        * 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.
@@ -370,18 +375,10 @@ dns_rdataslab__fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
        }
 
        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;
 }
index 7436af85738868370206ae8fab251c193c1a246e..335737520d609f01ebea4617be6ad49d743eb4f5 100644 (file)
@@ -352,27 +352,19 @@ dns_rdatavec_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
        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),
index 96c83002fa0cd5cb341467d83f359ccf3dd5e239..9b0ac0ce48d23b944d69846132aaa4630518ff98 100644 (file)
@@ -6546,7 +6546,7 @@ negcache(dns_message_t *message, fetchctx_t *fctx, const dns_name_t *name,
        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;
@@ -6562,7 +6562,7 @@ negcache(dns_message_t *message, fetchctx_t *fctx, const dns_name_t *name,
        if (message->rcode == dns_rcode_nxdomain &&
            fctx->type != dns_rdatatype_ds)
        {
-               covers = dns_rdatatype_any;
+               rdtype = dns_rdatatype_any;
        }
 
        /*
@@ -6570,7 +6570,7 @@ negcache(dns_message_t *message, fetchctx_t *fctx, const dns_name_t *name,
         * 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;
@@ -6592,7 +6592,7 @@ negcache(dns_message_t *message, fetchctx_t *fctx, const dns_name_t *name,
         */
        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);
 
        /*
@@ -6605,7 +6605,7 @@ negcache(dns_message_t *message, fetchctx_t *fctx, const dns_name_t *name,
                 * 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);
index e13c8850a09e47d3878f2259cd0401b20991385a..213a681af246b218d527a7f579721a99156ce92e 100644 (file)
@@ -902,21 +902,21 @@ validator_callback_ds(void *arg) {
        }
 
        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,
@@ -942,6 +942,7 @@ validator_callback_ds(void *arg) {
                        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 */
@@ -3931,7 +3932,7 @@ validator_start(void *arg) {
                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.
index a39a9a4c6bba972d39b14081ff47054e4ffcd1fa..53da43f9d277aabc954cc6ce3dc046ff8692a5a3 100644 (file)
@@ -7367,7 +7367,7 @@ query_respond_any(query_ctx_t *qctx) {
                        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)