From: JINMEI Tatuya Date: Sat, 10 Mar 2012 00:17:54 +0000 (-0800) Subject: [1608] handled additional records under a zone cut correctly. X-Git-Tag: trac2351_base~226^2~116^2~127^2~3^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8efd8d022529b4d5178329bee08a6909d5823c04;p=thirdparty%2Fkea.git [1608] handled additional records under a zone cut correctly. For this change added a new application-specific flag for RBtree nodes. Now all tests pass again. --- diff --git a/src/lib/datasrc/memory_datasrc.cc b/src/lib/datasrc/memory_datasrc.cc index efbd754762..1b335b2ed5 100644 --- a/src/lib/datasrc/memory_datasrc.cc +++ b/src/lib/datasrc/memory_datasrc.cc @@ -74,6 +74,14 @@ typedef boost::shared_ptr DomainPtr; typedef RBTree DomainTree; typedef RBNode DomainNode; +// This flag is used for additional record shortcut. If a node has this +// flag, it's under a zone cut for a delegation to a child zone. +// Note: for a statically built zone this information is stable, but if we +// change the implementation to be dynamically modifiable, it may not be +// realistic to keep this flag update for all affected nodes, and we may +// have to reconsider the mechanism. +const DomainNode::Flags DOMAINFLAG_GLUE = DomainNode::FLAG_USER2; + // Separate storage for NSEC3 RRs (and their RRSIGs). It's an STL map // from string to the NSEC3 RRset. The map key is the first label // (upper cased) of the owner name of the corresponding NSEC3 (i.e., map @@ -298,8 +306,12 @@ insertRRset(const RRType& type, const AdditionalNodeInfo* additional, void insertRRsets(const AdditionalNodeInfo& additional, const vector* requested_types, - vector* result) + vector* result, bool glue_ok) { + assert(additional.node_ != NULL); + if (!glue_ok && additional.node_->getFlag(DOMAINFLAG_GLUE)) { + return; + } for_each(requested_types->begin(), requested_types->end(), boost::bind(insertRRset, _1, &additional, result)); } @@ -336,7 +348,8 @@ protected: return; } for_each(additionals_->begin(), additionals_->end(), - boost::bind(insertRRsets, _1, &requested_types, &result)); + boost::bind(insertRRsets, _1, &requested_types, &result, + rrset->getType() == RRType::NS())); } private: @@ -1253,19 +1266,48 @@ getAdditionalName(RRType rrtype, const rdata::Rdata& rdata) { assert(false); } +bool +checkZoneCut(const DomainNode& node, pair* arg) { + // We are only interested in the highest zone cut information. + // Ignore others and continue the search. + if (arg->first) { + return (false); + } + if (node.getData()->find(RRType::NS()) != node.getData()->end()) { + arg->first = true; + arg->second = true; + return (false); + } + return (false); +} + void addAdditional(RBNodeRRset* rrset, ZoneData* zone_data) { RdataIteratorPtr rdata_iterator = rrset->getRdataIterator(); for (; !rdata_iterator->isLast(); rdata_iterator->next()) { - // TODO: zone cut consideration, empty node case + // For each domain name that requires additional section processing + // in each RDATA, search the tree for the name and remember it if + // found. If the name is under a zone cut (for a delegation to a + // child zone), mark the node as "GLUE", so we can selectively + // include/exclude them when we use it. + + // TODO: zone cut consideration (NS or DNAME), empty node case RBTreeNodeChain node_path; DomainNode* node = NULL; - DomainTree::Result result = - zone_data->domains_.find( + // The callback argument is a pair of bools: the first is a flag to + // only check the highest cut; the second one records whether the + // search goes under a zone cut. + pair callback_arg(false, false); + const DomainTree::Result result = + zone_data->domains_.find( getAdditionalName(rrset->getType(), rdata_iterator->getCurrent()), - &node, node_path, NULL, NULL); + &node, node_path, checkZoneCut, &callback_arg); if (result == DomainTree::EXACTMATCH) { + assert(node != NULL); + if (callback_arg.second) { + node->setFlag(DOMAINFLAG_GLUE); + } rrset->addAdditionalNode(node); } } diff --git a/src/lib/datasrc/rbtree.h b/src/lib/datasrc/rbtree.h index 4757a455e5..161affb8f4 100644 --- a/src/lib/datasrc/rbtree.h +++ b/src/lib/datasrc/rbtree.h @@ -123,7 +123,8 @@ public: /// set to on by the \c setFlag() method. enum Flags { FLAG_CALLBACK = 1, ///< Callback enabled. See \ref callback - FLAG_USER1 = 0x80000000U ///< Application specific flag + FLAG_USER1 = 0x80000000U, ///< Application specific flag + FLAG_USER2 = 0x40000000U ///< Application specific flag }; private: // Some flag values are expected to be used for internal purposes @@ -131,7 +132,8 @@ private: // limit the settable flags via the \c setFlag() method to those // explicitly defined in \c Flags. This constant represents all // such flags. - static const uint32_t SETTABLE_FLAGS = (FLAG_CALLBACK | FLAG_USER1); + static const uint32_t SETTABLE_FLAGS = (FLAG_CALLBACK | FLAG_USER1 | + FLAG_USER2); public: