Browse Source

[2107] added NSEC3Data

JINMEI Tatuya 12 years ago
parent
commit
042e617963

+ 31 - 2
src/lib/datasrc/memory/tests/zone_data_unittest.cc

@@ -14,6 +14,8 @@
 
 #include "memory_segment_test.h"
 
+#include <dns/rdataclass.h>
+
 #include <exceptions/exceptions.h>
 
 #include <dns/name.h>
@@ -31,6 +33,7 @@
 #include <new>                  // for bad_alloc
 
 using namespace isc::dns;
+using namespace isc::dns::rdata;
 using namespace isc::datasrc::memory;
 using namespace isc::datasrc::memory::test;
 using namespace isc::testutils;
@@ -83,9 +86,9 @@ TEST_F(ZoneDataTest, addRdataSets) {
     ConstRRsetPtr a_rrset_ =
         textToRRset("www.example.com. 3600 IN A 192.0.2.1");
 
-    ZoneData::ZoneNode* node = NULL;
+    ZoneNode* node = NULL;
     zone_data_->insertName(mem_sgmt_, a_rrset_->getName(), &node);
-    ASSERT_NE(static_cast<ZoneData::ZoneNode*>(NULL), node);
+    ASSERT_NE(static_cast<ZoneNode*>(NULL), node);
     EXPECT_TRUE(node->isEmpty()); // initially it should be empty
 
     RdataSet* rdataset_a =
@@ -102,4 +105,30 @@ TEST_F(ZoneDataTest, addRdataSets) {
 
     // TearDown() will confirm there's no leak on destroy
 }
+
+class NSEC3DataTest : public ::testing::Test {
+protected:
+    NSEC3DataTest() : param_rdata_("1 0 12 aabbccdd")
+    {}
+    void TearDown() {
+        // detect any memory leak in the test memory segment
+        EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
+    }
+
+    MemorySegmentTest mem_sgmt_;
+    NSEC3Data* nsec3_data_;
+    const generic::NSEC3PARAM param_rdata_;
+};
+
+TEST_F(NSEC3DataTest, create) {
+    nsec3_data_ = NSEC3Data::create(mem_sgmt_, param_rdata_);
+    EXPECT_EQ(0, nsec3_data_->getNSEC3Tree()->getNodeCount());
+    EXPECT_EQ(1, nsec3_data_->hashalg);
+    EXPECT_EQ(0, nsec3_data_->flags);
+    EXPECT_EQ(12, nsec3_data_->iterations);
+    EXPECT_EQ(param_rdata_.getSalt().size(), nsec3_data_->getSaltLen());
+    EXPECT_EQ(0, memcmp(&param_rdata_.getSalt()[0], nsec3_data_->getSaltData(),
+                        param_rdata_.getSalt().size()));
+    NSEC3Data::destroy(mem_sgmt_, nsec3_data_, RRClass::IN());
+}
 }

+ 32 - 0
src/lib/datasrc/memory/zone_data.cc

@@ -16,6 +16,7 @@
 
 #include <dns/name.h>
 #include <dns/rrclass.h>
+#include <dns/rdataclass.h>
 
 #include "rdataset.h"
 #include "rdata_encoder.h"
@@ -29,6 +30,7 @@
 #include <new>                  // for the placement new
 
 using namespace isc::dns;
+using namespace isc::dns::rdata;
 
 namespace isc {
 namespace datasrc {
@@ -52,6 +54,36 @@ nullDeleter(RdataSet* rdataset_head) {
 }
 }
 
+NSEC3Data*
+NSEC3Data::create(util::MemorySegment& mem_sgmt,
+                  const generic::NSEC3PARAM& rdata)
+{
+    ZoneTree* tree = ZoneTree::create(mem_sgmt, true);
+
+    const size_t salt_len = rdata.getSalt().size();
+
+    void* p = mem_sgmt.allocate(sizeof(NSEC3Data) + salt_len + 1);
+    NSEC3Data* const param_data =
+        new(p) NSEC3Data(tree, rdata.getHashalg(), rdata.getFlags(),
+                         rdata.getIterations());
+    uint8_t* dp = param_data->getSaltBuf();
+    *dp++ =  salt_len;
+    memcpy(dp, &rdata.getSalt().at(0), salt_len); // use at for safety
+
+    return (param_data);
+}
+
+void
+NSEC3Data::destroy(util::MemorySegment& mem_sgmt, NSEC3Data* data,
+                   RRClass nsec3_class)
+{
+    ZoneTree::destroy(mem_sgmt, data->nsec3_tree_.get(),
+                      boost::bind(rdataSetDeleter, nsec3_class, &mem_sgmt,
+                                  _1));
+
+    mem_sgmt.deallocate(data, sizeof(NSEC3Data) + 1 + data->getSaltLen());
+}
+
 ZoneData*
 ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
     // ZoneTree::insert() and ZoneData allocation can throw.  To avoid

+ 47 - 2
src/lib/datasrc/memory/zone_data.h

@@ -27,13 +27,58 @@
 #include <boost/noncopyable.hpp>
 
 namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+class NSEC3PARAM;
+}
+}
+}
+
 namespace datasrc {
 namespace memory {
 
+typedef DomainTree<RdataSet> ZoneTree;
+typedef DomainTreeNode<RdataSet> ZoneNode;
+
+class NSEC3Data : boost::noncopyable {
+public:
+    static NSEC3Data* create(util::MemorySegment& mem_sgmt,
+                             const dns::rdata::generic::NSEC3PARAM& rdata);
+    static void destroy(util::MemorySegment& mem_sgmt, NSEC3Data* data,
+                        dns::RRClass nsec3_class);
+
+    const boost::interprocess::offset_ptr<ZoneTree> nsec3_tree_;
+public:
+    const uint8_t hashalg;
+    const uint8_t flags;
+    const uint16_t iterations;
+    // For 64-bit machines there'll be a padding space here, but since
+    // only at most one (or a few in very rare cases) instance will be
+    // created per zone, the overhead should be acceptable.
+
+    const ZoneTree* getNSEC3Tree() const { return (nsec3_tree_.get()); }
+    ZoneTree* getNSEC3Tree() { return (nsec3_tree_.get()); }
+    size_t getSaltLen() const { return (*getSaltBuf()); }
+    const uint8_t* getSaltData() const { return (getSaltBuf() + 1); }
+
+private:
+    NSEC3Data(ZoneTree* nsec3_tree_param, uint8_t hashalg_param,
+              uint8_t flags_param, uint16_t iterations_param) :
+        nsec3_tree_(nsec3_tree_param), hashalg(hashalg_param),
+        flags(flags_param), iterations(iterations_param)
+    {}
+
+    const uint8_t* getSaltBuf() const {
+        return (reinterpret_cast<const uint8_t*>(this + 1));
+    }
+    uint8_t* getSaltBuf() {
+        return (reinterpret_cast<uint8_t*>(this + 1));
+    }
+};
+
 class ZoneData : boost::noncopyable {
 public:
-    typedef DomainTree<RdataSet> ZoneTree;
-    typedef DomainTreeNode<RdataSet> ZoneNode;
 
 private:
     ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :