typedef RBTree<Domain> DomainTree;
typedef RBNode<Domain> 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
void
insertRRsets(const AdditionalNodeInfo& additional,
const vector<RRType>* requested_types,
- vector<ConstRRsetPtr>* result)
+ vector<ConstRRsetPtr>* 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));
}
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:
assert(false);
}
+bool
+checkZoneCut(const DomainNode& node, pair<bool, bool>* 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<Domain> node_path;
DomainNode* node = NULL;
- DomainTree::Result result =
- zone_data->domains_.find<void*>(
+ // 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<bool, bool> 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);
}
}