Browse Source

[1198] Checkpoint after updating internal documentation

Stephen Morris 13 years ago
parent
commit
b8e8950926
3 changed files with 269 additions and 168 deletions
  1. 120 65
      src/lib/datasrc/database.cc
  2. 136 97
      src/lib/datasrc/database.h
  3. 13 6
      src/lib/datasrc/datasrc_messages.mes

+ 120 - 65
src/lib/datasrc/database.cc

@@ -392,8 +392,7 @@ DatabaseClient::Finder::findNSECCover(const Name& name) {
 
 
 DatabaseClient::Finder::DelegationSearchResult
 DatabaseClient::Finder::DelegationSearchResult
 DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
 DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
-                                            const FindOptions options)
+                                            const FindOptions options) {
-{
     // Result of search
     // Result of search
     isc::dns::ConstRRsetPtr result_rrset;
     isc::dns::ConstRRsetPtr result_rrset;
     ZoneFinder::Result result_status = SUCCESS;
     ZoneFinder::Result result_status = SUCCESS;
@@ -405,53 +404,60 @@ DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
     // Are we searching for glue?
     // Are we searching for glue?
     const bool glue_ok((options & FIND_GLUE_OK) != 0);
     const bool glue_ok((options & FIND_GLUE_OK) != 0);
 
 
-    // First, do we have any kind of delegation (NS/DNAME) here?
+    // We want to search from the apex down.  We are given the full domain
-    const Name origin(getOrigin());
+    // name so we have to do some manipulation to ensure that when we start
-    const size_t origin_label_count(origin.getLabelCount());
+    // checking superdomains, we start from the right label:
-
+    //
-    // Number of labels in the last known non-empty domain
+    // Set the number of labels in the origin (i.e. apex of the zone) and in
-    size_t last_known(origin_label_count);
+    // the last known non-empty domain (which, at this point, is the origin).
-    const size_t current_label_count(name.getLabelCount());
+    const size_t origin_label_count = getOrigin().getLabelCount();
+    size_t last_known = origin_label_count;
 
 
-    // This is how many labels we remove to get origin
+    // Set how many labels we remove to get origin: this is the number of
-    const size_t remove_labels(current_label_count - origin_label_count);
+    // labels we have to process in our search.
+    const size_t remove_labels = name.getLabelCount() - origin_label_count;
 
 
     // Go through all superdomains from the origin down searching for nodes
     // Go through all superdomains from the origin down searching for nodes
     // that indicate a delegation (NS or DNAME).
     // that indicate a delegation (NS or DNAME).
     for (int i = remove_labels; i > 0; --i) {
     for (int i = remove_labels; i > 0; --i) {
         const Name superdomain(name.split(i));
         const Name superdomain(name.split(i));
 
 
-        // Note if this is the origin.
+        // Note if this is the origin. (We don't count NS records at the origin
+        // as a delegation so this controls whether NS RRs are included in
+        // the results of some searches.)
         const bool not_origin = (i != remove_labels);
         const bool not_origin = (i != remove_labels);
 
 
-        // Look if there's NS or DNAME (but ignore the NS in origin)
+        // Look if there's NS or DNAME at this point of the tree, but ignore the
+        // NS RRs at the apex of the zone.
         const FoundRRsets found = getRRsets(superdomain.toText(),
         const FoundRRsets found = getRRsets(superdomain.toText(),
                                             DELEGATION_TYPES(), not_origin);
                                             DELEGATION_TYPES(), not_origin);
         if (found.first) {
         if (found.first) {
-            // It contains some RRs, so it exists.
+            // This node contains either NS or DNAME RRs so it does exist.
             last_known = superdomain.getLabelCount();
             last_known = superdomain.getLabelCount();
-
             const FoundIterator nsi(found.second.find(RRType::NS()));
             const FoundIterator nsi(found.second.find(RRType::NS()));
             const FoundIterator dni(found.second.find(RRType::DNAME()));
             const FoundIterator dni(found.second.find(RRType::DNAME()));
 
 
             // In case we are in GLUE_OK mode, we want to store the
             // In case we are in GLUE_OK mode, we want to store the
             // highest encountered NS (but not apex)
             // highest encountered NS (but not apex)
-            if (glue_ok && !first_ns && not_origin && nsi != found.second.end()) {
+            // TODO: WHY?
+            if (glue_ok && !first_ns && not_origin &&
+                    nsi != found.second.end()) {
                 first_ns = nsi->second;
                 first_ns = nsi->second;
 
 
             } else if (!glue_ok && not_origin && nsi != found.second.end()) {
             } else if (!glue_ok && not_origin && nsi != found.second.end()) {
-                // Do a NS delegation, but ignore NS in glue_ok mode. Ignore
+                // Not in glue OK mode and we have found an NS RRset that is
-                // delegation in apex
+                // not at the apex.  We have a delegation so return that fact.
                 LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                 LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                           DATASRC_DATABASE_FOUND_DELEGATION).
                           DATASRC_DATABASE_FOUND_DELEGATION).
                     arg(accessor_->getDBName()).arg(superdomain);
                     arg(accessor_->getDBName()).arg(superdomain);
                 result_rrset = nsi->second;
                 result_rrset = nsi->second;
                 result_status = DELEGATION;
                 result_status = DELEGATION;
-                // No need to go lower, found
+
+                // No need to go further down the tree.
                 break;
                 break;
 
 
             } else if (dni != found.second.end()) {
             } else if (dni != found.second.end()) {
-                // Very similar with DNAME
+                // We have found a DNAME so again return the fact.
                 LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                 LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                           DATASRC_DATABASE_FOUND_DNAME).
                           DATASRC_DATABASE_FOUND_DNAME).
                     arg(accessor_->getDBName()).arg(superdomain);
                     arg(accessor_->getDBName()).arg(superdomain);
@@ -462,6 +468,8 @@ DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
                               " has " << result_rrset->getRdataCount() <<
                               " has " << result_rrset->getRdataCount() <<
                               " rdata, 1 expected");
                               " rdata, 1 expected");
                 }
                 }
+
+                // No need to go further down the tree.
                 break;
                 break;
             }
             }
         }
         }
@@ -475,14 +483,17 @@ DatabaseClient::Finder::findWildcardMatch(
     const isc::dns::Name& name, const isc::dns::RRType& type,
     const isc::dns::Name& name, const isc::dns::RRType& type,
     const FindOptions options, const DelegationSearchResult& dresult)
     const FindOptions options, const DelegationSearchResult& dresult)
 {
 {
-    // Result of search
+    // Result of search (status initialized to assume we don't find any
+    // matching RRsets).
     isc::dns::ConstRRsetPtr result_rrset;
     isc::dns::ConstRRsetPtr result_rrset;
-    ZoneFinder::Result result_status = NXDOMAIN; // in case we don't find any
+    ZoneFinder::Result result_status = NXDOMAIN;
 
 
     // Search options
     // Search options
     const bool dnssec_data((options & FIND_DNSSEC) != 0);
     const bool dnssec_data((options & FIND_DNSSEC) != 0);
 
 
-    // Other
+    // 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(FINAL_TYPES());
     WantedTypes final_types(FINAL_TYPES());
     final_types.insert(type);
     final_types.insert(type);
 
 
@@ -583,33 +594,40 @@ DatabaseClient::Finder::findNoNameResult(const Name& name, const RRType& type,
                                          FindOptions options,
                                          FindOptions options,
                                          const DelegationSearchResult& dresult)
                                          const DelegationSearchResult& dresult)
 {
 {
-    const bool dnssec_data((options & FIND_DNSSEC) != 0);
+    const bool dnssec_data = ((options & FIND_DNSSEC) != 0);
+
+    // 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.
 
 
-    // We know the database doesn't have any record for the given name.
-    // But check if something lives below this domain and if so,
-    // pretend something is here as well.
     if (hasSubdomains(name.toText())) {
     if (hasSubdomains(name.toText())) {
+        // Does the domain have a subdomain (i.e. is is an empty non-terminal)?
+        // If so, return NXRRSET instead of NXDOMAIN (as although the name does
+        // not exist in the zone, it does exist in the DNS tree).
+        // pretend something is here as well.
         LOG_DEBUG(logger, DBG_TRACE_DETAILED,
         LOG_DEBUG(logger, DBG_TRACE_DETAILED,
                   DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL).
                   DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL).
             arg(accessor_->getDBName()).arg(name);
             arg(accessor_->getDBName()).arg(name);
         return (FindResult(NXRRSET, dnssec_data ? findNSECCover(name) :
         return (FindResult(NXRRSET, dnssec_data ? findNSECCover(name) :
                            ConstRRsetPtr()));
                            ConstRRsetPtr()));
-    } else if ((options & NO_WILDCARD) != 0) {
+
-        // If wildcard check is disabled, the search should terminate
+    } else if ((options & NO_WILDCARD) == 0) {
-        // with NXDOMAIN.
+        // It's not an empty non-terminal and wildcard matching is not disabled,
-        return (FindResult(NXDOMAIN, dnssec_data ? findNSECCover(name) :
+        // so check for wildcards.
-                           ConstRRsetPtr()));
-    } else {
-        // It's not an empty non-terminal so check for wildcards.
         const ZoneFinder::FindResult wresult =
         const ZoneFinder::FindResult wresult =
             findWildcardMatch(name, type, options, dresult);
             findWildcardMatch(name, type, options, dresult);
         if (wresult.code == NXDOMAIN && dnssec_data) {
         if (wresult.code == NXDOMAIN && dnssec_data) {
-            // If the result is NXDOMAIN case and the caller wanted
+            // No match on a wildcard, so return the covering NSEC if DNSSEC
-            // DNSSEC data, try getting the NSEC record.
+            // data was requested.
             return (FindResult(NXDOMAIN, findNSECCover(name)));
             return (FindResult(NXDOMAIN, findNSECCover(name)));
         }
         }
         return (FindResult(wresult.code, wresult.rrset));
         return (FindResult(wresult.code, wresult.rrset));
     }
     }
+
+    // All avenues to find a match are now exhausted, return NXDOMAIN (plus
+    // NSEC records if requested).
+    return (FindResult(NXDOMAIN, dnssec_data ? findNSECCover(name) :
+                           ConstRRsetPtr()));
 }
 }
 
 
 ZoneFinder::FindResult
 ZoneFinder::FindResult
@@ -621,8 +639,8 @@ DatabaseClient::Finder::logAndCreateResult(const Name& name,
 {
 {
     if (rrset) {
     if (rrset) {
         LOG_DEBUG(logger, DBG_TRACE_DETAILED, log_id).
         LOG_DEBUG(logger, DBG_TRACE_DETAILED, log_id).
-            arg(accessor_->getDBName()).arg(name).arg(getClass()).
+            arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass()).
-            arg(type).arg(*rrset);
+            arg(*rrset);
     } else {
     } else {
         LOG_DEBUG(logger, DBG_TRACE_DETAILED, log_id).
         LOG_DEBUG(logger, DBG_TRACE_DETAILED, log_id).
             arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass());
             arg(accessor_->getDBName()).arg(name).arg(type).arg(getClass());
@@ -634,61 +652,98 @@ ZoneFinder::FindResult
 DatabaseClient::Finder::find(const isc::dns::Name& name,
 DatabaseClient::Finder::find(const isc::dns::Name& name,
                              const isc::dns::RRType& type,
                              const isc::dns::RRType& type,
                              isc::dns::RRsetList*,
                              isc::dns::RRsetList*,
-                             const FindOptions options)
+                             const FindOptions options) {
-{
     LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
     LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
               .arg(accessor_->getDBName()).arg(name).arg(type);
               .arg(accessor_->getDBName()).arg(name).arg(type);
 
 
-    // First stage: go through all superdomains from the origin down,
+    // First, go through all superdomains from the origin down, searching for
-    // searching for nodes that indicate a delegation (NS or DNAME).
+    // nodes that indicate a delegation (i.e. NS or DNAME, ignoring NS records
+    // at the apex).  If one is found, the search stops there.
+    //
+    // (In fact there could be RRs in the database corresponding to subdomains
+    // of the delegation.  However as no search will find them, they are said
+    // to be occluded by the presence of the delegation.)
     const DelegationSearchResult dresult = findDelegationPoint(name, options);
     const DelegationSearchResult dresult = findDelegationPoint(name, options);
     if (dresult.rrset) {
     if (dresult.rrset) {
         return (FindResult(dresult.code, dresult.rrset));
         return (FindResult(dresult.code, dresult.rrset));
     }
     }
 
 
-    // Try getting the final result and extract it
+    // If there is no delegation in the page, look for the exact match to the
-    // It is special if there's a CNAME or NS, DNAME is ignored here
+    // request name/type/class.  However, there are special cases:
-    // And we don't consider the NS in origin
+    // - Requested name has a singleton CNAME record associated with it
+    // - Requested name is a delegation point (NS only but not at the zone
+    //   apex - DNAME is ignored here).
+    // TODO: Why is DNAME ignored?
     const bool is_origin = (name == getOrigin());
     const bool is_origin = (name == getOrigin());
     WantedTypes final_types(FINAL_TYPES());
     WantedTypes final_types(FINAL_TYPES());
     final_types.insert(type);
     final_types.insert(type);
-    const FoundRRsets found(getRRsets(name.toText(), final_types, !is_origin));
+    const FoundRRsets found = getRRsets(name.toText(), final_types, !is_origin);
 
 
-    // NS records, CNAME record and Wanted Type records
+    // Get iterators for the different types of records we are interested in -
+    // CNAME, NS and Wanted types.
     const FoundIterator nsi(found.second.find(RRType::NS()));
     const FoundIterator nsi(found.second.find(RRType::NS()));
     const FoundIterator cni(found.second.find(RRType::CNAME()));
     const FoundIterator cni(found.second.find(RRType::CNAME()));
     const FoundIterator wti(found.second.find(type));
     const FoundIterator wti(found.second.find(type));
 
 
-    if (!is_origin && (options & FIND_GLUE_OK) == 0 &&
+    if (!is_origin && ((options & FIND_GLUE_OK) == 0) &&
-        nsi != found.second.end()) { // delegation at the exact node
+            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 this this zone is not authoritative for the data.
+        // Just return the delegation information.
         return (logAndCreateResult(name, type, DELEGATION, nsi->second,
         return (logAndCreateResult(name, type, DELEGATION, nsi->second,
                                    DATASRC_DATABASE_FOUND_DELEGATION_EXACT));
                                    DATASRC_DATABASE_FOUND_DELEGATION_EXACT));
-    } else if (type != RRType::CNAME() && cni != found.second.end()) { // CNAME
+
+    } else if (type != RRType::CNAME() && cni != found.second.end()) {
+        // We are not searching for a CNAME but nevertheless we have found one
+        // at the name we are searching so we return it. (A resolver could have
+        // originated the query that caues this result.  If so, it will restart
+        // the resolution process with the name that is the target of this
+        // CNAME.) First though, do a sanity check to ensure that there is
+        // only one RR in the CNAME RRset.
+        //
+        // TODO: Check that throwing an exception here is correct.
+        // Unless the exception is caught higher up (probably not, given the
+        // general nature of the exception), it is probably better to log
+        // and error and terminate the query with SERVFAIL instead of crashing
+        // the server.  Although the CNAME is a singleton and multiple RRs
+        // in the RRset may indicate an error in the data, it does not mean
+        // that the entire database is corrupt.
         if (cni->second->getRdataCount() != 1) {
         if (cni->second->getRdataCount() != 1) {
             isc_throw(DataSourceError, "CNAME with " <<
             isc_throw(DataSourceError, "CNAME with " <<
-                      cni->second->getRdataCount() <<
+                      cni->second->getRdataCount() << " rdata at " << name <<
-                      " rdata at " << name << ", expected 1");
+                      ", expected 1");
         }
         }
         return (logAndCreateResult(name, type, CNAME, cni->second,
         return (logAndCreateResult(name, type, CNAME, cni->second,
                                    DATASRC_DATABASE_FOUND_CNAME));
                                    DATASRC_DATABASE_FOUND_CNAME));
-    } else if (wti != found.second.end()) { // normal answer
+
+    } else if (wti != found.second.end()) {
+        // Found an RR matching the query, so return it.  (Note that this
+        // includes the case where we were querying for a CNAME and found
+        // it.  It also includes the case where we were querying for an NS
+        // RRset and found it at the apex of the zone.)
         return (logAndCreateResult(name, type, SUCCESS, wti->second,
         return (logAndCreateResult(name, type, SUCCESS, wti->second,
                                    DATASRC_DATABASE_FOUND_RRSET));
                                    DATASRC_DATABASE_FOUND_RRSET));
-    } else if (!found.first) { // NXDOMAIN, empty name, wildcard
+
+    } else if (!found.first) {
+        // Did not find anything at all at the domain name, so check for
+        // subdomains or wildcards.
         return (findNoNameResult(name, type, options, dresult));
         return (findNoNameResult(name, type, options, dresult));
-    } else {
+
-        // This is the "usual" NXRRSET case.  So in case they want DNSSEC,
+    }
-        // provide the NSEC (which should be available already here)
+
-        if ((options & FIND_DNSSEC) != 0) {
+    // If we get here, we have found something at the requested name but not
-            const FoundIterator nci(found.second.find(RRType::NSEC()));
+    // one of the RR types we were interested in. This is the NXRRSET case so,
-            if (nci != found.second.end()) {
+    // if DNSSEC information was requested, provide the NSEC records.
-                return (logAndCreateResult(name, type, NXRRSET, nci->second,
+    if ((options & FIND_DNSSEC) != 0) {
-                                           DATASRC_DATABASE_FOUND_NXRRSET_NSEC));
+        const FoundIterator nci = found.second.find(RRType::NSEC());
-            }
+        if (nci != found.second.end()) {
+            return (logAndCreateResult(name, type, NXRRSET, nci->second,
+                                       DATASRC_DATABASE_FOUND_NXRRSET_NSEC));
         }
         }
-        return (logAndCreateResult(name, type, NXRRSET, ConstRRsetPtr(),
-                                   DATASRC_DATABASE_FOUND_NXRRSET));
     }
     }
+    return (logAndCreateResult(name, type, NXRRSET, ConstRRsetPtr(),
+                                   DATASRC_DATABASE_FOUND_NXRRSET));
 }
 }
 
 
 Name
 Name

+ 136 - 97
src/lib/datasrc/database.h

@@ -817,6 +817,17 @@ public:
             return (*accessor_);
             return (*accessor_);
         }
         }
 
 
+    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;
+        /// \brief Just shortcut for set of types
+        typedef std::set<dns::RRType> WantedTypes;
+
         /// \brief Search result of \c findDelegationPoint().
         /// \brief Search result of \c findDelegationPoint().
         ///
         ///
         /// This is a tuple combining the result of the search - a status code
         /// This is a tuple combining the result of the search - a status code
@@ -850,17 +861,6 @@ public:
             const size_t last_known; ///< No. labels in last non-empty domain
             const size_t last_known; ///< No. labels in last non-empty domain
         };
         };
 
 
-    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;
-        /// \brief Just shortcut for set of types
-        typedef std::set<dns::RRType> WantedTypes;
-
         /**
         /**
          * \brief Searches database for RRsets of one domain.
          * \brief Searches database for RRsets of one domain.
          *
          *
@@ -892,112 +892,151 @@ public:
                               const WantedTypes& types, bool check_ns,
                               const WantedTypes& types, bool check_ns,
                               const std::string* construct_name = NULL);
                               const std::string* construct_name = NULL);
 
 
-        /**
+        /// \brief Find delegation point
-         * \brief Find delegation point
+        ///
-         *
+        /// Given a name, searches through the superdomains from the origin
-         * Given a name, searches through the superdomains from the origin
+        /// down, searching for a point that indicates a delegation (i.e. an
-         * down, searching for a point that indicates a delegation (i.e. an
+        /// NS record or a DNAME).
-         * NS record or a DNAME).
+        ///
-         *
+        /// The method operates in two modes, non-glue-ok and glue-ok modes:
-         * The method operates in two modes, non-glue-ok and glue-ok modes:
+        ///
-         *
+        /// In non-glue-ok mode, the search is made purely for the NS or DNAME
-         * In non-glue-ok mode, the search is made purely for the NS or DNAME
+        /// RR.  The zone is searched from the origin down looking  for one
-         * RR.  The zone is searched from the origin down looking  for one
+        /// of these RRTypes (and ignoring the NS records at the zone origin).
-         * of these RRTypes (and ignoring the NS records at the zone origin).
+        /// A status is returned indicating what is found: DNAME, DELEGATION
-         * A status is returned indicating what is found: DNAME, DELEGATION
+        /// of SUCCESS, the last indicating that nothing was found, together
-         * of SUCCESS, the last indicating that nothing was found, together
+        /// with a pointer to the relevant RR.
-         * with a pointer to the relevant RR.
+        ///
-         *
+        /// In glue-ok mode, the first NS encountered in the search (apart from
-         * In glue-ok mode, the first NS encountered in the search (apart from
+        /// the NS at the zone apex) is remembered but otherwise NS records are
-         * the NS at the zone apex) is remembered but otherwise NS records are
+        /// ignored and the search attempts to find a DNAME.  The result is
-         * ignored and the search attempts to find a DNAME.  The result is
+        /// returned in the same format, along with a pointer to the first non-
-         * returned in the same format, along with a pointer to the first non-
+        /// apex NS (if found).
-         * apex NS (if found).
+        ///
-         *
+        /// \param name The name to find
-         * \param name The name to find
+        /// \param options Options about how to search. See the documentation
-         * \param options Options about how to search. See the documentation for
+        ///        for ZoneFinder::FindOptions.
-         *        ZoneFinder::FindOptions.
+        ///
-         *
+        /// \return Tuple holding the result of the search - the RRset of the
-         * \return Tuple holding the result of the search - the RRset of the
+        ///         delegation point and the type of the point (DELEGATION or
-         *         delegation point and the type of the point (DELEGATION or
+        ///         DNAME) - and associated information.  This latter item
-         *         DNAME) - and associated information.  This latter item
+        ///         comprises two pieces of data: a pointer to the highest
-         *         comprises two pieces of data: a pointer to the highest
+        ///         encountered NS, and the number of labels in the last known
-         *         encountered NS, and the number of labels in the last known
+        ///         non-empty domain.  The associated information is found as
-         *         non-empty domain.  The associated information is found as
+        ///         a natural part of the search for the delegation point and
-         *         a natural part of the search for the delegation point and
+        ///         is used later in the find() processing; it is passed back
-         *         is used later in the find() processing; it is passed back
+        ///         to avoid the need to perform a second search to obtain it.
-         *         to avoid the need to perform a second search to obtain it.
-         */
         DelegationSearchResult
         DelegationSearchResult
         findDelegationPoint(const isc::dns::Name& name,
         findDelegationPoint(const isc::dns::Name& name,
                             const FindOptions options);
                             const FindOptions options);
 
 
-        /**
+        /// \brief Find wildcard match
-         * \brief Find wildcard match
+        /// 
-         *
+        /// Having found that the name is not an empty non-terminal, this
-         * Having found that the name is not an empty non-terminal, this
+        /// searches the zone for for wildcards that match the name.
-         * searches the zone for for wildcards that match the name.
+        /// 
-         *
+        /// It searches superdomains of the name from the zone origin down
-         * It searches superdomains of the name from the zone origin down
+        /// looking for a wildcard in the zone that matches the name.  There
-         * looking for a wildcard in the zone that matches the name.  There
+        /// are several cases to consider:
-         * are several cases to consider:
+        /// 
-         *
+        /// - If the previous search for a delegation point has found that
-         * - If the previous search for a delegation point has found that
+        ///   there is an NS at the superdomain of the point at which the
-         *   there is an NS at the superdomain of the point at which the
+        ///   wildcard is found, the delegation is returned.
-         *   wildcard is found, the delegation is returned.
+        /// - If there is a match to the name, an appropriate status is
-         * - If there is a match to the name, an appropriate status is
+        ///   returned (match on requested type, delegation, cname, or just
-         *   returned (match on requested type, delegation, cname, or just
+        ///   the indication of a match but no RRs relevant to the query).
-         *   the indication of a match but no RRs relevant to the query).
+        /// - If the match is to an non-empty non-terminal wildcard, a
-         * - If the match is to an non-empty non-terminal wildcard, a
+        ///   wildcard NXRRSET is returned.
-         *   wildcard NXRRSET is returned.
+        /// 
-         *
+        /// Note that if DNSSEC is enabled for the search and the zone uses
-         * Note that if DNSSEC is enabled for the search and the zone uses
+        /// NSEC for authenticated denial of existence, the search may
-         * NSEC for authenticated denial of existence, the search may
+        /// return NSEC records.
-         * return NSEC records.
+        /// 
-         *
+        /// \param name The name to find
-         * \param name The name to find
+        /// \param type The RRType to find
-         * \param type The RRType to find
+        /// \param options Options about how to search. See the documentation
-         * \param options Options about how to search. See the documentation
+        ///        for ZoneFinder::FindOptions.
-         *        for ZoneFinder::FindOptions.
+        /// \param dresult Result of the search through the zone for a
-         * \param first_ns A pointer to the first NS found in a search for
+        ///        delegation.
-         *        the name (will only be non-null in glue-ok mode).
+        /// 
-         * \param last_known the number of labels in the last known non-empty
+        /// \return Tuple holding the result of the search - the RRset of the
-         *        domain in the name.
+        ///         wildcard records matching the name, together with a status
-         *
+        ///         indicating the match type (e.g. CNAME at the wildcard
-         * \return Tuple holding the result of the search - the RRset of the
+        ///         match, no RRs of the requested type at the wildcard,
-         *         wildcard records matching the name, together with a status
+        ///         success due to an exact match).  Also returned if there
-         *         indicating the match type (e.g. CNAME at the wildcard
+        ///         is no match is an indication as to whether there was an
-         *         match, no RRs of the requested type at the wildcard,
+        ///         NXDOMAIN or an NXRRSET.
-         *         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.
-         */
         FindResult findWildcardMatch(
         FindResult findWildcardMatch(
             const isc::dns::Name& name,
             const isc::dns::Name& name,
             const isc::dns::RRType& type, const FindOptions options,
             const isc::dns::RRType& type, const FindOptions options,
             const DelegationSearchResult& dresult);
             const DelegationSearchResult& dresult);
 
 
