BIND 10 trac1579, updated. 4eeff0e79de122645ffd3bf117a1486147fc9541 [1579] adjust codes for the flag in the find function. Using a helper class to deal with the flag.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Apr 11 15:38:42 UTC 2012


The branch, trac1579 has been updated
       via  4eeff0e79de122645ffd3bf117a1486147fc9541 (commit)
      from  c31cfdf8449030f874406f4efad754ba7eb786e6 (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 4eeff0e79de122645ffd3bf117a1486147fc9541
Author: haikuo zhang <zhanghaikuo at cnnic.cn>
Date:   Wed Apr 11 23:30:29 2012 +0800

    [1579] adjust codes for the flag in the find function. Using a helper class to
    deal with the flag.

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

Summary of changes:
 INSTALL                                    |    2 +-
 src/lib/datasrc/database.cc                |  288 +++++++++++++++++++---------
 src/lib/datasrc/database.h                 |  192 +++++++++++++++----
 src/lib/datasrc/tests/database_unittest.cc |   98 +++++-----
 4 files changed, 398 insertions(+), 182 deletions(-)

-----------------------------------------------------------------------
diff --git a/INSTALL b/INSTALL
index 839f120..945020e 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-If using git (not the tarball), build the "configure" file:
+f using git (not the tarball), build the "configure" file:
     autoreconf --install
 
 To then build from source:
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index 748b562..5ae00e7 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -423,17 +423,9 @@ DatabaseClient::Finder::findAll(const isc::dns::Name& name,
                                 std::vector<isc::dns::ConstRRsetPtr>& target,
                                 const FindOptions options)
 {
-    const bool need_nsec3 = (((options & FIND_DNSSEC) != 0) && isNSEC3());
-    if (need_nsec3 && isNSEC()) {
-        isc_throw(DataSourceError, "nsec and nsec3 coexist");
-    }
-    // If the zone is signed with NSEC3, need to add RESULT_NSEC3_SIGNED to the
-    // flags in FindContext when NXRRSET NXDOMAIN or WILDCARD in the DNSSEC
-    // query, no need  NSEC RRset at the same time.
     return (ZoneFinderContextPtr(new Context(*this, options,
                                              findInternal(name, RRType::ANY(),
-                                                          &target, options,
-                                                          need_nsec3),
+                                                          &target, options),
                                              target)));
 }
 
@@ -445,17 +437,9 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
     if (type == RRType::ANY()) {
         isc_throw(isc::Unexpected, "Use findAll to answer ANY");
     }
-    // If the zone is signed with NSEC3, need to add RESULT_NSEC3_SIGNED to the
-    // flags in FindContext when NXRRSET NXDOMAIN or WILDCARD in the DNSSEC
-    // query, no need NSEC RRset at the same time.
-    const bool need_nsec3 = (((options & FIND_DNSSEC) != 0) && isNSEC3());
-    if (need_nsec3 && isNSEC()) {
-        isc_throw(DataSourceError, "nsec and nsec3 coexist");
-    }
     return (ZoneFinderContextPtr(new Context(*this, options,
                                              findInternal(name, type, NULL,
-                                                          options,
-                                                          need_nsec3))));
+                                                          options))));
 }
 
 DatabaseClient::Finder::DelegationSearchResult
@@ -617,15 +601,17 @@ DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
 //
 // If none of the above applies in any level, the search fails with NXDOMAIN.
 ZoneFinder::ResultContext
-DatabaseClient::Finder::findWildcardMatch(
-    const isc::dns::Name& name, const isc::dns::RRType& type,
-    const FindOptions options, const DelegationSearchResult& dresult,
-    std::vector<isc::dns::ConstRRsetPtr>* target, const bool need_nsec3)
+DatabaseClient::Finder::findWildcardMatch(const isc::dns::Name& name,
+                                          const isc::dns::RRType& type,
+                                          const DelegationSearchResult& dresult,
+                                          std::vector<isc::dns::ConstRRsetPtr>*
+                                          target, FindDNSSECContext& dnssec_ctx)
 {
     // Note that during the search we are going to search not only for the
     // requested type, but also for types that indicate a delegation -
     // NS and DNAME.
-    WantedTypes final_types(need_nsec3 ? FINAL_TYPES_NO_NSEC() : FINAL_TYPES());
+    WantedTypes final_types(dnssec_ctx.isNSEC3() ? FINAL_TYPES_NO_NSEC() :
+        FINAL_TYPES());
     final_types.insert(type);
 
     const size_t remove_labels = name.getLabelCount() - dresult.last_known;
@@ -647,7 +633,7 @@ DatabaseClient::Finder::findWildcardMatch(
             if (dresult.first_ns) {
                 // About to use first_ns.  The only way this can be set is if
                 // we are searching for glue, so do a sanity check.
-                if ((options & FIND_GLUE_OK) == 0) {
+                if ((dnssec_ctx.getOptions() & FIND_GLUE_OK) == 0) {
                     isc_throw(Unexpected, "Inconsistent conditions during "
                               "cancel of wilcard search for " <<
                               name.toText() << ": find_ns non-null when not "
@@ -663,8 +649,8 @@ DatabaseClient::Finder::findWildcardMatch(
             } else if (!hasSubdomains(name.split(i - 1).toText())) {
                 // The wildcard match is the best one, find the final result
                 // at it.  Note that wildcard should never be the zone origin.
-                return (findOnNameResult(name, type, options, false,
-                                         found, &wildcard, target, need_nsec3));
+                return (findOnNameResult(name, type, found, &wildcard,
+                                         target, dnssec_ctx));
             } else {
 
                 // more specified match found, cancel wildcard match
@@ -680,17 +666,15 @@ DatabaseClient::Finder::findWildcardMatch(
             LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                       DATASRC_DATABASE_WILDCARD_EMPTY).
                 arg(accessor_->getDBName()).arg(wildcard).arg(name);
-            if (((options & FIND_DNSSEC) != 0) && !need_nsec3) {
+            FindResultFlags flags = (RESULT_WILDCARD |
+                dnssec_ctx.getResultFlags());
+            if (dnssec_ctx.isNSEC()) {
                 ConstRRsetPtr nsec = findNSECCover(Name(wildcard));
                 if (nsec) {
-                    return (ResultContext(NXRRSET, nsec,
-                                          RESULT_WILDCARD |
-                                          RESULT_NSEC_SIGNED));
+                    return (ResultContext(NXRRSET, nsec, flags));
                 }
             }
-            return (ResultContext(NXRRSET, ConstRRsetPtr(), need_nsec3 ?
-                        (RESULT_WILDCARD | RESULT_NSEC3_SIGNED) :
-                                  RESULT_WILDCARD));
+            return (ResultContext(NXRRSET, ConstRRsetPtr(), flags));
         }
     }
 
@@ -728,23 +712,157 @@ DatabaseClient::Finder::logAndCreateResult(
     return (ResultContext(code, rrset, flags));
 }
 
+DatabaseClient::Finder::FindDNSSECContext::FindDNSSECContext(
+    DatabaseClient::Finder* finderp,
+    const isc::datasrc::ZoneFinder::FindOptions options,
+    const Name& origin) :
+    finderp_(finderp),
+    options_(options),
+    origin_(origin),
+    initialized_(false)
+{}
+
+ZoneFinder::FindOptions
+DatabaseClient::Finder::FindDNSSECContext::getOptions() const
+{
+    return options_;
+}
+
+void
+DatabaseClient::Finder::FindDNSSECContext::init()
+{
+    if (finderp_ == NULL) {
+        isc_throw(DataSourceError, "no Finder to query");
+    }
+    if (!initialized_) {
+        initialized_ = true;
+        // If NSEC3PARAM rrset exists, the zone looks like signed with NSEC3
+        is_nsec3_ = ((options_ & FIND_DNSSEC) == 0) ? false :
+            finderp_->isNSEC3();
+        if (is_nsec3_) {
+            // If the zone is signed with NSEC3, no need to check NSEC. If NSEC
+            // and NSEC3 coexist, according to RFC 5155 10-4, it should return
+            // result as NSEC3.
+            is_nsec_ = false;
+        } else {
+            // If no NSEC3PARAM and it is DNSSEC query, check whether NSEC
+            // exist in apex of zone
+            is_nsec_ = ((options_ & FIND_DNSSEC) == 0) ? false :
+                finderp_->isNSEC();
+        }
+    }
+}
+
+bool
+DatabaseClient::Finder::FindDNSSECContext::isInited()
+{
+    return initialized_;
+}
+
+bool
+DatabaseClient::Finder::FindDNSSECContext::isNSEC3()
+{
+    if (isInited()) {
+        return is_nsec3_;
+    } else {
+        init();
+        return is_nsec3_;
+    }
+}
+
+bool
+DatabaseClient::Finder::FindDNSSECContext::isNSEC()
+{
+    if (isInited()) {
+        return is_nsec_;
+    } else {
+        init();
+        return is_nsec_;
+    }
+}
+
+isc::dns::ConstRRsetPtr
+DatabaseClient::Finder::FindDNSSECContext::getNSECRRset(
+        const FoundRRsets& found_set) const
+{
+    const FoundIterator nci = found_set.second.find(RRType::NSEC());
+    if (nci != found_set.second.end()) {
+        return nci->second;
+    } else {
+        return ConstRRsetPtr();
+    }
+}
+
+isc::dns::ConstRRsetPtr
+DatabaseClient::Finder::FindDNSSECContext::getNSECRRset(const Name &name) const
+{
+    if (finderp_ == NULL) {
+        isc_throw(DataSourceError, "no Finder to query");
+    }
+    const FoundRRsets wfound = finderp_->getRRsets(name.toText(), NSEC_TYPES(),
+                                                   true);
+    const FoundIterator nci = wfound.second.find(RRType::NSEC());
+    if (nci != wfound.second.end()) {
+        return nci->second;
+    } else {
+        return ConstRRsetPtr();
+    }
+}
+
+DatabaseClient::Finder::FoundRRsets
+DatabaseClient::Finder::FindDNSSECContext::getDNSSECRRset(const Name& name,
+                                                          const RRType& type)
+{
+    if (finderp_ == NULL) {
+        isc_throw(DataSourceError, "no Finder to query");
+    }
+    const bool is_origin = isOrigin(name);
+    bool is_nsec = isNSEC();
+    WantedTypes final_types(is_nsec ? FINAL_TYPES() : FINAL_TYPES_NO_NSEC());
+    final_types.insert(type);
+    return (finderp_->getRRsets(name.toText(), final_types, !is_origin, NULL,
+            type == RRType::ANY()));
+}
+
+bool
+DatabaseClient::Finder::FindDNSSECContext::isOrigin(const Name &name) const
+{
+    return (name == origin_);
+}
+
+ZoneFinder::FindResultFlags
+DatabaseClient::Finder::FindDNSSECContext::getResultFlags()
+{
+    // If it is not DNSSEC query, it should return RESULT_DEFAULT
+    if ((options_ & FIND_DNSSEC) == 0) {
+        return RESULT_DEFAULT;
+    }
+    // If it is a DNSSEC query and the zone is signed with NSEC3, it should
+    // return RESULT_NSEC3_SIGNED
+    if (isNSEC3()) {
+        return RESULT_NSEC3_SIGNED;
+    } else {
+        // If it is a DNSSEC query and the zone is signed with NSEC, it should
+        // return RESULT_NSEC_SIGNED, other else, return RESULT_DEFAULT
+        return (isNSEC() ? RESULT_NSEC_SIGNED : RESULT_DEFAULT);
+    }
+}
+
 ZoneFinder::ResultContext
 DatabaseClient::Finder::findOnNameResult(const Name& name,
                                          const RRType& type,
-                                         const FindOptions options,
-                                         const bool is_origin,
                                          const FoundRRsets& found,
                                          const string* wildname,
                                          std::vector<isc::dns::ConstRRsetPtr>*
-                                         target, const bool need_nsec3)
+                                         target, FindDNSSECContext& dnssec_ctx)
 {
     const bool wild = (wildname != NULL);
-    FindResultFlags flags;
-    if (need_nsec3) {
-        flags = wild ? (RESULT_WILDCARD | RESULT_NSEC3_SIGNED) :
-            RESULT_DEFAULT;
-    } else {
-        flags = wild ? RESULT_WILDCARD : RESULT_DEFAULT;
+    FindResultFlags flags = wild ? RESULT_WILDCARD : RESULT_DEFAULT;
+    // If the zone file is signed with NSEC3, need to set RESULT_NSEC3_SIGNED
+    // flag in the flags. It is good for upper caller to deal with the query
+    // response message.
+    if (wild & dnssec_ctx.isNSEC3()) {
+        flags = (flags | RESULT_NSEC3_SIGNED);
     }
     // Get iterators for the different types of records we are interested in -
     // CNAME, NS and Wanted types.
@@ -754,15 +872,13 @@ DatabaseClient::Finder::findOnNameResult(const Name& name,
     // For wildcard case with DNSSEC required, the caller would need to know
     // whether it's NSEC or NSEC3 signed.  So we need to do an additional
     // search here, even though the NSEC RR may not be returned.
-    // TODO: this part should be revised when we support NSEC3; ideally we
-    // should use more effective and efficient way to identify (whether and)
-    // in which way the zone is signed.
-    if (wild && (options & FIND_DNSSEC) != 0 && !need_nsec3 &&
+    if (wild && dnssec_ctx.isNSEC() &&
         found.second.find(RRType::NSEC()) != found.second.end()) {
-        flags = flags | RESULT_NSEC_SIGNED;
+        flags = (flags | RESULT_NSEC_SIGNED);
     }
 
-    if (!is_origin && ((options & FIND_GLUE_OK) == 0) &&
+    if (!dnssec_ctx.isOrigin(name) &&
+        ((dnssec_ctx.getOptions() & FIND_GLUE_OK) == 0) &&
         nsi != found.second.end()) {
         // A NS RRset was found at the domain we were searching for.  As it is
         // not at the origin of the zone, it is a delegation and indicates that
@@ -821,66 +937,54 @@ DatabaseClient::Finder::findOnNameResult(const Name& name,
     // NSEC records in the name of the wildcard, not the substituted one,
     // so we need to search the tree again.
     ConstRRsetPtr nsec_rrset;   // possibly used with DNSSEC, otherwise NULL
-    if ((options & FIND_DNSSEC) != 0 && !need_nsec3) {
-        if (wild) {
-            const FoundRRsets wfound = getRRsets(*wildname, NSEC_TYPES(),
-                                                 true);
-            const FoundIterator nci = wfound.second.find(RRType::NSEC());
-            if (nci != wfound.second.end()) {
-                nsec_rrset = nci->second;
-            }
-        } else {
-            const FoundIterator nci = found.second.find(RRType::NSEC());
-            if (nci != found.second.end()) {
-                nsec_rrset = nci->second;
-            }
-        }
+    if (dnssec_ctx.isNSEC()) {
+        nsec_rrset = wild ? dnssec_ctx.getNSECRRset(Name(*wildname)) :
+            dnssec_ctx.getNSECRRset(found);
     }
     if (nsec_rrset) {
         // This log message covers both normal and wildcard cases, so we pass
         // NULL for 'wildname'.
         return (logAndCreateResult(name, NULL, type, NXRRSET, nsec_rrset,
                                    DATASRC_DATABASE_FOUND_NXRRSET_NSEC,
-                                   flags | RESULT_NSEC_SIGNED));
+                                   (flags | RESULT_NSEC_SIGNED)));
     }
     return (logAndCreateResult(name, wildname, type, NXRRSET, nsec_rrset,
                                wild ? DATASRC_DATABASE_WILDCARD_NXRRSET :
-                               DATASRC_DATABASE_FOUND_NXRRSET, need_nsec3 ?
-                               (flags | RESULT_NSEC3_SIGNED) : flags));
+                               DATASRC_DATABASE_FOUND_NXRRSET,
+                               (flags | dnssec_ctx.getResultFlags())));
 }
 
 ZoneFinder::ResultContext
 DatabaseClient::Finder::findNoNameResult(const Name& name, const RRType& type,
-                                         FindOptions options,
                                          const DelegationSearchResult& dresult,
                                          std::vector<isc::dns::ConstRRsetPtr>*
-                                         target, const bool need_nsec3)
+                                         target, FindDNSSECContext& dnssec_ctx)
 {
-    const bool dnssec_data = ((options & FIND_DNSSEC) != 0);
-    const bool need_nsec = (dnssec_data && !need_nsec3);
     // On entry to this method, we know that the database doesn't have any
     // entry for this name.  Before returning NXDOMAIN, we need to check
     // for special cases.
 
     if (hasSubdomains(name.toText())) {
-        // Does the domain have a subdomain (i.e. it is an empty non-terminal)?
+        // Does the domain have a subdomain (i.e. it is an empty non-terminal)
         // If so, return NXRRSET instead of NXDOMAIN (as although the name does
         // not exist in the database, it does exist in the DNS tree).
         LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                   DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL).
             arg(accessor_->getDBName()).arg(name);
-        const ConstRRsetPtr nsec = need_nsec ? findNSECCover(name) :
+        const ConstRRsetPtr nsec = dnssec_ctx.isNSEC() ? findNSECCover(name) :
             ConstRRsetPtr();
-        return (ResultContext(NXRRSET, nsec, nsec ? RESULT_NSEC_SIGNED :
-            (need_nsec3 ? RESULT_NSEC3_SIGNED : RESULT_DEFAULT)));
-    } else if ((options & NO_WILDCARD) == 0) {
+        if(dnssec_ctx.isNSEC() && (!nsec)){
+            isc_throw(DataSourceError,
+                      "no NSEC RR covers in the NSEC signed zone");
+        }
+        return (ResultContext(NXRRSET, nsec, dnssec_ctx.getResultFlags()));
+    } else if ((dnssec_ctx.getOptions() & 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
         // (i.e. all results except NXDOMAIN) return it; otherwise fall
         // through to the NXDOMAIN case below.
         const ResultContext wcontext =
-            findWildcardMatch(name, type, options, dresult, target,
-                              need_nsec3);
+            findWildcardMatch(name, type, dresult, target, dnssec_ctx);
         if (wcontext.code != NXDOMAIN) {
             return (wcontext);
         }
@@ -890,11 +994,12 @@ DatabaseClient::Finder::findNoNameResult(const Name& name, const RRType& type,
     // NSEC records if requested).
     LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_NO_MATCH).
               arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass());
-    const ConstRRsetPtr nsec = need_nsec ? findNSECCover(name) :
+    const ConstRRsetPtr nsec = dnssec_ctx.isNSEC() ? findNSECCover(name) :
         ConstRRsetPtr();
-    return (ResultContext(NXDOMAIN, nsec,
-                          nsec ? RESULT_NSEC_SIGNED : (need_nsec3 ?
-                          RESULT_NSEC3_SIGNED : RESULT_DEFAULT)));
+    if(dnssec_ctx.isNSEC() && (!nsec)){
+        isc_throw(DataSourceError, "no NSEC RR covers in the NSEC signed zone");
+    }
+    return (ResultContext(NXDOMAIN, nsec, dnssec_ctx.getResultFlags()));
 }
 
 bool
@@ -910,9 +1015,9 @@ DatabaseClient::Finder::isNSEC3() {
 
 bool
 DatabaseClient::Finder::isNSEC() {
-    // If an NSEC RRsets exists at the zone apex, it's quite likely that
-    // the zone is signed with NSEC. (If not the zone is more or less broken,
-    // but it's caller's responsibility how to handle such cases)
+    // If an NSEC RR exists at the zone apex, it's quite likely that
+    // the zone is signed with NSEC.  (If not the zone is more or less broken,
+    // but it's caller's responsibility how to handle such cases).
     const FoundRRsets nsec_found = getRRsets(origin_.toText(),
                                              NSEC_TYPES(), false);
     const FoundIterator nfi(nsec_found.second.find(RRType::NSEC()));
@@ -922,8 +1027,7 @@ DatabaseClient::Finder::isNSEC() {
 ZoneFinder::ResultContext
 DatabaseClient::Finder::findInternal(const Name& name, const RRType& type,
                                      std::vector<ConstRRsetPtr>* target,
-                                     const FindOptions options,
-                                     const bool is_nsec3)
+                                     const FindOptions options)
 {
     LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
               .arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass());
@@ -961,22 +1065,16 @@ DatabaseClient::Finder::findInternal(const Name& name, const RRType& type,
     // - Requested name is a delegation point (NS only but not at the zone
     //   apex - DNAME is ignored here as it redirects DNS names subordinate to
     //   the owner name - the owner name itself is not redirected.)
-    const bool is_origin = (name == getOrigin());
-    WantedTypes final_types(is_nsec3 ? FINAL_TYPES_NO_NSEC() : FINAL_TYPES());
-    final_types.insert(type);
-    const FoundRRsets found = getRRsets(name.toText(), final_types,
-                                        !is_origin, NULL,
-                                        type == RRType::ANY());
+    FindDNSSECContext dnssec_ctx(this, options, getOrigin());
+    const FoundRRsets found = dnssec_ctx.getDNSSECRRset(name, type);
     if (found.first) {
         // Something found at the domain name.  Look into it further to get
         // the final result.
-        return (findOnNameResult(name, type, options, is_origin, found,
-                                 NULL, target, is_nsec3));
+        return (findOnNameResult(name, type, found, NULL, target, dnssec_ctx));
     } else {
         // Did not find anything at all at the domain name, so check for
         // subdomains or wildcards.
-        return (findNoNameResult(name, type, options, dresult, target,
-                                 is_nsec3));
+        return (findNoNameResult(name, type, dresult, target, dnssec_ctx));
     }
 }
 
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index b9421ca..2e8c885 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -673,6 +673,7 @@ public:
     DatabaseClient(isc::dns::RRClass rrclass,
                    boost::shared_ptr<DatabaseAccessor> accessor);
 
+
     /// \brief Corresponding ZoneFinder implementation
     ///
     /// The zone finder implementation for database data sources. Similarly
@@ -687,7 +688,126 @@ public:
     ///
     /// Methods directly corresponds to the ones in ZoneFinder.
     class Finder : public ZoneFinder {
-    public:
+
+        /// \brief Helper to the findInterval.
+        ///
+        /// Get the ResultFlags for findInterval. If the zone is signed with
+        /// NSEC3, it will return RESULT_NSEC3_SIGNED. If it is signed with
+        /// NSEC, it wll return RESULT_NSEC_SIGNED. Other else it will return
+        /// RESULT_DEFAULT. It wraps getRRsets function to do some special
+        /// search, like searching NSEC RRset by getNSECRRset function,
+        /// searching DNSSEC related RRset and RRsig by getNSECRRset.
+        class FindDNSSECContext{
+            public:
+
+                /// \brief Constructor for FindDNSSECContext class.
+                ///
+                /// It initalize a helper for findInterval function.
+                ///
+                /// \param finderp The Finder piont for search.
+                /// \param options Search options.
+                /// \param origin The origin name for this finder.
+                FindDNSSECContext(Finder* finderp, const FindOptions options,
+                                  const isc::dns::Name& origin);
+
+                /// \brief Get result flags of this query.
+                /// \return ResultFlags for this query. If the zone file is
+                /// signed with NSEC, is will return RESULT_NSEC_SIGNED with
+                /// dnssec query. If the zone file is signed with NSEC3, it
+                /// will return RESULT_NSEC3_SIGNED with dnssec query, others
+                /// it should return RESULT_DEFAULT.
+                ZoneFinder::FindResultFlags getResultFlags();
+
+                typedef std::pair<bool, std::map<dns::RRType, dns::RRsetPtr> >
+                    FoundRRsets;
+                /// \brief Get DNSSEC RRset for the queried name.
+                ///
+                /// It should return the RRsets and RRsigs for the queried
+                /// name with designated type.
+                ///
+                /// \param name The queried name.
+                /// \param type The queried type.
+                /// \return RRsets and RRsigs that are matched.
+                FoundRRsets getDNSSECRRset(const isc::dns::Name& name,
+                                           const isc::dns::RRType& type);
+
+                /// \brief Get the needed NSEC RRset.
+                ///
+                /// It should return the needed NSEC RRset.
+                ///
+                /// \param name The name which the NSEC RRset belong to.
+                /// \return the needed NSEC RRsets.
+                isc::dns::ConstRRsetPtr getNSECRRset(const isc::dns::Name&
+                                                     name) const;
+
+                /// \brief Get the needed NSEC RRset.
+                ///
+                /// It should return the needed NSEC RRset.
+                ///
+                /// \param found_set The RRset which contain the NSEC an other
+                /// type RRs.
+                /// \return the needed NSEC RRsets.
+                isc::dns::ConstRRsetPtr getNSECRRset(const FoundRRsets&
+                                                     found_set) const;
+
+                /// \brief Check whether the zone file is signed with NSECi3.
+                ///
+                /// It checks whether the zone file is signed with NSEC3. If
+                /// yes, return true, other else return false.
+                ///
+                /// \return True for NSEC3, false for other else.
+                bool isNSEC3();
+
+                /// \brief Check whether the zone file is signed with NSEC.
+                ///
+                /// It checks whether the zone file is signed with NSEC, If
+                /// yes, return true, other else return false.
+                ///
+                /// \return True for NSEC, false for other else.
+                bool isNSEC();
+
+                /// \brief Check whether the name is origin name of the zone.
+                ///
+                /// It checks whether the name is origin name of the zone. Yes
+                /// for the origin name, false for not.
+                ///
+                /// \param name The queried name.
+                /// \return True for origin name, false for not.
+                bool isOrigin(const isc::dns::Name& name) const;
+
+                /// \brief get the options of queried.
+                ///
+                /// It return the queried options.
+                ///
+                /// \return It return the queried options.
+                ZoneFinder::FindOptions getOptions() const;
+            private:
+
+                /// \brief Init the attributes in this entity.
+                ///
+                /// It should init the attributes of this entity. Check whether
+                /// it is the NSEC or NSEC3 zone file if it is a dnssec query.
+                ///
+                /// \note If the entity is initalized, no need to init it again.
+                void init();
+
+                /// \brief Check whether the entity is initalized.
+                ///
+                /// It should return true if the entity is inited, else return
+                /// false.
+                ///
+                /// \return True for inited, else return false.
+                bool isInited();
+                DatabaseClient::Finder* finderp_;
+                ZoneFinder::ZoneFinder::FindOptions options_;
+                FindResultFlags flags_;
+                isc::dns::Name origin_;
+                bool is_nsec3_;
+                bool is_nsec_;
+                bool initialized_;
+        };
+
+        public:
         /// \brief Constructor
         ///
         /// \param database The database (shared with DatabaseClient) to
@@ -706,19 +826,6 @@ public:
         virtual isc::dns::Name getOrigin() const;
         virtual isc::dns::RRClass getClass() const;
 
-
-        /// \brief check whether zone is signed with nsec3
-        ///
-        /// searches the NSEC3PARAM RRset in the zone apex, if it exists, the 
-        /// zone looks signed with nsec3
-        bool isNSEC3();
-
-        /// \brief check whether zone is signed with nsec
-        ///
-        /// searches the NSEC RRset in the zone apex, if it exists, the
-        /// zone looks signed with nsec
-        bool isNSEC();
-
         /// \brief Find an RRset in the datasource
         ///
         /// Searches the datasource for an RRset of the given name and
@@ -791,10 +898,22 @@ public:
             return (*accessor_);
         }
 
+        /// \brief check whether zone is signed with nsec
+        ///
+        /// searches the NSEC3PARAM RRset in the zone apex, if it exists, the
+        /// zone looks signed with nsec
+        bool isNSEC();
+        /// \brief check whether zone is signed with nsec3
+        ///
+        /// searches the NSEC3PARAM RRset in the zone apex, if it exists, the
+        /// zone looks signed with nsec3
+        bool isNSEC3();
+
     private:
         boost::shared_ptr<DatabaseAccessor> accessor_;
         const int zone_id_;
         const isc::dns::Name origin_;
+
         /// \brief Shortcut name for the result of getRRsets
         typedef std::pair<bool, std::map<dns::RRType, dns::RRsetPtr> >
             FoundRRsets;
@@ -814,9 +933,8 @@ public:
                                    const isc::dns::RRType& type,
                                    std::vector<isc::dns::ConstRRsetPtr>*
                                    target,
-                                   const FindOptions options = FIND_DEFAULT,
-                                   const bool need_nsec3 = false);
-
+                                   const FindOptions options = FIND_DEFAULT);
+    public:
         /// \brief Searches database for RRsets of one domain.
         ///
         /// This method scans RRs of single domain specified by name and
@@ -851,6 +969,7 @@ public:
                               const std::string* construct_name = NULL,
                               bool any = false);
 
+    private:
         /// \brief Search result of \c findDelegationPoint().
         ///
         /// This is a tuple combining the result of the search - a status code
@@ -946,15 +1065,13 @@ public:
         ///
         /// \param name The name to find
         /// \param type The RRType to find
-        /// \param options Options about how to search. See the documentation
-        ///        for ZoneFinder::FindOptions.
         /// \param dresult Result of the search through the zone for a
         ///        delegation.
         /// \param target If the type happens to be ANY, it will insert all
         ///        the RRsets of the found name (if any is found) here instead
         ///        of being returned by the result.
-        /// \param need_nsec3 When zone is signed with nsec3, no need to find 
-        ///        nsec rrset
+        /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for
+        ///        find function.
         /// \return Tuple holding the result of the search - the RRset of the
         ///         wildcard records matching the name, together with a status
         ///         indicating the match type (e.g. CNAME at the wildcard
@@ -962,13 +1079,11 @@ public:
         ///         success due to an exact match).  Also returned if there
         ///         is no match is an indication as to whether there was an
         ///         NXDOMAIN or an NXRRSET.
-        ResultContext findWildcardMatch(
-            const isc::dns::Name& name,
-            const isc::dns::RRType& type,
-            const FindOptions options,
-            const DelegationSearchResult& dresult,
-            std::vector<isc::dns::ConstRRsetPtr>* target,
-            const bool need_nsec3);
+        ResultContext findWildcardMatch(const isc::dns::Name& name,
+                                        const isc::dns::RRType& type,
+                                        const DelegationSearchResult& dresult,
+                                        std::vector<isc::dns::ConstRRsetPtr>*
+                                        target, FindDNSSECContext& dnssec_ctx);
 
         /// \brief Handle matching results for name
         ///
@@ -989,9 +1104,6 @@ public:
         ///
         /// \param name The name to find
         /// \param type The RRType to find
-        /// \param options Options about how to search. See the documentation
-        ///        for ZoneFinder::FindOptions.
-        /// \param is_origin If name is the zone's origin name.
         /// \param found A set of found RRsets in the search for the name
         ///        and type.  It could contain one or more of the requested
         ///        type, CNAME, NS, and NSEC RRsets of the name.
@@ -1001,8 +1113,9 @@ public:
         ///                 it's NULL in the case of non wildcard match.
         /// \param target When the query is any, this must be set to a vector
         ///    where the result will be stored.
-        /// \param need_nsec3 When zone is signed with nsec3, no need to find 
-        ///    nsec rrset
+        /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for
+        ///        find function.
+
         /// \return Tuple holding the result of the search - the RRset of the
         ///         wildcard records matching the name, together with a status
         ///         indicating the match type (corresponding to the each of
@@ -1011,12 +1124,10 @@ public:
         ///         method.
         ResultContext findOnNameResult(const isc::dns::Name& name,
                                        const isc::dns::RRType& type,
-                                       const FindOptions options,
-                                       const bool is_origin,
                                        const FoundRRsets& found,
                                        const std::string* wildname,
                                        std::vector<isc::dns::ConstRRsetPtr>*
-                                       target, const bool need_nsec3);
+                                       target, FindDNSSECContext& dnssec_ctx);
 
         /// \brief Handle no match for name
         ///
@@ -1041,8 +1152,8 @@ public:
         /// \param target If the query is for type ANY, the successfull result,
         ///        if there happens to be one, will be returned through the
         ///        parameter, as it doesn't fit into the result.
-        /// \param need_nsec3 When zone is signed with nsec3, no need to find
-        ///        nsec rrset
+        /// \param dnssec_ctx The dnssec context, it is a DNSSEC wrapper for
+        ///        find function.
         /// \return Tuple holding the result of the search - the RRset of the
         ///         wildcard records matching the name, together with a status
         ///         indicating the match type (e.g. CNAME at the wildcard
@@ -1050,10 +1161,9 @@ public:
         ///         success due to an exact match).
         ResultContext findNoNameResult(const isc::dns::Name& name,
                                        const isc::dns::RRType& type,
-                                       FindOptions options,
                                        const DelegationSearchResult& dresult,
                                        std::vector<isc::dns::ConstRRsetPtr>*
-                                       targeti, const bool need_nsec3);
+                                       target, FindDNSSECContext& dnssec_ctx);
 
         /// Logs condition and creates result
         ///
@@ -1106,6 +1216,8 @@ public:
         /// To find stuff in the result of getRRsets.
         typedef std::map<dns::RRType, dns::RRsetPtr>::const_iterator
             FoundIterator;
+
+
     };
 
     /// \brief Find a zone in the database
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index 3c1e892..bd99f5d 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -2292,11 +2292,18 @@ TYPED_TEST(DatabaseClientTest, wildcardNXRRSET_NSEC) {
                Name("*.wild.example.org"), ZoneFinder::FIND_DNSSEC);
 }
 
-TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) {
-    // ZoneFinder::find() for negative cases should show whether the zone is
-    // signed with NSEC or NSEC3, that is good for upper layer caller.
+TYPED_TEST(DatabaseClientTest, nsec3FlagFindDB) {
+    // ZoneFinder::find() for negative cases and wildcard cases should check
+    // whether the zone is signed with NSEC or NSEC3. If it is signed with
+    // NSEC3, RESULT_NSEC3_SIGNED flag should be returned. That is good for
+    // upper layer caller.
 
-    // First off, everything should be okay if no NSEC3PARAM rrset
+    // First off, everything should be okay if no NSEC3PARAM rrset. If
+    // NSEC3PARAM RRset doesn't exist and NSEC RRset exist at apex, it looks
+    // like signed with NSEC, and the RESULT_NSEC_SIGNED flag should be return.
+
+    // Check NXDOMAIN case in NSEC signed zone, and RESULT_NSEC_SIGNED flag
+    // should be returned to upper layer caller.
     this->expected_rdatas_.clear();
     this->expected_sig_rdatas_.clear();
     this->expected_rdatas_.push_back("www2.example.org. A AAAA NSEC RRSIG");
@@ -2309,6 +2316,9 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) {
                ZoneFinder::NXDOMAIN, this->expected_rdatas_,
                this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC_SIGNED,
                Name("www.example.org."), ZoneFinder::FIND_DNSSEC);
+
+    // Check NXRRSET case in NSEC signed zone, and RESULT_NSEC_SIGNED flag
+    // should be return.
     this->expected_rdatas_.clear();
     this->expected_sig_rdatas_.clear();
     this->expected_rdatas_.push_back("www2.example.org. A AAAA NSEC RRSIG");
@@ -2316,11 +2326,12 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) {
                                          "20000201000000 12345 example.org. "
                                          "FAKEFAKEFAKE");
     doFindTest(*finder, isc::dns::Name("www.example.org."),
-               isc::dns::RRType::TXT(), isc::dns::RRType::NSEC(),
-               this->rrttl_, ZoneFinder::NXRRSET,
-               this->expected_rdatas_, this->expected_sig_rdatas_,
-               ZoneFinder::RESULT_NSEC_SIGNED, isc::dns::Name::ROOT_NAME(),
-               ZoneFinder::FIND_DNSSEC);
+               isc::dns::RRType::TXT(), isc::dns::RRType::NSEC(), this->rrttl_,
+               ZoneFinder::NXRRSET, this->expected_rdatas_,
+               this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC_SIGNED,
+               isc::dns::Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
+
+    // Check wildcase cases, and the RESULT_NSEC_SIGNED should be return.
     this->expected_rdatas_.clear();
     this->expected_sig_rdatas_.clear();
     this->expected_rdatas_.push_back("192.0.2.5");
@@ -2346,26 +2357,10 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) {
                this->expected_sig_rdatas_,
                (ZoneFinder::RESULT_WILDCARD | ZoneFinder::RESULT_NSEC_SIGNED),
                Name("*.wild.example.org"), ZoneFinder::FIND_DNSSEC);
