Browse Source

[1607] implemented basic cases of getAdditional() and tests.

JINMEI Tatuya 13 years ago
parent
commit
1d3d7c5906

+ 8 - 1
src/lib/datasrc/tests/testdata/contexttest.zone

@@ -1,14 +1,19 @@
 ;; test zone file used for ZoneFinderContext tests.
 ;; test zone file used for ZoneFinderContext tests.
+;; RRSIGs are (obviouslly) faked ones for testing.
 
 
-example.org. 3600 IN SOA	ns1.example.org. bugs.x.w.example.org. 9 3600 300 3600000 3600
+example.org. 3600 IN SOA	ns1.example.org. bugs.x.w.example.org. 20 3600 300 3600000 3600
 example.org.			      3600 IN NS	ns1.example.org.
 example.org.			      3600 IN NS	ns1.example.org.
 example.org.			      3600 IN NS	ns2.example.org.
 example.org.			      3600 IN NS	ns2.example.org.
 example.org.			      3600 IN MX	1 mx1.example.org.
 example.org.			      3600 IN MX	1 mx1.example.org.
 example.org.			      3600 IN MX	2 mx2.example.org.
 example.org.			      3600 IN MX	2 mx2.example.org.
+example.org.			      3600 IN MX	3 mx.a.example.org.
 
 
 ns1.example.org.		      3600 IN A		192.0.2.1
 ns1.example.org.		      3600 IN A		192.0.2.1
+ns1.example.org.		      3600 IN RRSIG	A 7 3 3600 20150420235959 20051021000000 40430 example.org. FAKEFAKE
 ns1.example.org.		      3600 IN AAAA	2001:db8::1
 ns1.example.org.		      3600 IN AAAA	2001:db8::1
+ns1.example.org.		      3600 IN RRSIG	AAAA 7 3 3600 20150420235959 20051021000000 40430 example.org. FAKEFAKEFAKE
 ns2.example.org.		      3600 IN A		192.0.2.2
 ns2.example.org.		      3600 IN A		192.0.2.2
+ns2.example.org.		      3600 IN TXT	"text data"
 
 
 mx1.example.org.		      3600 IN A		192.0.2.10
 mx1.example.org.		      3600 IN A		192.0.2.10
 mx2.example.org.		      3600 IN AAAA	2001:db8::10
 mx2.example.org.		      3600 IN AAAA	2001:db8::10
@@ -16,7 +21,9 @@ mx2.example.org.		      3600 IN AAAA	2001:db8::10
 ;; delegation
 ;; delegation
 a.example.org.			      3600 IN NS	ns1.a.example.org.
 a.example.org.			      3600 IN NS	ns1.a.example.org.
 a.example.org.			      3600 IN NS	ns2.a.example.org.
 a.example.org.			      3600 IN NS	ns2.a.example.org.
+a.example.org.			      3600 IN NS	ns.example.com.
 
 
 ns1.a.example.org.		      3600 IN A		192.0.2.5
 ns1.a.example.org.		      3600 IN A		192.0.2.5
 ns2.a.example.org.		      3600 IN A		192.0.2.6
 ns2.a.example.org.		      3600 IN A		192.0.2.6
 ns2.a.example.org.		      3600 IN AAAA	2001:db8::6
 ns2.a.example.org.		      3600 IN AAAA	2001:db8::6
+mx.a.example.org.		      3600 IN A		192.0.2.7

+ 151 - 3
src/lib/datasrc/tests/zone_finder_context_unittest.cc

@@ -21,17 +21,23 @@
 #include <datasrc/database.h>
 #include <datasrc/database.h>
 #include <datasrc/sqlite3_accessor.h>
 #include <datasrc/sqlite3_accessor.h>
 
 
+#include <testutils/dnsmessage_test.h>
+
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
 #include <boost/bind.hpp>
 #include <boost/bind.hpp>
+#include <boost/foreach.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_ptr.hpp>
 
 
 #include <cstdlib>
 #include <cstdlib>
+#include <vector>
 
 
 using namespace std;
 using namespace std;
+using boost::shared_ptr;
+
 using namespace isc::dns;
 using namespace isc::dns;
 using namespace isc::datasrc;
 using namespace isc::datasrc;
-using boost::shared_ptr;
+using namespace isc::testutils;
 
 
 namespace {
 namespace {
 
 
@@ -88,6 +94,12 @@ createSQLite3Client(RRClass zclass, const Name& zname) {
     ZoneUpdaterPtr updater = client->getUpdater(zname, true);
     ZoneUpdaterPtr updater = client->getUpdater(zname, true);
     masterLoad(TEST_ZONE_FILE, zname, zclass, boost::bind(addRRset, updater,
     masterLoad(TEST_ZONE_FILE, zname, zclass, boost::bind(addRRset, updater,
                                                           _1));
                                                           _1));
+    // Insert an out-of-zone name to test if it's incorrectly returned.
+    // Note that neither updater nor SQLite3 accessor checks this condition,
+    // so this should succeed.
+    stringstream ss("ns.example.com. 3600 IN A 192.0.2.7");
+    masterLoad(ss, Name::ROOT_NAME(), zclass,
+               boost::bind(addRRset, updater, _1));
     updater->commit();
     updater->commit();
 
 
     return (client);
     return (client);
@@ -101,12 +113,22 @@ class ZoneFinderContextTest :
 protected:
 protected:
     ZoneFinderContextTest() : qclass_(RRClass::IN()), qzone_("example.org") {
     ZoneFinderContextTest() : qclass_(RRClass::IN()), qzone_("example.org") {
         client_ = (*GetParam())(qclass_, qzone_);
         client_ = (*GetParam())(qclass_, qzone_);
+        REQUESTED_A.push_back(RRType::A());
+        REQUESTED_AAAA.push_back(RRType::AAAA());
+        REQUESTED_BOTH.push_back(RRType::A());
+        REQUESTED_BOTH.push_back(RRType::AAAA());
     }
     }
 
 
     const RRClass qclass_;
     const RRClass qclass_;
     const Name qzone_;
     const Name qzone_;
     DataSourceClientPtr client_;
     DataSourceClientPtr client_;
     ZoneFinderPtr finder_;
     ZoneFinderPtr finder_;
+
+    vector<RRType> requested_types_;
+    vector<RRType> REQUESTED_A;
+    vector<RRType> REQUESTED_AAAA;
+    vector<RRType> REQUESTED_BOTH;
+    vector<ConstRRsetPtr> result_sets_;
 };
 };
 
 
 // We test the in-memory and SQLite3 data source implementations.
 // We test the in-memory and SQLite3 data source implementations.
@@ -114,9 +136,135 @@ INSTANTIATE_TEST_CASE_P(, ZoneFinderContextTest,
                         ::testing::Values(createInMemoryClient,
                         ::testing::Values(createInMemoryClient,
                                           createSQLite3Client));
                                           createSQLite3Client));
 
 
