BIND 10 master, updated. 57f3e532a4cb9ef57484b638cfb53296dc403e95 [master] Merge branch 'trac2310'
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Jan 29 21:53:14 UTC 2013
The branch, master has been updated
via 57f3e532a4cb9ef57484b638cfb53296dc403e95 (commit)
via 31707f9fd9a78add4895394d0168d5664184b18f (commit)
via 2ca96761f12b10e51faa6e394617baffbb68afdd (commit)
via b122fa56ec0caf72e351f973c9ef337b2b3122c1 (commit)
via ed2adc060ea123c5a6fec274950fdc68cde48059 (commit)
via 4760fba1fcc4d0fdb762b69cd6090002b9190be1 (commit)
via 5e9d101a16146d2bb60f128cba65083b72e04086 (commit)
via ad274a49ad5f36231b8997240272c89b4edf0c2f (commit)
via 6ff25a392e3d15ae5a9aa1ca11a4badeb95bf39d (commit)
via 9dbce1aa52c7342dc4fe4292983d33b826fc4217 (commit)
via 40bbfbc8f6fcfa08154b0c76ddbb41c2725f24f7 (commit)
via 0a94c9b7778c06dcadd0cf77ccf785afe53dc0b7 (commit)
via 0bd3e904e235bf19714dd6c39de6fd7810541d31 (commit)
via 555bf4c3d7d588de640091b4bf677c130d34d94d (commit)
via e4e606091def44d790b193fbcfe74623dd31ef43 (commit)
from 5cfbdc70c17f139c6c0d7d74afba76240ecd0474 (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 57f3e532a4cb9ef57484b638cfb53296dc403e95
Merge: 5cfbdc7 31707f9
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Tue Jan 29 13:43:35 2013 -0800
[master] Merge branch 'trac2310'
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/datasrc_messages.mes | 24 +-
src/lib/datasrc/memory/treenode_rrset.cc | 7 +-
src/lib/datasrc/memory/treenode_rrset.h | 29 +-
src/lib/datasrc/memory/zone_data.cc | 30 ++
src/lib/datasrc/memory/zone_data.h | 57 +++-
src/lib/datasrc/memory/zone_data_updater.cc | 11 +
src/lib/datasrc/memory/zone_finder.cc | 78 ++++-
src/lib/datasrc/memory/zone_finder.h | 14 +
.../tests/memory/treenode_rrset_unittest.cc | 47 ++-
.../tests/memory/zone_data_loader_unittest.cc | 19 +-
src/lib/datasrc/tests/memory/zone_data_unittest.cc | 28 +-
.../tests/memory/zone_data_updater_unittest.cc | 19 +-
.../datasrc/tests/memory/zone_finder_unittest.cc | 303 +++++++++++++++-----
13 files changed, 543 insertions(+), 123 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/datasrc_messages.mes b/src/lib/datasrc/datasrc_messages.mes
index 6ac9db0..5311203 100644
--- a/src/lib/datasrc/datasrc_messages.mes
+++ b/src/lib/datasrc/datasrc_messages.mes
@@ -197,6 +197,16 @@ modify the database). This is what the client would do when such RRs
were given in a DNS response according to RFC2181. The data in
database should be checked and fixed.
+% DATASRC_DATABASE_JOURNALREADER_BADDATA failed to convert a diff to RRset in %1/%2 on %3 between %4 and %5: %6
+This is an error message indicating that a zone's diff is broken and
+the data source library failed to convert it to a valid RRset. The
+most likely cause of this is that someone has manually modified the
+zone's diff in the database and inserted invalid data as a result.
+The zone's name and class, database name, and the start and end
+serials, and an additional detail of the error are shown in the
+message. The administrator should examine the diff in the database
+to find any invalid data and fix it.
+
% DATASRC_DATABASE_JOURNALREADER_END %1/%2 on %3 from %4 to %5
This is a debug message indicating that the program (successfully)
reaches the end of sequences of a zone's differences. The zone's name
@@ -215,16 +225,6 @@ a zone's difference sequences from a database-based data source. The
zone's name and class, database name, and the start and end serials
are shown in the message.
-% DATASRC_DATABASE_JOURNALREADER_BADDATA failed to convert a diff to RRset in %1/%2 on %3 between %4 and %5: %6
-This is an error message indicating that a zone's diff is broken and
-the data source library failed to convert it to a valid RRset. The
-most likely cause of this is that someone has manually modified the
-zone's diff in the database and inserted invalid data as a result.
-The zone's name and class, database name, and the start and end
-serials, and an additional detail of the error are shown in the
-message. The administrator should examine the diff in the database
-to find any invalid data and fix it.
-
% DATASRC_DATABASE_NO_MATCH not match for %2/%3/%4 in %1
No match (not even a wildcard) was found in the named data source for the given
name/type/class in the data source.
@@ -442,6 +442,10 @@ shown name, the search tries the superdomain name that share the shown
www.example.com. with shown label count of 3, example.com. is being
tried).
+% DATASRC_MEM_FIND_TYPE_AT_ORIGIN origin query for type %1 in in-memory zone %2/%3 successful
+Debug information. A specific type RRset is requested at a zone origin
+of an in-memory zone and it is found.
+
% DATASRC_MEM_FIND_ZONE looking for zone '%1'
Debug information. A zone object for this zone is being searched for in the
in-memory data source.
diff --git a/src/lib/datasrc/memory/treenode_rrset.cc b/src/lib/datasrc/memory/treenode_rrset.cc
index e7ed20c..c4e16a6 100644
--- a/src/lib/datasrc/memory/treenode_rrset.cc
+++ b/src/lib/datasrc/memory/treenode_rrset.cc
@@ -59,8 +59,7 @@ TreeNodeRRset::getName() const {
const RRTTL&
TreeNodeRRset::getTTL() const {
if (ttl_ == NULL) {
- util::InputBuffer ttl_buffer(rdataset_->getTTLData(),
- sizeof(uint32_t));
+ util::InputBuffer ttl_buffer(ttl_data_, sizeof(uint32_t));
ttl_ = new RRTTL(ttl_buffer);
}
@@ -169,7 +168,7 @@ TreeNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
// Render the main (non RRSIG) RRs
const size_t rendered_rdata_count =
writeRRs(renderer, rdataset_->getRdataCount(), name_labels,
- rdataset_->type, rrclass_, rdataset_->getTTLData(), reader,
+ rdataset_->type, rrclass_, ttl_data_, reader,
&RdataReader::iterateRdata);
if (renderer.isTruncated()) {
return (rendered_rdata_count);
@@ -180,7 +179,7 @@ TreeNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
// Render any RRSIGs, if we supposed to do so
const size_t rendered_rrsig_count = dnssec_ok_ ?
writeRRs(renderer, rrsig_count_, name_labels, RRType::RRSIG(),
- rrclass_, rdataset_->getTTLData(), reader,
+ rrclass_, ttl_data_, reader,
&RdataReader::iterateSingleSig) : 0;
return (rendered_rdata_count + rendered_rrsig_count);
diff --git a/src/lib/datasrc/memory/treenode_rrset.h b/src/lib/datasrc/memory/treenode_rrset.h
index 460a704..295a95a 100644
--- a/src/lib/datasrc/memory/treenode_rrset.h
+++ b/src/lib/datasrc/memory/treenode_rrset.h
@@ -112,12 +112,34 @@ public:
const RdataSet* rdataset, bool dnssec_ok) :
node_(node), rdataset_(rdataset),
rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
- dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL), ttl_(NULL)
+ dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL),
+ ttl_data_(rdataset->getTTLData()), ttl_(NULL)
+ {}
+
+ /// \brief Constructor with a specific TTL.
+ ///
+ /// This constructor is mostly the same as the normal version, but takes
+ /// an extra parameter, \c ttl_data. It's expected to point to a memory
+ /// region at least for 32 bits, and the corresponding 32-bit data will
+ /// be used as wire-format TTL value of the RRset, instead of the TTL
+ /// associated with \c rdataset.
+ ///
+ /// It's the caller's responsibility to guarantee the memory region is
+ /// valid and intact throughout the lifetime of the RRset.
+ ///
+ /// \throw None
+ TreeNodeRRset(const dns::RRClass& rrclass, const ZoneNode* node,
+ const RdataSet* rdataset, bool dnssec_ok,
+ const void* ttl_data) :
+ node_(node), rdataset_(rdataset),
+ rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
+ dnssec_ok_(dnssec_ok), name_(NULL), realname_(NULL),
+ ttl_data_(ttl_data), ttl_(NULL)
{}
/// \brief Constructor for wildcard-expanded owner name.
///
- /// This constructor is mostly the same as the other version, but takes
+ /// This constructor is mostly the same as the normal version, but takes
/// an extra parameter, \c realname. It effectively overrides the owner
/// name of the RRset; wherever the owner name is used (e.g., in the
/// \c toWire() method), the specified name will be used instead of
@@ -133,7 +155,7 @@ public:
node_(node), rdataset_(rdataset),
rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
dnssec_ok_(dnssec_ok), name_(NULL), realname_(new dns::Name(realname)),
- ttl_(NULL)
+ ttl_data_(rdataset->getTTLData()), ttl_(NULL)
{}
virtual ~TreeNodeRRset() {
@@ -255,6 +277,7 @@ private:
const bool dnssec_ok_;
mutable dns::Name* name_;
const dns::Name* const realname_;
+ const void* const ttl_data_;
mutable dns::RRTTL* ttl_;
};
diff --git a/src/lib/datasrc/memory/zone_data.cc b/src/lib/datasrc/memory/zone_data.cc
index cc31419..d32fc87 100644
--- a/src/lib/datasrc/memory/zone_data.cc
+++ b/src/lib/datasrc/memory/zone_data.cc
@@ -134,6 +134,31 @@ NSEC3Data::insertName(util::MemorySegment& mem_sgmt, const Name& name,
result == ZoneTree::ALREADYEXISTS) && node != NULL);
}
+namespace {
+// A helper to convert a TTL value in network byte order and set it in
+// ZoneData::min_ttl_. We can use util::OutputBuffer, but copy the logic
+// here to guarantee it is exception free.
+// Note: essentially this function is a local (re)implementation of the
+// standard htonl() library function, but we avoid relying on it in case it's
+// not available (it's not in the C++ standard library).
+void
+setTTLInNetOrder(uint32_t val, uint32_t* result) {
+ uint8_t buf[4];
+ buf[0] = static_cast<uint8_t>((val & 0xff000000) >> 24);
+ buf[1] = static_cast<uint8_t>((val & 0x00ff0000) >> 16);
+ buf[2] = static_cast<uint8_t>((val & 0x0000ff00) >> 8);
+ buf[3] = static_cast<uint8_t>(val & 0x000000ff);
+ std::memcpy(result, buf, sizeof(*result));
+}
+}
+
+ZoneData::ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
+ zone_tree_(zone_tree), origin_node_(origin_node),
+ min_ttl_(0) // tentatively set to silence static checkers
+{
+ setTTLInNetOrder(RRTTL::MAX_TTL().getValue(), &min_ttl_);
+}
+
ZoneData*
ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
// ZoneTree::insert() and ZoneData allocation can throw. See also
@@ -178,6 +203,11 @@ ZoneData::insertName(util::MemorySegment& mem_sgmt, const Name& name,
result == ZoneTree::ALREADYEXISTS) && node != NULL);
}
+void
+ZoneData::setMinTTL(uint32_t min_ttl_val) {
+ setTTLInNetOrder(min_ttl_val, &min_ttl_);
+}
+
} // namespace memory
} // namespace datasrc
} // datasrc isc
diff --git a/src/lib/datasrc/memory/zone_data.h b/src/lib/datasrc/memory/zone_data.h
index 974ce24..c6b3dcc 100644
--- a/src/lib/datasrc/memory/zone_data.h
+++ b/src/lib/datasrc/memory/zone_data.h
@@ -287,7 +287,7 @@ private:
/// from NSEC to NSEC3 or vice versa, support incremental signing, or support
/// multiple sets of NSEC3 parameters.
///
-/// One last type of meta data is the status of the zone in terms of DNSSEC
+/// One other type of meta data is the status of the zone in terms of DNSSEC
/// signing. This class supports the following concepts:
/// - Whether the zone is signed or not, either with NSEC records or NSEC3
/// records.
@@ -315,6 +315,15 @@ private:
/// because we won't have to change the application code when we implement
/// the future separation.
///
+/// One last type of meta data is the zone's "minimum" TTL. It's expected
+/// to be a shortcut copy of the minimum field of the zone's SOA RDATA,
+/// and is expected to be used to create an SOA RR for a negative response,
+/// whose RR TTL may have to be set to this value according to RFC2308.
+/// This class is not aware of such usage, however, and only provides a
+/// simple getter and setter method for this value: \c getMinTTLData() and
+/// \c setMinTTL(). The user of this class is responsible for setting the
+/// value with \c setMinTTL() when it loads or updates the SOA RR.
+///
/// The intended usage of these two status concepts is to implement the
/// \c ZoneFinder::Context::isNSECSigned() and
/// \c ZoneFinder::Context::isNSEC3Signed() methods. A possible implementation
@@ -349,9 +358,7 @@ private:
/// allocator (\c create()), so the constructor is hidden as private.
///
/// It never throws an exception.
- ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
- zone_tree_(zone_tree), origin_node_(origin_node)
- {}
+ ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node);
// Zone node flags.
private:
@@ -413,7 +420,7 @@ public:
///
/// The class encapsulation ensures that the origin node always exists at
/// the same address, so this method always returns a non-NULL valid
- /// valid pointer.
+ /// pointer.
///
/// \throw none
const ZoneNode* getOriginNode() const {
@@ -456,6 +463,26 @@ public:
///
/// \throw none
const NSEC3Data* getNSEC3Data() const { return (nsec3_data_.get()); }
+
+ /// \brief Return a pointer to the zone's minimum TTL data.
+ ///
+ /// The returned pointer points to a memory region that is valid at least
+ /// for 32 bits, storing the zone's minimum TTL in the network byte
+ /// order. The corresponding 32-bit value as an integer is initially
+ /// set to the value of \c dns::RRTTL::MAX_TTL(), and, once
+ /// \c setMinTTL() is called, set to the value specified at the latest
+ /// call to \c setMinTTL().
+ ///
+ /// It returns opaque data to make it clear that unless the wire
+ /// format data is necessary (e.g., when rendering it in a DNS message),
+ /// it should be converted to, e.g., an \c RRTTL object explicitly.
+ ///
+ /// The returned pointer is valid as long as the \c ZoneData is valid,
+ /// and the corresponding 32-bit data are the same until \c setMinTTL()
+ /// is called.
+ ///
+ /// \throw none
+ const void* getMinTTLData() const { return (&min_ttl_); }
//@}
///
@@ -552,12 +579,32 @@ public:
nsec3_data_ = nsec3_data;
return (old);
}
+
+ /// \brief Set the zone's "minimum" TTL.
+ ///
+ /// This method updates the recorded minimum TTL of the zone data.
+ /// It's expected to be identical to the value of the Minimum field
+ /// of the SOA RR at the zone apex, but this method does not check the
+ /// consistency; it's the caller's responsibility.
+ ///
+ /// While RFC2181 specifies the max TTL value to be 2^31-1, this method
+ /// does not check the range; it accepts any unsigned 32-bit integer
+ /// value. In practice, this shouldn't cause a problem, however, because
+ /// the only expected usage of this value is to use the minimum of this
+ /// value and SOA RR's TTL, and the latter is expected to be in the
+ /// valid range.
+ ///
+ /// \throw None
+ /// \param min_ttl_val The minimum TTL value as unsigned 32-bit integer
+ /// in the host byte order.
+ void setMinTTL(uint32_t min_ttl_val);
//@}
private:
const boost::interprocess::offset_ptr<ZoneTree> zone_tree_;
const boost::interprocess::offset_ptr<ZoneNode> origin_node_;
boost::interprocess::offset_ptr<NSEC3Data> nsec3_data_;
+ uint32_t min_ttl_;
};
} // namespace memory
diff --git a/src/lib/datasrc/memory/zone_data_updater.cc b/src/lib/datasrc/memory/zone_data_updater.cc
index 51ec03c..5bde6d4 100644
--- a/src/lib/datasrc/memory/zone_data_updater.cc
+++ b/src/lib/datasrc/memory/zone_data_updater.cc
@@ -336,6 +336,17 @@ ZoneDataUpdater::addRdataSet(const Name& name, const RRType& rrtype,
// "NSEC signed")
zone_data_.setSigned(true);
}
+
+ // If we are adding a new SOA at the origin, update zone's min TTL.
+ // Note: if the input is broken and contains multiple SOAs, the load
+ // or update will be rejected higher level. We just always (though
+ // this should be only once in normal cases) update the TTL.
+ if (rrset && rrtype == RRType::SOA() && is_origin) {
+ // Our own validation ensures the RRset is not empty.
+ zone_data_.setMinTTL(
+ dynamic_cast<const generic::SOA&>(
+ rrset->getRdataIterator()->getCurrent()).getMinimum());
+ }
}
}
diff --git a/src/lib/datasrc/memory/zone_finder.cc b/src/lib/datasrc/memory/zone_finder.cc
index bc21869..56c4110 100644
--- a/src/lib/datasrc/memory/zone_finder.cc
+++ b/src/lib/datasrc/memory/zone_finder.cc
@@ -23,10 +23,13 @@
#include <dns/name.h>
#include <dns/rrset.h>
#include <dns/rrtype.h>
+#include <dns/rrttl.h>
#include <dns/nsec3hash.h>
#include <datasrc/logger.h>
+#include <util/buffer.h>
+
#include <boost/scoped_ptr.hpp>
#include <boost/bind.hpp>
@@ -104,14 +107,19 @@ createTreeNodeRRset(const ZoneNode* node,
const RdataSet* rdataset,
const RRClass& rrclass,
ZoneFinder::FindOptions options,
- const Name* realname = NULL)
+ const Name* realname = NULL,
+ const void* ttl_data = NULL)
{
const bool dnssec = ((options & ZoneFinder::FIND_DNSSEC) != 0);
- if (node != NULL && rdataset != NULL) {
- if (realname != NULL) {
+ if (node && rdataset) {
+ if (realname) {
return (TreeNodeRRsetPtr(new TreeNodeRRset(*realname, rrclass,
node, rdataset,
dnssec)));
+ } else if (ttl_data) {
+ assert(!realname); // these two cases should be mixed in our use
+ return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
+ dnssec, ttl_data)));
} else {
return (TreeNodeRRsetPtr(new TreeNodeRRset(rrclass, node, rdataset,
dnssec)));
@@ -229,6 +237,12 @@ createNSEC3RRset(const ZoneNode* node, const RRClass& rrclass) {
ZoneFinder::FIND_DNSSEC));
}
+inline RRTTL
+createTTLFromData(const void* ttl_data) {
+ util::InputBuffer b(ttl_data, sizeof(uint32_t));
+ return (RRTTL(b));
+}
+
// convenience function to fill in the final details
//
// Set up ZoneFinderResultContext object as a return value of find(),
@@ -250,7 +264,8 @@ createFindResult(const RRClass& rrclass,
const RdataSet* rdataset,
ZoneFinder::FindOptions options,
bool wild = false,
- const Name* qname = NULL)
+ const Name* qname = NULL,
+ bool use_minttl = false)
{
ZoneFinder::FindResultFlags flags = ZoneFinder::RESULT_DEFAULT;
const Name* rename = NULL;
@@ -268,6 +283,15 @@ createFindResult(const RRClass& rrclass,
}
}
+ if (use_minttl && rdataset &&
+ createTTLFromData(zone_data.getMinTTLData()) <
+ createTTLFromData(rdataset->getTTLData())) {
+ return (ZoneFinderResultContext(
+ code,
+ createTreeNodeRRset(node, rdataset, rrclass, options,
+ rename, zone_data.getMinTTLData()),
+ flags, zone_data, node, rdataset));
+ }
return (ZoneFinderResultContext(code, createTreeNodeRRset(node, rdataset,
rrclass, options,
rename),
@@ -721,8 +745,8 @@ InMemoryZoneFinder::Context::findAdditional(
boost::shared_ptr<ZoneFinder::Context>
InMemoryZoneFinder::find(const isc::dns::Name& name,
- const isc::dns::RRType& type,
- const FindOptions options)
+ const isc::dns::RRType& type,
+ const FindOptions options)
{
return (ZoneFinderContextPtr(new Context(*this, options, rrclass_,
findInternal(name, type,
@@ -731,8 +755,8 @@ InMemoryZoneFinder::find(const isc::dns::Name& name,
boost::shared_ptr<ZoneFinder::Context>
InMemoryZoneFinder::findAll(const isc::dns::Name& name,
- std::vector<isc::dns::ConstRRsetPtr>& target,
- const FindOptions options)
+ std::vector<isc::dns::ConstRRsetPtr>& target,
+ const FindOptions options)
{
return (ZoneFinderContextPtr(new Context(*this, options, rrclass_,
findInternal(name,
@@ -741,6 +765,44 @@ InMemoryZoneFinder::findAll(const isc::dns::Name& name,
options))));
}
+// The implementation is a special case of the generic findInternal: we know
+// the qname should have an "exact match" and its node is accessible via
+// getOriginNode(); and, since there should be at least SOA RR at the origin
+// the case of CNAME can be eliminated (these should be guaranteed at the load
+// or update time, but even if they miss a corner case and allows a CNAME to
+// be added at origin, the zone is broken anyway, so we'd just let this
+// method return garbage, too). As a result, there can be only too cases
+// for the result codes: SUCCESS if the requested type of RR exists; NXRRSET
+// otherwise. Due to its simplicity we implement it separately, rather than
+// sharing the code with findInternal.
+boost::shared_ptr<ZoneFinder::Context>
+InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
+ bool use_minttl,
+ const FindOptions options)
+{
+ const ZoneNode* const node = zone_data_.getOriginNode();
+ const RdataSet* const found = RdataSet::find(node->getData(), type);
+
+ if (found != NULL) {
+ LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_FIND_TYPE_AT_ORIGIN).
+ arg(type).arg(getOrigin()).arg(rrclass_);
+ return (ZoneFinderContextPtr(
+ new Context(*this, options, rrclass_,
+ createFindResult(rrclass_, zone_data_, SUCCESS,
+ node, found, options, false,
+ NULL, use_minttl))));
+ }
+ return (ZoneFinderContextPtr(
+ new Context(*this, options, rrclass_,
+ createFindResult(rrclass_, zone_data_, NXRRSET,
+ node,
+ getNSECForNXRRSET(zone_data_,
+ options,
+ node),
+ options, false, NULL,
+ use_minttl))));
+}
+
ZoneFinderResultContext
InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
const isc::dns::RRType& type,
diff --git a/src/lib/datasrc/memory/zone_finder.h b/src/lib/datasrc/memory/zone_finder.h
index 254f5d2..cd2bd58 100644
--- a/src/lib/datasrc/memory/zone_finder.h
+++ b/src/lib/datasrc/memory/zone_finder.h
@@ -60,6 +60,16 @@ public:
const isc::dns::RRType& type,
const FindOptions options = FIND_DEFAULT);
+ /// \brief Search for an RRset of given RR type at the zone origin
+ /// specialized for in-memory data source.
+ ///
+ /// This specialized version exploits internal data structure to find
+ /// RRsets at the zone origin and (if \c use_minttl is true) extract
+ /// the SOA Minimum TTL much more efficiently.
+ virtual boost::shared_ptr<Context> findAtOrigin(
+ const isc::dns::RRType& type, bool use_minttl,
+ FindOptions options);
+
/// \brief Version of find that returns all types at once
///
/// It acts the same as find, just that when the correct node is found,
@@ -108,3 +118,7 @@ private:
} // namespace isc
#endif // DATASRC_MEMORY_ZONE_FINDER_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc b/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc
index 02ad2bd..c331eaa 100644
--- a/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc
+++ b/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc
@@ -194,8 +194,14 @@ checkBasicFields(const AbstractRRset& actual_rrset, const RdataSet* rdataset,
// a temporary non-copyable object.
boost::shared_ptr<TreeNodeRRset>
createRRset(const RRClass& rrclass, const ZoneNode* node,
- const RdataSet* rdataset, bool dnssec_ok)
+ const RdataSet* rdataset, bool dnssec_ok,
+ const void* ttl_data = NULL)
{
+ if (ttl_data) {
+ return (boost::shared_ptr<TreeNodeRRset>(
+ new TreeNodeRRset(rrclass, node, rdataset, dnssec_ok,
+ ttl_data)));
+ }
return (boost::shared_ptr<TreeNodeRRset>(
new TreeNodeRRset(rrclass, node, rdataset, dnssec_ok)));
}
@@ -243,6 +249,13 @@ TEST_F(TreeNodeRRsetTest, create) {
true),
wildcard_rdataset_, match_name_, rrclass_, RRType::A(),
3600, 2, 1);
+
+ // Constructed with explicit TTL
+ const uint32_t ttl = 0; // use 0 to avoid byte-order conversion
+ checkBasicFields(*createRRset(rrclass_, www_node_, a_rdataset_, true,
+ &ttl),
+ a_rdataset_, www_name_, rrclass_, RRType::A(), 0, 2,
+ 1);
}
// The following two templated functions are helper to encapsulate the
@@ -337,6 +350,21 @@ TEST_F(TreeNodeRRsetTest, toWire) {
}
{
+ SCOPED_TRACE("with RRSIG, DNSSEC OK, explicit TTL");
+ const uint32_t ttl = 0;
+ const TreeNodeRRset rrset(rrclass_, www_node_, a_rdataset_, true,
+ &ttl);
+ checkToWireResult(expected_renderer, actual_renderer, rrset,
+ www_name_,
+ textToRRset("www.example.com. 0 IN A 192.0.2.1\n"
+ "www.example.com. 0 IN A 192.0.2.2"),
+ textToRRset("www.example.com. 0 IN RRSIG "
+ "A 5 2 3600 20120814220826 "
+ "20120715220826 1234 example.com. FAKE"),
+ true);
+ }
+
+ {
SCOPED_TRACE("with RRSIG, DNSSEC not OK");
const TreeNodeRRset rrset(rrclass_, www_node_, a_rdataset_, false);
checkToWireResult(expected_renderer, actual_renderer, rrset,
@@ -396,7 +424,7 @@ TEST_F(TreeNodeRRsetTest, toWire) {
const TreeNodeRRset rrset(rrclass_, www_node_, rrsig_only_rdataset_,
true);
checkToWireResult(expected_renderer, actual_renderer, rrset,
- www_name_, ConstRRsetPtr(), txt_rrsig_rrset_,true);
+ www_name_, ConstRRsetPtr(), txt_rrsig_rrset_, true);
}
{
@@ -407,7 +435,7 @@ TEST_F(TreeNodeRRsetTest, toWire) {
const TreeNodeRRset rrset(rrclass_, www_node_, rrsig_only_rdataset_,
false);
checkToWireResult(expected_renderer, actual_renderer, rrset,
- www_name_, ConstRRsetPtr(), txt_rrsig_rrset_,false);
+ www_name_, ConstRRsetPtr(), txt_rrsig_rrset_, false);
}
}
@@ -522,6 +550,14 @@ TEST_F(TreeNodeRRsetTest, toText) {
// Constructed with RRSIG, and it should be visible.
checkToText(*createRRset(rrclass_, www_node_, a_rdataset_, true),
a_rrset_, a_rrsig_rrset_);
+ // Same as the previous, but with explicit TTL.
+ const uint32_t ttl = 0;
+ checkToText(*createRRset(rrclass_, www_node_, a_rdataset_, true, &ttl),
+ textToRRset("www.example.com. 0 IN A 192.0.2.1\n"
+ "www.example.com. 0 IN A 192.0.2.2"),
+ textToRRset("www.example.com. 0 IN RRSIG A 5 2 3600 "
+ "20120814220826 20120715220826 1234 example.com. "
+ "FAKE"));
// Constructed with RRSIG, and it should be invisible.
checkToText(*createRRset(rrclass_, www_node_, a_rdataset_, false),
a_rrset_, ConstRRsetPtr());
@@ -556,6 +592,11 @@ TEST_F(TreeNodeRRsetTest, isSameKind) {
EXPECT_TRUE(rrset.isSameKind(*createRRset(rrclass_, www_node_,
a_rdataset_, true)));
+ // Similar to the previous, but with explicit (different TTL) => still same
+ const uint32_t ttl = 0;
+ EXPECT_TRUE(rrset.isSameKind(*createRRset(rrclass_, www_node_,
+ a_rdataset_, true, &ttl)));
+
// Same name (node), different type (rdataset) => not same kind
EXPECT_FALSE(rrset.isSameKind(*createRRset(rrclass_, www_node_,
aaaa_rdataset_, true)));
diff --git a/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc
index c005bf1..abc6f13 100644
--- a/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_loader_unittest.cc
@@ -12,13 +12,15 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-#include <dns/name.h>
-#include <dns/rrclass.h>
-
+#include <datasrc/memory/zone_data_loader.h>
#include <datasrc/memory/rdataset.h>
#include <datasrc/memory/zone_data.h>
#include <datasrc/memory/zone_data_updater.h>
-#include <datasrc/memory/zone_data_loader.h>
+
+#include <util/buffer.h>
+
+#include <dns/name.h>
+#include <dns/rrclass.h>
#include "memory_segment_test.h"
@@ -62,4 +64,13 @@ TEST_F(ZoneDataLoaderTest, loadRRSIGFollowsNothing) {
// Teardown checks for memory segment leaks
}
+TEST_F(ZoneDataLoaderTest, zoneMinTTL) {
+ // This should hold outside of the loader class, but we do double check.
+ zone_data_ = loadZoneData(mem_sgmt_, zclass_, Name("example.org"),
+ TEST_DATA_DIR
+ "/example.org-nsec3-signed.zone");
+ isc::util::InputBuffer b(zone_data_->getMinTTLData(), sizeof(uint32_t));
+ EXPECT_EQ(RRTTL(1200), RRTTL(b));
+}
+
}
diff --git a/src/lib/datasrc/tests/memory/zone_data_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_unittest.cc
index 1605fa2..ffbd0f6 100644
--- a/src/lib/datasrc/tests/memory/zone_data_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_unittest.cc
@@ -12,19 +12,22 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <datasrc/memory/zone_data.h>
+#include <datasrc/memory/rdata_serialization.h>
+#include <datasrc/memory/rdataset.h>
+
#include "memory_segment_test.h"
#include <dns/rdataclass.h>
#include <exceptions/exceptions.h>
+#include <util/buffer.h>
+
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/rrclass.h>
-
-#include <datasrc/memory/rdata_serialization.h>
-#include <datasrc/memory/rdataset.h>
-#include <datasrc/memory/zone_data.h>
+#include <dns/rrttl.h>
#include <testutils/dnsmessage_test.h>
@@ -258,4 +261,21 @@ TEST_F(ZoneDataTest, isSigned) {
zone_data_->setSigned(false);
EXPECT_FALSE(zone_data_->isSigned());
}
+
+// A simple wrapper to reconstruct an RRTTL object from wire-format TTL
+// data (32 bits)
+RRTTL
+createRRTTL(const void* ttl_data) {
+ isc::util::InputBuffer b(ttl_data, sizeof(uint32_t));
+ return (RRTTL(b));
+}
+
+TEST_F(ZoneDataTest, minTTL) {
+ // By default it's tentatively set to "max TTL"
+ EXPECT_EQ(RRTTL::MAX_TTL(), createRRTTL(zone_data_->getMinTTLData()));
+
+ // Explicitly set, then retrieve it.
+ zone_data_->setMinTTL(1200);
+ EXPECT_EQ(RRTTL(1200), createRRTTL(zone_data_->getMinTTLData()));
+}
}
diff --git a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
index 63c69c8..93ca0c9 100644
--- a/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_data_updater_unittest.cc
@@ -12,6 +12,10 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <datasrc/memory/zone_data_updater.h>
+#include <datasrc/memory/rdataset.h>
+#include <datasrc/memory/zone_data.h>
+
#include <testutils/dnsmessage_test.h>
#include <exceptions/exceptions.h>
@@ -19,10 +23,7 @@
#include <dns/name.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
-
-#include <datasrc/memory/rdataset.h>
-#include <datasrc/memory/zone_data.h>
-#include <datasrc/memory/zone_data_updater.h>
+#include <dns/rrttl.h>
#include "memory_segment_test.h"
@@ -86,6 +87,16 @@ getNode(isc::util::MemorySegment& mem_sgmt, const Name& name,
return (node);
}
+TEST_F(ZoneDataUpdaterTest, zoneMinTTL) {
+ // If we add SOA, zone's min TTL will be updated.
+ updater_->add(textToRRset(
+ "example.org. 3600 IN SOA . . 0 0 0 0 1200",
+ zclass_, zname_),
+ ConstRRsetPtr());
+ isc::util::InputBuffer b(zone_data_->getMinTTLData(), sizeof(uint32_t));
+ EXPECT_EQ(RRTTL(1200), RRTTL(b));
+}
+
TEST_F(ZoneDataUpdaterTest, rrsigOnly) {
// RRSIG that doesn't have covered RRset can be added. The resulting
// rdataset won't have "normal" RDATA but sig RDATA.
diff --git a/src/lib/datasrc/tests/memory/zone_finder_unittest.cc b/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
index 42667da..055708d 100644
--- a/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_finder_unittest.cc
@@ -53,19 +53,6 @@ namespace {
using result::SUCCESS;
using result::EXIST;
-/// \brief expensive rrset converter
-///
-/// converts any specialized rrset (which may not have implemented some
-/// methods for efficiency) into a 'full' RRsetPtr, for easy use in test
-/// checks.
-///
-/// Done very inefficiently through text representation, speed should not
-/// be a concern here.
-ConstRRsetPtr
-convertRRset(ConstRRsetPtr src) {
- return (textToRRset(src->toText()));
-}
-
/// \brief Test fixture for the InMemoryZoneFinder class
class InMemoryZoneFinderTest : public ::testing::Test {
// A straightforward pair of textual RR(set) and a RRsetPtr variable
@@ -105,7 +92,6 @@ protected:
ZoneFinder::FindResultFlags expected_flags =
ZoneFinder::RESULT_DEFAULT);
-public:
InMemoryZoneFinderTest() :
class_(RRClass::IN()),
origin_("example.org"),
@@ -119,6 +105,7 @@ public:
// Note that this contains an out-of-zone RR, and due to the
// validation check of masterLoad() used below, we cannot add SOA.
const RRsetData zone_data[] = {
+ {"example.org. 300 IN SOA . . 0 0 0 0 100", &rr_soa_},
{"example.org. 300 IN NS ns.example.org.", &rr_ns_},
{"example.org. 300 IN A 192.0.2.1", &rr_a_},
{"ns.example.org. 300 IN A 192.0.2.2", &rr_ns_a_},
@@ -185,7 +172,18 @@ public:
};
for (unsigned int i = 0; zone_data[i].text != NULL; ++i) {
- *zone_data[i].rrset = textToRRset(zone_data[i].text);
+ if (zone_data[i].rrset == &rr_soa_) {
+ // This is zone's SOA. We need to specify the origin for
+ // textToRRset; otherwise it would throw.
+ *zone_data[i].rrset = textToRRset(zone_data[i].text, class_,
+ origin_);
+ } else {
+ // For other data, we should rather omit the origin (the root
+ // name will be used by default); there's some out-of-zone
+ // name, which would trigger an exception if we specified
+ // origin_.
+ *zone_data[i].rrset = textToRRset(zone_data[i].text);
+ }
}
}
@@ -200,6 +198,24 @@ public:
updater_.add(rrset, rrset->getRRsig());
}
+ /// \brief expensive rrset converter
+ ///
+ /// converts any specialized rrset (which may not have implemented some
+ /// methods for efficiency) into a 'full' RRsetPtr, for easy use in test
+ /// checks.
+ ///
+ /// Done very inefficiently through text representation, speed should not
+ /// be a concern here.
+ ConstRRsetPtr
+ convertRRset(ConstRRsetPtr src) {
+ // If the type is SOA, textToRRset performs a stricter check, so we
+ // should specify the origin. For now we don't use out-of-zone
+ // owner names (e.g. for pathological cases) with this method, so it
+ // works for all test data. If future changes break this assumption
+ // we should adjust it.
+ return (textToRRset(src->toText(), class_, origin_));
+ }
+
// Some data to test with
const RRClass class_;
const Name origin_;
@@ -218,6 +234,8 @@ public:
RRsetPtr
// Out of zone RRset
rr_out_,
+ // SOA of example.org
+ rr_soa_,
// NS of example.org
rr_ns_,
// A of ns.example.org
@@ -293,75 +311,110 @@ public:
if (zone_finder == NULL) {
zone_finder = &zone_finder_;
}
- const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
- RRsetPtr(); // note we use the same type as of retval of getRRsig()
// The whole block is inside, because we need to check the result and
// we can't assign to FindResult
EXPECT_NO_THROW({
ZoneFinderContextPtr find_result(zone_finder->find(
name, rrtype, options));
- // Check it returns correct answers
- EXPECT_EQ(result, find_result->code);
- EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
- find_result->isWildcard());
- EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
- != 0, find_result->isNSECSigned());
- EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
- != 0, find_result->isNSEC3Signed());
- if (check_answer) {
- if (!answer) {
- ASSERT_FALSE(find_result->rrset);
- } else {
- ASSERT_TRUE(find_result->rrset);
- ConstRRsetPtr result_rrset(
- convertRRset(find_result->rrset));
- rrsetCheck(answer, result_rrset);
- if (answer_sig &&
- (options & ZoneFinder::FIND_DNSSEC) != 0) {
- ASSERT_TRUE(result_rrset->getRRsig());
- rrsetCheck(answer_sig, result_rrset->getRRsig());
- } else {
- EXPECT_FALSE(result_rrset->getRRsig());
- }
- }
- } else if (check_wild_answer) {
- ASSERT_NE(ConstRRsetPtr(), answer) <<
- "Wrong test, don't check for wild names if you expect "
- "empty answer";
- ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
- "No answer found";
- // Build the expected answer using the given name and
- // other parameter of the base wildcard RRset.
- RRsetPtr wildanswer(new RRset(name, answer->getClass(),
- answer->getType(),
- answer->getTTL()));
- RdataIteratorPtr expectedIt(answer->getRdataIterator());
- for (; !expectedIt->isLast(); expectedIt->next()) {
- wildanswer->addRdata(expectedIt->getCurrent());
- }
-
- ConstRRsetPtr result_rrset(
- convertRRset(find_result->rrset));
- rrsetCheck(wildanswer, result_rrset);
-
- // Same for the RRSIG, if any.
- if (answer_sig) {
- ASSERT_TRUE(result_rrset->getRRsig());
-
- RRsetPtr wildsig(new RRset(name,
- answer_sig->getClass(),
- RRType::RRSIG(),
- answer_sig->getTTL()));
- RdataIteratorPtr expectedIt(
- answer_sig->getRdataIterator());
- for (; !expectedIt->isLast(); expectedIt->next()) {
- wildsig->addRdata(expectedIt->getCurrent());
- }
- rrsetCheck(wildsig, result_rrset->getRRsig());
- }
- }
+ findTestCommon(name, result, find_result, check_answer,
+ answer, expected_flags, options,
+ check_wild_answer);
});
}
+
+ void findAtOriginTest(const RRType& rrtype,
+ ZoneFinder::Result result,
+ bool check_answer = true,
+ const ConstRRsetPtr& answer = ConstRRsetPtr(),
+ ZoneFinder::FindResultFlags expected_flags =
+ ZoneFinder::RESULT_DEFAULT,
+ memory::InMemoryZoneFinder* zone_finder = NULL,
+ ZoneFinder::FindOptions options =
+ ZoneFinder::FIND_DEFAULT,
+ bool use_minttl = false)
+ {
+ SCOPED_TRACE("findAtOriginTest for " + rrtype.toText());
+
+ if (zone_finder == NULL) {
+ zone_finder = &zone_finder_;
+ }
+ ZoneFinderContextPtr find_result(zone_finder->findAtOrigin(
+ rrtype, use_minttl, options));
+ findTestCommon(origin_, result, find_result, check_answer, answer,
+ expected_flags, options, false);
+ }
+
+private:
+ void findTestCommon(const Name& name, ZoneFinder::Result result,
+ ZoneFinderContextPtr find_result,
+ bool check_answer,
+ const ConstRRsetPtr& answer,
+ ZoneFinder::FindResultFlags expected_flags,
+ ZoneFinder::FindOptions options,
+ bool check_wild_answer)
+ {
+ const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
+ RRsetPtr(); // note we use the same type as of retval of getRRsig()
+
+ // Check it returns correct answers
+ EXPECT_EQ(result, find_result->code);
+ EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
+ find_result->isWildcard());
+ EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0,
+ find_result->isNSECSigned());
+ EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0,
+ find_result->isNSEC3Signed());
+ if (check_answer) {
+ if (!answer) {
+ ASSERT_FALSE(find_result->rrset);
+ } else {
+ ASSERT_TRUE(find_result->rrset);
+ ConstRRsetPtr result_rrset(convertRRset(find_result->rrset));
+ rrsetCheck(answer, result_rrset);
+ if (answer_sig && (options & ZoneFinder::FIND_DNSSEC) != 0) {
+ ASSERT_TRUE(result_rrset->getRRsig());
+ rrsetCheck(answer_sig, result_rrset->getRRsig());
+ } else {
+ EXPECT_FALSE(result_rrset->getRRsig());
+ }
+ }
+ } else if (check_wild_answer) {
+ ASSERT_NE(ConstRRsetPtr(), answer) <<
+ "Wrong test, don't check for wild names if you expect "
+ "empty answer";
+ ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
+ "No answer found";
+ // Build the expected answer using the given name and
+ // other parameter of the base wildcard RRset.
+ RRsetPtr wildanswer(new RRset(name, answer->getClass(),
+ answer->getType(),
+ answer->getTTL()));
+ RdataIteratorPtr expectedIt(answer->getRdataIterator());
+ for (; !expectedIt->isLast(); expectedIt->next()) {
+ wildanswer->addRdata(expectedIt->getCurrent());
+ }
+
+ ConstRRsetPtr result_rrset(convertRRset(find_result->rrset));
+ rrsetCheck(wildanswer, result_rrset);
+
+ // Same for the RRSIG, if any.
+ if (answer_sig) {
+ ASSERT_TRUE(result_rrset->getRRsig());
+
+ RRsetPtr wildsig(new RRset(name, answer_sig->getClass(),
+ RRType::RRSIG(),
+ answer_sig->getTTL()));
+ RdataIteratorPtr expectedIt(
+ answer_sig->getRdataIterator());
+ for (; !expectedIt->isLast(); expectedIt->next()) {
+ wildsig->addRdata(expectedIt->getCurrent());
+ }
+ rrsetCheck(wildsig, result_rrset->getRRsig());
+ }
+ }
+ }
+
+protected:
/**
* \brief Calls the findAll on the finder and checks the result.
*/
@@ -583,7 +636,6 @@ TEST_F(InMemoryZoneFinderTest, glue) {
findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
true, rr_child_ns_);
-
// If we do it in the "glue OK" mode, we should find the exact match.
findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
@@ -619,6 +671,101 @@ TEST_F(InMemoryZoneFinderTest, glue) {
NULL, ZoneFinder::FIND_GLUE_OK);
}
+TEST_F(InMemoryZoneFinderTest, findAtOrigin) {
+ // Add origin NS.
+ rr_ns_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
+ "NS 5 3 3600 20120814220826 20120715220826 "
+ "1234 example.org. FAKE"));
+ addToZoneData(rr_ns_);
+
+ // Specified type of RR exists, no DNSSEC
+ findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
+
+ // Specified type of RR exists, with DNSSEC
+ findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_,
+ ZoneFinder::RESULT_DEFAULT, NULL,
+ ZoneFinder::FIND_DNSSEC);
+
+ // Specified type of RR doesn't exist, no DNSSEC
+ findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET);
+
+ // Specified type of RR doesn't exist, with DNSSEC. First, make the
+ // zone "NSEC-signed", then check.
+ rr_nsec_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
+ "NSEC 5 3 3600 20120814220826 "
+ "20120715220826 1234 example.org. FAKE"));
+ addToZoneData(rr_nsec_);
+ findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, rr_nsec_,
+ ZoneFinder::RESULT_NSEC_SIGNED, NULL,
+ ZoneFinder::FIND_DNSSEC);
+
+ // Specified type of RR doesn't exist, with DNSSEC, enabling NSEC3. First,
+ // make the zone "NSEC3-signed" (by just installing NSEC3PARAM; we don't
+ // need to add NSEC3s for the purpose of this test), then check.
+ addToZoneData(textToRRset("example.org. 300 IN NSEC3PARAM "
+ "1 0 12 aabbccdd"));
+ findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
+ ZoneFinder::RESULT_NSEC3_SIGNED, NULL,
+ ZoneFinder::FIND_DNSSEC);
+}
+
+TEST_F(InMemoryZoneFinderTest, findAtOriginWithMinTTL) {
+ // Install zone's SOA. This also sets internal zone data min TTL field.
+ addToZoneData(rr_soa_);
+
+ // Specify the use of min TTL, then the resulting TTL should be derived
+ // from the SOA MINTTL (which is smaller).
+ findAtOriginTest(RRType::SOA(), ZoneFinder::SUCCESS, true,
+ textToRRset("example.org. 100 IN SOA . . 0 0 0 0 100",
+ class_, origin_),
+ ZoneFinder::RESULT_DEFAULT, NULL,
+ ZoneFinder::FIND_DEFAULT, true);
+
+ // Add signed NS for the following test.
+ RRsetPtr ns_rrset(textToRRset("example.org. 300 IN NS ns.example.org."));
+ ns_rrset->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
+ "NS 5 3 3600 20120814220826 20120715220826 "
+ "1234 example.org. FAKE"));
+ addToZoneData(ns_rrset);
+
+ // If DNSSEC is requested, TTL of the RRSIG should also be the min.
+ ns_rrset->setTTL(RRTTL(100)); // reset TTL to the expected one
+ findAtOriginTest(RRType::NS(), ZoneFinder::SUCCESS, true, ns_rrset,
+ ZoneFinder::RESULT_DEFAULT, NULL,
+ ZoneFinder::FIND_DEFAULT, true);
+
+ // If we don't request the use of min TTL, the original TTL will be used.
+ findAtOriginTest(RRType::SOA(), ZoneFinder::SUCCESS, true, rr_soa_,
+ ZoneFinder::RESULT_DEFAULT, NULL,
+ ZoneFinder::FIND_DEFAULT, false);
+
+ // If the found RRset has a smaller TTL than SOA, the original TTL should
+ // win.
+ rr_a_->setTTL(RRTTL(10));
+ addToZoneData(rr_a_);
+ findAtOriginTest(RRType::A(), ZoneFinder::SUCCESS, true, rr_a_,
+ ZoneFinder::RESULT_DEFAULT, NULL,
+ ZoneFinder::FIND_DEFAULT, true);
+
+ // If no RRset is returned, use_minttl doesn't matter (it shouldn't cause
+ // disruption)
+ findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
+ ZoneFinder::RESULT_DEFAULT, NULL,
+ ZoneFinder::FIND_DEFAULT, true);
+
+ // If it results in NXRRSET with NSEC, and if we specify the use of min
+ // TTL, the NSEC and RRSIG should have the min TTL (again, though, this
+ // use case is not really the intended one)
+ rr_nsec_->addRRsig(createRdata(RRType::RRSIG(), RRClass::IN(),
+ "NSEC 5 3 3600 20120814220826 "
+ "20120715220826 1234 example.org. FAKE"));
+ addToZoneData(rr_nsec_);
+ rr_nsec_->setTTL(RRTTL(100)); // reset it to the expected one
+ findAtOriginTest(RRType::TXT(), ZoneFinder::NXRRSET, true, rr_nsec_,
+ ZoneFinder::RESULT_NSEC_SIGNED, NULL,
+ ZoneFinder::FIND_DNSSEC, true);
+}
+
/**
* \brief Test searching.
*
More information about the bind10-changes
mailing list