]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1997. [bug] Named was failing to replace negative cache entries
authorMark Andrews <marka@isc.org>
Thu, 2 Mar 2006 23:18:20 +0000 (23:18 +0000)
committerMark Andrews <marka@isc.org>
Thu, 2 Mar 2006 23:18:20 +0000 (23:18 +0000)
                        when a positive one for the type was learnt.
                        [RT #15818]

CHANGES
lib/dns/rbtdb.c

diff --git a/CHANGES b/CHANGES
index ba1216ebfd53b109ceb55bacc39d93002a672750..a8e79e2ec46d53a1ae1c0cd21a86dd575e1794cb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+1997.  [bug]           Named was failing to replace negative cache entries
+                       when a positive one for the type was learnt.
+                       [RT #15818]
+
 1995.  [bug]           'host' was reporting multiple "is an alias" messages.
                        [RT #15702]
 
index b1156bfb4813db25692b957b548ea68b52884ef8..8930d355fd0abc453c02f2efdba680e24076d3da 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rbtdb.c,v 1.168.2.11.2.25 2006/02/16 01:24:07 marka Exp $ */
+/* $Id: rbtdb.c,v 1.168.2.11.2.26 2006/03/02 23:18:20 marka Exp $ */
 
 /*
  * Principal Author: Bob Halley
@@ -2919,7 +2919,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
        rdatasetheader_t *header, *header_prev, *header_next;
        rdatasetheader_t *found, *nsheader;
        rdatasetheader_t *foundsig, *nssig, *cnamesig;
-       rbtdb_rdatatype_t sigtype, nsectype;
+       rbtdb_rdatatype_t sigtype, negtype;
 
        UNUSED(version);
 
@@ -2994,7 +2994,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
        found = NULL;
        foundsig = NULL;
        sigtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
-       nsectype = RBTDB_RDATATYPE_VALUE(0, type);
+       negtype = RBTDB_RDATATYPE_VALUE(0, type);
        nsheader = NULL;
        nssig = NULL;
        cnamesig = NULL;
@@ -3066,7 +3066,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
                                 */
                                foundsig = header;
                        } else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
-                                  header->type == nsectype) {
+                                  header->type == negtype) {
                                /*
                                 * We've found a negative cache entry.
                                 */
@@ -3677,7 +3677,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
        dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
        rdatasetheader_t *header, *header_next, *found, *foundsig;
-       rbtdb_rdatatype_t matchtype, sigmatchtype, nsectype;
+       rbtdb_rdatatype_t matchtype, sigmatchtype, negtype;
        isc_result_t result;
 
        REQUIRE(VALID_RBTDB(rbtdb));
@@ -3695,7 +3695,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        found = NULL;
        foundsig = NULL;
        matchtype = RBTDB_RDATATYPE_VALUE(type, covers);
-       nsectype = RBTDB_RDATATYPE_VALUE(0, type);
+       negtype = RBTDB_RDATATYPE_VALUE(0, type);
        if (covers == 0)
                sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
        else
@@ -3718,7 +3718,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
                        if (header->type == matchtype)
                                found = header;
                        else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
-                                header->type == nsectype)
+                                header->type == negtype)
                                found = header;
                        else if (header->type == sigmatchtype)
                                foundsig = header;
@@ -3895,7 +3895,8 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
        isc_boolean_t header_nx;
        isc_boolean_t newheader_nx;
        isc_boolean_t merge;
