BIND 10 trac1431, updated. 93f4485d035d308bf60041f331ce75138ff5d7bb [1431] updated auth test MockZoneFinder to confirm to the new result format. the tentative attempt of returning NSEC3 RRsets in negative cases were canceled, and updated the doxygen doc accordingly.

BIND 10 source code commits bind10-changes at lists.isc.org
Sat Jan 21 02:01:15 UTC 2012


The branch, trac1431 has been updated
       via  93f4485d035d308bf60041f331ce75138ff5d7bb (commit)
       via  2528257c4f3621822cdc030d0201453506c5a56b (commit)
       via  3dabb15d73f757c4e30ab8dfbfbb84a94eea8a86 (commit)
      from  2b16771b9cd34d55fe3916669b53531b29bdf0ce (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 93f4485d035d308bf60041f331ce75138ff5d7bb
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Fri Jan 20 17:59:52 2012 -0800

    [1431] updated auth test MockZoneFinder to confirm to the new result format.
    the tentative attempt of returning NSEC3 RRsets in negative cases were
    canceled, and updated the doxygen doc accordingly.

commit 2528257c4f3621822cdc030d0201453506c5a56b
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Fri Jan 20 17:18:52 2012 -0800

    [1431] introduced FindResultFlags so that we can separate find result codes
    themselves and special attributes.  for now, provided a quick-hack wrapper
    for auth::Query so we don't have to all data source implementations at once.

commit 3dabb15d73f757c4e30ab8dfbfbb84a94eea8a86
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Fri Jan 20 15:34:28 2012 -0800

    [1431] canceled the idea of passing RRsetPtr as a hint for findNSEC3() for now.

-----------------------------------------------------------------------

Summary of changes:
 src/bin/auth/query.cc                |   98 ++++++++++++++-------
 src/bin/auth/tests/query_unittest.cc |  163 ++++++++++++----------------------
 src/lib/datasrc/database.cc          |    2 +-
 src/lib/datasrc/database.h           |    3 +-
 src/lib/datasrc/memory_datasrc.cc    |    2 +-
 src/lib/datasrc/memory_datasrc.h     |    3 +-
 src/lib/datasrc/zone.h               |  116 ++++++++++++++++---------
 7 files changed, 199 insertions(+), 188 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc
index 2bf8f5e..7d6886c 100644
--- a/src/bin/auth/query.cc
+++ b/src/bin/auth/query.cc
@@ -30,6 +30,42 @@ using namespace isc::dns;
 using namespace isc::datasrc;
 using namespace isc::dns::rdata;
 
+namespace {
+// This is a temporary wrapper to convert old format of FindResult to new
+// one, until we update all supported data source implementations.
+ZoneFinder::FindResult
+findWrapper(const ZoneFinder::FindResult& orig_result) {
+    // Retrieve the original flags
+    ZoneFinder::FindResultFlags flags = ZoneFinder::RESULT_DEFAULT;
+    if (orig_result.isWildcard()) {
+        flags = flags | ZoneFinder::RESULT_WILDCARD;
+    }
+    if (orig_result.isNSECSigned()) {
+        flags = flags | ZoneFinder::RESULT_NSEC_SIGNED;
+    }
+    if (orig_result.isNSEC3Signed()) {
+        flags = flags | ZoneFinder::RESULT_NSEC3_SIGNED;
+    }
+
+    // Convert older code to new one, adjusting flags if necessary
+    ZoneFinder::Result code = orig_result.code;
+    if (code == ZoneFinder::WILDCARD) {
+        code = ZoneFinder::SUCCESS;
+        flags = flags | ZoneFinder::RESULT_WILDCARD;
+    } else if (code == ZoneFinder::WILDCARD_CNAME) {
+        code = ZoneFinder::CNAME;
+        flags = flags | ZoneFinder::RESULT_WILDCARD;
+    } else if (code == ZoneFinder::WILDCARD_NXRRSET) {
+        code = ZoneFinder::NXRRSET;
+        flags = flags | ZoneFinder::RESULT_WILDCARD;
+    }
+    if (orig_result.rrset && orig_result.rrset->getType() == RRType::NSEC()) {
+        flags = flags | ZoneFinder::RESULT_NSEC_SIGNED;
+    }
+    return (ZoneFinder::FindResult(code, orig_result.rrset, flags));
+}
+}
+
 namespace isc {
 namespace auth {
 
@@ -69,8 +105,8 @@ Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
 
     // Find A rrset
     if (qname_ != qname || qtype_ != RRType::A()) {
-        ZoneFinder::FindResult a_result = zone.find(qname, RRType::A(),
-                                                    options | dnssec_opt_);
+        ZoneFinder::FindResult a_result =
+            findWrapper(zone.find(qname, RRType::A(), options | dnssec_opt_));
         if (a_result.code == ZoneFinder::SUCCESS) {
             response_.addRRset(Message::SECTION_ADDITIONAL,
                     boost::const_pointer_cast<RRset>(a_result.rrset), dnssec_);
@@ -80,7 +116,8 @@ Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
     // Find AAAA rrset
     if (qname_ != qname || qtype_ != RRType::AAAA()) {
         ZoneFinder::FindResult aaaa_result =
-            zone.find(qname, RRType::AAAA(), options | dnssec_opt_);
+            findWrapper(zone.find(qname, RRType::AAAA(),
+                                  options | dnssec_opt_));
         if (aaaa_result.code == ZoneFinder::SUCCESS) {
             response_.addRRset(Message::SECTION_ADDITIONAL,
                     boost::const_pointer_cast<RRset>(aaaa_result.rrset),
@@ -91,8 +128,9 @@ Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
 
 void
 Query::addSOA(ZoneFinder& finder) {
-    ZoneFinder::FindResult soa_result(finder.find(finder.getOrigin(),
-        RRType::SOA(), dnssec_opt_));
+    ZoneFinder::FindResult soa_result =
+        findWrapper(finder.find(finder.getOrigin(),
+                                RRType::SOA(), dnssec_opt_));
     if (soa_result.code != ZoneFinder::SUCCESS) {
         isc_throw(NoSOA, "There's no SOA record in zone " <<
             finder.getOrigin().toText());
@@ -147,9 +185,8 @@ Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
     // Confirm the wildcard doesn't exist (this should result in NXDOMAIN;
     // otherwise we shouldn't have got NXDOMAIN for the original query in
     // the first place).
-    const ZoneFinder::FindResult fresult = finder.find(wildname,
-                                                       RRType::NSEC(),
-                                                       dnssec_opt_);
+    const ZoneFinder::FindResult fresult =
+        findWrapper(finder.find(wildname, RRType::NSEC(), dnssec_opt_));
     if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
         fresult.rrset->getRdataCount() == 0) {
         isc_throw(BadNSEC, "Unexpected result for wildcard NXDOMAIN proof");
@@ -173,8 +210,8 @@ Query::addWildcardProof(ZoneFinder& finder) {
     // substitution.  Confirm that by specifying NO_WILDCARD.  It should result
     // in NXDOMAIN and an NSEC RR that proves it should be returned.
     const ZoneFinder::FindResult fresult =
-        finder.find(qname_, RRType::NSEC(),
-                    dnssec_opt_ | ZoneFinder::NO_WILDCARD);
+        findWrapper(finder.find(qname_, RRType::NSEC(),
+                                dnssec_opt_ | ZoneFinder::NO_WILDCARD));
     if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
         fresult.rrset->getRdataCount() == 0) {
         isc_throw(BadNSEC, "Unexpected result for wildcard proof");
@@ -191,13 +228,10 @@ Query::addWildcardNXRRSETProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
     if (nsec->getRdataCount() == 0) {
         isc_throw(BadNSEC, "NSEC for WILDCARD_NXRRSET is empty");
     }
-    // Add this NSEC RR to authority section.
-    response_.addRRset(Message::SECTION_AUTHORITY,
-                      boost::const_pointer_cast<RRset>(nsec), dnssec_);
     
     const ZoneFinder::FindResult fresult =
-        finder.find(qname_, RRType::NSEC(),
-                    dnssec_opt_ | ZoneFinder::NO_WILDCARD);
+        findWrapper(finder.find(qname_, RRType::NSEC(),
+                                dnssec_opt_ | ZoneFinder::NO_WILDCARD));
     if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
         fresult.rrset->getRdataCount() == 0) {
         isc_throw(BadNSEC, "Unexpected result for no match QNAME proof");
@@ -214,8 +248,9 @@ Query::addWildcardNXRRSETProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
 void
 Query::addAuthAdditional(ZoneFinder& finder) {
     // Fill in authority and addtional sections.
-    ZoneFinder::FindResult ns_result = finder.find(finder.getOrigin(),
-                                                   RRType::NS(), dnssec_opt_);
+    ZoneFinder::FindResult ns_result =
+        findWrapper(finder.find(finder.getOrigin(), RRType::NS(),
+                                dnssec_opt_));
     // zone origin name should have NS records
     if (ns_result.code != ZoneFinder::SUCCESS) {
         isc_throw(NoApexNS, "There's no apex NS records in zone " <<
@@ -260,7 +295,7 @@ Query::process() {
         find = boost::bind(&ZoneFinder::find, &zfinder, qname_, qtype_,
                            dnssec_opt_);
     }
-    ZoneFinder::FindResult db_result(find());
+    ZoneFinder::FindResult db_result(findWrapper(find()));
     switch (db_result.code) {
         case ZoneFinder::DNAME: {
             // First, put the dname into the answer
@@ -306,7 +341,6 @@ Query::process() {
             break;
         }
         case ZoneFinder::CNAME:
-        case ZoneFinder::WILDCARD_CNAME:
             /*
              * We don't do chaining yet. Therefore handling a CNAME is
              * mostly the same as handling SUCCESS, but we didn't get
@@ -322,12 +356,11 @@ Query::process() {
 
             // If the answer is a result of wildcard substitution,
             // add a proof that there's no closer name.
-            if (dnssec_ && db_result.code == ZoneFinder::WILDCARD_CNAME) {
+            if (dnssec_ && db_result.isWildcard()) {
                 addWildcardProof(*result.zone_finder);
             }
             break;
         case ZoneFinder::SUCCESS:
-        case ZoneFinder::WILDCARD:
             if (qtype_is_any) {
                 // If quety type is ANY, insert all RRs under the domain
                 // into answer section.
@@ -357,7 +390,7 @@ Query::process() {
 
             // If the answer is a result of wildcard substitution,
             // add a proof that there's no closer name.
-            if (dnssec_ && db_result.code == ZoneFinder::WILDCARD) {
+            if (dnssec_ && db_result.isWildcard()) {
                 addWildcardProof(*result.zone_finder);
             }
             break;
@@ -377,17 +410,16 @@ Query::process() {
             break;
         case ZoneFinder::NXRRSET:
             addSOA(*result.zone_finder);
-            if (dnssec_ && db_result.rrset) {
-                response_.addRRset(Message::SECTION_AUTHORITY,
-                                   boost::const_pointer_cast<RRset>(
-                                       db_result.rrset),
-                                   dnssec_);
-            }
-            break;
-        case ZoneFinder::WILDCARD_NXRRSET:
-            addSOA(*result.zone_finder);
-            if (dnssec_ && db_result.rrset) {
-                addWildcardNXRRSETProof(zfinder, db_result.rrset);
+            if (dnssec_) {
+                if (db_result.isNSECSigned() && db_result.rrset) {
+                    response_.addRRset(Message::SECTION_AUTHORITY,
+                                       boost::const_pointer_cast<RRset>(
+                                           db_result.rrset),
+                                       dnssec_);
+                    if (db_result.isWildcard()) {
+                        addWildcardNXRRSETProof(zfinder, db_result.rrset);
+                    }
+                }
             }
             break;
         default:
diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc
index ab3dace..e63cfd9 100644
--- a/src/bin/auth/tests/query_unittest.cc
+++ b/src/bin/auth/tests/query_unittest.cc
@@ -244,8 +244,7 @@ public:
                                const FindOptions options = FIND_DEFAULT);
 
     virtual ZoneFinder::FindNSEC3Result
-    findNSEC3(const Name& name, bool recursive,
-              ConstRRsetPtr known_encloser = ConstRRsetPtr());
+    findNSEC3(const Name& name, bool recursive);
 
     // If false is passed, it makes the zone broken as if it didn't have the
     // SOA.
@@ -321,9 +320,6 @@ private:
         }
     }
 
-    ZoneFinder::FindNSEC3Result
-    findNSEC3Helper(const Name& name, bool recursive);
-
     const Name origin_;
     // Names where we delegate somewhere else
     const Name delegation_name_;
@@ -380,7 +376,7 @@ MockZoneFinder::findAll(const Name& name, std::vector<ConstRRsetPtr>& target,
 }
 
 ZoneFinder::FindNSEC3Result
-MockZoneFinder::findNSEC3Helper(const Name& name, bool recursive) {
+MockZoneFinder::findNSEC3(const Name& name, bool recursive) {
     ConstRRsetPtr covering_proof;
     const int labels = name.getLabelCount();
 
@@ -422,28 +418,6 @@ MockZoneFinder::findNSEC3Helper(const Name& name, bool recursive) {
     isc_throw(isc::Unexpected, "findNSEC3() isn't expected to fail");
 }
 
-ZoneFinder::FindNSEC3Result
-MockZoneFinder::findNSEC3(const Name& name, bool recursive,
-                          ConstRRsetPtr known_encloser)
-{
-    if (!known_encloser || known_encloser->getName() == name) {
-        return (findNSEC3Helper(name, recursive));
-    }
-
-    // If it's recursive mode and we are given a know encloser that is a
-    // real ancestor of name, we may possibly be able to skip some intermediate
-    // level.  The split below returns the immediate child of the owner name
-    // of the known ancestor toward the query name.
-    if (!recursive) {
-        isc_throw(isc::InvalidParameter, "Encloser cannot be an ancestor "
-                  "in non recursive mode");
-    }
-    return (findNSEC3Helper(name.split(
-                                name.getLabelCount() -
-                                known_encloser->getName().getLabelCount() -
-                                1), true));
-}
-
 ZoneFinder::FindResult
 MockZoneFinder::find(const Name& name, const RRType& type,
                      const FindOptions options)
@@ -507,18 +481,15 @@ MockZoneFinder::find(const Name& name, const RRType& type,
         // Otherwise it's NXRRSET case.
         if ((options & FIND_DNSSEC) != 0) {
             if (use_nsec3_) {
-                return (FindResult(NXRRSET,
-                                   RRsetPtr(new RRset(found_domain->first,
-                                                      RRClass::IN(),
-                                                      RRType::NSEC3(),
-                                                      RRTTL(0)))));
+                return (FindResult(NXRRSET, RRsetPtr(), RESULT_NSEC3_SIGNED));
             }
             found_rrset = found_domain->second.find(RRType::NSEC());
             if (found_rrset != found_domain->second.end()) {
-                return (FindResult(NXRRSET, found_rrset->second));
+                return (FindResult(NXRRSET, found_rrset->second,
+                                   RESULT_NSEC_SIGNED));
             }
         }
-        return (FindResult(NXRRSET, RRsetPtr()));
+        return (FindResult(NXRRSET, RRsetPtr(), RESULT_NSEC_SIGNED));
     }
 
     // query name isn't found in our domains.
@@ -538,15 +509,13 @@ MockZoneFinder::find(const Name& name, const RRType& type,
         --domain;               // reset domain to the "previous name"
         if ((options & FIND_DNSSEC) != 0) {
             if (use_nsec3_) {
-                return (FindResult(NXRRSET,
-                                   RRsetPtr(new RRset(name, RRClass::IN(),
-                                                      RRType::NSEC3(),
-                                                      RRTTL(0)))));
+                return (FindResult(NXRRSET, RRsetPtr(), RESULT_NSEC3_SIGNED));
             }
             RRsetStore::const_iterator found_rrset =
                 (*domain).second.find(RRType::NSEC());
             if (found_rrset != (*domain).second.end()) {
-                return (FindResult(NXRRSET, found_rrset->second));
+                return (FindResult(NXRRSET, found_rrset->second,
+                                   RESULT_NSEC_SIGNED));
             }
         }
         return (FindResult(NXRRSET, RRsetPtr()));
@@ -570,38 +539,38 @@ MockZoneFinder::find(const Name& name, const RRType& type,
                         domain->second.find(type);
                     // Matched the QTYPE
                     if(found_rrset != domain->second.end()) {
-                        return (FindResult(WILDCARD,
+                        return (FindResult(SUCCESS,
                                            substituteWild(
-                                               *found_rrset->second, name)));
+                                               *found_rrset->second, name),
+                                           RESULT_WILDCARD |
+                                           (use_nsec3_ ?
+                                            RESULT_NSEC3_SIGNED :
+                                            RESULT_NSEC_SIGNED)));
                     } else {
                         // No matched QTYPE, this case is for WILDCARD_NXRRSET
-                        const Name new_name =
-                            Name("*").concatenate(wild_suffix);
                         if (use_nsec3_) {
-                            return (FindResult(WILDCARD_NXRRSET,
-                                               RRsetPtr(new RRset(
-                                                            new_name,
-                                                            RRClass::IN(),
-                                                            RRType::NSEC3(),
-                                                            RRTTL(0)))));
+                            return (FindResult(NXRRSET, RRsetPtr(),
+                                               RESULT_WILDCARD |
+                                               RESULT_NSEC3_SIGNED));
                         }
+                        const Name new_name =
+                            Name("*").concatenate(wild_suffix);
                         found_rrset = domain->second.find(RRType::NSEC());
                         assert(found_rrset != domain->second.end());
-                        return (FindResult(WILDCARD_NXRRSET,
+                        return (FindResult(NXRRSET,
                                            substituteWild(
                                                *found_rrset->second,
-                                               new_name)));
+                                               new_name),
+                                           RESULT_WILDCARD |
+                                           RESULT_NSEC_SIGNED));
                     }
                 } else {
                     // This is empty non terminal name case on wildcard.
                     const Name empty_name = Name("*").concatenate(wild_suffix);
                     if (use_nsec3_) {
-                        return (FindResult(WILDCARD_NXRRSET,
-                                           RRsetPtr(new RRset(
-                                                        empty_name,
-                                                        RRClass::IN(),
-                                                        RRType::NSEC3(),
-                                                        RRTTL(0)))));
+                        return (FindResult(NXRRSET, RRsetPtr(),
+                                           RESULT_WILDCARD |
+                                           RESULT_NSEC3_SIGNED));
                     }
                     for (Domains::reverse_iterator it = domains_.rbegin();
                          it != domains_.rend();
@@ -610,12 +579,13 @@ MockZoneFinder::find(const Name& name, const RRType& type,
                         if ((*it).first < empty_name &&
                             (nsec_it = (*it).second.find(RRType::NSEC()))
                             != (*it).second.end()) {
-                            return (FindResult(WILDCARD_NXRRSET,
-                                               (*nsec_it).second));
+                            return (FindResult(NXRRSET, (*nsec_it).second,
+                                               RESULT_WILDCARD |
+                                               RESULT_NSEC_SIGNED));
                         }
                     }
                 }
-                return (FindResult(WILDCARD_NXRRSET,RRsetPtr()));
+                return (FindResult(NXRRSET, RRsetPtr(), RESULT_WILDCARD));
              }
         }
         const Name cnamewild_suffix("cnamewild.example.com");
@@ -626,8 +596,11 @@ MockZoneFinder::find(const Name& name, const RRType& type,
             RRsetStore::const_iterator found_rrset =
                 domain->second.find(RRType::CNAME());
             assert(found_rrset != domain->second.end());
-            return (FindResult(WILDCARD_CNAME,
-                               substituteWild(*found_rrset->second, name)));
+            return (FindResult(CNAME,
+                               substituteWild(*found_rrset->second, name),
+                               RESULT_WILDCARD |
+                               (use_nsec3_ ? RESULT_NSEC3_SIGNED :
+                                RESULT_NSEC_SIGNED)));
         }
     }
 
@@ -640,13 +613,7 @@ MockZoneFinder::find(const Name& name, const RRType& type,
     // than the origin)
     if ((options & FIND_DNSSEC) != 0) {
         if (use_nsec3_) {
-            // In many cases the closest encloser should be the apex name.
-            // So for now we always return it.
-            return (FindResult(NXDOMAIN,
-                               RRsetPtr(new RRset(Name("example.com"),
-                                                  RRClass::IN(),
-                                                  RRType::NSEC3(),
-                                                  RRTTL(0)))));
+            return (FindResult(NXDOMAIN, RRsetPtr(), RESULT_NSEC3_SIGNED));
         }
 
         // Emulate a broken DataSourceClient for some special names.
@@ -664,7 +631,8 @@ MockZoneFinder::find(const Name& name, const RRType& type,
             if ((*it).first < name &&
                 (nsec_it = (*it).second.find(RRType::NSEC()))
                 != (*it).second.end()) {
-                return (FindResult(NXDOMAIN, (*nsec_it).second));
+                return (FindResult(NXDOMAIN, (*nsec_it).second,
+                                   RESULT_NSEC_SIGNED));
             }
         }
     }
@@ -1495,18 +1463,9 @@ nsec3Check(bool expected_matched, const string& expected_rrsets_txt,
 }
 
 TEST_F(QueryTest, findNSEC3) {
-    ConstRRsetPtr apex_nsec3 = ConstRRsetPtr(new RRset(Name("example.com"),
-                                                       RRClass::IN(),
-                                                       RRType::NSEC3(),
-                                                       RRTTL(0)));
-
     // Apex name.  It should have a matching NSEC3
     nsec3Check(true, nsec3_apex_txt,
                mock_finder->findNSEC3(Name("example.com"), false));
-    // giving an RRset as a hint shouldn't change the result.
-    nsec3Check(true, nsec3_apex_txt,
-               mock_finder->findNSEC3(Name("example.com"), false,
-                                      apex_nsec3));
 
     // Recursive mode doesn't change the result in this case.
     nsec3Check(true, nsec3_apex_txt,
@@ -1516,27 +1475,16 @@ TEST_F(QueryTest, findNSEC3) {
     // returned.
     nsec3Check(false, nsec3_www_txt,
                mock_finder->findNSEC3(Name("nxdomain.example.com"), false));
-    // In non recursion mode we cannot give a higher level hint
-    EXPECT_THROW(mock_finder->findNSEC3(Name("nxdomain.example.com"), false,
-                                        apex_nsec3),
-                 isc::InvalidParameter);
 
     // Non existent name.  The closest provable encloser is the apex,
     // and next closer is the query name.
     nsec3Check(true, string(nsec3_apex_txt) + string(nsec3_www_txt),
                mock_finder->findNSEC3(Name("nxdomain.example.com"), true));
-    // Giving the hint should produce the same result
-    nsec3Check(true, string(nsec3_apex_txt) + string(nsec3_www_txt),
-               mock_finder->findNSEC3(Name("nxdomain.example.com"), true,
-                                      apex_nsec3));
 
     // Similar to the previous case, but next closer name is different
     // (is the parent) of the non existent name.
     nsec3Check(true, string(nsec3_apex_txt) + string(nsec3_www_txt),
                mock_finder->findNSEC3(Name("nx.domain.example.com"), true));
-    nsec3Check(true, string(nsec3_apex_txt) + string(nsec3_www_txt),
-               mock_finder->findNSEC3(Name("nx.domain.example.com"), true,
-                                      apex_nsec3));
 
     // In the rest of test we check hash comparison for wrap around cases.
     nsec3Check(false, nsec3_apex_txt,
@@ -1553,9 +1501,9 @@ TEST_F(QueryTest, nxdomainWithNSEC3) {
     ZoneFinder::FindResult result = mock_finder->find(
         Name("nxdomain.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
     EXPECT_EQ(ZoneFinder::NXDOMAIN, result.code);
-    ASSERT_TRUE(result.rrset);
-    EXPECT_EQ(RRType::NSEC3(), result.rrset->getType());
-    EXPECT_EQ(Name("example.com"), result.rrset->getName());
+    EXPECT_FALSE(result.rrset);
+    EXPECT_TRUE(result.isNSEC3Signed());
+    EXPECT_FALSE(result.isWildcard());
 }
 
 TEST_F(QueryTest, nxrrsetWithNSEC3) {
@@ -1563,9 +1511,9 @@ TEST_F(QueryTest, nxrrsetWithNSEC3) {
     ZoneFinder::FindResult result = mock_finder->find(
         Name("www.example.com"), RRType::TXT(), ZoneFinder::FIND_DNSSEC);
     EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
-    ASSERT_TRUE(result.rrset);
-    EXPECT_EQ(RRType::NSEC3(), result.rrset->getType());
-    EXPECT_EQ(Name("www.example.com"), result.rrset->getName());
+    EXPECT_FALSE(result.rrset);
+    EXPECT_TRUE(result.isNSEC3Signed());
+    EXPECT_FALSE(result.isWildcard());
 }
 
 TEST_F(QueryTest, emptyNameWithNSEC3) {
@@ -1573,9 +1521,9 @@ TEST_F(QueryTest, emptyNameWithNSEC3) {
     ZoneFinder::FindResult result = mock_finder->find(
         Name("no.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
     EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
-    ASSERT_TRUE(result.rrset);
-    EXPECT_EQ(RRType::NSEC3(), result.rrset->getType());
-    EXPECT_EQ(Name("no.example.com"), result.rrset->getName());
+    EXPECT_FALSE(result.rrset);
+    EXPECT_TRUE(result.isNSEC3Signed());
+    EXPECT_FALSE(result.isWildcard());
 }
 
 TEST_F(QueryTest, wildcardNxrrsetWithNSEC3) {
@@ -1583,19 +1531,18 @@ TEST_F(QueryTest, wildcardNxrrsetWithNSEC3) {
     ZoneFinder::FindResult result = mock_finder->find(
         Name("www1.uwild.example.com"), RRType::TXT(),
         ZoneFinder::FIND_DNSSEC);
-    EXPECT_EQ(ZoneFinder::WILDCARD_NXRRSET, result.code);
-    ASSERT_TRUE(result.rrset);
-    EXPECT_EQ(RRType::NSEC3(), result.rrset->getType());
-    EXPECT_EQ(Name("*.uwild.example.com"), result.rrset->getName());
+    EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
+    EXPECT_FALSE(result.rrset);
+    EXPECT_TRUE(result.isNSEC3Signed());
+    EXPECT_TRUE(result.isWildcard());
 }
 
 TEST_F(QueryTest, wildcardEmptyWithNSEC3) {
     mock_finder->setNSEC3Flag(true);
     ZoneFinder::FindResult result = mock_finder->find(
         Name("a.t.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
-    EXPECT_EQ(ZoneFinder::WILDCARD_NXRRSET, result.code);
-    ASSERT_TRUE(result.rrset);
-    EXPECT_EQ(RRType::NSEC3(), result.rrset->getType());
-    EXPECT_EQ(Name("*.t.example.com"), result.rrset->getName());
+    EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
+    EXPECT_TRUE(result.isNSEC3Signed());
+    EXPECT_TRUE(result.isWildcard());
 }
 }
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index 8ff78ff..0f24cff 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -893,7 +893,7 @@ DatabaseClient::Finder::findInternal(const isc::dns::Name& name,
 }
 
 ZoneFinder::FindNSEC3Result
-DatabaseClient::Finder::findNSEC3(const Name&, bool, ConstRRsetPtr) {
+DatabaseClient::Finder::findNSEC3(const Name&, bool) {
     isc_throw(NotImplemented, "findNSEC3 is not yet implemented for database "
               "data source");
 }
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index 84217e1..c897b77 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -758,8 +758,7 @@ public:
 	///
 	/// See documentation in \c Zone.
 	virtual FindNSEC3Result
-        findNSEC3(const isc::dns::Name& name, bool recursive,
-                  const isc::dns::ConstRRsetPtr known_encloser);
+        findNSEC3(const isc::dns::Name& name, bool recursive);
 
         /// \brief The zone ID
         ///
diff --git a/src/lib/datasrc/memory_datasrc.cc b/src/lib/datasrc/memory_datasrc.cc
index f90e75c..b019ba3 100644
--- a/src/lib/datasrc/memory_datasrc.cc
+++ b/src/lib/datasrc/memory_datasrc.cc
@@ -642,7 +642,7 @@ InMemoryZoneFinder::findAll(const Name& name,
 }
 
 ZoneFinder::FindNSEC3Result
-InMemoryZoneFinder::findNSEC3(const Name&, bool, ConstRRsetPtr) {
+InMemoryZoneFinder::findNSEC3(const Name&, bool) {
     isc_throw(NotImplemented, "findNSEC3 is not yet implemented for in memory "
               "data source");
 }
diff --git a/src/lib/datasrc/memory_datasrc.h b/src/lib/datasrc/memory_datasrc.h
index 68de40d..fcd9c8b 100644
--- a/src/lib/datasrc/memory_datasrc.h
+++ b/src/lib/datasrc/memory_datasrc.h
@@ -87,8 +87,7 @@ public:
     ///
     /// See documentation in \c Zone.
     virtual FindNSEC3Result
-    findNSEC3(const isc::dns::Name& name, bool recursive,
-              const isc::dns::ConstRRsetPtr known_encloser);
+    findNSEC3(const isc::dns::Name& name, bool recursive);
 
     /// \brief Imelementation of the ZoneFinder::findPreviousName method
     ///
diff --git a/src/lib/datasrc/zone.h b/src/lib/datasrc/zone.h
index 9e83286..cd42332 100644
--- a/src/lib/datasrc/zone.h
+++ b/src/lib/datasrc/zone.h
@@ -142,19 +142,41 @@ public:
         WILDCARD_NXRRSET ///< NXRRSET on wildcard, for DNSSEC
     };
 
+    /// Special attribute flags on the result of the \c find() method
+    ///
+    /// The flag values defined here are intended to signal to the caller
+    /// that it may need special handling on the result.  This is particularly
+    /// of concern when DNSSEC is requested.  For example, for negative
+    /// responses the caller would want to know whether the zone is signed
+    /// with NSEC or NSEC3 so that it can subsequently provide necessary
+    /// proof of the result.
+    ///
+    /// The caller is generally expected to get access to the information
+    /// via read-only getter methods of \c FindResult so that it won't rely
+    /// on specific details of the representation of the flags.  So these
+    /// definitions are basically only meaningful for data source
+    /// implementations.
+    enum FindResultFlags {
+        RESULT_DEFAULT = 0,       ///< The default flags
+        RESULT_WILDCARD = 1,      ///< find() resulted in a wildcard match
+        RESULT_NSEC_SIGNED = 2,   ///< The zone is signed with NSEC RRs
+        RESULT_NSEC3_SIGNED = 4   ///< The zone is signed with NSEC3 RRs
+    };
+
     /// A helper structure to represent the search result of \c find().
     ///
     /// This is a straightforward tuple of the result code and a pointer
-    /// to the found RRset to represent the result of \c find()
-    /// (there will be more members in the future - see the class
-    /// description).
+    /// (and optionally special flags) to the found RRset to represent the
+    /// result of \c find() (there will be more members in the future -
+    /// see the class description).
     /// We use this in order to avoid overloading the return value for both
     /// the result code ("success" or "not found") and the found object,
     /// i.e., avoid using \c NULL to mean "not found", etc.
     ///
     /// This is a simple value class whose internal state never changes,
-    /// so for convenience we allow the applications to refer to the members
-    /// directly.
+    /// so for convenience we allow the applications to refer to some of the
+    /// members directly.  For others we provide read-only accessor methods
+    /// to hide specific representation.
     ///
     /// Note: we should eventually include a notion of "zone node", which
     /// corresponds to a particular domain name of the zone, so that we can
@@ -165,11 +187,39 @@ public:
     /// optimize including the NSEC for no-wildcard proof (FWIW NSD does that).
     struct FindResult {
         FindResult(Result param_code,
-                   const isc::dns::ConstRRsetPtr param_rrset) :
-            code(param_code), rrset(param_rrset)
+                   const isc::dns::ConstRRsetPtr param_rrset,
+                   FindResultFlags param_flags = RESULT_DEFAULT) :
+            code(param_code), rrset(param_rrset), flags(param_flags)
         {}
         const Result code;
         const isc::dns::ConstRRsetPtr rrset;
+
+        /// Return true iff find() results in a wildcard match.
+        bool isWildcard() const { return ((flags & RESULT_WILDCARD) != 0); }
+
+        /// Return true when the underlying zone is signed with NSEC.
+        ///
+        /// The \c find() implementation allow this to return false if
+        /// \c FIND_DNSSEC isn't specified regardless of whether the zone
+        /// is signed or which of NSEC/NSEC3 is used.
+        ///
+        /// When this is returned, the implementation of find() must ensure
+        /// that \c rrset be a valid NSEC RRset as described in \c find()
+        /// documentation.
+        bool isNSECSigned() const {
+            return ((flags & RESULT_NSEC_SIGNED) != 0);
+        }
+
+        /// Return true when the underlying zone is signed with NSEC3.
+        ///
+        /// The \c find() implementation allow this to return false if
+        /// \c FIND_DNSSEC isn't specified regardless of whether the zone
+        /// is signed or which of NSEC/NSEC3 is used.
+        bool isNSEC3Signed() const {
+            return ((flags & RESULT_NSEC3_SIGNED) != 0);
+        }
+    private:
+        FindResultFlags flags;
     };
 
     /// Find options.
@@ -229,20 +279,15 @@ public:
     ///   of \c DELEGATION and the NS RRset at the zone cut.
     /// - If there is no matching name, it returns the code of \c NXDOMAIN,
     ///   and, if DNSSEC is requested, the NSEC RRset that proves the
-    ///   non-existence if the zone is signed with NSEC; if it's signed with
-    ///   NSEC3, an empty NSEC3 RRset (an RRset that doesn't have RDATA)
-    ///   whose name is the closest encloser of the given name.
+    ///   non-existence if the zone is signed with NSEC.
     /// - If there is a matching name but no RRset of the search type, it
     ///   returns the code of \c NXRRSET, and, if DNSSEC is required,
-    ///   the NSEC RRset for that name if the zone is signed with NSEC;
-    ///   if it's signed with NSEC3, an empty NSEC3 RRset whose name is the
-    ///   given name.
+    ///   the NSEC RRset for that name if the zone is signed with NSEC.
     /// - If there is no matching name but there is a matching wild card name,
     ///   but it doesn't have a requested type of RR, and if DNSSEC is
     ///   required, then it returns the code of \c WILDCARD_NXRRSET.
     ///   If the zone is signed with NSEC, it returns corresponding NSEC
-    ///   (see the description of \c Result); if it's signed with NSEC3,
-    ///   it returns an empty NSEC3 RRset whose name is the matching wildcard.
+    ///   (see the description of \c Result).
     /// - If there is a CNAME RR of the searched name but there is no
     ///   RR of the searched type of the name (so this type is different from
     ///   CNAME), it returns the code of \c CNAME and that CNAME RR.
@@ -375,7 +420,7 @@ public:
     ///
     /// When looking for NSEC3, this method retrieves NSEC3 parameters from
     /// the corresponding zone to calculate hash values.  Actual implementation
-    /// of how to do this will defer in different data sources.  If the
+    /// of how to do this will differ in different data sources.  If the
     /// NSEC3 parameters are not available \c DataSourceError exception
     /// will be thrown.
     ///
@@ -387,24 +432,6 @@ public:
     /// extend this method so that, e.g., the caller can specify the parameter
     /// set.
     ///
-    /// This method takes an optional parameter \c known_encloser.  If it's
-    /// non NULL, its owner name must be the closest encloser of \c name.
-    /// Its RR type is expected to be NSEC3, but other attributes other than
-    /// the owner name is not important for this method and will generally be
-    /// ignored.  When this parameter is provided, the actual implementation
-    /// of the derived class can use it as a hint for identifying the closest
-    /// provable encloser (it can be helpful if \c name is known to be non
-    /// existent and possibly contains many labels below the closest encloser).
-    /// The underlying data source may also specialize the RRset to hold
-    /// some information specific to the data source implementation to allow
-    /// further optimization.  Whether or not this parameter is non NULL,
-    /// the result of this method should be the same; this parameter is only
-    /// provided to possibly enable some implementation specific optimization.
-    /// When it's non NULL, however, its owner name must be equal to \c name
-    /// when \c recursive is false and must be a real (non equal) super domain
-    /// of \c name when \c recursive is true; otherwise
-    /// \c isc::InvalidParameter exception will be thrown.
-    ///
     /// In general, this method expects the zone is properly signed with NSEC3
     /// RRs.  Specifically, it assumes at least the apex node has a matching
     /// NSEC3 RR (so the search in the recursive mode must always succeed);
@@ -412,8 +439,7 @@ public:
     /// algorithm, and salt) from the zone as noted above.  If these
     /// assumptions aren't met, \c DataSourceError exception will be thrown.
     ///
-    /// \exception InvalidParameter name is not a subdomain of the zone origin;
-    /// known_encloser does not meet the requirement (see above)
+    /// \exception InvalidParameter name is not a subdomain of the zone origin
     /// \exception DataSourceError Low-level or internal datasource errors
     /// happened, or the zone isn't properly signed with NSEC3
     /// (NSEC3 parameters cannot be found, no NSEC3s are available, etc).
@@ -424,15 +450,11 @@ public:
     /// be a subdomain of the zone.
     /// \param recursive Whether or not search should continue until it finds
     /// a provable encloser (see above).
-    /// \param known_encloser If non NULL, specifies the closest encloser
-    /// (may or may not be provable) of \c name via its owner name.
     ///
     /// \return The search result and whether or not the closest_proof is
     /// a matching NSEC3, in the form of \c FindNSEC3Result object.
     virtual FindNSEC3Result
-    findNSEC3(const isc::dns::Name& name, bool recursive,
-              const isc::dns::ConstRRsetPtr known_encloser =
-              isc::dns::ConstRRsetPtr()) = 0;
+    findNSEC3(const isc::dns::Name& name, bool recursive) = 0;
 
     /// \brief Get previous name in the zone
     ///
@@ -474,6 +496,18 @@ inline ZoneFinder::FindOptions operator |(ZoneFinder::FindOptions a,
                                                  static_cast<unsigned>(b)));
 }
 
+/// \brief Operator to combine FindResultFlags
+///
+/// Similar to the same operator for \c FindOptions.  Refer to the description
+/// of that function.
+inline ZoneFinder::FindResultFlags operator |(
+    ZoneFinder::FindResultFlags a,
+    ZoneFinder::FindResultFlags b)
+{
+    return (static_cast<ZoneFinder::FindResultFlags>(
+                static_cast<unsigned>(a) | static_cast<unsigned>(b)));
+}
+
 /// \brief A pointer-like type pointing to a \c ZoneFinder object.
 typedef boost::shared_ptr<ZoneFinder> ZoneFinderPtr;
 




More information about the bind10-changes mailing list