Browse Source

corrected the behavior for zone mismatch cases. added tests for them.

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1420 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 15 years ago
parent
commit
574aada7ef
2 changed files with 208 additions and 76 deletions
  1. 62 24
      src/lib/auth/static_datasrc.cc
  2. 146 52
      src/lib/auth/tests/static_unittest.cc

+ 62 - 24
src/lib/auth/static_datasrc.cc

@@ -16,6 +16,8 @@
 
 
 #include "config.h"
 #include "config.h"
 
 
+#include <cassert>
+
 #include <dns/name.h>
 #include <dns/name.h>
 #include <dns/rdataclass.h>
 #include <dns/rdataclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrclass.h>
@@ -102,26 +104,31 @@ StaticDataSrc::~StaticDataSrc()
     delete impl_;
     delete impl_;
 }
 }
 
 
+namespace {
+bool
+isSubdomain(const Name& qname, const Name& zone) {
+    const NameComparisonResult::NameRelation cmp =
+        qname.compare(zone).getRelation();
+    return (cmp == NameComparisonResult::EQUAL ||
+            cmp == NameComparisonResult::SUBDOMAIN);
+}
+}
+
 void
 void
 StaticDataSrc::findClosestEnclosure(NameMatch& match,
 StaticDataSrc::findClosestEnclosure(NameMatch& match,
                                     const RRClass& qclass) const {
                                     const RRClass& qclass) const {
     const Name& qname = match.qname();
     const Name& qname = match.qname();
-    NameComparisonResult::NameRelation cmp;
 
 
     if (qclass != getClass() && qclass != RRClass::ANY()) {
     if (qclass != getClass() && qclass != RRClass::ANY()) {
         return;
         return;
     }
     }
 
 
-    cmp = qname.compare(impl_->version_name).getRelation();
-    if (cmp == NameComparisonResult::EQUAL ||
-        cmp == NameComparisonResult::SUBDOMAIN) {
+    if (isSubdomain(qname, impl_->version_name)) {
         match.update(*this, impl_->version_name);
         match.update(*this, impl_->version_name);
         return;
         return;
     }
     }
 
 
-    cmp = qname.compare(impl_->authors_name).getRelation();
-    if (cmp == NameComparisonResult::EQUAL ||
-        cmp == NameComparisonResult::SUBDOMAIN) {
+    if (isSubdomain(qname, impl_->authors_name)) {
         match.update(*this, impl_->authors_name);
         match.update(*this, impl_->authors_name);
         return;
         return;
     }
     }
@@ -131,35 +138,66 @@ DataSrc::Result
 StaticDataSrc::findRRset(const Name& qname,
 StaticDataSrc::findRRset(const Name& qname,
                          const RRClass& qclass, const RRType& qtype,
                          const RRClass& qclass, const RRType& qtype,
                          RRsetList& target, uint32_t& flags,
                          RRsetList& target, uint32_t& flags,
-                         const Name* zonename) const
+                         const Name* const zonename) const
 {
 {
     flags = 0;
     flags = 0;
     if (qclass != getClass() && qclass != RRClass::ANY()) {
     if (qclass != getClass() && qclass != RRClass::ANY()) {
         return (ERROR);
         return (ERROR);
     }
     }
 
 
-    const bool any = (qtype == RRType::ANY());
-
-    if (qname == impl_->version_name) {
-        if (qtype == RRType::TXT() || any) {
-            target.addRRset(impl_->version);
-        } else if (qtype == RRType::NS()) {
-            target.addRRset(impl_->version_ns);
+    // Identify the appropriate zone.
+    bool is_versionname = false, is_authorsname = false;
+    if (zonename != NULL) {
+        if (*zonename == impl_->version_name &&
+            isSubdomain(qname, impl_->version_name)) {
+            is_versionname = true;
+        } else if (*zonename == impl_->authors_name &&
+                   isSubdomain(qname, impl_->authors_name)) {
+            is_authorsname = true;
         } else {
         } else {
-            flags = TYPE_NOT_FOUND;
-        }
-    } else if (qname == impl_->authors_name) {
-        if (qtype == RRType::TXT() || any) {
-            target.addRRset(impl_->authors);
+            flags = NO_SUCH_ZONE;
             return (SUCCESS);
             return (SUCCESS);
-        } else if (qtype == RRType::NS()) {
-            target.addRRset(impl_->authors_ns);
+        }
+    } else {
+        if (isSubdomain(qname, impl_->version_name)) {
+            is_versionname = true;
+        } else if (isSubdomain(qname, impl_->authors_name)) {
+            is_authorsname = true;
+        } else {
+            flags = NO_SUCH_ZONE;
             return (SUCCESS);
             return (SUCCESS);
+        }
+    }
+
+    const bool any = (qtype == RRType::ANY());
+
+    if (is_versionname) {
+        if (qname == impl_->version_name) {
+            if (qtype == RRType::TXT() || any) {
+                target.addRRset(impl_->version);
+            } else if (qtype == RRType::NS()) {
+                target.addRRset(impl_->version_ns);
+            } else {
+                flags = TYPE_NOT_FOUND;
+            }
         } else {
         } else {
-            flags = TYPE_NOT_FOUND;
+            flags = NAME_NOT_FOUND;
         }
         }
     } else {
     } else {
-        flags = NAME_NOT_FOUND;
+        assert(is_authorsname);
+        if (qname == impl_->authors_name) {
+            if (qtype == RRType::TXT() || any) {
+                target.addRRset(impl_->authors);
+                return (SUCCESS);
+            } else if (qtype == RRType::NS()) {
+                target.addRRset(impl_->authors_ns);
+                return (SUCCESS);
+            } else {
+                flags = TYPE_NOT_FOUND;
+            }
+        } else {
+            flags = NAME_NOT_FOUND;
+        }
     }
     }
 
 
     return (SUCCESS);
     return (SUCCESS);

+ 146 - 52
src/lib/auth/tests/static_unittest.cc

@@ -112,6 +112,38 @@ checkRRset(ConstRRsetPtr rrset, const Name& expected_name,
     EXPECT_TRUE(rdata_iterator->isLast());
     EXPECT_TRUE(rdata_iterator->isLast());
 }
 }
 
 
+void
+checkFind(const DataSrc& data_source,
+          const Name& qname, const Name* zone_name,
+          const RRClass& qclass, const RRClass& expected_class,
+          const RRType& qtype,  // == expected RRType
+          const RRTTL& expected_ttl, const uint32_t expected_flags,
+          const vector<string>& expected_answers)
+{
+    RRsetList result_sets;
+    uint32_t find_flags;
+
+    EXPECT_EQ(DataSrc::SUCCESS,
+              data_source.findRRset(qname, qclass, qtype, result_sets,
+                                    find_flags, zone_name));
+    EXPECT_EQ(expected_flags, find_flags);
+    if ((find_flags & (DataSrc::NO_SUCH_ZONE | DataSrc::NAME_NOT_FOUND |
+                       DataSrc::TYPE_NOT_FOUND)) != 0) {
+        // result should be empty
+        EXPECT_TRUE(result_sets.begin() == result_sets.end());
+        return;
+    }
+
+    // There's always exactly one RRset, whose RR type should match the
+    // expected type.
+    RRsetList::iterator it = result_sets.begin();
+    EXPECT_EQ(qtype, (*it)->getType());
+    checkRRset((*it), qname, expected_class, qtype, expected_ttl,
+               expected_answers);
+    ++it;
+    EXPECT_TRUE(result_sets.end() == it);
+}
+
 TEST_F(StaticDataSourceTest, init) {
 TEST_F(StaticDataSourceTest, init) {
     EXPECT_EQ(DataSrc::SUCCESS, data_source.init());
     EXPECT_EQ(DataSrc::SUCCESS, data_source.init());
 }
 }
@@ -127,6 +159,22 @@ TEST_F(StaticDataSourceTest, findClosestEnclosureForVersion) {
     EXPECT_EQ(&data_source, name_match.bestDataSrc());
     EXPECT_EQ(&data_source, name_match.bestDataSrc());
 }
 }
 
 
+// Class Any query should result in the same answer.
+TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionClassAny) {
+    NameMatch name_match(version_name);
+    data_source.findClosestEnclosure(name_match, RRClass::ANY());
+    EXPECT_EQ(version_name, *name_match.closestName());
+    EXPECT_EQ(&data_source, name_match.bestDataSrc());
+}
+
+// If class doesn't match the lookup should fail.
+TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionClassMismatch) {
+    NameMatch name_match(version_name);
+    data_source.findClosestEnclosure(name_match, RRClass::IN());
+    EXPECT_EQ(NULL, name_match.closestName());
+    EXPECT_EQ(NULL, name_match.bestDataSrc());
+}
+
 TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionPartial) {
 TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionPartial) {
     NameMatch name_match(Name("foo").concatenate(version_name));
     NameMatch name_match(Name("foo").concatenate(version_name));
     data_source.findClosestEnclosure(name_match, rrclass);
     data_source.findClosestEnclosure(name_match, rrclass);
@@ -156,69 +204,115 @@ TEST_F(StaticDataSourceTest, findClosestEnclosureNoMatch) {
 }
 }
 
 
 TEST_F(StaticDataSourceTest, findRRsetVersionTXT) {
 TEST_F(StaticDataSourceTest, findRRsetVersionTXT) {
-    EXPECT_EQ(DataSrc::SUCCESS,
-              data_source.findRRset(version_name, rrclass, rrtype,
-                                    result_sets, find_flags, NULL));
-    EXPECT_EQ(0, find_flags);
-    // There should be only item in result_sets, which should be
-    // version_name/TXT.
-    RRsetList::iterator it = result_sets.begin();
-    for (; it != result_sets.end(); ++it) {
-        if ((*it)->getType() == rrtype) {
-            checkRRset(*it, version_name, rrclass, rrtype, rrttl, version_data);
-            ++matched_rdata;
-        }
-    }
-    EXPECT_EQ(1, matched_rdata);
+    checkFind(data_source, version_name, NULL, rrclass, rrclass,
+              rrtype, rrttl, 0, version_data);
+    checkFind(data_source, version_name, &version_name, rrclass, rrclass,
+              rrtype, rrttl, 0, version_data);
 }
 }
 
 
 TEST_F(StaticDataSourceTest, findRRsetVersionNS) {
 TEST_F(StaticDataSourceTest, findRRsetVersionNS) {
     rrtype = RRType::NS();
     rrtype = RRType::NS();
-    EXPECT_EQ(DataSrc::SUCCESS,
-              data_source.findRRset(version_name, rrclass, rrtype,
-                                    result_sets, find_flags, NULL));
-    EXPECT_EQ(0, find_flags);
-    RRsetList::iterator it = result_sets.begin();
-    for (; it != result_sets.end(); ++it) {
-        if ((*it)->getType() == rrtype) {
-            checkRRset(*it, version_name, rrclass, rrtype, rrttl,
-                       version_ns_data);
-            ++matched_rdata;
-        }
-    }
-    EXPECT_EQ(1, matched_rdata);
+    checkFind(data_source, version_name, NULL, rrclass, rrclass,
+              rrtype, rrttl, 0, version_ns_data);
+    checkFind(data_source, version_name, &version_name, rrclass, rrclass,
+              rrtype, rrttl, 0, version_ns_data);
 }
 }
 
 
 TEST_F(StaticDataSourceTest, findRRsetAuthorsTXT) {
 TEST_F(StaticDataSourceTest, findRRsetAuthorsTXT) {
-    EXPECT_EQ(DataSrc::SUCCESS,
-              data_source.findRRset(authors_name, rrclass, rrtype,
-                                    result_sets, find_flags, NULL));
-    EXPECT_EQ(0, find_flags);
-    RRsetList::iterator it = result_sets.begin();
-    for (; it != result_sets.end(); ++it) {
-        if ((*it)->getType() == rrtype) {
-            checkRRset(*it, authors_name, rrclass, rrtype, rrttl, authors_data);
-            ++matched_rdata;
-        }
-    }
-    EXPECT_EQ(1, matched_rdata);
+    checkFind(data_source, authors_name, NULL, rrclass, rrclass,
+              rrtype, rrttl, 0, authors_data);
+    checkFind(data_source, authors_name, &authors_name, rrclass, rrclass,
+              rrtype, rrttl, 0, authors_data);
 }
 }
 
 
 TEST_F(StaticDataSourceTest, findRRsetAuthorsNS) {
 TEST_F(StaticDataSourceTest, findRRsetAuthorsNS) {
     rrtype = RRType::NS();
     rrtype = RRType::NS();
-    EXPECT_EQ(DataSrc::SUCCESS,
-              data_source.findRRset(authors_name, rrclass, rrtype,
-                                    result_sets, find_flags, NULL));
-    EXPECT_EQ(0, find_flags);
-    RRsetList::iterator it = result_sets.begin();
-    for (; it != result_sets.end(); ++it) {
-        if ((*it)->getType() == rrtype) {
-            checkRRset(*it, authors_name, rrclass, rrtype, rrttl,
-                       authors_ns_data);
-            ++matched_rdata;
-        }
-    }
-    EXPECT_EQ(1, matched_rdata);
+    checkFind(data_source, authors_name, NULL, rrclass, rrclass,
+              rrtype, rrttl, 0, authors_ns_data);
+    checkFind(data_source, authors_name, &authors_name, rrclass, rrclass,
+              rrtype, rrttl, 0, authors_ns_data);
+}
+
+// Class ANY lookup should result in the same answer.
+TEST_F(StaticDataSourceTest, findRRsetVersionClassAny) {
+    checkFind(data_source, version_name, NULL, RRClass::ANY(), rrclass,
+              rrtype, rrttl, 0, version_data);
+    checkFind(data_source, version_name, &version_name, RRClass::ANY(), rrclass,
+              rrtype, rrttl, 0, version_data);
+}
+
+// If the class doesn't match, it should simply fail.
+TEST_F(StaticDataSourceTest, findRRsetVersionClassMismatch) {
+    EXPECT_EQ(DataSrc::ERROR,
+              data_source.findRRset(version_name, RRClass::IN(), rrtype,
+                                    result_sets, find_flags, &version_name));
+}
+
+TEST_F(StaticDataSourceTest, findRRsetOutOfZone) {
+    // If the qname doesn't match any of the static zones, the result should
+    // be "no such zone", regardless of whether the zone is explicitly
+    // specified.  Other "expected" result parameters will be ignored.
+    checkFind(data_source, nomatch_name, NULL, rrclass, rrclass,
+              rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
+    checkFind(data_source, nomatch_name, &version_name, rrclass, rrclass,
+              rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
+    checkFind(data_source, nomatch_name, &authors_name, rrclass, rrclass,
+              rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
+}
+
+// If a zone name is given but doesn't match any of the static zones,
+// the result should be "no such zone"
+TEST_F(StaticDataSourceTest, findRRsetZoneMismatch) {
+    const Name& short_zonename(Name("bind"));
+    checkFind(data_source, version_name, &short_zonename, rrclass, rrclass,
+              rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
+    checkFind(data_source, authors_name, &short_zonename, rrclass, rrclass,
+              rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
+}
+
+// Zone matches, but name doesn't exist in the zone
+TEST_F(StaticDataSourceTest, findRRsetNoName) {
+    checkFind(data_source, Name("foo").concatenate(version_name), NULL, rrclass,
+              rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND, authors_ns_data);
+    checkFind(data_source, Name("foo").concatenate(version_name), &version_name,
+              rrclass, rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND,
+              authors_ns_data);
+    checkFind(data_source, Name("foo").concatenate(authors_name), NULL, rrclass,
+              rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND, authors_ns_data);
+    checkFind(data_source, Name("foo").concatenate(authors_name), &authors_name,
+              rrclass, rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND,
+              authors_ns_data);
+}
+
+// Zone matches and qname exists, but type doesn't exist for the name.
+TEST_F(StaticDataSourceTest, findRRsetNoType) {
+    const RRType& nomatch_type = RRType::A();
+
+    checkFind(data_source, version_name, NULL, rrclass,
+              rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
+              authors_ns_data);
+    checkFind(data_source, version_name, &version_name, rrclass,
+              rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
+              authors_ns_data);
+    checkFind(data_source, authors_name, NULL, rrclass,
+              rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
+              authors_ns_data);
+    checkFind(data_source, authors_name, &authors_name, rrclass,
+              rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
+              authors_ns_data);
+}
+
+// Simple tests for "unsupported" tests.
+TEST_F(StaticDataSourceTest, notImplemented) {
+    Name target_name(version_name);
+    EXPECT_EQ(DataSrc::NOT_IMPLEMENTED,
+              data_source.findPreviousName(version_name, target_name,
+                                           &version_name));
+
+    string target_hash;
+    EXPECT_EQ(DataSrc::NOT_IMPLEMENTED,
+              data_source.findCoveringNSEC3(version_name, target_hash,
+                                            result_sets));
 }
 }
 
 
 }
 }