]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1416. [bug] Empty node should return NOERROR NODATA, not NXDOMAIN.
authorMark Andrews <marka@isc.org>
Sat, 18 Jan 2003 03:18:31 +0000 (03:18 +0000)
committerMark Andrews <marka@isc.org>
Sat, 18 Jan 2003 03:18:31 +0000 (03:18 +0000)
                        [RT #4715]
developer: marka
reviewer: explorer

CHANGES
bin/named/query.c
lib/dns/include/dns/db.h
lib/dns/include/dns/rdataset.h
lib/dns/include/dns/result.h
lib/dns/ncache.c
lib/dns/rbtdb.c
lib/dns/resolver.c
lib/dns/result.c
lib/dns/validator.c

diff --git a/CHANGES b/CHANGES
index 3a4da3d4c0c9d7d018838dd52c8df346504db4b5..0473cd574f0ed52b1d77ddedcfe9895b208118fa 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+1416.  [bug]           Empty node should return NOERROR NODATA, not NXDOMAIN.
+                       [RT #4715]
+
 1415.  [func]          DS TTL now derived from NS ttl.  NXT TTL now derived
                        from SOA MINIMUM.
 
index 4b7caaebccaa8c860766d6650f3ec02e787781ed..d6e7f6b5fc370d84dd392877e20da5ef1f20d41a 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.239 2003/01/14 00:28:49 marka Exp $ */
+/* $Id: query.c,v 1.240 2003/01/18 03:18:30 marka Exp $ */
 
 #include <config.h>
 
@@ -2687,6 +2687,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        }
                }
                goto cleanup;
+       case DNS_R_EMPTYNAME:
+               result = DNS_R_NXRRSET;
+               /* FALLTHROUGH */
        case DNS_R_NXRRSET:
                INSIST(is_zone);
                if (dns_rdataset_isassociated(rdataset)) {
index 5b156eece3596d57bbf79670b45cbd40709480c0..4f4d1caac53dab20e4468d96c78b38b762cc58d1 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: db.h,v 1.70 2002/08/06 01:50:28 marka Exp $ */
+/* $Id: db.h,v 1.71 2003/01/18 03:18:31 marka Exp $ */
 
 #ifndef DNS_DB_H
 #define DNS_DB_H 1
@@ -767,6 +767,9 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
  *                                             name, and 'rdataset' contains
  *                                             the negative caching proof.
  *
+ *             DNS_R_EMPTYNAME                 The name exists but there is
+ *                                             no data at the name. 
+ *
  *     Error results:
  *
  *             ISC_R_NOMEMORY
index 290a769f22eea12cae66998778bb25ce14175a7a..710e3c83184eb4af91b5a4720e32956338e35321 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdataset.h,v 1.45 2002/02/20 03:34:37 marka Exp $ */
+/* $Id: rdataset.h,v 1.46 2003/01/18 03:18:31 marka Exp $ */
 
 #ifndef DNS_RDATASET_H
 #define DNS_RDATASET_H 1
@@ -129,6 +129,7 @@ struct dns_rdataset {
 #define DNS_RDATASETATTR_FIXEDORDER    0x0400
 #define DNS_RDATASETATTR_RANDOMIZE     0x0800
 #define DNS_RDATASETATTR_CHASE         0x1000          /* Used by resolver. */
+#define DNS_RDATASETATTR_NXDOMAIN      0x2000
 
 /*
  * _OMITDNSSEC:
index c706360ce45152db1d964ac1afe59cca06157a7d..263e9e78af07c039055246b057f92c98a2130269 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: result.h,v 1.95 2003/01/14 00:28:50 marka Exp $ */
+/* $Id: result.h,v 1.96 2003/01/18 03:18:31 marka Exp $ */
 
 #ifndef DNS_RESULT_H
 #define DNS_RESULT_H 1
 #define DNS_R_UNEXPECTEDRCODE          (ISC_RESULTCLASS_DNS + 89)
 #define DNS_R_UNEXPECTEDOPCODE         (ISC_RESULTCLASS_DNS + 90)
 #define DNS_R_CHASEDSSERVERS           (ISC_RESULTCLASS_DNS + 91)
+#define DNS_R_EMPTYNAME                        (ISC_RESULTCLASS_DNS + 92)
 
-#define DNS_R_NRESULTS                 92      /* Number of results */
+#define DNS_R_NRESULTS                 93      /* Number of results */
 
 /*
  * DNS wire format rcodes.
index d15a65bf3e8eb0d7bf5054c9c7794abc88abba6d..d9e3221c815bf4da819cc07b65e0d42934afa6d3 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ncache.c,v 1.30 2002/07/19 03:29:15 marka Exp $ */
+/* $Id: ncache.c,v 1.31 2003/01/18 03:18:30 marka Exp $ */
 
 #include <config.h>
 
@@ -247,6 +247,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
        RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
                      == ISC_R_SUCCESS);
        ncrdataset.trust = trust;
+       if (message->rcode == dns_rcode_nxdomain)
+               ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
 
        return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
                                   0, addedrdataset));
