BIND 10 trac3145, updated. 537e404c74470a717a4044260d7076b4b1a805ce [3145] Added 2 new tests for IAPREFIX

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Sep 10 09:52:42 UTC 2013


The branch, trac3145 has been updated
       via  537e404c74470a717a4044260d7076b4b1a805ce (commit)
       via  660f725b6fb6b326668d7c3c4395ec90b018535d (commit)
       via  8f3591204bb394d7b2aa00508e99ec71a5720a8b (commit)
      from  302a01c6707d2f46d9c4077eb9fb726533fad50c (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 537e404c74470a717a4044260d7076b4b1a805ce
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Tue Sep 10 11:52:26 2013 +0200

    [3145] Added 2 new tests for IAPREFIX

commit 660f725b6fb6b326668d7c3c4395ec90b018535d
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Tue Sep 10 11:50:59 2013 +0200

    [3145] Several clean-ups in IAPREFIX option, prefix-len checked

commit 8f3591204bb394d7b2aa00508e99ec71a5720a8b
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Tue Sep 10 11:50:21 2013 +0200

    [3145] Added negative test case for IAADDR option

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

Summary of changes:
 src/lib/dhcp/option6_iaaddr.cc                  |    3 +
 src/lib/dhcp/option6_iaaddr.h                   |    8 +-
 src/lib/dhcp/option6_iaprefix.cc                |   12 +-
 src/lib/dhcp/option6_iaprefix.h                 |   25 ++--
 src/lib/dhcp/tests/option6_iaaddr_unittest.cc   |   15 ++
 src/lib/dhcp/tests/option6_iaprefix_unittest.cc |  166 ++++++++++++++++-------
 6 files changed, 167 insertions(+), 62 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/option6_iaaddr.cc b/src/lib/dhcp/option6_iaaddr.cc
index d0ba087..c452430 100644
--- a/src/lib/dhcp/option6_iaaddr.cc
+++ b/src/lib/dhcp/option6_iaaddr.cc
@@ -35,6 +35,9 @@ Option6IAAddr::Option6IAAddr(uint16_t type, const isc::asiolink::IOAddress& addr
                              uint32_t pref, uint32_t valid)
     :Option(V6, type), addr_(addr), preferred_(pref),
      valid_(valid) {
+    if (!addr.isV6()) {
+        isc_throw(isc::BadValue, addr_.toText() << " is not an IPv6 address");
+    }
 }
 
 Option6IAAddr::Option6IAAddr(uint32_t type, OptionBuffer::const_iterator begin,
diff --git a/src/lib/dhcp/option6_iaaddr.h b/src/lib/dhcp/option6_iaaddr.h
index cb85bed..c188f88 100644
--- a/src/lib/dhcp/option6_iaaddr.h
+++ b/src/lib/dhcp/option6_iaaddr.h
@@ -33,7 +33,9 @@ public:
     /// length of the fixed part of the IAADDR option
     static const size_t OPTION6_IAADDR_LEN = 24;
 
-    /// @brief Ctor, used for options constructed (during transmission).
+    /// @brief Constructor, used for options constructed (during transmission).
+    ///
+    /// @throw BadValue if specified addr is not IPv6
     ///
     /// @param type option type
     /// @param addr reference to an address
@@ -42,7 +44,9 @@ public:
     Option6IAAddr(uint16_t type, const isc::asiolink::IOAddress& addr,
                   uint32_t preferred, uint32_t valid);
 
-    /// @brief ctor, used for received options.
+    /// @brief Constructor, used for received options.
+    ///
+    /// @throw OutOfRange if specified option is truncated
     ///
     /// @param type option type
     /// @param begin iterator to first byte of option data
diff --git a/src/lib/dhcp/option6_iaprefix.cc b/src/lib/dhcp/option6_iaprefix.cc
index 403b11f..f942405 100644
--- a/src/lib/dhcp/option6_iaprefix.cc
+++ b/src/lib/dhcp/option6_iaprefix.cc
@@ -34,6 +34,11 @@ namespace dhcp {
 Option6IAPrefix::Option6IAPrefix(uint16_t type, const isc::asiolink::IOAddress& prefix,
                                  uint8_t prefix_len, uint32_t pref, uint32_t valid)
     :Option6IAAddr(type, prefix, pref, valid), prefix_len_(prefix_len) {
+    // Option6IAAddr will check if prefix is IPv6 and will throw if it is not
+    if (prefix_len > 128) {
+        isc_throw(BadValue, prefix_len << " is not a valid prefix length. "
+                  << "Allowed range is 0..128");
+    }
 }
 
 Option6IAPrefix::Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator begin,
@@ -44,8 +49,7 @@ Option6IAPrefix::Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator beg
 
 void Option6IAPrefix::pack(isc::util::OutputBuffer& buf) {
     if (!addr_.isV6()) {
-        isc_throw(isc::BadValue, addr_.toText()
-                  << " is not an IPv6 address");
+        isc_throw(isc::BadValue, addr_.toText() << " is not an IPv6 address");
     }
 
     buf.writeUint16(type_);
@@ -99,7 +103,7 @@ std::string Option6IAPrefix::toText(int indent /* =0 */) {
     for (OptionCollection::const_iterator opt=options_.begin();
          opt!=options_.end();
          ++opt) {
-        tmp << (*opt).second->toText(indent+2);
+        tmp << (*opt).second->toText(indent + 2);
     }
     return tmp.str();
 }
@@ -109,7 +113,7 @@ uint16_t Option6IAPrefix::len() {
     uint16_t length = OPTION6_HDR_LEN + OPTION6_IAPREFIX_LEN;
 
     // length of all suboptions
-    for (Option::OptionCollection::iterator it = options_.begin();
+    for (Option::OptionCollection::const_iterator it = options_.begin();
          it != options_.end(); ++it) {
         length += (*it).second->len();
     }
diff --git a/src/lib/dhcp/option6_iaprefix.h b/src/lib/dhcp/option6_iaprefix.h
index dddf556..0a790be 100644
--- a/src/lib/dhcp/option6_iaprefix.h
+++ b/src/lib/dhcp/option6_iaprefix.h
@@ -25,16 +25,16 @@ namespace dhcp {
 
 /// @brief Class that represents IAPREFIX option in DHCPv6
 ///
-/// It is based on a similar class that handles addresses.
-/// The major differences are fields order and prefix has also
+/// It is based on a similar class that handles addresses. There are major
+/// differences, though. The fields are in different order. There is also
 /// additional prefix length field.
 ///
-/// It should be noted that to get a full prefix (2 values: base address, and
+/// It should be noted that to get a full prefix (2 values: base prefix, and
 /// a prefix length) 2 methods are used: getAddress() and getLength(). Although
-/// using getAddress() to obtain base address is somewhat counter-intuitive at
+/// using getAddress() to obtain base prefix is somewhat counter-intuitive at
 /// first, it becomes obvious when one realizes that an address is a special
-/// case of a prefix with /128. It make everyone's like much easier, because
-/// the base address doubles as a regular address in many cases, e.g. when
+/// case of a prefix with /128. It makes everyone's like much easier, because
+/// the base prefix doubles as a regular address in many cases, e.g. when
 /// searching for a lease.
 class Option6IAPrefix : public Option6IAAddr {
 
@@ -42,7 +42,7 @@ public:
     /// length of the fixed part of the IAPREFIX option
     static const size_t OPTION6_IAPREFIX_LEN = 25;
 
-    /// @brief Ctor, used for options constructed (during transmission).
+    /// @brief Constructor, used for options constructed (during transmission).
     ///
     /// @param type option type
     /// @param addr reference to an address
@@ -52,7 +52,9 @@ public:
     Option6IAPrefix(uint16_t type, const isc::asiolink::IOAddress& addr,
                     uint8_t prefix_length, uint32_t preferred, uint32_t valid);
 
-    /// @brief ctor, used for received options.
+    /// @brief Constructor, used for received options.
+    ///
+    /// @throw OutOfRange if buffer is too short
     ///
     /// @param type option type
     /// @param begin iterator to first byte of option data
@@ -65,11 +67,15 @@ public:
     /// Writes option in wire-format to buf, returns pointer to first unused
     /// byte after stored option.
     ///
+    /// @throw BadValue if the address is not IPv6
+    ///
     /// @param buf pointer to a buffer
     void pack(isc::util::OutputBuffer& buf);
 
     /// @brief Parses received buffer.
     ///
+    /// @throw OutOfRange when buffer is shorter than 25 bytes
+    ///
     /// @param begin iterator to first byte of option data
     /// @param end iterator to end of option data (first byte after option end)
     virtual void unpack(OptionBufferConstIter begin,
@@ -80,8 +86,7 @@ public:
     /// @param indent number of spaces before printing text
     ///
     /// @return string with text representation.
-    virtual std::string
-    toText(int indent = 0);
+    virtual std::string toText(int indent = 0);
 
     /// sets address in this option.
     ///
diff --git a/src/lib/dhcp/tests/option6_iaaddr_unittest.cc b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
index e28e2e0..d2e6a15 100644
--- a/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
+++ b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
@@ -106,4 +106,19 @@ TEST_F(Option6IAAddrTest, basic) {
     EXPECT_NO_THROW(opt.reset());
 }
 
+/// @todo: Write test for (type, addr, pref, valid) constructor
+/// See option6_iaprefix_unittest.cc for similar test
+
+// Tests if broken usage causes exception to be thrown
+TEST_F(Option6IAAddrTest, negative) {
+
+    // Too short. Minimum length is 24
+    EXPECT_THROW(Option6IAAddr(D6O_IAADDR, buf_.begin(), buf_.begin() + 23),
+                 OutOfRange);
+
+    // This option is for IPv6 addresses only
+    EXPECT_THROW(Option6IAAddr(D6O_IAADDR, isc::asiolink::IOAddress("192.0.2.1"),
+                               1000, 2000), BadValue);
+}
+
 }
diff --git a/src/lib/dhcp/tests/option6_iaprefix_unittest.cc b/src/lib/dhcp/tests/option6_iaprefix_unittest.cc
index ad22c54..45701b2 100644
--- a/src/lib/dhcp/tests/option6_iaprefix_unittest.cc
+++ b/src/lib/dhcp/tests/option6_iaprefix_unittest.cc
@@ -31,6 +31,7 @@ using namespace std;
 using namespace isc;
 using namespace isc::dhcp;
 using namespace isc::util;
+using namespace isc::asiolink;
 
 namespace {
 class Option6IAPrefixTest : public ::testing::Test {
@@ -40,74 +41,147 @@ public:
             buf_[i] = 255 - i;
         }
     }
+
+    /// @brief creates on-wire representation of IAPREFIX option
+    ///
+    /// buf_ field is set up to have IAPREFIX with preferred=1000,
+    /// valid=3000000000 and prefix beign 2001:db8:1::dead:beef/77
+    void setExampleBuffer() {
+        for (int i = 0; i < 255; i++) {
+            buf_[i] = 0;
+        }
+
+        buf_[ 0] = 0x00;
+        buf_[ 1] = 0x00;
+        buf_[ 2] = 0x03;
+        buf_[ 3] = 0xe8; // preferred lifetime = 1000
+
+        buf_[ 4]  = 0xb2;
+        buf_[ 5] = 0xd0;
+        buf_[ 6] = 0x5e;
+        buf_[ 7] = 0x00; // valid lifetime = 3,000,000,000
+
+        buf_[ 8] = 77; // Prefix length = 77
+
+        buf_[ 9] = 0x20;
+        buf_[10] = 0x01;
+        buf_[11] = 0x0d;
+        buf_[12] = 0xb8;
+        buf_[13] = 0x00;
+        buf_[14] = 0x01;
+        buf_[21] = 0xde;
+        buf_[22] = 0xad;
+        buf_[23] = 0xbe;
+        buf_[24] = 0xef; // 2001:db8:1::dead:beef
+    }
+
+
+    /// @brief Checks whether specified IAPREFIX option meets expected values
+    ///
+    /// To be used with option generated by setExampleBuffer
+    ///
+    /// @param opt IAPREFIX option being tested
+    /// @param expected_type expected option type
+    void checkOption(Option6IAPrefix& opt, uint16_t expected_type) {
+
+        // Check if all fields have expected values
+        EXPECT_EQ(Option::V6, opt.getUniverse());
+        EXPECT_EQ(expected_type, opt.getType());
+        EXPECT_EQ("2001:db8:1::dead:beef", opt.getAddress().toText());
+        EXPECT_EQ(1000, opt.getPreferred());
+        EXPECT_EQ(3000000000U, opt.getValid());
+        EXPECT_EQ(77, opt.getLength());
+
+        // 4 bytes header + 25 bytes content
+        EXPECT_EQ(Option::OPTION6_HDR_LEN + Option6IAPrefix::OPTION6_IAPREFIX_LEN,
+                  opt.len());
+    }
+
+    /// @brief Checks whether content of output buffer is correct
+    ///
+    /// Output buffer is expected to be filled with an option matchin
+    /// buf_ content as defined in setExampleBuffer().
+    ///
+    /// @param expected_type expected option type
+    void checkOutputBuffer(uint16_t expected_type) {
+        // Check if pack worked properly:
+        const uint8_t* out = (const uint8_t*)outBuf_.getData();
+
+        // - if option type is correct
+        EXPECT_EQ(expected_type, out[0]*256 + out[1]);
+
+        // - if option length is correct
+        EXPECT_EQ(25, out[2]*256 + out[3]);
+
+        // - if option content is correct
+        EXPECT_EQ(0, memcmp(out + 4, &buf_[0], 25));
+    }
+
     OptionBuffer buf_;
     OutputBuffer outBuf_;
 };
 
+// Tests if receiving option can be parsed correctly
 TEST_F(Option6IAPrefixTest, basic) {
-    for (int i = 0; i < 255; i++) {
-        buf_[i] = 0;
-    }
 
-    buf_[ 0] = 0x00;
-    buf_[ 1] = 0x00;
-    buf_[ 2] = 0x03;
-    buf_[ 3] = 0xe8; // preferred lifetime = 1000
-
-    buf_[ 4]  = 0xb2;
-    buf_[ 5] = 0xd0;
-    buf_[ 6] = 0x5e;
-    buf_[ 7] = 0x00; // valid lifetime = 3,000,000,000
-
-    buf_[ 8] = 77; // Prefix length = 77
-
-    buf_[ 9] = 0x20;
-    buf_[10] = 0x01;
-    buf_[11] = 0x0d;
-    buf_[12] = 0xb8;
-    buf_[13] = 0x00;
-    buf_[14] = 0x01;
-    buf_[21] = 0xde;
-    buf_[22] = 0xad;
-    buf_[23] = 0xbe;
-    buf_[24] = 0xef; // 2001:db8:1::dead:beef
+    setExampleBuffer();
 
     // Create an option (unpack content)
-    boost::scoped_ptr<Option6IAPrefix> opt(new Option6IAPrefix(D6O_IAPREFIX,
-                                                           buf_.begin(),
-                                                           buf_.begin() + 25));
+    boost::scoped_ptr<Option6IAPrefix> opt;
+    EXPECT_NO_THROW(opt.reset(new Option6IAPrefix(D6O_IAPREFIX, buf_.begin(),
+                                                  buf_.begin() + 25)));
 
     // Pack this option
     opt->pack(outBuf_);
-
     EXPECT_EQ(29, outBuf_.getLength());
 
-    EXPECT_EQ(Option::V6, opt->getUniverse());
+    checkOption(*opt, D6O_IAPREFIX);
 
-    // 4 bytes header + 4 bytes content
-    EXPECT_EQ("2001:db8:1::dead:beef", opt->getAddress().toText());
-    EXPECT_EQ(1000, opt->getPreferred());
-    EXPECT_EQ(3000000000U, opt->getValid());
-    EXPECT_EQ(77, opt->getLength());
+    checkOutputBuffer(D6O_IAPREFIX);
 
-    EXPECT_EQ(D6O_IAPREFIX, opt->getType());
+    // Check that option can be disposed safely
+    EXPECT_NO_THROW(opt.reset());
+}
 
-    EXPECT_EQ(Option::OPTION6_HDR_LEN + Option6IAPrefix::OPTION6_IAPREFIX_LEN,
-              opt->len());
+// Checks whether a new option can be built correctly
+TEST_F(Option6IAPrefixTest, build) {
 
-    // Check if pack worked properly:
-    const uint8_t* out = (const uint8_t*)outBuf_.getData();
+    boost::scoped_ptr<Option6IAPrefix> opt;
+    setExampleBuffer();
 
-    // - if option type is correct
-    EXPECT_EQ(D6O_IAPREFIX, out[0]*256 + out[1]);
+    EXPECT_NO_THROW(opt.reset(new Option6IAPrefix(12345,
+                    IOAddress("2001:db8:1::dead:beef"), 77, 1000, 3000000000)));
+    ASSERT_TRUE(opt);
 
-    // - if option length is correct
-    EXPECT_EQ(25, out[2]*256 + out[3]);
+    checkOption(*opt, 12345);
 
-    // - if option content is correct
-    EXPECT_EQ(0, memcmp(out + 4, &buf_[0], 25));
+    // Check if we can build it properly
+    EXPECT_NO_THROW(opt->pack(outBuf_));
+    EXPECT_EQ(29, outBuf_.getLength());
+    checkOutputBuffer(12345);
 
+    // Check that option can be disposed safely
     EXPECT_NO_THROW(opt.reset());
 }
 
+// Checks negative cases
+TEST_F(Option6IAPrefixTest, negative) {
+
+    // Truncated option (at least 25 bytes is needed)
+    EXPECT_THROW(Option6IAPrefix(D6O_IAPREFIX, buf_.begin(), buf_.begin() + 24),
+                 OutOfRange);
+
+    // Empty option
+    EXPECT_THROW(Option6IAPrefix(D6O_IAPREFIX, buf_.begin(), buf_.begin()),
+                 OutOfRange);
+
+    // This is for IPv6 prefixes only
+    EXPECT_THROW(Option6IAPrefix(12345, IOAddress("192.0.2.1"), 77, 1000, 2000),
+                 BadValue);
+
+    // Prefix length can't be larger than 128
+    EXPECT_THROW(Option6IAPrefix(12345, IOAddress("192.0.2.1"), 255, 1000, 2000),
+                 BadValue);
+}
+
 }



More information about the bind10-changes mailing list