Browse Source

[1579] suggested change: made findNoNameResult a bit more DNSSEC-agnostic.

to make a related test pass, incorporated the NotImplemented exception
handling from findNSECCover to getDNSSECRRset.
note: in this commit I reversed the behavior when we encounter the situation
where NSEC is expected but cannot be found; it now returns a NULL pointer,
although the NSEC_SIGNED flag can be still set.

It's a quite broken case of zone config so it's probably up to the
implementation, and in that sense throwing an exception is not necessary
wrong.  But we may have such a situation in a valid scenario if and when we
support incremental zone signing.  Also, this behavior is consistent with
BIND 9.

The emptyNonterminalNSEC test case was adjusted accordingly.
JINMEI Tatuya 13 years ago
parent
commit
07274f662a
2 changed files with 30 additions and 24 deletions
  1. 23 16
      src/lib/datasrc/database.cc
  2. 7 8
      src/lib/datasrc/tests/database_unittest.cc

+ 23 - 16
src/lib/datasrc/database.cc

@@ -780,16 +780,28 @@ DatabaseClient::Finder::FindDNSSECContext::getDNSSECRRset(const Name &name,
         return (ConstRRsetPtr());
     }
 
-    const Name& nsec_name = covering ? finder_.findPreviousName(name) : name;
-    const bool need_nscheck = (nsec_name == finder_.getOrigin());
-    const FoundRRsets found = finder_.getRRsets(nsec_name.toText(),
-                                                NSEC_TYPES(), need_nscheck);
-    const FoundIterator nci = found.second.find(RRType::NSEC());
-    if (nci != found.second.end()) {
-        return (nci->second);
-    } else {
-        return (ConstRRsetPtr());
+    try {
+        const Name& nsec_name =
+            covering ? finder_.findPreviousName(name) : name;
+        const bool need_nscheck = (nsec_name == finder_.getOrigin());
+        const FoundRRsets found = finder_.getRRsets(nsec_name.toText(),
+                                                    NSEC_TYPES(),
+                                                    need_nscheck);
+        const FoundIterator nci = found.second.find(RRType::NSEC());
+        if (nci != found.second.end()) {
+            return (nci->second);
+        }
+    } catch (const isc::NotImplemented&) {
+        // This happens when the underlying database accessor doesn't support
+        // findPreviousName() (it probably doesn't support DNSSEC at all) but
+        // there is somehow an NSEC RR at the zone apex.  We log the fact but
+        // otherwise let the caller decide what to do (so, for example, a
+        // higher level query processing won't completely fail but can return
+        // anything it can get).
+        LOG_INFO(logger, DATASRC_DATABASE_COVER_NSEC_UNSUPPORTED).
+            arg(finder_.accessor_->getDBName()).arg(name);
     }
+    return (ConstRRsetPtr());
 }
 
 ZoneFinder::FindResultFlags
@@ -924,13 +936,8 @@ DatabaseClient::Finder::findNoNameResult(const Name& name, const RRType& type,
         LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                   DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL).
             arg(accessor_->getDBName()).arg(name);
-        const ConstRRsetPtr nsec = dnssec_ctx.isNSEC() ? findNSECCover(name) :
-            ConstRRsetPtr();
-        if (dnssec_ctx.isNSEC() && !nsec) {
-            isc_throw(DataSourceError,
-                      "no NSEC RR covers in the NSEC signed zone");
-        }
-        return (ResultContext(NXRRSET, nsec, dnssec_ctx.getResultFlags()));
+        return (ResultContext(NXRRSET, dnssec_ctx.getDNSSECRRset(name, true),
+                              dnssec_ctx.getResultFlags()));
     } else if ((options & NO_WILDCARD) == 0) {
         // It's not an empty non-terminal and wildcard matching is not
         // disabled, so check for wildcards. If there is a wildcard match

+ 7 - 8
src/lib/datasrc/tests/database_unittest.cc

@@ -2471,14 +2471,13 @@ TYPED_TEST(DatabaseClientTest, emptyNonterminalNSEC) {
     if (!this->is_mock_) {
         return; // We don't make the real DB to throw
     }
-    // If the zone is signed with NSEC, find function should throw an error
-    // when no NSEC RRset for NXRRset case
-    EXPECT_THROW(doFindTest(*finder, Name("here.wild.example.org."),
-                            RRType::TXT(), RRType::NSEC(), this->rrttl_,
-                            ZoneFinder::NXRRSET, this->empty_rdatas_,
-                            this->empty_rdatas_, ZoneFinder::RESULT_DEFAULT,
-                            Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC),
-                 DataSourceError);
+    // In this case the accessor doesn't support findPreviousName(), but the
+    // zone apex has NSEC, and the zone itself is considered NSEC-signed.
+    doFindTest(*finder, Name("here.wild.example.org."),
+               RRType::TXT(), RRType::NSEC(), this->rrttl_,
+               ZoneFinder::NXRRSET, this->empty_rdatas_,
+               this->empty_rdatas_, ZoneFinder::RESULT_NSEC_SIGNED,
+               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
 }
 
 TYPED_TEST(DatabaseClientTest, anyFromFind) {