-    this->updater_ = this->client_->getUpdater(this->zname_, false);
-    this->rrset_.reset(new RRset(this->zname_, this->qclass_,
-                       isc::dns::RRType::NSEC3PARAM(), this->rrttl_));
-    this->rrset_->addRdata(rdata::createRdata(isc::dns::RRType::NSEC3PARAM(), 
-                           this->rrset_->getClass(), "1 0 12 aabbccdd"));
-    this->updater_->addRRset(*this->rrset_);
-    this->updater_->commit();
-    try {
-        this->expected_rdatas_.clear();
-        this->expected_sig_rdatas_.clear();
-        doFindTest(this->updater_->getFinder(), Name("www1.example.org."),
-                   this->qtype_, this->qtype_, this->rrttl_,
-                   ZoneFinder::NXDOMAIN, this->expected_rdatas_,
-                   this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC3_SIGNED,
-                   Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
-    } catch (const DataSourceError&) {}
-    // The following test should be tested in zone which is signed by NSEC3
-#if 0
-    // Then, if NSEC3PARAM exists at the origin, the flags of result should
+
+    // Then, if NSEC3PARAM exists at the apex, the flags of result should
     // contain RESULT_NSEC3_SIGNED flag when NXDOMAIN NXRRSET or wildcard
+    // cases.
 
     // Add NSEC3PARAM RRSET at the apex of the zone. It looks weird if the
     // zone only has NSEC3PARM RRset (but no NSEC3s), but it is okay for unit
@@ -2377,23 +2372,27 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) {
                                               this->rrset_->getClass(),
                                               "1 0 12 aabbccdd"));
     this->updater_->addRRset(*this->rrset_);
