BIND 10 trac2108_3, updated. d074626ee7d65dee4011443bbf0be2b16bb44411 [2108] Save RRsets and call RdataSet::create() with their corresponding RRSIGs
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Sep 5 05:32:14 UTC 2012
The branch, trac2108_3 has been updated
via d074626ee7d65dee4011443bbf0be2b16bb44411 (commit)
from 372c18dac614fd8cfbe0e55bcf3aaf1aa6749ef4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d074626ee7d65dee4011443bbf0be2b16bb44411
Author: Mukund Sivaraman <muks at isc.org>
Date: Wed Sep 5 11:02:02 2012 +0530
[2108] Save RRsets and call RdataSet::create() with their corresponding RRSIGs
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/memory/memory_client.cc | 308 ++++++++++++++++---------------
1 file changed, 158 insertions(+), 150 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory/memory_client.cc b/src/lib/datasrc/memory/memory_client.cc
index ea4eba3..7aab10c 100644
--- a/src/lib/datasrc/memory/memory_client.cc
+++ b/src/lib/datasrc/memory/memory_client.cc
@@ -111,6 +111,7 @@ public:
unsigned int zone_count_;
ZoneTable* zone_table_;
FileNameTree* file_name_tree_;
+ ConstRRsetPtr last_rrset_;
// Common process for zone load.
// rrset_installer is a functor that takes another functor as an argument,
@@ -292,87 +293,9 @@ public:
}
}
- result::Result addRRsig(const ConstRRsetPtr sig_rrset, ZoneData& zone_data)
- {
- // Check consistency of the type covered.
- // We know the RRset isn't empty, so the following check is safe.
- RdataIteratorPtr rit = sig_rrset->getRdataIterator();
- const RRType covered = dynamic_cast<const generic::RRSIG&>(
- rit->getCurrent()).typeCovered();
- for (rit->next(); !rit->isLast(); rit->next()) {
- if (dynamic_cast<const generic::RRSIG&>(
- rit->getCurrent()).typeCovered() != covered) {
- isc_throw(AddError, "RRSIG contains mixed covered types: "
- << sig_rrset->toText());
- }
- }
-
- // Find the RRset to be covered; if not found, treat it as an error
- // for now.
- ConstRRsetPtr covered_rrset;
- if (covered != RRType::NSEC3()) {
- DomainNode* node = NULL;
- if (zone_data.domains_.find(sig_rrset->getName(), &node) !=
- DomainTree::EXACTMATCH || node == NULL || !node->getData()) {
- isc_throw(AddError,
- "RRSIG is being added, but no RR to be covered: "
- << sig_rrset->getName());
- }
- const Domain::const_iterator it = node->getData()->find(covered);
- if (it != node->getData()->end()) {
- covered_rrset = it->second;
- }
- } else {
- // In case of NSEC3 if something is found it must be NSEC3 RRset
- // under the assumption of our current implementation.
- if (zone_data.nsec3_data_) {
- // Convert the first label to upper-cased text. Note that
- // for a valid NSEC3 RR the label should only consist of
- // positive 8-bit char values, so using toupper(int) should be
- // safe (if it's a bogus label for NSEC3 the zone won't work
- // anyway). Also note the '::' below: g++'s STL implementation
- // seems to require it to toupper to make this compile.
- string fst_label =
- sig_rrset->getName().split(0, 1).toText(true);
- transform(fst_label.begin(), fst_label.end(),
- fst_label.begin(), ::toupper);
-
- NSEC3Map::const_iterator found =
- zone_data.nsec3_data_->map_.find(fst_label);
- if (found != zone_data.nsec3_data_->map_.end()) {
- covered_rrset = found->second;
- assert(covered_rrset->getType() == covered);
- }
- }
- }
- if (!covered_rrset) {
- isc_throw(AddError, "RRSIG is being added, but no RR of "
- "covered type found: " << sig_rrset->toText());
- }
-
- // The current implementation doesn't allow an existing RRSIG to be
- // overridden (or updated with additional ones).
- if (covered_rrset->getRRsig()) {
- isc_throw(AddError,
- "RRSIG is being added to override an existing one: "
- << sig_rrset->toText());
- }
-
- // All okay, setting the RRSIG.
- // XXX: we break const-ness of the covered RRsets. In practice the
- // ownership of these RRsets would have been given to us so it should
- // be safe, but it's still a very bad practice.
- // We'll fix this problem anyway when we update the underlying
- // representation so that it's more space efficient.
- // Note: there's a slight chance of getting an exception.
- // As noted in add(), we give up strong exception guarantee in such
- // cases.
- boost::const_pointer_cast<AbstractRRset>(covered_rrset)->addRRsig(sig_rrset);
-
- return (result::SUCCESS);
- }
-
- result::Result addNSEC3(const ConstRRsetPtr rrset, ZoneData& zone_data) {
+ void addNSEC3(const ConstRRsetPtr rrset,
+ const ConstRRsetPtr rrsig,
+ ZoneData& zone_data) {
// We know rrset has exactly one RDATA
const generic::NSEC3& nsec3_rdata =
dynamic_cast<const generic::NSEC3&>(
@@ -405,13 +328,155 @@ public:
nsec3_data->insertName(local_mem_sgmt_, Name(fst_label), &node);
RdataEncoder encoder;
+
+ // We assume that rrsig has already been checked to match rrset
+ // by the caller.
RdataSet *set = RdataSet::create(local_mem_sgmt_, encoder,
- rrset, ConstRRsetPtr());
+ rrset, rrsig);
RdataSet *old_set = node->setData(set);
if (old_set != NULL) {
RdataSet::destroy(local_mem_sgmt_, rrclass_, old_set);
}
+ }
+
+ void addRdataSet(const Name& zone_name, ZoneData& zone_data,
+ const ConstRRsetPtr rrset, const ConstRRsetPtr rrsig) {
+ // Only one of these can be passed at a time.
+ assert(!(rrset && rrsig));
+
+ // If rrsig is passed, validate it against the last-saved rrset.
+ if (rrsig) {
+ // The covered RRset should have been saved by now.
+ if (!last_rrset_) {
+ isc_throw(AddError,
+ "RRSIG is being added, "
+ "but doesn't follow its covered RR: "
+ << rrsig->getName());
+ }
+
+ if (rrsig->getName() != last_rrset_->getName()) {
+ isc_throw(AddError,
+ "RRSIG is being added, "
+ "but doesn't match the last RR's name: "
+ << last_rrset_->getName() << " vs. "
+ << rrsig->getName());
+ }
+
+ // Consistency of other types in rrsig are checked in addRRsig().
+ RdataIteratorPtr rit = rrsig->getRdataIterator();
+ const RRType covered = dynamic_cast<const generic::RRSIG&>(
+ rit->getCurrent()).typeCovered();
+
+ if (covered != last_rrset_->getType()) {
+ isc_throw(AddError,
+ "RRSIG is being added, "
+ "but doesn't match the last RR's type: "
+ << last_rrset_->getType() << " vs. "
+ << rrsig->getType());
+ }
+ }
+ if (!last_rrset_) {
+ last_rrset_ = rrset;
+ return;
+ }
+
+ if (last_rrset_->getType() == RRType::NSEC3()) {
+ addNSEC3(last_rrset_, rrsig, zone_data);
+ } else {
+ ZoneNode* node;
+ zone_data.insertName(local_mem_sgmt_, last_rrset_->getName(), &node);
+
+ RdataSet* set = node->getData();
+
+ // Checks related to the surrounding data.
+ // Note: when the check fails and the exception is thrown,
+ // it may break strong exception guarantee. At the moment
+ // we prefer code simplicity and don't bother to introduce
+ // complicated recovery code.
+ contextCheck(zone_name, *last_rrset_, set);
+
+ if (RdataSet::find(set, last_rrset_->getType()) != NULL) {
+ isc_throw(AddError,
+ "RRset of the type already exists: "
+ << last_rrset_->getName() << " (type: "
+ << last_rrset_->getType() << ")");
+ }
+
+ RdataEncoder encoder;
+ RdataSet *new_set = RdataSet::create(local_mem_sgmt_, encoder,
+ last_rrset_, rrsig);
+ new_set->next = set;
+ node->setData(new_set);
+
+ // Ok, we just put it in
+
+ // If this RRset creates a zone cut at this node, mark the
+ // node indicating the need for callback in find().
+ if (last_rrset_->getType() == RRType::NS() &&
+ last_rrset_->getName() != zone_name) {
+ node->setFlag(ZoneNode::FLAG_CALLBACK);
+ // If it is DNAME, we have a callback as well here
+ } else if (last_rrset_->getType() == RRType::DNAME()) {
+ node->setFlag(ZoneNode::FLAG_CALLBACK);
+ }
+
+ // If we've added NSEC3PARAM at zone origin, set up NSEC3
+ // specific data or check consistency with already set up
+ // parameters.
+ if (last_rrset_->getType() == RRType::NSEC3PARAM() &&
+ last_rrset_->getName() == zone_name) {
+ // We know rrset has exactly one RDATA
+ const generic::NSEC3PARAM& param =
+ dynamic_cast<const generic::NSEC3PARAM&>
+ (last_rrset_->getRdataIterator()->getCurrent());
+
+ NSEC3Data* nsec3_data = zone_data.getNSEC3Data();
+ if (nsec3_data == NULL) {
+ nsec3_data = NSEC3Data::create(local_mem_sgmt_, param);
+ zone_data.setNSEC3Data(nsec3_data);
+ } else {
+ size_t salt_len = nsec3_data->getSaltLen();
+ const uint8_t* salt_data = nsec3_data->getSaltData();
+ const vector<uint8_t>& salt_data_2 = param.getSalt();
+
+ if ((param.getHashalg() != nsec3_data->hashalg) ||
+ (param.getIterations() != nsec3_data->iterations) ||
+ (salt_data_2.size() != salt_len) ||
+ (std::memcmp(&salt_data_2[0],
+ salt_data, salt_len) != 0)) {
+ isc_throw(AddError,
+ "NSEC3PARAM with inconsistent parameters: "
+ << last_rrset_->toText());
+ }
+ }
+ } else if (last_rrset_->getType() == RRType::NSEC()) {
+ // If it is NSEC signed zone, so we put a flag there
+ // (flag is enough)
+ zone_data.setSigned(true);
+ }
+ }
+
+ last_rrset_ = rrset;
+ }
+
+ result::Result addRRsig(const ConstRRsetPtr sig_rrset,
+ const Name& zone_name, ZoneData& zone_data)
+ {
+ // Check consistency of the type covered.
+ // We know the RRset isn't empty, so the following check is safe.
+ RdataIteratorPtr rit = sig_rrset->getRdataIterator();
+ const RRType covered = dynamic_cast<const generic::RRSIG&>(
+ rit->getCurrent()).typeCovered();
+ for (rit->next(); !rit->isLast(); rit->next()) {
+ if (dynamic_cast<const generic::RRSIG&>(
+ rit->getCurrent()).typeCovered() != covered) {
+ isc_throw(AddError, "RRSIG contains mixed covered types: "
+ << sig_rrset->toText());
+ }
+ }
+
+ addRdataSet(zone_name, zone_data, ConstRRsetPtr(), sig_rrset);
return (result::SUCCESS);
}
@@ -433,13 +498,14 @@ public:
arg(rrset->getName()).arg(rrset->getType()).arg(zone_name);
if (rrset->getType() == RRType::NSEC3()) {
- return (addNSEC3(rrset, zone_data));
+ addRdataSet(zone_name, zone_data, rrset, ConstRRsetPtr());
+ return (result::SUCCESS);
}
// RRSIGs are special in various points, so we handle it in a
// separate dedicated method.
if (rrset->getType() == RRType::RRSIG()) {
- return (addRRsig(rrset, zone_data));
+ return (addRRsig(rrset, zone_name, zone_data));
}
// Add wildcards possibly contained in the owner name to the domain
@@ -448,72 +514,7 @@ public:
// guarantee. (see also the note for contextCheck() below).
addWildcards(zone_name, zone_data, rrset->getName());
- ZoneNode* node;
- zone_data.insertName(local_mem_sgmt_, rrset->getName(), &node);
-
- RdataSet* set = node->getData();
-
- // Checks related to the surrounding data.
- // Note: when the check fails and the exception is thrown, it may
- // break strong exception guarantee. At the moment we prefer
- // code simplicity and don't bother to introduce complicated
- // recovery code.
- contextCheck(zone_name, *rrset, set);
-
- if (RdataSet::find(set, rrset->getType()) != NULL) {
- return (result::EXIST);
- }
-
- RdataEncoder encoder;
- RdataSet *new_set = RdataSet::create(local_mem_sgmt_, encoder,
- rrset, ConstRRsetPtr());
- new_set->next = set;
- node->setData(new_set);
-
- // Ok, we just put it in
-
- // If this RRset creates a zone cut at this node, mark the node
- // indicating the need for callback in find().
- if (rrset->getType() == RRType::NS() &&
- rrset->getName() != zone_name) {
- node->setFlag(ZoneNode::FLAG_CALLBACK);
- // If it is DNAME, we have a callback as well here
- } else if (rrset->getType() == RRType::DNAME()) {
- node->setFlag(ZoneNode::FLAG_CALLBACK);
- }
-
- // If we've added NSEC3PARAM at zone origin, set up NSEC3 specific
- // data or check consistency with already set up parameters.
- if (rrset->getType() == RRType::NSEC3PARAM() &&
- rrset->getName() == zone_name) {
- // We know rrset has exactly one RDATA
- const generic::NSEC3PARAM& param =
- dynamic_cast<const generic::NSEC3PARAM&>
- (rrset->getRdataIterator()->getCurrent());
-
- NSEC3Data* nsec3_data = zone_data.getNSEC3Data();
- if (nsec3_data == NULL) {
- nsec3_data = NSEC3Data::create(local_mem_sgmt_, param);
- zone_data.setNSEC3Data(nsec3_data);
- } else {
- size_t salt_len = nsec3_data->getSaltLen();
- const uint8_t* salt_data = nsec3_data->getSaltData();
- const vector<uint8_t>& salt_data_2 = param.getSalt();
-
- if ((param.getHashalg() != nsec3_data->hashalg) ||
- (param.getIterations() != nsec3_data->iterations) ||
- (salt_data_2.size() != salt_len) ||
- (std::memcmp(&salt_data_2[0], salt_data, salt_len) != 0)) {
- isc_throw(AddError,
- "NSEC3PARAM with inconsistent parameters: " <<
- rrset->toText());
- }
- }
- } else if (rrset->getType() == RRType::NSEC()) {
- // If it is NSEC signed zone, so we put a flag there (flag
- // is enough)
- zone_data.setSigned(true);
- }
+ addRdataSet(zone_name, zone_data, rrset, ConstRRsetPtr());
return (result::SUCCESS);
}
@@ -549,9 +550,16 @@ InMemoryClient::InMemoryClientImpl::load(
local_mem_sgmt_, ZoneData::create(local_mem_sgmt_, zone_name), rrclass_);
scoped_ptr<ZoneData> tmp(holder.get());
+ assert(!last_rrset_);
+
rrset_installer(boost::bind(&InMemoryClientImpl::addFromLoad, this,
_1, zone_name, tmp.get()));
+ // Add any last RRset that was left
+ addRdataSet(zone_name, *tmp.get(), ConstRRsetPtr(), ConstRRsetPtr());
+
+ assert(!last_rrset_);
+
// If the zone is NSEC3-signed, check if it has NSEC3PARAM
if (tmp->isNSEC3Signed()) {
// Note: origin_data_ is set on creation of ZoneData, and the load
More information about the bind10-changes
mailing list