#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>
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)));
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(),
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;
}
}
+ 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),
boost::shared_ptr<ZoneFinder::Context>
InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
- bool /*use_minttl*/, // not yet supported
+ bool use_minttl,
const FindOptions options)
{
const ZoneNode* const node = zone_data_.getOriginNode();
return (ZoneFinderContextPtr(
new Context(*this, options, rrclass_,
createFindResult(rrclass_, zone_data_, SUCCESS,
- node, found, options))));
+ node, found, options, false,
+ NULL, use_minttl))));
}
return (ZoneFinderContextPtr(
new Context(*this, options, rrclass_,
getNSECForNXRRSET(zone_data_,
options,
node),
- options))));
+ options, false, NULL,
+ use_minttl))));
}
ZoneFinderResultContext
/// be a concern here.
ConstRRsetPtr
convertRRset(ConstRRsetPtr src) {
- return (textToRRset(src->toText()));
+ // If the type is SOA, textToRRset performs a stricter check, so we should
+ // specify the origin.
+ const Name& origin = (src->getType() == RRType::SOA()) ?
+ src->getName() : Name::ROOT_NAME();
+ return (textToRRset(src->toText(), src->getClass(), origin));
}
/// \brief Test fixture for the InMemoryZoneFinder class
memory::InMemoryZoneFinder* zone_finder = NULL,
ZoneFinder::FindOptions options =
ZoneFinder::FIND_DEFAULT,
- bool check_wild_answer = false)
+ bool use_minttl = false)
{
SCOPED_TRACE("findAtOriginTest for " + rrtype.toText());
zone_finder = &zone_finder_;
}
ZoneFinderContextPtr find_result(zone_finder->findAtOrigin(
- rrtype, false, options));
+ rrtype, use_minttl, options));
findTestCommon(origin_, result, find_result, check_answer, answer,
- expected_flags, options, check_wild_answer);
+ expected_flags, options, false);
}
private:
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,
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 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.
*