Parcourir la source

merge #439(Implement normal query processing), skip ChangeLog

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@4001 e5f2f494-b856-4b98-b285-d166d9295462
Jerry il y a 14 ans
Parent
commit
a6f3e21d91

+ 3 - 3
src/bin/auth/Makefile.am

@@ -34,10 +34,10 @@ auth.spec: auth.spec.pre
 spec_config.h: spec_config.h.pre
 	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
 
-BUILT_SOURCES = spec_config.h 
+BUILT_SOURCES = spec_config.h
 pkglibexec_PROGRAMS = b10-auth
-b10_auth_SOURCES = auth_srv.cc auth_srv.h
-b10_auth_SOURCES += query.cc query.h
+b10_auth_SOURCES = query.cc query.h
+b10_auth_SOURCES += auth_srv.cc auth_srv.h
 b10_auth_SOURCES += change_user.cc change_user.h
 b10_auth_SOURCES += config.cc config.h
 b10_auth_SOURCES += common.h

+ 14 - 2
src/bin/auth/auth_srv.cc

@@ -54,6 +54,7 @@
 #include <auth/common.h>
 #include <auth/config.h>
 #include <auth/auth_srv.h>
+#include <auth/query.h>
 
 using namespace std;
 
@@ -61,6 +62,7 @@ using namespace isc;
 using namespace isc::cc;
 using namespace isc::datasrc;
 using namespace isc::dns;
+using namespace isc::auth;
 using namespace isc::dns::rdata;
 using namespace isc::data;
 using namespace isc::config;
@@ -433,8 +435,18 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, MessagePtr message,
     }
 
     try {
-        Query query(*message, cache_, dnssec_ok);
-        data_sources_.doQuery(query);
+        // If a memory data source is configured call the separate
+        // Query::process()
+        if (memory_datasrc_) {
+            ConstQuestionPtr question = *message->beginQuestion();
+            const RRType& qtype = question->getType();
+            const Name& qname = question->getName();
+            isc::auth::Query query(*memory_datasrc_, qname, qtype, *message);
+            query.process();
+        } else {
+            isc::datasrc::Query query(*message, cache_, dnssec_ok);
+            data_sources_.doQuery(query);
+        }
     } catch (const Exception& ex) {
         if (verbose_mode_) {
             cerr << "[b10-auth] Internal error, returning SERVFAIL: " <<

+ 6 - 3
src/bin/auth/auth_srv.h

@@ -37,6 +37,7 @@ class AbstractXfroutClient;
 }
 }
 
+
 /// \brief The implementation class for the \c AuthSrv class using the pimpl
 /// idiom.
 class AuthSrvImpl;
@@ -130,9 +131,11 @@ public:
     /// If there is a data source installed, it will be replaced with the
     /// new one.
     ///
-    /// In the current implementation, the SQLite data source is assumed.
-    /// The \c config parameter will simply be passed to the initialization
-    /// routine of the \c Sqlite3DataSrc class.
+    /// In the current implementation, the SQLite data source and MemoryDataSrc
+    /// are assumed.
+    /// We can enable memory data source and get the path of SQLite database by
+    /// the \c config parameter.  If we disabled memory data source, the SQLite
+    /// data source will be used.
     ///
     /// On success this method returns a data \c Element (in the form of a
     /// pointer like object) indicating the successful result,

+ 1 - 0
src/bin/auth/benchmarks/Makefile.am

@@ -8,6 +8,7 @@ CLEANFILES = *.gcno *.gcda
 
 noinst_PROGRAMS = query_bench
 query_bench_SOURCES = query_bench.cc
+query_bench_SOURCES += ../query.h  ../query.cc
 query_bench_SOURCES += ../auth_srv.h ../auth_srv.cc
 query_bench_SOURCES += ../config.h ../config.cc
 

+ 3 - 0
src/bin/auth/benchmarks/query_bench.cc

@@ -33,11 +33,14 @@
 #include <xfr/xfrout_client.h>
 
 #include <auth/auth_srv.h>
+#include <auth/query.h>
+
 #include <asiolink/asiolink.h>
 
 using namespace std;
 using namespace isc;
 using namespace isc::data;
