Parcourir la source

initial implementation of #463: "glue OK" mode of Zone::find()

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac463@4097 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya il y a 14 ans
Parent
commit
ce2e289a20

+ 3 - 2
src/bin/auth/tests/query_unittest.cc

@@ -53,7 +53,8 @@ public:
     virtual const isc::dns::RRClass& getClass() const;
     virtual const isc::dns::RRClass& getClass() const;
 
 
     FindResult find(const isc::dns::Name& name,
     FindResult find(const isc::dns::Name& name,
-            const isc::dns::RRType& type) const;
+                    const isc::dns::RRType& type,
+                    const FindOptions options = FIND_DEFAULT) const;
 
 
 private:
 private:
     Name origin_;
     Name origin_;
@@ -71,7 +72,7 @@ MockZone::getClass() const {
 }
 }
 
 
 Zone::FindResult
 Zone::FindResult
-MockZone::find(const Name& name, const RRType& type) const {
+MockZone::find(const Name& name, const RRType& type, const FindOptions) const {
     // hardcode the find results
     // hardcode the find results
     if (name == Name("www.example.com")) {
     if (name == Name("www.example.com")) {
         return (FindResult(SUCCESS, a_rrset));
         return (FindResult(SUCCESS, a_rrset));

+ 20 - 16
src/lib/datasrc/memory_datasrc.cc

@@ -144,9 +144,12 @@ struct MemoryZone::MemoryZoneImpl {
     /// It will be passed to \c zonecutCallback() and record a possible
     /// It will be passed to \c zonecutCallback() and record a possible
     /// zone cut node and related RRset (normally NS or DNAME).
     /// zone cut node and related RRset (normally NS or DNAME).
     struct FindState {
     struct FindState {
-        FindState() : zonecut_node(NULL) {}
-        const DomainNode* zonecut_node;
-        ConstRRsetPtr rrset;
+        FindState(FindOptions options) : zonecut_node_(NULL),
+                                         options_(options)
+        {}
+        const DomainNode* zonecut_node_;
+        ConstRRsetPtr rrset_;
+        const FindOptions options_;
     };
     };
 
 
     // A callback called from possible zone cut nodes.  This will be passed
     // A callback called from possible zone cut nodes.  This will be passed
@@ -154,10 +157,7 @@ struct MemoryZone::MemoryZoneImpl {
     static bool zonecutCallback(const DomainNode& node, FindState* state) {
     static bool zonecutCallback(const DomainNode& node, FindState* state) {
         // We perform callback check only for the highest zone cut in the
         // We perform callback check only for the highest zone cut in the
         // rare case of nested zone cuts.
         // rare case of nested zone cuts.
-        // [This check is necessary when we support the "glue OK" mode later.
-        // This code should better be added then with a test, but is added
-        // now not to forget it.]
-        if (state->zonecut_node != NULL) {
+        if (state->zonecut_node_ != NULL) {
             return (false);
             return (false);
         }
         }
 
 
@@ -167,9 +167,9 @@ struct MemoryZone::MemoryZoneImpl {
             // be the origin because we don't enable the callback at the
             // be the origin because we don't enable the callback at the
             // origin node (see MemoryZoneImpl::add()).  Or should we do a
             // origin node (see MemoryZoneImpl::add()).  Or should we do a
             // double check for it?
             // double check for it?
-            state->zonecut_node = &node;
-            state->rrset = found->second;
-            return (true);
+            state->zonecut_node_ = &node;
+            state->rrset_ = found->second;
+            return ((state->options_ & FIND_GLUE_OK) != 0 ? false : true);
         }
         }
 
 
         // This case should not happen because we enable callback only
         // This case should not happen because we enable callback only
@@ -178,14 +178,16 @@ struct MemoryZone::MemoryZoneImpl {
     }
     }
 
 
     // Implementation of MemoryZone::find
     // Implementation of MemoryZone::find
-    FindResult find(const Name& name, RRType type) const {
+    FindResult find(const Name& name, RRType type,
+                    const FindOptions options) const
+    {
         // Get the node
         // Get the node
         DomainNode* node(NULL);
         DomainNode* node(NULL);
-        FindState state;
+        FindState state(options);
         switch (domains_.find(name, &node, zonecutCallback, &state)) {
         switch (domains_.find(name, &node, zonecutCallback, &state)) {
             case DomainTree::PARTIALMATCH:
             case DomainTree::PARTIALMATCH:
-                if (state.zonecut_node != NULL) {
-                    return (FindResult(DELEGATION, state.rrset));
+                if (state.zonecut_node_ != NULL) {
+                    return (FindResult(DELEGATION, state.rrset_));
                 }
                 }
                 // TODO: we should also cover empty non-terminal cases, which
                 // TODO: we should also cover empty non-terminal cases, which
                 // will require non trivial code and is deferred for later
                 // will require non trivial code and is deferred for later
@@ -247,8 +249,10 @@ MemoryZone::getClass() const {
 }
 }
 
 
 Zone::FindResult
 Zone::FindResult
-MemoryZone::find(const Name& name, const RRType& type) const {
-    return (impl_->find(name, type));
+MemoryZone::find(const Name& name, const RRType& type,
+                 const FindOptions options) const
+{
+    return (impl_->find(name, type, options));
 }
 }
 
 
 result::Result
 result::Result

+ 2 - 1
src/lib/datasrc/memory_datasrc.h

@@ -62,7 +62,8 @@ public:
     /// It returns NULL pointer in case of NXDOMAIN and NXRRSET
     /// It returns NULL pointer in case of NXDOMAIN and NXRRSET
     /// (the base class documentation does not seem to require that).
     /// (the base class documentation does not seem to require that).
     virtual FindResult find(const isc::dns::Name& name,
     virtual FindResult find(const isc::dns::Name& name,
-                            const isc::dns::RRType& type) const;
+                            const isc::dns::RRType& type,
+                            const FindOptions options = FIND_DEFAULT) const;
 
 
     /// \brief Inserts an rrset into the zone.
     /// \brief Inserts an rrset into the zone.
     ///
     ///

+ 66 - 11
src/lib/datasrc/tests/memory_datasrc_unittest.cc

@@ -143,7 +143,9 @@ public:
         origin_("example.org"),
         origin_("example.org"),
         ns_name_("ns.example.org"),
         ns_name_("ns.example.org"),
         child_ns_name_("child.example.org"),
         child_ns_name_("child.example.org"),
+        child_glue_name_("ns.child.example.org"),
         grandchild_ns_name_("grand.child.example.org"),
         grandchild_ns_name_("grand.child.example.org"),
+        grandchild_glue_name_("ns.grand.child.example.org"),
         zone_(class_, origin_),
         zone_(class_, origin_),
         rr_out_(new RRset(Name("example.com"), class_, RRType::A(),
         rr_out_(new RRset(Name("example.com"), class_, RRType::A(),
             RRTTL(300))),
             RRTTL(300))),
@@ -153,13 +155,18 @@ public:
         rr_a_(new RRset(origin_, class_, RRType::A(), RRTTL(300))),
         rr_a_(new RRset(origin_, class_, RRType::A(), RRTTL(300))),
         rr_child_ns_(new RRset(child_ns_name_, class_, RRType::NS(),
         rr_child_ns_(new RRset(child_ns_name_, class_, RRType::NS(),
                                RRTTL(300))),
                                RRTTL(300))),
+        rr_child_glue_(new RRset(child_glue_name_, class_, RRType::A(),
+                              RRTTL(300))),
         rr_grandchild_ns_(new RRset(grandchild_ns_name_, class_, RRType::NS(),
         rr_grandchild_ns_(new RRset(grandchild_ns_name_, class_, RRType::NS(),
-                               RRTTL(300)))
+                                    RRTTL(300))),
+        rr_grandchild_glue_(new RRset(grandchild_glue_name_, class_,
+                                      RRType::AAAA(), RRTTL(300)))
     {
     {
     }
     }
     // Some data to test with
     // Some data to test with
     const RRClass class_;
     const RRClass class_;
-    const Name origin_, ns_name_, child_ns_name_, grandchild_ns_name_;
+    const Name origin_, ns_name_, child_ns_name_, child_glue_name_,
+        grandchild_ns_name_, grandchild_glue_name_;
     // The zone to torture by tests
     // The zone to torture by tests
     MemoryZone zone_;
     MemoryZone zone_;
 
 
@@ -181,7 +188,9 @@ public:
         // A of example.org
         // A of example.org
         rr_a_;
         rr_a_;
     ConstRRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
     ConstRRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
+    ConstRRsetPtr rr_child_glue_; // glue RR of the child domain
     ConstRRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
     ConstRRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
+    ConstRRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
 
 
     /**
     /**
      * \brief Test one find query to the zone.
      * \brief Test one find query to the zone.
@@ -200,8 +209,10 @@ public:
      *     uses zone_)
      *     uses zone_)
      */
      */
     void findTest(const Name& name, const RRType& rrtype, Zone::Result result,
     void findTest(const Name& name, const RRType& rrtype, Zone::Result result,
-        bool check_answer = true,
-        const ConstRRsetPtr& answer = ConstRRsetPtr(), MemoryZone *zone = NULL)
+                  bool check_answer = true,
+                  const ConstRRsetPtr& answer = ConstRRsetPtr(),
+                  MemoryZone *zone = NULL,
+                  Zone::FindOptions options = Zone::FIND_DEFAULT)
     {
     {
         if (!zone) {
         if (!zone) {
             zone = &zone_;
             zone = &zone_;
@@ -209,13 +220,14 @@ public:
         // The whole block is inside, because we need to check the result and
         // The whole block is inside, because we need to check the result and
         // we can't assign to FindResult
         // we can't assign to FindResult
         EXPECT_NO_THROW({
         EXPECT_NO_THROW({
-            Zone::FindResult find_result(zone->find(name, rrtype));
-            // Check it returns correct answers
-            EXPECT_EQ(result, find_result.code);
-            if (check_answer) {
-                EXPECT_EQ(answer, find_result.rrset);
-            }
-        });
+                Zone::FindResult find_result(zone->find(name, rrtype,
+                                                        options));
+                // Check it returns correct answers
+                EXPECT_EQ(result, find_result.code);
+                if (check_answer) {
+                    EXPECT_EQ(answer, find_result.rrset);
+                }
+            });
     }
     }
 };
 };
 
 
@@ -280,6 +292,49 @@ TEST_F(MemoryZoneTest, delegationNS) {
              Zone::DELEGATION, true, rr_child_ns_); // note: !rr_grandchild_ns_
              Zone::DELEGATION, true, rr_child_ns_); // note: !rr_grandchild_ns_
 }
 }
 
 
+TEST_F(MemoryZoneTest, glue) {
+    // install zone data:
+    // a zone cut
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_ns_)));
+    // glue for this cut
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_glue_)));
+    // a nested zone cut (unusual)
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_ns_)));
+    // glue under the deeper zone cut
+    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_glue_)));
+
+    // by default glue is hidden due to the zone cut
+    findTest(child_glue_name_, RRType::A(), Zone::DELEGATION, true,
+             rr_child_ns_);
+
+
+    // If we do it in the "glue OK" mode, we should find the exact match.
+    findTest(child_glue_name_, RRType::A(), Zone::SUCCESS, true,
+             rr_child_glue_, NULL, Zone::FIND_GLUE_OK);
+
+    // glue OK + NXRRSET case
+    findTest(child_glue_name_, RRType::AAAA(), Zone::NXRRSET, true,
+             ConstRRsetPtr(), NULL, Zone::FIND_GLUE_OK);
+
+    // glue OK + NXDOMAIN case
+    findTest(Name("www.child.example.org"), RRType::A(), Zone::DELEGATION,
+             true, rr_child_ns_, NULL, Zone::FIND_GLUE_OK);
+
+    // TODO:
+    // glue name would match a wildcard under a zone cut: wildcard match
+    // shouldn't happen under a cut and result must be PARTIALMATCH
+    // (This case cannot be tested yet)
+
+    // nested cut case.  The glue should be found.
+    findTest(grandchild_glue_name_, RRType::AAAA(), Zone::SUCCESS,
+             true, rr_grandchild_glue_, NULL, Zone::FIND_GLUE_OK);    
+
+    // A non-existent name in nested cut.  This should result in delegation
+    // at the highest zone cut.
+    findTest(Name("www.grand.child.example.org"), RRType::TXT(),
+             Zone::DELEGATION, true, rr_child_ns_, NULL, Zone::FIND_GLUE_OK);
+}
+
 // Test adding DNAMEs and resulting delegation handling
 // Test adding DNAMEs and resulting delegation handling
 // Listing ideas only for now
 // Listing ideas only for now
 TEST_F(MemoryZoneTest, delegationDNAME) {
 TEST_F(MemoryZoneTest, delegationDNAME) {

+ 30 - 2
src/lib/datasrc/zone.h

@@ -100,6 +100,16 @@ public:
         const isc::dns::ConstRRsetPtr rrset;
         const isc::dns::ConstRRsetPtr rrset;
     };
     };
 
 
+    /// Find options.
+    ///
+    /// The option values are used as a parameter for \c find().
+    /// These are values of a bitmask type.  Bitwise operations can be
+    /// performed on these values to express compound options.
+    enum FindOptions {
+        FIND_DEFAULT = 0,       ///< The default options
+        FIND_GLUE_OK = 1        ///< Allow search under a zone cut
+    };
+
     ///
     ///
     /// \name Constructors and Destructor.
     /// \name Constructors and Destructor.
     ///
     ///
@@ -150,6 +160,17 @@ public:
     /// - If the search name matches a delegation point of DNAME, it returns
     /// - If the search name matches a delegation point of DNAME, it returns
     ///   the code of \c DNAME and that DNAME RR.
     ///   the code of \c DNAME and that DNAME RR.
     ///
     ///
+    /// The \c options parameter specifies customized behavior of the search.
+    /// Their semantics is as follows:
+    /// - \c GLUE_OK Allow search under a zone cut.  By default the search
+    ///   will stop once it encounters a zone cut.  If this option is specified
+    ///   it remembers information about the highest zone cut and continues
+    ///   the search until it finds an exact match for the given name or it
+    ///   detects there is no exact match.  If an exact match is found,
+    ///   RRsets for that name are searched just like the normal case;
+    ///   otherwise, if the search has encountered a zone cut, \c DELEGATION
+    ///   with the information of the highest zone cut will be returned.
+    ///
     /// A derived version of this method may involve internal resource
     /// A derived version of this method may involve internal resource
     /// allocation, especially for constructing the resulting RRset, and may
     /// allocation, especially for constructing the resulting RRset, and may
     /// throw an exception if it fails.
     /// throw an exception if it fails.
@@ -162,9 +183,12 @@ public:
     ///
     ///
     /// \param name The domain name to be searched for.
     /// \param name The domain name to be searched for.
     /// \param type The RR type to be searched for.
     /// \param type The RR type to be searched for.
+    /// \param options The search options.
     /// \return A \c FindResult object enclosing the search result (see above).
     /// \return A \c FindResult object enclosing the search result (see above).
     virtual FindResult find(const isc::dns::Name& name,
     virtual FindResult find(const isc::dns::Name& name,
-                            const isc::dns::RRType& type) const = 0;
+                            const isc::dns::RRType& type,
+                            const FindOptions options
+                            = FIND_DEFAULT) const = 0;
     //@}
     //@}
 };
 };
 
 
@@ -177,4 +201,8 @@ typedef boost::shared_ptr<const Zone> ConstZonePtr;
 }
 }
 }
 }
 
 
-#endif
+#endif  // __ZONE_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 1 - 1
src/lib/datasrc/zonetable.h

@@ -25,7 +25,7 @@ namespace isc {
 namespace dns {
 namespace dns {
 class Name;
 class Name;
 class RRClass;
 class RRClass;
-};
+}
 
 
 namespace datasrc {
 namespace datasrc {