Commit a6f3e21d authored by Jerry's avatar Jerry
Browse files

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


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@4001 e5f2f494-b856-4b98-b285-d166d9295462
parents b1a824e0 289a358d
......@@ -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
......
......@@ -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: " <<
......
......@@ -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,
......
......@@ -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
......
......@@ -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;
......
......@@ -85,7 +85,7 @@ my_command_handler(const string& command, ConstElementPtr args) {
} else if (command == "shutdown") {
io_service.stop();
}
return (answer);
}
......
......@@ -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;
}
}
}
}
}
......@@ -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_;
......
......@@ -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) {
......
......@@ -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());
}
}
......@@ -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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment