Commit 6ff25a39 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2310] update ZoneData so it can store/return the "minimum" TTL.

parent 9dbce1aa
......@@ -134,6 +134,28 @@ 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.
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 +200,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
......@@ -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:
......@@ -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
......
......@@ -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()));
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment