BIND 10 trac2312, updated. 276a08d3371eef268c0e0b738d0c8583c3d8641d [2312] Implement pack and unpack.

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Nov 27 12:44:03 UTC 2012


The branch, trac2312 has been updated
       via  276a08d3371eef268c0e0b738d0c8583c3d8641d (commit)
      from  0a5970240b9e8ae08e4a06b67a0678a19b5def45 (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 276a08d3371eef268c0e0b738d0c8583c3d8641d
Author: Marcin Siodelski <marcin at isc.org>
Date:   Tue Nov 27 13:43:54 2012 +0100

    [2312] Implement pack and unpack.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dhcp/option_custom.cc                |   24 ++--
 src/lib/dhcp/option_custom.h                 |   12 +-
 src/lib/dhcp/tests/option_custom_unittest.cc |  180 ++++++++++++++++++++++++++
 3 files changed, 196 insertions(+), 20 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/option_custom.cc b/src/lib/dhcp/option_custom.cc
index cdaa305..d4ffb32 100644
--- a/src/lib/dhcp/option_custom.cc
+++ b/src/lib/dhcp/option_custom.cc
@@ -116,8 +116,13 @@ OptionCustom::pack4(isc::util::OutputBuffer& buf) {
     buf.writeUint8(type_);
     buf.writeUint8(len() - getHeaderLen());
 
-    // @todo write option data here
+    // Write data from buffers.
+    for (std::vector<OptionBuffer>::const_iterator it = buffers_.begin();
+         it != buffers_.end(); ++it) {
+        buf.writeData(&(*it)[0], it->size());
+    }
 
+    // Write suboptions.
     LibDHCP::packOptions(buf, options_);
 }
 
@@ -126,7 +131,11 @@ OptionCustom::pack6(isc::util::OutputBuffer& buf) {
     buf.writeUint16(type_);
     buf.writeUint16(len() - getHeaderLen());
 
-    // @todo write option data here.
+    // Write data from buffers.
+    for (std::vector<OptionBuffer>::const_iterator it = buffers_.begin();
+         it != buffers_.end(); ++it) {
+        buf.writeData(&(*it)[0], it->size());
+    }
 
     LibDHCP::packOptions(buf, options_);
 }
@@ -168,8 +177,10 @@ OptionCustom::readString(const uint32_t index, std::string& value) const {
 
 void
 OptionCustom::unpack(OptionBufferConstIter begin,
-                           OptionBufferConstIter end) {
+                     OptionBufferConstIter end) {
     data_ = OptionBuffer(begin, end);
+    // Chop the buffer stored in data_ into set of sub buffers.
+    createBuffers();
 }
 
 uint16_t
@@ -180,7 +191,7 @@ OptionCustom::len() {
     // ... lengths of all buffers that hold option data ...
     for (std::vector<OptionBuffer>::const_iterator buf = buffers_.begin();
          buf != buffers_.end(); ++buf) {
-        length += buf.size();
+        length += buf->size();
     }
 
     // ... and lengths of all suboptions
@@ -193,11 +204,6 @@ OptionCustom::len() {
     return (length);
 }
 
-bool
-OptionCustom::valid() {
-    return (Option::valid());
-}
-
 std::string OptionCustom::toText(int /* =0 */ ) {
     std::stringstream tmp;
 
diff --git a/src/lib/dhcp/option_custom.h b/src/lib/dhcp/option_custom.h
index ecf7167..5c792cb 100644
--- a/src/lib/dhcp/option_custom.h
+++ b/src/lib/dhcp/option_custom.h
@@ -91,6 +91,7 @@ public:
     /// @brief Read a buffer as integer value.
     ///
     /// @param index buffer index.
+    /// @tparam integer type of a value being returned.
     ///
     /// @throw isc::OutOfRange if index is out of range.
     /// @return read integer value.
@@ -161,17 +162,6 @@ public:
     /// @return length of the option
     virtual uint16_t len();
 
-    /// Check if option is valid.
-    ///
-    /// @return true, if option is valid.
-    virtual bool valid();
-
-    /// Returns pointer to actual data.
-    ///
-    /// @return pointer to actual data (or reference to an empty vector
-    /// if there is no data).
-    virtual const OptionBuffer& getData() { return (data_); }
-
     /// @brief Sets content of this option from buffer.
     ///
     /// Option will be resized to length of buffer.
diff --git a/src/lib/dhcp/tests/option_custom_unittest.cc b/src/lib/dhcp/tests/option_custom_unittest.cc
index e2edd54..bdb0322 100644
--- a/src/lib/dhcp/tests/option_custom_unittest.cc
+++ b/src/lib/dhcp/tests/option_custom_unittest.cc
@@ -437,4 +437,184 @@ TEST_F(OptionCustomTest, recordData) {
     EXPECT_EQ("ABCD", value4);
 }
 
+// The purpose of this test is to verify that pack function for
+// DHCPv4 custom option works correctly.
+TEST_F(OptionCustomTest, pack4) {
+    OptionDefinition opt_def("OPTION_FOO", 234, "record");
+    ASSERT_NO_THROW(opt_def.addRecordField("uint8"));
+    ASSERT_NO_THROW(opt_def.addRecordField("uint16"));
+    ASSERT_NO_THROW(opt_def.addRecordField("uint32"));
+
+    OptionBuffer buf;
+    writeInt<uint8_t>(1, buf);
+    writeInt<uint16_t>(1000, buf);
+    writeInt<uint32_t>(100000, buf);
+
+    boost::scoped_ptr<OptionCustom> option;
+    ASSERT_NO_THROW(
+        option.reset(new OptionCustom(opt_def, Option::V4, buf));
+    );
+    ASSERT_TRUE(option);
+
+    util::OutputBuffer buf_out(7);
+    ASSERT_NO_THROW(option->pack(buf_out));
+    ASSERT_EQ(9, buf_out.getLength());
+
+    // The original buffer holds the option data but it lacks a header.
+    // We append data length and option code so as it can be directly
+    // compared with the output buffer that holds whole option.
+    buf.insert(buf.begin(), 7);
+    buf.insert(buf.begin(), 234);
+
+    // Validate the buffer.
+    EXPECT_EQ(0, memcmp(&buf[0], buf_out.getData(), 7));
+}
+
+// The purpose of this test is to verify that pack function for
+// DHCPv6 custom option works correctly.
+TEST_F(OptionCustomTest, pack6) {
+    OptionDefinition opt_def("OPTION_FOO", 1000, "record");
+    ASSERT_NO_THROW(opt_def.addRecordField("boolean"));
+    ASSERT_NO_THROW(opt_def.addRecordField("uint16"));
+    ASSERT_NO_THROW(opt_def.addRecordField("string"));
+
+    OptionBuffer buf;
+    buf.push_back(1);
+    writeInt<uint16_t>(1000, buf);
+    writeString("hello world", buf);
+
+    boost::scoped_ptr<OptionCustom> option;
+    ASSERT_NO_THROW(
+        option.reset(new OptionCustom(opt_def, Option::V6, buf));
+    );
+    ASSERT_TRUE(option);
+
+    util::OutputBuffer buf_out(buf.size() + option->getHeaderLen());
+    ASSERT_NO_THROW(option->pack(buf_out));
+    ASSERT_EQ(buf.size() + option->getHeaderLen(), buf_out.getLength());
+
+    // The original buffer holds the option data but it lacks a header.
+    // We append data length and option code so as it can be directly
+    // compared with the output buffer that holds whole option.
+    OptionBuffer tmp;
+    writeInt<uint16_t>(1000, tmp);
+    writeInt<uint16_t>(buf.size(), tmp);
+    buf.insert(buf.begin(), tmp.begin(), tmp.end());
+
+    // Validate the buffer.
+    EXPECT_EQ(0, memcmp(&buf[0], buf_out.getData(), 7));
+}
+
+// The purpose of this test is to verify that unpack function works
+// correctly for a custom option.
+TEST_F(OptionCustomTest, unpack) {
+    OptionDefinition opt_def("OPTION_FOO", 231, "ipv4-address", true);
+
+    // Initialize reference data.
+    std::vector<IOAddress> addresses;
+    addresses.push_back(IOAddress("192.168.0.1"));
+    addresses.push_back(IOAddress("127.0.0.1"));
+    addresses.push_back(IOAddress("10.10.1.2"));
+
+    // Store the collection of IPv4 addresses into the buffer.
+    OptionBuffer buf;
+    for (int i = 0; i < addresses.size(); ++i) {
+        writeAddress(addresses[i], buf);
+    }
+
+    // Use the input buffer to create custom option.
+    boost::scoped_ptr<OptionCustom> option;
+    ASSERT_NO_THROW(
+        option.reset(new OptionCustom(opt_def, Option::V4, buf.begin(), buf.begin() + 13));
+    );
+    ASSERT_TRUE(option);
+
+    // We expect 3 IPv4 addresses being stored in the option.
+    for (int i = 0; i < 3; ++i) {
+        IOAddress address("10.10.10.10");
+        ASSERT_NO_THROW(option->readAddress(i, address));
+        EXPECT_EQ(addresses[i].toText(), address.toText());
+    }
+
+    // Remove all addresses we had added. We are going to replace
+    // them with a new set of addresses.
+    addresses.clear();
+
+    // Add new addresses.
+    addresses.push_back(IOAddress("10.1.2.3"));
+    addresses.push_back(IOAddress("85.26.43.234"));
+
+    // Clear the buffer as we need to store new addresses in it.
+    buf.clear();
+    for (int i = 0; i < addresses.size(); ++i) {
+        writeAddress(addresses[i], buf);
+    }
+
+    // Perform 'unpack'.
+    ASSERT_NO_THROW(option->unpack(buf.begin(), buf.end()));
+
+    // Verify that the addresses have been overwritten.
+    for (int i = 0; i < 2; ++i) {
+        IOAddress address("10.10.10.10");
+        ASSERT_NO_THROW(option->readAddress(i, address));
+        EXPECT_EQ(addresses[i].toText(), address.toText());
+    }
+}
+
+// The purpose of this test is to verify that new data can be set for
+// a custom option.
+TEST_F(OptionCustomTest, setData) 
+{
+    OptionDefinition opt_def("OPTION_FOO", 1000, "ipv6-address", true);
+
+    // Initialize reference data.
+    std::vector<IOAddress> addresses;
+    addresses.push_back(IOAddress("2001:db8:1::3"));
+    addresses.push_back(IOAddress("::1"));
+    addresses.push_back(IOAddress("fe80::3"));
+
+    // Store the collection of IPv6 addresses into the buffer.
+    OptionBuffer buf;
+    for (int i = 0; i < addresses.size(); ++i) {
+        writeAddress(addresses[i], buf);
+    }
+
+    // Use the input buffer to create custom option.
+    boost::scoped_ptr<OptionCustom> option;
+    ASSERT_NO_THROW(
+        option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 70));
+    );
+    ASSERT_TRUE(option);
+
+    // We expect 3 IPv6 addresses being stored in the option.
+    for (int i = 0; i < 3; ++i) {
+        IOAddress address("fe80::4");
+        ASSERT_NO_THROW(option->readAddress(i, address));
+        EXPECT_EQ(addresses[i].toText(), address.toText());
+    }
+
+    // Clear addresses we had previously added.
+    addresses.clear();
+
+    // Store new addresses.
+    addresses.push_back(IOAddress("::1"));
+    addresses.push_back(IOAddress("fe80::10"));
+
+    // Clear the buffer as we need to store new addresses in it.
+    buf.clear();
+    for (int i = 0; i < addresses.size(); ++i) {
+        writeAddress(addresses[i], buf);
+    }
+
+    // Replace the option data.
+    ASSERT_NO_THROW(option->setData(buf.begin(), buf.end()));
+
+    // Check that it has been replaced.
+    for (int i = 0; i < 2; ++i) {
+        IOAddress address("10.10.10.10");
+        ASSERT_NO_THROW(option->readAddress(i, address));
+        EXPECT_EQ(addresses[i].toText(), address.toText());
+    }
+}
+
 } // anonymous namespace



More information about the bind10-changes mailing list