index a7d7a687299ba357186cdc7747da8a984ec56ed7..9120f1c29605abc08973d2de7625740046abed5d 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rbtdb.c,v 1.183 2003/01/14 00:38:07 marka Exp $ */
+/* $Id: rbtdb.c,v 1.184 2003/01/18 03:18:30 marka Exp $ */
 
 /*
  * Principal Author: Bob Halley
@@ -91,7 +91,7 @@ typedef isc_uint32_t                  rbtdb_rdatatype_t;
                RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, dns_rdatatype_cname)
 #define RBTDB_RDATATYPE_SIGDNAME \
                RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, dns_rdatatype_dname)
-#define RBTDB_RDATATYPE_NXDOMAIN \
+#define RBTDB_RDATATYPE_NCACHEANY \
                RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)
 
 typedef struct rdatasetheader {
@@ -128,6 +128,7 @@ typedef struct rdatasetheader {
 #define RDATASET_ATTR_STALE            0x0002
 #define RDATASET_ATTR_IGNORE           0x0004
 #define RDATASET_ATTR_RETAIN           0x0008
+#define RDATASET_ATTR_NXDOMAIN         0x0010
 
 /*
  * XXX
@@ -147,6 +148,8 @@ typedef struct rdatasetheader {
        (((header)->attributes & RDATASET_ATTR_IGNORE) != 0)
 #define RETAIN(header) \
        (((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
+#define NXDOMAIN(header) \
+       (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
 
 #define DEFAULT_NODE_LOCK_COUNT                7               /* Should be prime. */
 
@@ -1307,6 +1310,8 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
        rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);
        rdataset->ttl = header->ttl - now;
        rdataset->trust = header->trust;
+       if (NXDOMAIN(header))
+               rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
        rdataset->private1 = rbtdb;
        rdataset->private2 = node;
        raw = (unsigned char *)header + sizeof(*header);
@@ -1841,6 +1846,12 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
        rdatasetheader_t *header, *header_next, *found, *nxtheader;
        rdatasetheader_t *foundsig, *cnamesig, *nxtsig;
        rbtdb_rdatatype_t sigtype;
+       dns_fixedname_t fnext;
+       dns_fixedname_t forigin;
+       dns_name_t nname, *next, *origin;
+       isc_boolean_t active;
+       dns_rbtnodechain_t chain;
+
 
        search.rbtdb = (dns_rbtdb_t *)db;
 
@@ -1914,6 +1925,45 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
                                goto tree_exit;
                }
 
+               /*
+                * Find if this is a active empty node (next active node is
+                * subdomain if 'name').  This is a simpler test than is
+                * required for activeemptynode() where name is not as
+                * constained.
+                */
+               active = ISC_FALSE;
+               dns_fixedname_init(&fnext);
+               next = dns_fixedname_name(&fnext);
+               dns_fixedname_init(&forigin);
+               origin = dns_fixedname_name(&forigin);
+               dns_name_init(&nname, NULL);
+               chain = search.chain;
+               result = dns_rbtnodechain_next(&chain, NULL, NULL);
+               while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+                       node = NULL;
+                       result = dns_rbtnodechain_current(&chain, &nname,
+                                                         origin, &node);
+                       if (result != ISC_R_SUCCESS)
+                               break;
+                       LOCK(&(search.rbtdb->node_locks[node->locknum].lock));
+                       for (header = node->data;
+                            header != NULL;
+                            header = header->next) {
+                               if (header->serial <= search.serial &&
+                                   !IGNORE(header) && EXISTS(header))
+                                       break;
+                       }
+                       UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
+                       if (header != NULL) {
+                               result = dns_name_concatenate(&nname, origin,
+                                                             next, NULL);
+                               if (result == ISC_R_SUCCESS &&
+                                   dns_name_issubdomain(next, name))
+                                       active = ISC_TRUE;
+                               break;
+                       }
+                       result = dns_rbtnodechain_next(&chain, NULL, NULL);
+               }
                /*
                 * If we're here, then the name does not exist, is not
                 * beneath a zonecut, and there's no matching wildcard.
@@ -1925,9 +1975,10 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
                                                  rdataset, sigrdataset,
                                                  search.rbtdb->secure);
                        if (result == ISC_R_SUCCESS)
-                               result = DNS_R_NXDOMAIN;
+                               result = active ? DNS_R_EMPTYNAME :
+                                                 DNS_R_NXDOMAIN;
                } else
-                       result = DNS_R_NXDOMAIN;
+                       result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN;
                goto tree_exit;
        } else if (result != ISC_R_SUCCESS)
                goto tree_exit;
@@ -2668,7 +2719,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
                                 * target type.  Remember it.
                                 */
                                foundsig = header;
-                       } else if (header->type == RBTDB_RDATATYPE_NXDOMAIN ||
+                       } else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
                                   header->type == nxtype) {
                                /*
                                 * We've found a negative cache entry.
@@ -2756,7 +2807,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
                /*
                 * We found a negative cache entry.
                 */
-               if (found->type == RBTDB_RDATATYPE_NXDOMAIN)
+               if (NXDOMAIN(found))
                        result = DNS_R_NCACHENXDOMAIN;
                else
                        result = DNS_R_NCACHENXRRSET;
@@ -2776,7 +2827,8 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
                result = ISC_R_SUCCESS;
        }
 
-       if (type != dns_rdatatype_any || result == DNS_R_NCACHENXDOMAIN) {
+       if (type != dns_rdatatype_any || result == DNS_R_NCACHENXDOMAIN ||
+           result == DNS_R_NCACHENXRRSET) {
                bind_rdataset(search.rbtdb, node, found, search.now,
                              rdataset);
                if (foundsig != NULL)
@@ -3298,7 +3350,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
                           0) {
                        if (header->type == matchtype)
                                found = header;
-                       else if (header->type == RBTDB_RDATATYPE_NXDOMAIN ||
+                       else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
                                 header->type == nxtype)
                                found = header;
                        else if (header->type == sigmatchtype)
@@ -3321,7 +3373,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
                /*
                 * We found a negative cache entry.
                 */
-               if (found->type == RBTDB_RDATATYPE_NXDOMAIN)
+               if (NXDOMAIN(found))
                        result = DNS_R_NCACHENXDOMAIN;
                else
                        result = DNS_R_NCACHENXRRSET;
@@ -3549,8 +3601,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
                        for (topheader = rbtnode->data;
                             topheader != NULL;
                             topheader = topheader->next) {
-                               if (topheader->type ==
-                                   RBTDB_RDATATYPE_NXDOMAIN)
+                               if (NXDOMAIN(topheader))
                                        break;
                        }
                        if (topheader != NULL && EXISTS(topheader) &&
@@ -3857,6 +3908,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        } else {
                newheader->serial = 1;
                newheader->trust = rdataset->trust;
+               if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+                       newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
        }
 
        /*
index 77c725f378c32f76c5f04aa04e4af7b1615ad63a..981a21f8c3c2637ae1fecaa0674491551f7698c3 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.259 2003/01/16 03:59:25 marka Exp $ */
+/* $Id: resolver.c,v 1.260 2003/01/18 03:18:30 marka Exp $ */
 
 #include <config.h>
 
@@ -309,6 +309,8 @@ struct dns_resolver {
 #define ISFORWARDER(a)                 (((a)->flags & \
                                         FCTX_ADDRINFO_FORWARDER) != 0)
 
+#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+
 static void destroy(dns_resolver_t *res);
 static void empty_bucket(dns_resolver_t *res);
 static isc_result_t resquery_send(resquery_t *query);
@@ -3337,8 +3339,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) {
                                         * a negative cache entry, so we
                                         * must set eresult appropriately.
                                         */
-                                        if (ardataset->covers ==
-                                            dns_rdatatype_any)
+                                        if (NXDOMAIN(ardataset))
                                                 eresult =
                                                         DNS_R_NCACHENXDOMAIN;
                                         else
@@ -3445,7 +3446,7 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
                         * The cache data is also a negative cache
                         * entry.
                         */
-                       if (ardataset->covers == dns_rdatatype_any)
+                       if (NXDOMAIN(ardataset))
                                *eresultp = DNS_R_NCACHENXDOMAIN;
                        else
                                *eresultp = DNS_R_NCACHENXRRSET;
@@ -3464,7 +3465,7 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
                        result = ISC_R_SUCCESS;
                }
        } else if (result == ISC_R_SUCCESS) {
-               if (covers == dns_rdatatype_any)
+               if (NXDOMAIN(ardataset))
                        *eresultp = DNS_R_NCACHENXDOMAIN;
                else
                        *eresultp = DNS_R_NCACHENXRRSET;
index 4d2afb16ddf2c28336dcb31e2a342a821ac3e11f..823e78ab2f56dc594dcd447c86411ffc6df777de 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: result.c,v 1.105 2003/01/14 00:28:49 marka Exp $ */
+/* $Id: result.c,v 1.106 2003/01/18 03:18:30 marka Exp $ */
 
 #include <config.h>
 
@@ -139,7 +139,8 @@ static const char *text[DNS_R_NRESULTS] = {
        "unexpected RCODE",                    /* 89 DNS_R_UNEXPECTEDRCODE   */
 
        "unexpected OPCODE",                   /* 90 DNS_R_UNEXPECTEDOPCODE  */
-       "chase DS servers"                     /* 91 DNS_R_CHASEDSSERVERS    */
+       "chase DS servers",                    /* 91 DNS_R_CHASEDSSERVERS    */
+       "empty name"                           /* 92 DNS_R_EMPTYNAME         */
 };
 
 static const char *rcode_text[DNS_R_NRCODERESULTS] = {
index 053d02d5218efea97b9315cd25730edfd289828b..6eebef377db1e2ba82c7f3b6829f88241c0b9af7 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.c,v 1.110 2002/07/22 03:00:49 marka Exp $ */
+/* $Id: validator.c,v 1.111 2003/01/18 03:18:30 marka Exp $ */
 
 #include <config.h>
 
@@ -440,6 +440,8 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
        dns_rdata_t rdata = DNS_RDATA_INIT;
        isc_boolean_t isnxdomain;
        isc_result_t result;
+       dns_namereln_t relation;
+       unsigned int labels, bits;
 
        INSIST(DNS_MESSAGE_VALID(val->event->message));
 
@@ -486,9 +488,23 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
                 * The NXT owner name is less than the nonexistent name.
                 */
                if (!isnxdomain) {
+                       /*
+                        * Is this a empty node?
+                        */
+                       result = dns_rdata_tostruct(&rdata, &nxt, NULL);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+                       relation = dns_name_fullcompare(&nxt.next,
+                                                       val->event->name,
+                                                       &order, &labels, &bits);
+                       dns_rdata_freestruct(&nxt);
+                       if (order <= 0 || relation != dns_namereln_subdomain) {
+                               validator_log(val, ISC_LOG_DEBUG(3),
+                                             "missing NXT record at name");
+                               return (ISC_FALSE);
+                       }
                        validator_log(val, ISC_LOG_DEBUG(3),
-                                     "missing NXT record at name");
-                       return (ISC_FALSE);
+                                     "nxt proves empty node, ok");
+                       return (ISC_TRUE);
                }
                if (dns_name_issubdomain(val->event->name, nxtname) &&
                    dns_nxt_typepresent(&rdata, dns_rdatatype_ns) &&
@@ -507,8 +523,9 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
                if (result != ISC_R_SUCCESS)
                        return (ISC_FALSE);
                dns_rdata_reset(&rdata);
-               order = dns_name_compare(val->event->name, &nxt.next);
-               if (order >= 0) {
+               relation = dns_name_fullcompare(&nxt.next, val->event->name,
+                                               &order, &labels, &bits);
+               if (order <= 0) {
                        /*
                         * The NXT next name is less than the nonexistent
                         * name.  This is only ok if the next name is the zone
@@ -522,6 +539,11 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
                        }
                        validator_log(val, ISC_LOG_DEBUG(3),
                                      "nxt points to zone apex, ok");
+               } else if (relation == dns_namereln_subdomain) {
+                       validator_log(val, ISC_LOG_DEBUG(3),
+                                     "nxt proves empty node, bad");
+                       dns_rdata_freestruct(&nxt);
+                       return (ISC_FALSE);
                }
                dns_rdata_freestruct(&nxt);
                validator_log(val, ISC_LOG_DEBUG(3), "nxt range ok");