-    // check NXDOMAIN
+
+    // check NXDOMAIN, it should set RESULT_NSEC3_SIGNED in the flags.
     this->expected_rdatas_.clear();
     this->expected_sig_rdatas_.clear();
-    doFindTest(this->updater_->getFinder(),
-            isc::dns::Name("www1.example.org."), this->qtype_, this->qtype_, 
-            this->rrttl_, ZoneFinder::NXDOMAIN, this->expected_rdatas_,
-            this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC3_SIGNED,
-            isc::dns::Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
-    // check NXRRSET
+    doFindTest(this->updater_->getFinder(), Name("www1.example.org."),
+            this->qtype_, this->qtype_, this->rrttl_, ZoneFinder::NXDOMAIN,
+            this->expected_rdatas_, this->expected_sig_rdatas_,
+            ZoneFinder::RESULT_NSEC3_SIGNED,Name::ROOT_NAME(),
+            ZoneFinder::FIND_DNSSEC);
+
+    // check NXRRSET, it should set RESULT_NSEC3_SIGNED in the flags.
     this->expected_rdatas_.clear();
     this->expected_sig_rdatas_.clear();
     doFindTest(this->updater_->getFinder(), Name("www.example.org."),
                RRType::TXT(), RRType::TXT(), this->rrttl_,
                ZoneFinder::NXRRSET, this->expected_rdatas_,
                this->expected_sig_rdatas_, ZoneFinder::RESULT_NSEC3_SIGNED,
-               isc::dns::Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
-    // check flags if wildcard matches
+               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
+
+    // check flags if wildcard matches, it should set RESULT_NSEC3_SIGNED in
+    // the flags.
     this->expected_rdatas_.push_back("192.0.2.5");
     this->expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 "
                                          "20000201000000 12345 example.org. "
@@ -2403,16 +2402,17 @@ TYPED_TEST(DatabaseClientTest, dbNegativeCaseFind) {
                this->expected_rdatas_, this->expected_sig_rdatas_,
                ZoneFinder::RESULT_WILDCARD | ZoneFinder::RESULT_NSEC3_SIGNED,
                Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
-    // check flags if NXRRSET in wildcard case
+
+    // check flags if NXRRSET in wildcard case, it should set
+    // RESULT_NSEC3_SIGNED in the flags.
     this->expected_rdatas_.clear();
     this->expected_sig_rdatas_.clear();
     doFindTest(this->updater_->getFinder(), Name("b.a.wild.example.org"),
                RRType::TXT(), RRType::TXT(), this->rrttl_,
                ZoneFinder::NXRRSET, this->expected_rdatas_,
                this->empty_rdatas_, (ZoneFinder::RESULT_WILDCARD |
-                                     ZoneFinder::RESULT_NSEC3_SIGNED),
-               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC);
-#endif
+               ZoneFinder::RESULT_NSEC3_SIGNED), Name::ROOT_NAME(),
+               ZoneFinder::FIND_DNSSEC);
 }
 
 TYPED_TEST(DatabaseClientTest, NXDOMAIN_NSEC) {
@@ -2444,14 +2444,17 @@ TYPED_TEST(DatabaseClientTest, NXDOMAIN_NSEC) {
     if (!this->is_mock_) {
         return; // We don't make the real DB to throw
     }
-    EXPECT_NO_THROW(doFindTest(*finder,
+    // If the zone is signed with NSEC, find function should throw an error
+    // when no NSEC RRset for NXDOMAIN case.
+    EXPECT_THROW(doFindTest(*finder,
                                isc::dns::Name("notimplnsec.example.org."),
                                isc::dns::RRType::TXT(),
                                isc::dns::RRType::NSEC(), this->rrttl_,
                                ZoneFinder::NXDOMAIN, this->empty_rdatas_,
                                this->empty_rdatas_,
                                ZoneFinder::RESULT_DEFAULT,
-                               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC));
+                               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC),
+                 DataSourceError);
 }
 
 TYPED_TEST(DatabaseClientTest, emptyNonterminalNSEC) {
@@ -2471,14 +2474,17 @@ TYPED_TEST(DatabaseClientTest, emptyNonterminalNSEC) {
     if (!this->is_mock_) {
         return; // We don't make the real DB to throw
     }
-    EXPECT_NO_THROW(doFindTest(*finder,
+    // If the zone is signed with NSEC, find function should throw an error
+    // when no NSEC RRset for NXRRset case
+    EXPECT_THROW(doFindTest(*finder,
                                isc::dns::Name("here.wild.example.org."),
                                isc::dns::RRType::TXT(),
                                isc::dns::RRType::NSEC(),
                                this->rrttl_, ZoneFinder::NXRRSET,
                                this->empty_rdatas_, this->empty_rdatas_,
                                ZoneFinder::RESULT_DEFAULT,
-                               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC));
+                               Name::ROOT_NAME(), ZoneFinder::FIND_DNSSEC),
+                 DataSourceError);
 }
 
 TYPED_TEST(DatabaseClientTest, anyFromFind) {



More information about the bind10-changes mailing list