-TEST_P(ZoneFinderContextTest, getAdditional) {
-    finder_ = client_->findZone(Name("www.a.example.org")).zone_finder;
+TEST_P(ZoneFinderContextTest, getAdditionalAuthNS) {
+    finder_ = client_->findZone(qzone_).zone_finder;
+    ASSERT_TRUE(finder_);
+
+    ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::NS());
+    EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
+
+    // Getting both A and AAAA NS addresses
+    ctx->getAdditional(REQUESTED_BOTH, result_sets_);
+    rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
+                "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
+                "ns2.example.org. 3600 IN A 192.0.2.2\n",
+                result_sets_.begin(), result_sets_.end());
+
+    // Getting only A
+    result_sets_.clear();
+    ctx->getAdditional(REQUESTED_A, result_sets_);
+    rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
+                "ns2.example.org. 3600 IN A 192.0.2.2\n",
+                result_sets_.begin(), result_sets_.end());
+
+    // Getting only AAAA
+    result_sets_.clear();
+    ctx->getAdditional(REQUESTED_AAAA, result_sets_);
+    rrsetsCheck("ns1.example.org. 3600 IN AAAA 2001:db8::1\n",
+                result_sets_.begin(), result_sets_.end());
+
+    // Normally expected type set contain only A and/or AAAA, but others aren't
+    // excluded.
+    result_sets_.clear();
+    requested_types_.push_back(RRType::TXT());
+    ctx->getAdditional(requested_types_, result_sets_);
+    rrsetsCheck("ns2.example.org. 3600 IN TXT \"text data\"",
+                result_sets_.begin(), result_sets_.end());
+
+    // Even empty set is okay.  The result should also be empty.
+    result_sets_.clear();
+    ctx->getAdditional(vector<RRType>(), result_sets_);
+    EXPECT_TRUE(result_sets_.empty());
+}
+
+TEST_P(ZoneFinderContextTest, getAdditionalDelegation) {
+    // Basically similar to the AuthNS case, but NS names are glues.
+    // It contains an out-of-zone NS name.  Its address (even if it's somehow
+    // inserted to the zone data) shouldn't be returned.
+
+    const Name qname("www.a.example.org");
+    finder_ = client_->findZone(qname).zone_finder;
+    ASSERT_TRUE(finder_);
+
+    ZoneFinderContextPtr ctx = finder_->find(qname, RRType::AAAA());
+    EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
+
+    ctx->getAdditional(REQUESTED_BOTH, result_sets_);
+    rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
+                "ns2.a.example.org. 3600 IN A 192.0.2.6\n"
+                "ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
+                result_sets_.begin(), result_sets_.end());
+
+    result_sets_.clear();
+    ctx->getAdditional(REQUESTED_A, result_sets_);
+    rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
+                "ns2.a.example.org. 3600 IN A 192.0.2.6\n",
+                result_sets_.begin(), result_sets_.end());
+
+    result_sets_.clear();
+    ctx->getAdditional(REQUESTED_AAAA, result_sets_);
+    rrsetsCheck("ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
+                result_sets_.begin(), result_sets_.end());
+}
+
+TEST_P(ZoneFinderContextTest, getAdditionalMX) {
+    // Similar to the previous cases, but for MX addresses.  The test zone
+    // contains MX name under a zone cut.  Its address shouldn't be returned.
+
+    finder_ = client_->findZone(qzone_).zone_finder;
     ASSERT_TRUE(finder_);
     ASSERT_TRUE(finder_);
+
+    ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::MX());
+    EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
+
+    // Getting both A and AAAA NS addresses
+    ctx->getAdditional(REQUESTED_BOTH, result_sets_);
+    rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n"
+                "mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
+                result_sets_.begin(), result_sets_.end());
+
+    // Getting only A
+    result_sets_.clear();
+    ctx->getAdditional(REQUESTED_A, result_sets_);
+    rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n",
+                result_sets_.begin(), result_sets_.end());
+
+    // Getting only AAAA
+    result_sets_.clear();
+    ctx->getAdditional(REQUESTED_AAAA, result_sets_);
+    rrsetsCheck("mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
+                result_sets_.begin(), result_sets_.end());
+}
+
+TEST_P(ZoneFinderContextTest, getAdditionalWithSIG) {
+    // Similar to the AuthNS test, but the original find() requested DNSSEC
+    // RRSIGs.  Then additional records will also have RRSIGs.
+
+    finder_ = client_->findZone(qzone_).zone_finder;
+    ASSERT_TRUE(finder_);
+    
+    ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::NS(),
+                                             ZoneFinder::FIND_DNSSEC);
+    EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
+
+    ctx->getAdditional(REQUESTED_BOTH, result_sets_);
+    rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
+                "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
+                "ns2.example.org. 3600 IN A 192.0.2.2\n",
+                result_sets_.begin(), result_sets_.end());
+
+    vector<ConstRRsetPtr> sigresult_sets;
+    BOOST_FOREACH(ConstRRsetPtr rrset, result_sets_) {
+        ConstRRsetPtr sig_rrset = rrset->getRRsig();
+        if (sig_rrset) {
+            sigresult_sets.push_back(sig_rrset);
+        }
+    }
+    rrsetsCheck("ns1.example.org. 3600 IN RRSIG	A 7 3 3600 20150420235959 "
+                "20051021000000 40430 example.org. FAKEFAKE\n"
+                "ns1.example.org. 3600 IN RRSIG	AAAA 7 3 3600 20150420235959 "
+                "20051021000000 40430 example.org. FAKEFAKEFAKEFAKE\n",
+                sigresult_sets.begin(), sigresult_sets.end());
 }
 }
 
 
 }
 }

+ 45 - 2
src/lib/datasrc/zone_finder_context.cc

@@ -15,9 +15,12 @@
 #include <dns/rdata.h>
 #include <dns/rdata.h>
 #include <dns/rrset.h>
 #include <dns/rrset.h>
 #include <dns/rrtype.h>
 #include <dns/rrtype.h>
+#include <dns/rdataclass.h>
 
 
 #include <datasrc/zone.h>
 #include <datasrc/zone.h>
 
 
+#include <boost/foreach.hpp>
+
 #include <vector>
 #include <vector>
 
 
 using namespace std;
 using namespace std;
@@ -27,10 +30,50 @@ using namespace isc::dns::rdata;
 namespace isc {
 namespace isc {
 namespace datasrc {
 namespace datasrc {
 
 
+namespace {
 void
 void
-ZoneFinder::Context::getAdditional(const vector<RRType>& /*requested_types*/,
-                                   vector<ConstRRsetPtr>& /*result*/)
+getAdditionalAddrs(ZoneFinder& finder, const Name& name,
+                   const vector<RRType>& requested_types,
+                   vector<ConstRRsetPtr>& result_rrsets,
+                   ZoneFinder::FindOptions options)
 {
 {
+    // Ignore out-of-zone names
+    const NameComparisonResult cmp = finder.getOrigin().compare(name);
+    if ((cmp.getRelation() != NameComparisonResult::SUPERDOMAIN) &&
+        (cmp.getRelation() != NameComparisonResult::EQUAL)) {
+        return;
+    }
+
+    BOOST_FOREACH(RRType rrtype, requested_types) {
+        ConstZoneFinderContextPtr ctx = finder.find(name, rrtype, options);
+        if (ctx->code == ZoneFinder::SUCCESS) {
+            result_rrsets.push_back(ctx->rrset);
+        }
+    }
+}
+}
+
+void
+ZoneFinder::Context::getAdditional(const vector<RRType>& requested_types,
+                                   vector<ConstRRsetPtr>& result)
+{
+    RdataIteratorPtr rdata_iterator(rrset->getRdataIterator());
+    ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT;
+
+    for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
+        const Rdata& rdata(rdata_iterator->getCurrent());
+
+        if (rrset->getType() == RRType::NS()) {
+            // Need to perform the search in the "GLUE OK" mode.
+            const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
+            getAdditionalAddrs(finder_, ns.getNSName(), requested_types,
+                               result, options | ZoneFinder::FIND_GLUE_OK);
+        } else if (rrset->getType() == RRType::MX()) {
+            const generic::MX& mx = dynamic_cast<const generic::MX&>(rdata);
+            getAdditionalAddrs(finder_, mx.getMXName(), requested_types,
+                               result, options);
+        }
+    }
 }
 }
 
 
 } // namespace datasrc
 } // namespace datasrc