From 6ff25a392e3d15ae5a9aa1ca11a4badeb95bf39d Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 24 Jan 2013 18:27:00 -0800 Subject: [PATCH] [2310] update ZoneData so it can store/return the "minimum" TTL. --- src/lib/datasrc/memory/zone_data.cc | 27 +++++++++ src/lib/datasrc/memory/zone_data.h | 55 +++++++++++++++++-- .../tests/memory/zone_data_unittest.cc | 28 ++++++++-- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/lib/datasrc/memory/zone_data.cc b/src/lib/datasrc/memory/zone_data.cc index cc314196ff..f9c0e3aa4f 100644 --- a/src/lib/datasrc/memory/zone_data.cc +++ b/src/lib/datasrc/memory/zone_data.cc @@ -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((val & 0xff000000) >> 24); + buf[1] = static_cast((val & 0x00ff0000) >> 16); + buf[2] = static_cast((val & 0x0000ff00) >> 8); + buf[3] = static_cast(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 diff --git a/src/lib/datasrc/memory/zone_data.h b/src/lib/datasrc/memory/zone_data.h index 14e6e6dfff..c6b3dcca47 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: @@ -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 zone_tree_; const boost::interprocess::offset_ptr origin_node_; boost::interprocess::offset_ptr nsec3_data_; + uint32_t min_ttl_; }; } // namespace memory diff --git a/src/lib/datasrc/tests/memory/zone_data_unittest.cc b/src/lib/datasrc/tests/memory/zone_data_unittest.cc index 1605fa2951..ffbd0f66bc 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 +#include +#include + #include "memory_segment_test.h" #include #include +#include + #include #include #include - -#include -#include -#include +#include #include @@ -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())); +} }