Commit 3f51d6ed authored by Jerry's avatar Jerry
Browse files

merge branch #453 : Delegation processing and additional processing for NS


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@4140 e5f2f494-b856-4b98-b285-d166d9295462
parents db2a8bd6 f63a2aa7
......@@ -14,6 +14,7 @@
#include <dns/message.h>
#include <dns/rcode.h>
#include <dns/rdataclass.h>
#include <datasrc/memory_datasrc.h>
......@@ -21,10 +22,51 @@
using namespace isc::dns;
using namespace isc::datasrc;
using namespace isc::dns::rdata;
namespace isc {
namespace auth {
void
Query::getAdditional(const isc::datasrc::Zone& zone,
const isc::dns::RRset& rrset) const
{
if (rrset.getType() == RRType::NS()) {
// Need to perform the search in the "GLUE OK" mode.
RdataIteratorPtr rdata_iterator = rrset.getRdataIterator();
for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
const Rdata& rdata(rdata_iterator->getCurrent());
const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
findAddrs(zone, ns.getNSName(), Zone::FIND_GLUE_OK);
}
}
}
void
Query::findAddrs(const isc::datasrc::Zone& zone,
const isc::dns::Name& qname,
const isc::datasrc::Zone::FindOptions options) const
{
// Out of zone name
NameComparisonResult result = zone.getOrigin().compare(qname);
if ((result.getRelation() != NameComparisonResult::SUPERDOMAIN) &&
(result.getRelation() != NameComparisonResult::EQUAL))
return;
// Find A rrset
Zone::FindResult a_result = zone.find(qname, RRType::A(), options);
if (a_result.code == Zone::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(a_result.rrset));
}
// Find AAAA rrset
Zone::FindResult aaaa_result = zone.find(qname, RRType::AAAA(), options);
if (aaaa_result.code == Zone::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(aaaa_result.rrset));
}
}
void
Query::putSOA(const Zone& zone) const {
Zone::FindResult soa_result(zone.find(zone.getOrigin(),
......@@ -74,7 +116,11 @@ Query::process() const {
// TODO : fill in authority and addtional sections.
break;
case Zone::DELEGATION:
// TODO : add NS to authority section, fill in additional section.
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
response_.setRcode(Rcode::NOERROR());
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(db_result.rrset));
getAdditional(*result.zone, *db_result.rrset);
break;
case Zone::NXDOMAIN:
// Just empty answer with SOA in authority section
......
......@@ -15,17 +15,18 @@
*/
#include <exceptions/exceptions.h>
#include <datasrc/zone.h>
namespace isc {
namespace dns {
class Message;
class Name;
class RRType;
class RRset;
}
namespace datasrc {
class MemoryDataSrc;
class Zone;
}
namespace auth {
......@@ -63,6 +64,48 @@ namespace auth {
/// accidentally, and since it's considered a temporary development state,
/// we keep this name at the moment.
class Query {
private:
/// \short Adds a SOA.
///
/// Adds a SOA of the zone into the authority zone of response_.
/// Can throw NoSOA.
///
void putSOA(const isc::datasrc::Zone& zone) const;
/// Look up additional data (i.e., address records for the names included
/// in NS or MX records).
///
/// This method may throw a exception because its underlying methods may
/// throw exceptions.
///
/// \param zone The Zone wherein the additional data to the query is bo be
/// found.
/// \param rrset The RRset (i.e., NS or MX rrset) which require additional
/// processing.
void getAdditional(const isc::datasrc::Zone& zone,
const isc::dns::RRset& rrset) const;
/// Find address records for a specified name.
///
/// Search the specified zone for AAAA/A RRs of each of the NS/MX RDATA
/// (domain name), and insert the found ones into the additional section
/// if address records are available. By default the search will stop
/// once it encounters a zone cut.
///
/// Note: we need to perform the search in the "GLUE OK" mode for NS RDATA,
/// which means that we should include A/AAAA RRs under a zone cut.
/// The glue records must exactly match the name in the NS RDATA, without
/// CNAME or wildcard processing.
///
/// \param zone The Zone wherein the address records is to be found.
/// \param qname The name in rrset RDATA.
/// \param options The search options.
void findAddrs(const isc::datasrc::Zone& zone,
const isc::dns::Name& qname,
const isc::datasrc::Zone::FindOptions options
= isc::datasrc::Zone::FIND_DEFAULT) const;
public:
/// Constructor from query parameters.
///
......@@ -135,14 +178,6 @@ private:
const isc::dns::Name& qname_;
const isc::dns::RRType& qtype_;
isc::dns::Message& response_;
/**
* \short Adds a SOA.
*
* Adds a SOA of the zone into the authority zone of response_.
* Can throw NoSOA.
*/
void putSOA(const isc::datasrc::Zone& zone) const;
};
}
......
......@@ -17,6 +17,7 @@
#include <dns/rcode.h>
#include <dns/rrttl.h>
#include <dns/rrtype.h>
#include <dns/rdataclass.h>
#include <datasrc/memory_datasrc.h>
......@@ -36,19 +37,48 @@ RRsetPtr a_rrset = RRsetPtr(new RRset(Name("www.example.com"),
RRsetPtr soa_rrset = RRsetPtr(new RRset(Name("example.com"),
RRClass::IN(), RRType::SOA(),
RRTTL(3600)));
RRsetPtr ns_rrset(RRsetPtr(new RRset(Name("ns.example.com"),
RRClass::IN(), RRType::NS(),
RRTTL(3600))));
RRsetPtr glue_a_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
RRClass::IN(), RRType::A(),
RRTTL(3600))));
RRsetPtr glue_aaaa_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
RRClass::IN(), RRType::AAAA(),
RRTTL(3600))));
RRsetPtr noglue_a_rrset(RRsetPtr(new RRset(Name("noglue.example.com"),
RRClass::IN(), RRType::A(),
RRTTL(3600))));
// 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
// otherwise return DNAME
class MockZone : public Zone {
public:
MockZone(bool has_SOA = true) :
origin_(Name("example.com")),
has_SOA_(has_SOA)
{}
has_SOA_(has_SOA),
delegation_rrset(RRsetPtr(new RRset(Name("delegation.example.com"),
RRClass::IN(), RRType::NS(),
RRTTL(3600)))),
cname_rrset(RRsetPtr(new RRset(Name("cname.example.com"),
RRClass::IN(), RRType::CNAME(),
RRTTL(3600))))
{
delegation_rrset->addRdata(rdata::generic::NS(
Name("glue.ns.example.com")));
delegation_rrset->addRdata(rdata::generic::NS(
Name("noglue.example.com")));
delegation_rrset->addRdata(rdata::generic::NS(
Name("cname.example.com")));
delegation_rrset->addRdata(rdata::generic::NS(
Name("example.org")));
cname_rrset->addRdata(rdata::generic::CNAME(
Name("www.example.com")));
}
virtual const isc::dns::Name& getOrigin() const;
virtual const isc::dns::RRClass& getClass() const;
......@@ -59,6 +89,8 @@ public:
private:
Name origin_;
bool has_SOA_;
RRsetPtr delegation_rrset;
RRsetPtr cname_rrset;
};
const Name&
......@@ -72,22 +104,34 @@ MockZone::getClass() const {
}
Zone::FindResult
MockZone::find(const Name& name, const RRType& type, const FindOptions) const {
MockZone::find(const Name& name, const RRType& type,
const FindOptions options) const
{
// hardcode the find results
if (name == Name("www.example.com")) {
return (FindResult(SUCCESS, a_rrset));
} else if (name == Name("glue.ns.example.com") && type == RRType::A() &&
options == FIND_GLUE_OK) {
return (FindResult(SUCCESS, glue_a_rrset));
} else if (name == Name("noglue.example.com") && type == RRType::A()) {
return (FindResult(SUCCESS, noglue_a_rrset));
} else if (name == Name("glue.ns.example.com") && type == RRType::AAAA() &&
options == FIND_GLUE_OK) {
return (FindResult(SUCCESS, glue_aaaa_rrset));
} else if (name == Name("example.com") && type == RRType::SOA() &&
has_SOA_)
{
return (FindResult(SUCCESS, soa_rrset));
} else if (name == Name("delegation.example.com")) {
return (FindResult(DELEGATION, RRsetPtr()));
return (FindResult(DELEGATION, delegation_rrset));
} else if (name == Name("ns.example.com")) {
return (FindResult(DELEGATION, ns_rrset));
} 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 if ((name == Name("cname.example.com"))) {
return (FindResult(CNAME, cname_rrset));
} else {
return (FindResult(DNAME, RRsetPtr()));
}
......@@ -121,11 +165,41 @@ TEST_F(QueryTest, matchZone) {
// add a matching zone.
memory_datasrc.addZone(ZonePtr(new MockZone()));
query.process();
EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
Name("www.example.com"), RRClass::IN(),
RRType::A()));
// Delegation
const Name delegation_name(Name("delegation.example.com"));
Query delegation_query(memory_datasrc, delegation_name, qtype, response);
delegation_query.process();
EXPECT_FALSE(response.getHeaderFlag(Message::HEADERFLAG_AA));
EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
Name("delegation.example.com"),
RRClass::IN(), RRType::NS()));
// glue address records
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("glue.ns.example.com"),
RRClass::IN(), RRType::A()));
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("glue.ns.example.com"),
RRClass::IN(), RRType::AAAA()));
// noglue address records
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("noglue.example.com"),
RRClass::IN(), RRType::A()));
// NS name has a CNAME
EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("www.example.com"),
RRClass::IN(), RRType::A()));
// NS name is out of zone
EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("example.org"),
RRClass::IN(), RRType::A()));
// NXDOMAIN
const Name nxdomain_name(Name("nxdomain.example.com"));
Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
......
......@@ -81,7 +81,7 @@ class HotCacheImpl;
/// from the tail of the list. This operation is not locked. BIND 10
/// does not currently use threads, but if it ever does (or if libdatasrc
/// is ever used by a threaded application), this will need to be
//revisited.
/// revisited.
class HotCache {
private:
/// \name Static definitions
......@@ -164,7 +164,7 @@ public:
///
/// Retrieves a record from the cache matching the given
/// query-tuple. Returns true if one is found. If it is a
/// posiitve cache entry, then 'rrset' is set to the cached
/// positive cache entry, then 'rrset' is set to the cached
/// RRset. For both positive and negative cache entries, 'flags'
/// is set to the query response flags. The cache entry is
/// then promoted to the head of the LRU queue. (NOTE: Because
......
......@@ -103,14 +103,14 @@ getAdditional(Query& q, ConstRRsetPtr rrset) {
new QueryTask(q, ns.getNSName(),
Message::SECTION_ADDITIONAL,
QueryTask::GLUE_QUERY,
QueryTask::GETADDITIONAL)));
QueryTask::GETADDITIONAL)));
} else if (rrset->getType() == RRType::MX()) {
const generic::MX& mx = dynamic_cast<const generic::MX&>(rd);
q.tasks().push(QueryTaskPtr(
new QueryTask(q, mx.getMXName(),
Message::SECTION_ADDITIONAL,
QueryTask::NOGLUE_QUERY,
QueryTask::GETADDITIONAL)));
QueryTask::GETADDITIONAL)));
}
}
}
......
......@@ -672,7 +672,7 @@ void
RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
using namespace helper;
const isc::dns::Name sub_name = node.name_ - base_name;
// using auto_ptr here is to avoid memory leak in case of exceptoin raised
// using auto_ptr here is to avoid memory leak in case of exception raised
// after the RBNode creation
std::auto_ptr<RBNode<T> > down_node(new RBNode<T>(sub_name));
std::swap(node.data_, down_node->data_);
......@@ -680,7 +680,7 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
down_node->down_ = node.down_;
node.name_ = base_name;
node.down_ = down_node.get();
//root node of sub tree, the initial color is BLACK
// root node of sub tree, the initial color is BLACK
down_node->color_ = RBNode<T>::BLACK;
++node_count_;
down_node.release();
......
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