|
@@ -12,12 +12,16 @@
|
|
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
+#include <exceptions/exceptions.h>
|
|
|
+
|
|
|
#include <datasrc/memory/zone_data_updater.h>
|
|
|
#include <datasrc/memory/logger.h>
|
|
|
#include <datasrc/zone.h>
|
|
|
|
|
|
#include <dns/rdataclass.h>
|
|
|
|
|
|
+#include <cassert>
|
|
|
+
|
|
|
using namespace isc::dns;
|
|
|
using namespace isc::dns::rdata;
|
|
|
|
|
@@ -99,9 +103,7 @@ ZoneDataUpdater::contextCheck(const AbstractRRset& rrset,
|
|
|
|
|
|
void
|
|
|
ZoneDataUpdater::validate(const isc::dns::ConstRRsetPtr rrset) const {
|
|
|
- if (!rrset) {
|
|
|
- isc_throw(NullRRset, "The rrset provided is NULL");
|
|
|
- }
|
|
|
+ assert(rrset);
|
|
|
|
|
|
if (rrset->getRdataCount() == 0) {
|
|
|
isc_throw(AddError,
|
|
@@ -258,14 +260,15 @@ ZoneDataUpdater::addNSEC3(const ConstRRsetPtr rrset, const ConstRRsetPtr rrsig)
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-ZoneDataUpdater::addRdataSet(const ConstRRsetPtr rrset,
|
|
|
+ZoneDataUpdater::addRdataSet(const Name& name, const RRType& rrtype,
|
|
|
+ const ConstRRsetPtr rrset,
|
|
|
const ConstRRsetPtr rrsig)
|
|
|
{
|
|
|
- if (rrset->getType() == RRType::NSEC3()) {
|
|
|
- addNSEC3(rrset, rrsig);
|
|
|
+ if (rrtype == RRType::NSEC3()) {
|
|
|
+ addNSEC3(rrset, rrsig); // TBD: check RRSIG only case
|
|
|
} else {
|
|
|
ZoneNode* node;
|
|
|
- zone_data_.insertName(mem_sgmt_, rrset->getName(), &node);
|
|
|
+ zone_data_.insertName(mem_sgmt_, name, &node);
|
|
|
|
|
|
RdataSet* rdataset_head = node->getData();
|
|
|
|
|
@@ -273,13 +276,14 @@ ZoneDataUpdater::addRdataSet(const ConstRRsetPtr rrset,
|
|
|
// 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(*rrset, rdataset_head);
|
|
|
+ if (rrset) { // this check is only for covered RRset, not RRSIG
|
|
|
+ contextCheck(*rrset, rdataset_head);
|
|
|
+ }
|
|
|
|
|
|
- if (RdataSet::find(rdataset_head, rrset->getType()) != NULL) {
|
|
|
+ if (RdataSet::find(rdataset_head, rrtype) != NULL) {
|
|
|
isc_throw(AddError,
|
|
|
"RRset of the type already exists: "
|
|
|
- << rrset->getName() << " (type: "
|
|
|
- << rrset->getType() << ")");
|
|
|
+ << name << " (type: " << rrtype << ")");
|
|
|
}
|
|
|
|
|
|
RdataSet* rdataset_new = RdataSet::create(mem_sgmt_, encoder_,
|
|
@@ -290,22 +294,21 @@ ZoneDataUpdater::addRdataSet(const ConstRRsetPtr rrset,
|
|
|
// 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_) {
|
|
|
+ // indicating the need for callback in find(). Note that we do this
|
|
|
+ // only when non RRSIG RRset of that type is added.
|
|
|
+ if (rrset && rrtype == RRType::NS() && name != zone_name_) {
|
|
|
node->setFlag(ZoneNode::FLAG_CALLBACK);
|
|
|
// If it is DNAME, we have a callback as well here
|
|
|
- } else if (rrset->getType() == RRType::DNAME()) {
|
|
|
+ } else if (rrset && rrtype == 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_) {
|
|
|
+ if (rrset && rrtype == RRType::NSEC3PARAM() && name == zone_name_) {
|
|
|
setupNSEC3<generic::NSEC3PARAM>(rrset);
|
|
|
- } else if (rrset->getType() == RRType::NSEC()) {
|
|
|
+ } else if (rrset && rrtype == RRType::NSEC()) {
|
|
|
// If it is NSEC signed zone, we mark the zone as signed
|
|
|
// (conceptually "signed" is a broader notion but our
|
|
|
// current zone finder implementation regards "signed" as
|
|
@@ -315,31 +318,57 @@ ZoneDataUpdater::addRdataSet(const ConstRRsetPtr rrset,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+namespace {
|
|
|
+RRType
|
|
|
+getCoveredType(const ConstRRsetPtr& sig_rrset) {
|
|
|
+ RdataIteratorPtr it = sig_rrset->getRdataIterator();
|
|
|
+ // Empty RRSIG shouldn't be passed either via a master file or
|
|
|
+ // another data source iterator, but it could still happen if the
|
|
|
+ // iterator has a bug. We catch and reject such cases.
|
|
|
+ if (it->isLast()) {
|
|
|
+ isc_throw(isc::Unexpected,
|
|
|
+ "Empty RRset is passed in-memory loader, name: "
|
|
|
+ << sig_rrset->getName());
|
|
|
+ }
|
|
|
+ return (dynamic_cast<const generic::RRSIG&>(it->getCurrent()).
|
|
|
+ typeCovered());
|
|
|
+}
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
ZoneDataUpdater::add(const ConstRRsetPtr& rrset,
|
|
|
const ConstRRsetPtr& sig_rrset)
|
|
|
{
|
|
|
- // Validate input. This will cause an exception to be thrown if the
|
|
|
- // input RRset is empty.
|
|
|
- validate(rrset);
|
|
|
+ // Validate input.
|
|
|
+ if (!rrset && !sig_rrset) {
|
|
|
+ isc_throw(NullRRset,
|
|
|
+ "ZoneDataUpdater::add is given 2 NULL pointers");
|
|
|
+ }
|
|
|
+ if (rrset) {
|
|
|
+ validate(rrset);
|
|
|
+ }
|
|
|
if (sig_rrset) {
|
|
|
validate(sig_rrset);
|
|
|
}
|
|
|
|
|
|
+ const Name& name = rrset ? rrset->getName() : sig_rrset->getName();
|
|
|
+ const RRType& rrtype = rrset ? rrset->getType() :
|
|
|
+ getCoveredType(sig_rrset);
|
|
|
+
|
|
|
// OK, can add the RRset.
|
|
|
LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_MEM_ADD_RRSET).
|
|
|
- arg(rrset->getName()).arg(rrset->getType()).arg(zone_name_);
|
|
|
+ arg(name).arg(rrtype).arg(zone_name_);
|
|
|
|
|
|
// Add wildcards possibly contained in the owner name to the domain
|
|
|
// tree. This can only happen for the normal (non-NSEC3) tree.
|
|
|
// Note: this can throw an exception, breaking strong exception
|
|
|
// guarantee. (see also the note for the call to contextCheck()
|
|
|
// above).
|
|
|
- if (rrset->getType() != RRType::NSEC3()) {
|
|
|
- addWildcards(rrset->getName());
|
|
|
+ if (rrtype != RRType::NSEC3()) {
|
|
|
+ addWildcards(name);
|
|
|
}
|
|
|
|
|
|
- addRdataSet(rrset, sig_rrset);
|
|
|
+ addRdataSet(name, rrtype, rrset, sig_rrset);
|
|
|
}
|
|
|
|
|
|
} // namespace memory
|