-        /// To be documented.
+        /// \brief Handle no match for name
+        ///
+        /// This is called when it is known that there is no delegation and
+        /// there is no exact match for the name (regardless of RR types
+        /// requested).  Before returning NXDOMAIN, we need to check two
+        /// cases:
+        /// - Empty non-terminal: if the name has subdomains in the database,
+        ///   flag the fact.  An NXRRSET will be returned (along with the
+        ///   NSEC record covering the requested domain name if DNSSEC data
+        ///   is being returned).
+        /// - Wildcard: is there a wildcard record in the zone that matches
+        ///   requested name? If so, return it.  If not, return the relevant
+        ///   NSEC records (if requested).
+        /// 
+        /// \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.
+        /// 
+        /// \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
+        ///         match, no RRs of the requested type at the wildcard,
+        ///         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.
         FindResult findNoNameResult(const isc::dns::Name& name,
         FindResult findNoNameResult(const isc::dns::Name& name,
                                     const isc::dns::RRType& type,
                                     const isc::dns::RRType& type,
                                     FindOptions options,
                                     FindOptions options,
                                     const DelegationSearchResult& dresult);
                                     const DelegationSearchResult& dresult);
 
 
-        // To be documented.
+        /// Logs condition and creates result
+        ///
+        /// A convenience function used by find(), it both creates the
+        /// FindResult object that find() will return to its caller as well
+        /// as logging a debug message for the information being returned.
+        ///
+        /// \param name Domain name of the RR that was being sought.
+        /// \param type Type of RR being sought.
+        /// \param code Result of the find operation
+        /// \param rrset RRset found as a result of the find (which may be
+        ///        null).
+        /// \param log_id ID of the message being logged.  Up to five
+        ///        parameters are available to the message: data source name,
+        ///        requested domain name, requested class, requested type
+        ///        and (but only if the search was successful and returned
+        ///        an RRset) details of the RRset found.
+        ///
+        /// \return FindResult object constructed from the code and rrset
+        ///         arguments.
         FindResult logAndCreateResult(const isc::dns::Name& name,
         FindResult logAndCreateResult(const isc::dns::Name& name,
                                       const isc::dns::RRType& type,
                                       const isc::dns::RRType& type,
                                       ZoneFinder::Result code,
                                       ZoneFinder::Result code,
                                       isc::dns::ConstRRsetPtr rrset,
                                       isc::dns::ConstRRsetPtr rrset,
                                       const isc::log::MessageID& log_id);
                                       const isc::log::MessageID& log_id);
 
 
