Commit ce2e289a authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

initial implementation of #463: "glue OK" mode of Zone::find()


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac463@4097 e5f2f494-b856-4b98-b285-d166d9295462
parent 1391a2e1
......@@ -53,7 +53,8 @@ public:
virtual const isc::dns::RRClass& getClass() const;
FindResult find(const isc::dns::Name& name,
const isc::dns::RRType& type) const;
const isc::dns::RRType& type,
const FindOptions options = FIND_DEFAULT) const;
private:
Name origin_;
......@@ -71,7 +72,7 @@ MockZone::getClass() const {
}
Zone::FindResult
MockZone::find(const Name& name, const RRType& type) const {
MockZone::find(const Name& name, const RRType& type, const FindOptions) const {
// hardcode the find results
if (name == Name("www.example.com")) {
return (FindResult(SUCCESS, a_rrset));
......
......@@ -144,9 +144,12 @@ struct MemoryZone::MemoryZoneImpl {
/// It will be passed to \c zonecutCallback() and record a possible
/// zone cut node and related RRset (normally NS or DNAME).
struct FindState {
FindState() : zonecut_node(NULL) {}
const DomainNode* zonecut_node;
ConstRRsetPtr rrset;
FindState(FindOptions options) : zonecut_node_(NULL),
options_(options)
{}
const DomainNode* zonecut_node_;
ConstRRsetPtr rrset_;
const FindOptions options_;
};
// A callback called from possible zone cut nodes. This will be passed
......@@ -154,10 +157,7 @@ struct MemoryZone::MemoryZoneImpl {
static bool zonecutCallback(const DomainNode& node, FindState* state) {
// We perform callback check only for the highest zone cut in the
// rare case of nested zone cuts.
// [This check is necessary when we support the "glue OK" mode later.
// This code should better be added then with a test, but is added
// now not to forget it.]
if (state->zonecut_node != NULL) {
if (state->zonecut_node_ != NULL) {
return (false);
}
......@@ -167,9 +167,9 @@ struct MemoryZone::MemoryZoneImpl {
// be the origin because we don't enable the callback at the
// origin node (see MemoryZoneImpl::add()). Or should we do a
// double check for it?
state->zonecut_node = &node;
state->rrset = found->second;
return (true);
state->zonecut_node_ = &node;
state->rrset_ = found->second;
return ((state->options_ & FIND_GLUE_OK) != 0 ? false : true);
}
// This case should not happen because we enable callback only
......@@ -178,14 +178,16 @@ struct MemoryZone::MemoryZoneImpl {
}
// Implementation of MemoryZone::find
FindResult find(const Name& name, RRType type) const {
FindResult find(const Name& name, RRType type,
const FindOptions options) const
{
// Get the node
DomainNode* node(NULL);
FindState state;
FindState state(options);
switch (domains_.find(name, &node, zonecutCallback, &state)) {
case DomainTree::PARTIALMATCH:
if (state.zonecut_node != NULL) {
return (FindResult(DELEGATION, state.rrset));
if (state.zonecut_node_ != NULL) {
return (FindResult(DELEGATION, state.rrset_));
}
// TODO: we should also cover empty non-terminal cases, which
// will require non trivial code and is deferred for later
......@@ -247,8 +249,10 @@ MemoryZone::getClass() const {
}
Zone::FindResult
MemoryZone::find(const Name& name, const RRType& type) const {
return (impl_->find(name, type));
MemoryZone::find(const Name& name, const RRType& type,
const FindOptions options) const
{
return (impl_->find(name, type, options));
}
result::Result
......
......@@ -62,7 +62,8 @@ public:
/// It returns NULL pointer in case of NXDOMAIN and NXRRSET
/// (the base class documentation does not seem to require that).
virtual FindResult find(const isc::dns::Name& name,
const isc::dns::RRType& type) const;
const isc::dns::RRType& type,
const FindOptions options = FIND_DEFAULT) const;
/// \brief Inserts an rrset into the zone.
///
......
......@@ -143,7 +143,9 @@ public:
origin_("example.org"),
ns_name_("ns.example.org"),
child_ns_name_("child.example.org"),
child_glue_name_("ns.child.example.org"),
grandchild_ns_name_("grand.child.example.org"),
grandchild_glue_name_("ns.grand.child.example.org"),
zone_(class_, origin_),
rr_out_(new RRset(Name("example.com"), class_, RRType::A(),
RRTTL(300))),
......@@ -153,13 +155,18 @@ public:
rr_a_(new RRset(origin_, class_, RRType::A(), RRTTL(300))),
rr_child_ns_(new RRset(child_ns_name_, class_, RRType::NS(),
RRTTL(300))),
rr_child_glue_(new RRset(child_glue_name_, class_, RRType::A(),
RRTTL(300))),
rr_grandchild_ns_(new RRset(grandchild_ns_name_, class_, RRType::NS(),
RRTTL(300)))
RRTTL(300))),
rr_grandchild_glue_(new RRset(grandchild_glue_name_, class_,
RRType::AAAA(), RRTTL(300)))
{
}
// Some data to test with
const RRClass class_;
const Name origin_, ns_name_, child_ns_name_, grandchild_ns_name_;
const Name origin_, ns_name_, child_ns_name_, child_glue_name_,
grandchild_ns_name_, grandchild_glue_name_;
// The zone to torture by tests
MemoryZone zone_;
......@@ -181,7 +188,9 @@ public:
// A of example.org
rr_a_;
ConstRRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
ConstRRsetPtr rr_child_glue_; // glue RR of the child domain
ConstRRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
ConstRRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
/**
* \brief Test one find query to the zone.
......@@ -200,8 +209,10 @@ public:
* uses zone_)
*/
void findTest(const Name& name, const RRType& rrtype, Zone::Result result,
bool check_answer = true,
const ConstRRsetPtr& answer = ConstRRsetPtr(), MemoryZone *zone = NULL)
bool check_answer = true,
const ConstRRsetPtr& answer = ConstRRsetPtr(),
MemoryZone *zone = NULL,
Zone::FindOptions options = Zone::FIND_DEFAULT)
{
if (!zone) {
zone = &zone_;
......@@ -209,13 +220,14 @@ public:
// The whole block is inside, because we need to check the result and
// we can't assign to FindResult
EXPECT_NO_THROW({
Zone::FindResult find_result(zone->find(name, rrtype));
// Check it returns correct answers
EXPECT_EQ(result, find_result.code);
if (check_answer) {
EXPECT_EQ(answer, find_result.rrset);
}
});
Zone::FindResult find_result(zone->find(name, rrtype,
options));
// Check it returns correct answers
EXPECT_EQ(result, find_result.code);
if (check_answer) {
EXPECT_EQ(answer, find_result.rrset);
}
});
}
};
......@@ -280,6 +292,49 @@ TEST_F(MemoryZoneTest, delegationNS) {
Zone::DELEGATION, true, rr_child_ns_); // note: !rr_grandchild_ns_
}
TEST_F(MemoryZoneTest, glue) {
// install zone data:
// a zone cut
EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_ns_)));
// glue for this cut
EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_glue_)));
// a nested zone cut (unusual)
EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_ns_)));
// glue under the deeper zone cut
EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_glue_)));
// by default glue is hidden due to the zone cut
findTest(child_glue_name_, RRType::A(), Zone::DELEGATION, true,
rr_child_ns_);
// If we do it in the "glue OK" mode, we should find the exact match.
findTest(child_glue_name_, RRType::A(), Zone::SUCCESS, true,
rr_child_glue_, NULL, Zone::FIND_GLUE_OK);
// glue OK + NXRRSET case
findTest(child_glue_name_, RRType::AAAA(), Zone::NXRRSET, true,
ConstRRsetPtr(), NULL, Zone::FIND_GLUE_OK);
// glue OK + NXDOMAIN case
findTest(Name("www.child.example.org"), RRType::A(), Zone::DELEGATION,
true, rr_child_ns_, NULL, Zone::FIND_GLUE_OK);
// TODO:
// glue name would match a wildcard under a zone cut: wildcard match
// shouldn't happen under a cut and result must be PARTIALMATCH
// (This case cannot be tested yet)
// nested cut case. The glue should be found.
findTest(grandchild_glue_name_, RRType::AAAA(), Zone::SUCCESS,
true, rr_grandchild_glue_, NULL, Zone::FIND_GLUE_OK);
// A non-existent name in nested cut. This should result in delegation
// at the highest zone cut.
findTest(Name("www.grand.child.example.org"), RRType::TXT(),
Zone::DELEGATION, true, rr_child_ns_, NULL, Zone::FIND_GLUE_OK);
}
// Test adding DNAMEs and resulting delegation handling
// Listing ideas only for now
TEST_F(MemoryZoneTest, delegationDNAME) {
......
......@@ -100,6 +100,16 @@ public:
const isc::dns::ConstRRsetPtr rrset;
};
/// Find options.
///
/// The option values are used as a parameter for \c find().
/// These are values of a bitmask type. Bitwise operations can be
/// performed on these values to express compound options.
enum FindOptions {
FIND_DEFAULT = 0, ///< The default options
FIND_GLUE_OK = 1 ///< Allow search under a zone cut
};
///
/// \name Constructors and Destructor.
///
......@@ -150,6 +160,17 @@ public:
/// - If the search name matches a delegation point of DNAME, it returns
/// the code of \c DNAME and that DNAME RR.
///
/// The \c options parameter specifies customized behavior of the search.
/// Their semantics is as follows:
/// - \c GLUE_OK Allow search under a zone cut. By default the search
/// will stop once it encounters a zone cut. If this option is specified
/// it remembers information about the highest zone cut and continues
/// the search until it finds an exact match for the given name or it
/// detects there is no exact match. If an exact match is found,
/// RRsets for that name are searched just like the normal case;
/// otherwise, if the search has encountered a zone cut, \c DELEGATION
/// with the information of the highest zone cut will be returned.
///
/// A derived version of this method may involve internal resource
/// allocation, especially for constructing the resulting RRset, and may
/// throw an exception if it fails.
......@@ -162,9 +183,12 @@ public:
///
/// \param name The domain name to be searched for.
/// \param type The RR type to be searched for.
/// \param options The search options.
/// \return A \c FindResult object enclosing the search result (see above).
virtual FindResult find(const isc::dns::Name& name,
const isc::dns::RRType& type) const = 0;
const isc::dns::RRType& type,
const FindOptions options
= FIND_DEFAULT) const = 0;
//@}
};
......@@ -177,4 +201,8 @@ typedef boost::shared_ptr<const Zone> ConstZonePtr;
}
}
#endif
#endif // __ZONE_H
// Local Variables:
// mode: c++
// End:
......@@ -25,7 +25,7 @@ namespace isc {
namespace dns {
class Name;
class RRClass;
};
}
namespace datasrc {
......
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