-       dns_rdatatype_t nsectype, rdtype, covers;
+       dns_rdatatype_t rdtype, covers;
+       rbtdb_rdatatype_t negtype;
        dns_trust_t trust;
 
        /*
@@ -3933,7 +3934,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
        newheader_nx = NONEXISTENT(newheader) ? ISC_TRUE : ISC_FALSE;
        topheader_prev = NULL;
 
-       nsectype = 0;
+       negtype = 0;
        if (rbtversion == NULL && !newheader_nx) {
                rdtype = RBTDB_RDATATYPE_BASE(newheader->type);
                if (rdtype == 0) {
@@ -3943,12 +3944,13 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                        covers = RBTDB_RDATATYPE_EXT(newheader->type);
                        if (covers == dns_rdatatype_any) {
                                /*
-                                * We're adding an NXDOMAIN negative cache
-                                * entry.
+                                * We're adding an negative cache entry
+                                * which covers all types (NXDOMAIN,
+                                * NODATA(QTYPE=ANY)).
                                 *
                                 * We make all other data stale so that the
                                 * only rdataset that can be found at this
-                                * node is the NXDOMAIN negative cache entry.
+                                * node is the negative cache entry.
                                 */
                                for (topheader = rbtnode->data;
                                     topheader != NULL;
@@ -3960,17 +3962,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                                rbtnode->dirty = 1;
                                goto find_header;
                        }
-                       nsectype = RBTDB_RDATATYPE_VALUE(covers, 0);
+                       negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
                } else {
                        /*
                         * We're adding something that isn't a
                         * negative cache entry.  Look for an extant
-                        * non-stale NXDOMAIN negative cache entry.
+                        * non-stale NXDOMAIN/NODATA(QTYPE=ANY) negative
+                        * cache entry.
                         */
                        for (topheader = rbtnode->data;
                             topheader != NULL;
                             topheader = topheader->next) {
-                               if (NXDOMAIN(topheader))
+                               if (topheader->type == 
+                                   RBTDB_RDATATYPE_NCACHEANY)
                                        break;
                        }
                        if (topheader != NULL && EXISTS(topheader) &&
@@ -3980,7 +3984,8 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                                 */
                                if (trust < topheader->trust) {
                                        /*
-                                        * The NXDOMAIN is more trusted.
+                                        * The NXDOMAIN/NODATA(QTYPE=ANY)
+                                        * is more trusted.
                                         */
                                        free_rdataset(rbtdb->common.mctx,
                                                      newheader);
@@ -3992,7 +3997,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                                }
                                /*
                                 * The new rdataset is better.  Expire the
-                                * NXDOMAIN.
+                                * NXDOMAIN/NODATA(QTYPE=ANY).
                                 */
                                topheader->ttl = 0;
                                topheader->attributes |= RDATASET_ATTR_STALE;
@@ -4000,7 +4005,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                                topheader = NULL;
                                goto find_header;
                        }
-                       nsectype = RBTDB_RDATATYPE_VALUE(0, rdtype);
+                       negtype = RBTDB_RDATATYPE_VALUE(0, rdtype);
                }
        }
 
@@ -4008,7 +4013,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
             topheader != NULL;
             topheader = topheader->next) {
                if (topheader->type == newheader->type ||
-                   topheader->type == nsectype)
+                   topheader->type == negtype)
                        break;
                topheader_prev = topheader;
        }
@@ -4174,6 +4179,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                        rbtnode->dirty = 1;
                        if (changed != NULL)
                                changed->dirty = ISC_TRUE;
+                       if (rbtversion == NULL) {
+                               header->ttl = 0;
+                               header->attributes |= RDATASET_ATTR_STALE;
+                       }
                }
        } else {
                /*
@@ -5270,7 +5279,8 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) {
        rdatasetheader_t *header, *top_next;
        rbtdb_serial_t serial;
        isc_stdtime_t now;
-       rbtdb_rdatatype_t type;
+       rbtdb_rdatatype_t type, negtype;
+       dns_rdatatype_t rdtype, covers;
 
        header = rbtiterator->current;
        if (header == NULL)
@@ -5287,9 +5297,18 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) {
        LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
 
        type = header->type;
+       rdtype = RBTDB_RDATATYPE_BASE(header->type);
+       if (rdtype == 0) {
+               covers = RBTDB_RDATATYPE_EXT(header->type);
+               negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
+       } else 
+               negtype = RBTDB_RDATATYPE_VALUE(0, rdtype);
        for (header = header->next; header != NULL; header = top_next) {
                top_next = header->next;
-               if (header->type != type) {
+               /*
+                * If not walking back up the down list.
+                */
+               if (header->type != type && header->type != negtype) {
                        do {
                                if (header->serial <= serial &&
                                    !IGNORE(header)) {