Parcourir la source

[trac534] Test a rare case of DNAME under NS

And fix a bug why it didn't work (a check or nested zonecuts prevented
detection of DNAME).
Michal 'vorner' Vaner il y a 14 ans
Parent
commit
a0f8c9ee2b

+ 6 - 6
src/lib/datasrc/memory_datasrc.cc

@@ -231,12 +231,6 @@ struct MemoryZone::MemoryZoneImpl {
     // A callback called from possible zone cut nodes and nodes with DNAME.
     // This will be passed from the \c find() method to \c RBTree::find().
     static bool cutCallback(const DomainNode& node, FindState* state) {
-        // We perform callback check only for the highest zone cut in the
-        // rare case of nested zone cuts.
-        if (state->zonecut_node_ != NULL) {
-            return (false);
-        }
-
         // We need to look for DNAME first, there's allowed case where
         // DNAME and NS coexist in the apex. DNAME is the one to notice,
         // the NS is authoritative, not delegation (corner case explicitly
@@ -259,6 +253,12 @@ struct MemoryZone::MemoryZoneImpl {
         const Domain::const_iterator foundNS(node.getData()->find(
             RRType::NS()));
         if (foundNS != node.getData()->end()) {
+            // We perform callback check only for the highest zone cut in the
+            // rare case of nested zone cuts.
+            if (state->zonecut_node_ != NULL) {
+                return (false);
+            }
+
             // BIND 9 checks if this node is not the origin.  That's probably
             // because it can support multiple versions for dynamic updates
             // and IXFR, and it's possible that the callback is called at

+ 20 - 2
src/lib/datasrc/tests/memory_datasrc_unittest.cc

@@ -153,6 +153,7 @@ public:
         child_glue_name_("ns.child.example.org"),
         grandchild_ns_name_("grand.child.example.org"),
         grandchild_glue_name_("ns.grand.child.example.org"),
+        child_dname_name_("dname.child.example.org"),
         zone_(class_, origin_),
         rr_out_(new RRset(Name("example.com"), class_, RRType::A(),
             RRTTL(300))),
@@ -175,13 +176,16 @@ public:
         rr_grandchild_ns_(new RRset(grandchild_ns_name_, class_, RRType::NS(),
                                     RRTTL(300))),
         rr_grandchild_glue_(new RRset(grandchild_glue_name_, class_,
-                                      RRType::AAAA(), RRTTL(300)))
+                                      RRType::AAAA(), RRTTL(300))),
+        rr_child_dname_(new RRset(child_dname_name_, class_, RRType::DNAME(),
+            RRTTL(300)))
     {
     }
     // Some data to test with
     const RRClass class_;
     const Name origin_, ns_name_, cname_name_, dname_name_, child_ns_name_,
-        child_glue_name_, grandchild_ns_name_, grandchild_glue_name_;
+        child_glue_name_, grandchild_ns_name_, grandchild_glue_name_,
+        child_dname_name_;
     // The zone to torture by tests
     MemoryZone zone_;
 
@@ -212,6 +216,7 @@ public:
     ConstRRsetPtr rr_child_glue_; // glue RR of the child domain
     ConstRRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
     ConstRRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
+    ConstRRsetPtr rr_child_dname_; // A DNAME under NS
 
     /**
      * \brief Test one find query to the zone.
@@ -392,6 +397,19 @@ TEST_F(MemoryZoneTest, findAtDNAME) {
     findTest(dname_name_, RRType::TXT(), Zone::NXRRSET, true);
 }
 
+// Try searching something that is both under NS and DNAME, without and with
+// GLUE_OK mode (it should stop at the NS and DNAME respectively).
+TEST_F(MemoryZoneTest, DNAMEUnderNS) {
+    zone_.add(rr_child_ns_);
+    zone_.add(rr_child_dname_);
+
+    Name lowName("below.dname.child.example.org.");
+
+    findTest(lowName, RRType::A(), Zone::DELEGATION, true, rr_child_ns_);
+    findTest(lowName, RRType::A(), Zone::DNAME, true, rr_child_dname_, NULL,
+        NULL, Zone::FIND_GLUE_OK);
+}
+
 // Test adding child zones and zone cut handling
 TEST_F(MemoryZoneTest, delegationNS) {
     // add in-zone data