+using namespace isc::auth;
 using namespace isc::dns;
 using namespace isc::xfr;
 using namespace isc::bench;

+ 1 - 1
src/bin/auth/main.cc

@@ -85,7 +85,7 @@ my_command_handler(const string& command, ConstElementPtr args) {
     } else if (command == "shutdown") {
         io_service.stop();
     }
-    
+
     return (answer);
 }
 

+ 37 - 7
src/bin/auth/query.cc

@@ -15,7 +15,7 @@
 #include <dns/message.h>
 #include <dns/rcode.h>
 
-#include <datasrc/zonetable.h>
+#include <datasrc/memory_datasrc.h>
 
 #include <auth/query.h>
 
@@ -24,19 +24,49 @@ using namespace isc::datasrc;
 
 namespace isc {
 namespace auth {
+
 void
 Query::process() const {
-    const ZoneTable::FindResult result = zone_table_.findZone(qname_);
+    bool keep_doing = true;
+    response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
+    const MemoryDataSrc::FindResult result =
+        memory_datasrc_.findZone(qname_);
 
-    if (result.code != isc::datasrc::result::SUCCESS &&
-        result.code != isc::datasrc::result::PARTIALMATCH) {
+    if (result.code != result::SUCCESS &&
+        result.code != result::PARTIALMATCH) {
         response_.setRcode(Rcode::SERVFAIL());
         return;
     }
 
-    // Right now we have no code to search the zone, so we simply return
-    // NXDOMAIN for tests.
-    response_.setRcode(Rcode::NXDOMAIN());
+    // Found a zone which is the nearest ancestor to QNAME, set the AA bit
+    response_.setHeaderFlag(Message::HEADERFLAG_AA);
+    while (keep_doing) {
+        keep_doing = false;
+        Zone::FindResult db_result = result.zone->find(qname_, qtype_);
+        switch (db_result.code) {
+            case Zone::SUCCESS:
+                response_.setRcode(Rcode::NOERROR());
+                response_.addRRset(Message::SECTION_ANSWER,
+                            boost::const_pointer_cast<RRset>(db_result.rrset));
+                // TODO : fill in authority and addtional sections.
+                break;
+            case Zone::DELEGATION:
+                // TODO : add NS to authority section, fill in additional section.
+                break;
+            case Zone::NXDOMAIN:
+                response_.setRcode(Rcode::NXDOMAIN());
+                // TODO : add SOA to authority section
+                break;
+            case Zone::NXRRSET:
+                response_.setRcode(Rcode::NXRRSET());
+                // TODO : add SOA to authority section
+                break;
+            case Zone::CNAME:
+            case Zone::DNAME:
+                // TODO : replace qname, continue lookup
+                break;
+        }
+    }
 }
 }
 }

+ 12 - 12
src/bin/auth/query.h

@@ -22,7 +22,7 @@ class RRType;
 }
 
 namespace datasrc {
-class ZoneTable;
+class MemoryDataSrc;
 }
 
 namespace auth {
@@ -32,11 +32,11 @@ namespace auth {
 ///
 /// Many of the design details for this class are still in flux.
 /// We'll revisit and update them as we add more functionality, for example:
-/// - zone_table parameter of the constructor.  This will eventually be
-///   replaced with a generic DataSrc object, or perhaps a notion of "view".
+/// - memory_datasrc parameter of the constructor.  It is a data source that
+///   uses in memory dedicated backend.
 /// - as a related point, we may have to pass the RR class of the query.
-///   in the initial implementation the RR class is an attribute of zone
-///   table and omitted.  It's not clear if this assumption holds with
+///   in the initial implementation the RR class is an attribute of memory
+///   datasource and omitted.  It's not clear if this assumption holds with
 ///   generic data sources.  On the other hand, it will help keep
 ///   implementation simpler, and we might rather want to modify the design
 ///   of the data source on this point.
@@ -47,8 +47,8 @@ namespace auth {
 ///   separate attribute setter.
 /// - likewise, we'll eventually need to do per zone access control, for which
 ///   we need querier's information such as its IP address.
-/// - zone_table (or DataSrc eventually) and response may better be parameters
-///   to process() instead of the constructor.
+/// - memory_datasrc and response may better be parameters to process() instead
+///   of the constructor.
 ///
 /// <b>Note:</b> The class name is intentionally the same as the one used in
 /// the datasrc library.  This is because the plan is to eventually merge
@@ -65,15 +65,15 @@ public:
     ///
     /// This constructor never throws an exception.
     ///
-    /// \param zone_table The zone table wherein the answer to the query is
+    /// \param memory_datasrc The memory datasource wherein the answer to the query is
     /// to be found.
     /// \param qname The query name
     /// \param qtype The RR type of the query
     /// \param response The response message to store the answer to the query.
-    Query(const isc::datasrc::ZoneTable& zone_table,
+    Query(const isc::datasrc::MemoryDataSrc& memory_datasrc,
           const isc::dns::Name& qname, const isc::dns::RRType& qtype,
           isc::dns::Message& response) :
-        zone_table_(zone_table), qname_(qname), qtype_(qtype),
+        memory_datasrc_(memory_datasrc), qname_(qname), qtype_(qtype),
         response_(response)
     {}
 
@@ -87,7 +87,7 @@ public:
     /// successful search would result in adding a corresponding RRset to
     /// the answer section of the response.
     ///
-    /// If no matching zone is found in the zone table, the RCODE of
+    /// If no matching zone is found in the memory datasource, the RCODE of
     /// SERVFAIL will be set in the response.
     /// <b>Note:</b> this is different from the error code that BIND 9 returns
     /// by default when it's configured as an authoritative-only server (and
@@ -105,7 +105,7 @@ public:
     void process() const;
 
 private:
-    const isc::datasrc::ZoneTable& zone_table_;
+    const isc::datasrc::MemoryDataSrc& memory_datasrc_;
     const isc::dns::Name& qname_;
     const isc::dns::RRType& qtype_;
     isc::dns::Message& response_;

+ 7 - 1
src/bin/auth/tests/auth_srv_unittest.cc

@@ -19,7 +19,6 @@
 #include <auth/auth_srv.h>
 #include <testutils/srv_unittest.h>
 
-using namespace std;
 using namespace isc::cc;
 using namespace isc::dns;
 using namespace isc::data;
@@ -394,6 +393,13 @@ TEST_F(AuthSrvTest, updateWithMemoryDataSrc) {
     // after successful configuration, we should have one (with empty zoneset).
     ASSERT_NE(AuthSrv::MemoryDataSrcPtr(), server.getMemoryDataSrc(rrclass));
     EXPECT_EQ(0, server.getMemoryDataSrc(rrclass)->getZoneCount());
+
+    // The memory data source is empty, should return SERVFAIL rcode.
+    createDataFromFile("examplequery_fromWire.wire");
+    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv);
+    EXPECT_TRUE(dnsserv.hasAnswer());
+    headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(), opcode.getCode(),
+                QR_FLAG, 1, 0, 0, 0);
 }
 
 TEST_F(AuthSrvTest, cacheSlots) {

+ 79 - 11
src/bin/auth/tests/query_unittest.cc

@@ -15,9 +15,9 @@
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/rcode.h>
+#include <dns/rrttl.h>
 #include <dns/rrtype.h>
 
-#include <datasrc/zonetable.h>
 #include <datasrc/memory_datasrc.h>
 
 #include <auth/query.h>
@@ -28,17 +28,69 @@ using namespace isc::dns;
 using namespace isc::datasrc;
 using namespace isc::auth;
 
+RRsetPtr a_rrset = RRsetPtr(new RRset(Name("www.example.com"),
+                                      RRClass::IN(), RRType::A(),
+                                      RRTTL(3600)));
 namespace {
+// This is a mock Zone class for testing.
+// It is a derived class of Zone, and simply hardcode the results of find()
+// return SUCCESS for "www.example.com",
+// return NXDOMAIN for "nxdomain.example.com",
+// return NXRRSET for "nxrrset.example.com",
+// return CNAME for "cname.example.com",
+// else return DNAME
+class MockZone : public Zone {
+public:
+    MockZone() : origin_(Name("example.com"))
+    {}
+    virtual const isc::dns::Name& getOrigin() const;
+    virtual const isc::dns::RRClass& getClass() const;
+
+    FindResult find(const isc::dns::Name& name,
+            const isc::dns::RRType& type) const;
+
+private:
+    Name origin_;
+};
+
+const Name&
+MockZone::getOrigin() const {
+    return (origin_);
+}
+
+const RRClass&
+MockZone::getClass() const {
+    return (RRClass::IN());
+}
+
+Zone::FindResult
+MockZone::find(const Name& name, const RRType&) const {
+    // hardcode the find results
+    if (name == Name("www.example.com")) {
+        return FindResult(SUCCESS, a_rrset);
+    } else if (name == Name("delegation.example.com")) {
+        return FindResult(DELEGATION, RRsetPtr());
+    } else if (name == Name("nxdomain.example.com")) {
+        return FindResult(NXDOMAIN, RRsetPtr());
+    } else if (name == Name("nxrrset.example.com")) {
+        return FindResult(NXRRSET, RRsetPtr());
+    } else if (name == Name("cname.example.com")) {
+        return FindResult(CNAME, RRsetPtr());
+    } else {
+        return FindResult(DNAME, RRsetPtr());
+    }
+}
+
 class QueryTest : public ::testing::Test {
 protected:
     QueryTest() :
         qname(Name("www.example.com")), qclass(RRClass::IN()),
         qtype(RRType::A()), response(Message::RENDER),
-        query(zone_table, qname, qtype, response)
+        query(memory_datasrc, qname, qtype, response)
     {
         response.setRcode(Rcode::NOERROR());
     }
-    ZoneTable zone_table;
+    MemoryDataSrc memory_datasrc;
     const Name qname;
     const RRClass qclass;
     const RRType qtype;
@@ -47,25 +99,41 @@ protected:
 };
 
 TEST_F(QueryTest, noZone) {
-    // There's no zone in the zone table.  So the response should have
+    // There's no zone in the memory datasource.  So the response should have
     // SERVFAIL.
     query.process();
     EXPECT_EQ(Rcode::SERVFAIL(), response.getRcode());
 }
 
 TEST_F(QueryTest, matchZone) {
-    // add a matching zone.  since the zone is empty right now, the response
-    // should have NXDOMAIN.
-    zone_table.addZone(ZonePtr(new MemoryZone(qclass, Name("example.com"))));
+    // match qname, normal query
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
     query.process();
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
+                                  Name("www.example.com"), RRClass::IN(),
+                                  RRType::A()));
+
+    // NXDOMAIN
+    const Name nxdomain_name(Name("nxdomain.example.com"));
+    Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
+    nxdomain_query.process();
     EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
+
+    // NXRRSET
+    const Name nxrrset_name(Name("nxrrset.example.com"));
+    Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
+    nxrrset_query.process();
+    EXPECT_EQ(Rcode::NXRRSET(), response.getRcode());
 }
 
 TEST_F(QueryTest, noMatchZone) {
-    // there's a zone in the table but it doesn't match the qname.  should
-    // result in SERVFAIL.
-    zone_table.addZone(ZonePtr(new MemoryZone(qclass, Name("example.org"))));
-    query.process();
+    // there's a zone in the memory datasource but it doesn't match the qname.
+    // should result in SERVFAIL.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    const Name nomatch_name(Name("example.org"));
+    Query nomatch_query(memory_datasrc, nomatch_name, qtype, response);
+    nomatch_query.process();
     EXPECT_EQ(Rcode::SERVFAIL(), response.getRcode());
 }
 }

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

@@ -248,7 +248,7 @@ public:
     void addDataSrc(ConstDataSrcPtr data_src);
     void removeDataSrc(ConstDataSrcPtr data_src);
     size_t dataSrcCount() { return (data_sources.size()); }
-    
+
     void findClosestEnclosure(DataSrcMatch& match) const;
 
     // Actual queries for data should not be sent to a MetaDataSrc object,