-        /**
+        /// \brief Checks if something lives below this domain.
-         * \brief Checks if something lives below this domain.
+        ///
-         *
+        /// This looks if there's any subdomain of the given name. It can be
-         * This looks if there's any subdomain of the given name. It can be
+        /// used to test if domain is empty non-terminal.
-         * used to test if domain is empty non-terminal.
+        ///
-         *
+        /// \param name The domain to check.
-         * \param name The domain to check.
+        ///
-         */
+        /// \return true if the name has subdomains, false if not.
         bool hasSubdomains(const std::string& name);
         bool hasSubdomains(const std::string& name);
 
 
         /**
         /**

+ 13 - 6
src/lib/datasrc/datasrc_messages.mes

@@ -79,7 +79,11 @@ an error, so we set it to the lowest value we found (but we don't modify the
 database). The data in database should be checked and fixed.
 database). The data in database should be checked and fixed.
 
 
 % DATASRC_DATABASE_FOUND_CNAME search in datasource %1 for %2/%3/%4 resulted in CNAME %5
 % DATASRC_DATABASE_FOUND_CNAME search in datasource %1 for %2/%3/%4 resulted in CNAME %5
-(TBD)
+When searching the domain for a name a CNAME was found at that name.  Even
+though it was not the RR type being sought, it is returned.  If the query
+of the database was issued by a result searching for the name, the return of
+the CNAME record will cause that resolver to issue another query for the
+target of the CNAME.
 
 
 % DATASRC_DATABASE_FOUND_DELEGATION Found delegation at %2 in %1
 % DATASRC_DATABASE_FOUND_DELEGATION Found delegation at %2 in %1
 When searching for a domain, the program met a delegation to a different zone
 When searching for a domain, the program met a delegation to a different zone
@@ -96,9 +100,10 @@ place in the domain space at the given domain name. It will return that one
 instead.
 instead.
 
 
 % DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL empty non-terminal %2 in %1
 % DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL empty non-terminal %2 in %1
-The domain name doesn't have any RRs, so it doesn't exist in the database.
+The domain name does not have any RRs associated with it, so it doesn't
-However, it has a subdomain, so it exists in the DNS address space. So we
+exist in the database.  However, it has a subdomain, so it does exist
-return NXRRSET instead of NXDOMAIN.
+in the DNS address space. This type of domain is known an an "empty
+non-terminal" and so we return NXRRSET instead of NXDOMAIN.
 
 
 % DATASRC_DATABASE_FOUND_NXDOMAIN search in datasource %1 resulted in NXDOMAIN for %2/%3/%4
 % DATASRC_DATABASE_FOUND_NXDOMAIN search in datasource %1 resulted in NXDOMAIN for %2/%3/%4
 The data returned by the database backend did not contain any data for the given
 The data returned by the database backend did not contain any data for the given
@@ -109,7 +114,9 @@ The data returned by the database backend contained data for the given domain
 name and class, but not for the given type.
 name and class, but not for the given type.
 
 
 % DATASRC_DATABASE_FOUND_NXRRSET_NSEC search in datasource %1 for %2/%3/%4 resulted in RRset %5
 % DATASRC_DATABASE_FOUND_NXRRSET_NSEC search in datasource %1 for %2/%3/%4 resulted in RRset %5
-(TBD)
+A search in the database for RRs for the specified name, type and class has
+located RRs that match the name and class but not the type.  DNSSEC information
+has been requested, but there is no NSEC record corresponding to the node.
 
 
 % DATASRC_DATABASE_FOUND_RRSET search in datasource %1 resulted in RRset %2
 % DATASRC_DATABASE_FOUND_RRSET search in datasource %1 resulted in RRset %2
 The data returned by the database backend contained data for the given domain
 The data returned by the database backend contained data for the given domain
@@ -300,7 +307,7 @@ Debug information. The requested record was found.
 
 
 % DATASRC_MEM_SUPER_STOP stopped at superdomain '%1', domain '%2' is empty
 % DATASRC_MEM_SUPER_STOP stopped at superdomain '%1', domain '%2' is empty
 Debug information. The search stopped at a superdomain of the requested
 Debug information. The search stopped at a superdomain of the requested
-domain. The domain is a empty nonterminal, therefore it is treated  as NXRRSET
+domain. The domain is an empty nonterminal, therefore it is treated  as NXRRSET
 case (eg. the domain exists, but it doesn't have the requested record type).
 case (eg. the domain exists, but it doesn't have the requested record type).
 
 
 % DATASRC_MEM_SWAP swapping contents of two zone representations ('%1' and '%2')
 % DATASRC_MEM_SWAP swapping contents of two zone representations ('%1' and '%2')