BIND 10 master, updated. bf6f8ee24cd9fee7c642114d3f1ca083625d6d9d [master] Merge branch 'trac3145' (IA_PD and IAPREFIX DHCPv6 options)
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Sep 10 19:00:07 UTC 2013
The branch, master has been updated
via bf6f8ee24cd9fee7c642114d3f1ca083625d6d9d (commit)
via 3a844e85ecc3067ccd1c01841f4a61366cb278f4 (commit)
via 9d3952fc9739348ccc34694c36036d7d46a5e273 (commit)
via 537e404c74470a717a4044260d7076b4b1a805ce (commit)
via 660f725b6fb6b326668d7c3c4395ec90b018535d (commit)
via 8f3591204bb394d7b2aa00508e99ec71a5720a8b (commit)
via 302a01c6707d2f46d9c4077eb9fb726533fad50c (commit)
via 066f45d1ddf9f6998904cfa8402ea0d3a3f287f8 (commit)
from 9273dca334ac61f89578b1b318b794325ced97d6 (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 bf6f8ee24cd9fee7c642114d3f1ca083625d6d9d
Merge: 9273dca 3a844e8
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Sep 10 20:59:51 2013 +0200
[master] Merge branch 'trac3145' (IA_PD and IAPREFIX DHCPv6 options)
Conflicts:
ChangeLog
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 9 +-
src/lib/dhcp/Makefile.am | 1 +
src/lib/dhcp/option6_ia.cc | 16 +-
src/lib/dhcp/option6_iaaddr.cc | 3 +
src/lib/dhcp/option6_iaaddr.h | 8 +-
.../{option6_iaaddr.cc => option6_iaprefix.cc} | 71 ++++----
.../dhcp/{option6_iaaddr.h => option6_iaprefix.h} | 96 ++++------
src/lib/dhcp/std_option_defs.h | 2 +-
src/lib/dhcp/tests/Makefile.am | 1 +
src/lib/dhcp/tests/option6_ia_unittest.cc | 186 +++++++++++++------
src/lib/dhcp/tests/option6_iaaddr_unittest.cc | 15 ++
src/lib/dhcp/tests/option6_iaprefix_unittest.cc | 188 ++++++++++++++++++++
12 files changed, 443 insertions(+), 153 deletions(-)
copy src/lib/dhcp/{option6_iaaddr.cc => option6_iaprefix.cc} (58%)
copy src/lib/dhcp/{option6_iaaddr.h => option6_iaprefix.h} (53%)
create mode 100644 src/lib/dhcp/tests/option6_iaprefix_unittest.cc
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 39c7247..1c23e07 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,12 @@
+673. [func] tomek
+ libdhcp: Added support for IA_PD and IAPREFIX options. New class
+ for IAPREFIX (Option6_IAPrefix) has been added.
+ (Trac #3145, git 3a844e85ecc3067ccd1c01841f4a61366cb278f4)
+
672. [func] tmark
Added b10-dhcp-ddnsupdate transaction base class, NameChangeTransaction.
- This class provides the common structure and methods to implement the state
- models described in the DHCP_DDNS design, plus integration with DNSClient
+ This class provides the common structure and methods to implement the state
+ models described in the DHCP_DDNS design, plus integration with DNSClient
and its callback mechanism for asynchronous IO with the DNS servers.
(Trac #3086, git 079b862c9eb21056fdf957e560b8fe7b218441b6)
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index 31ecdee..7402dbe 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -26,6 +26,7 @@ libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
libb10_dhcp___la_SOURCES += option4_client_fqdn.cc option4_client_fqdn.h
libb10_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
libb10_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
+libb10_dhcp___la_SOURCES += option6_iaprefix.cc option6_iaprefix.h
libb10_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
libb10_dhcp___la_SOURCES += option6_client_fqdn.cc option6_client_fqdn.h
libb10_dhcp___la_SOURCES += option_int.h
diff --git a/src/lib/dhcp/option6_ia.cc b/src/lib/dhcp/option6_ia.cc
index 64c2936..2efadd8 100644
--- a/src/lib/dhcp/option6_ia.cc
+++ b/src/lib/dhcp/option6_ia.cc
@@ -30,10 +30,24 @@ namespace dhcp {
Option6IA::Option6IA(uint16_t type, uint32_t iaid)
:Option(Option::V6, type), iaid_(iaid), t1_(0), t2_(0) {
+
+ // IA_TA has different layout than IA_NA and IA_PD. We can't sue this class
+ if (type == D6O_IA_TA) {
+ isc_throw(BadValue, "Can't use Option6IA for IA_TA as it has "
+ "a different layout");
+ }
}
-Option6IA::Option6IA(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
+Option6IA::Option6IA(uint16_t type, OptionBufferConstIter begin,
+ OptionBufferConstIter end)
:Option(Option::V6, type) {
+
+ // IA_TA has different layout than IA_NA and IA_PD. We can't use this class
+ if (type == D6O_IA_TA) {
+ isc_throw(BadValue, "Can't use Option6IA for IA_TA as it has "
+ "a different layout");
+ }
+
unpack(begin, end);
}
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
new file mode 100644
index 0000000..f942405
--- /dev/null
+++ b/src/lib/dhcp/option6_iaprefix.cc
@@ -0,0 +1,124 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <asiolink/io_address.h>
+#include <dhcp/dhcp6.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option6_iaprefix.h>
+#include <exceptions/exceptions.h>
+#include <util/io_utilities.h>
+
+#include <sstream>
+
+#include <stdint.h>
+#include <arpa/inet.h>
+
+using namespace std;
+using namespace isc::asiolink;
+using namespace isc::util;
+
+namespace isc {
+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,
+ OptionBuffer::const_iterator end)
+ :Option6IAAddr(type, begin, end) {
+ unpack(begin, end);
+}
+
+void Option6IAPrefix::pack(isc::util::OutputBuffer& buf) {
+ if (!addr_.isV6()) {
+ isc_throw(isc::BadValue, addr_.toText() << " is not an IPv6 address");
+ }
+
+ buf.writeUint16(type_);
+
+ // len() returns complete option length. len field contains
+ // length without 4-byte option header
+ buf.writeUint16(len() - getHeaderLen());
+
+ buf.writeUint32(preferred_);
+ buf.writeUint32(valid_);
+ buf.writeUint8(prefix_len_);
+
+ buf.writeData(&addr_.toBytes()[0], isc::asiolink::V6ADDRESS_LEN);
+
+ // store encapsulated options (the only defined so far is PD_EXCLUDE)
+ packOptions(buf);
+}
+
+void Option6IAPrefix::unpack(OptionBuffer::const_iterator begin,
+ OptionBuffer::const_iterator end) {
+ if ( distance(begin, end) < OPTION6_IAPREFIX_LEN) {
+ isc_throw(OutOfRange, "Option " << type_ << " truncated");
+ }
+
+ preferred_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
+
+ valid_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
+
+ prefix_len_ = *begin;
+ begin += sizeof(uint8_t);
+
+ // 16 bytes: IPv6 address
+ addr_ = IOAddress::fromBytes(AF_INET6, &(*begin));
+ begin += V6ADDRESS_LEN;
+
+ // unpack encapsulated options (the only defined so far is PD_EXCLUDE)
+ unpackOptions(OptionBuffer(begin, end));
+}
+
+std::string Option6IAPrefix::toText(int indent /* =0 */) {
+ stringstream tmp;
+ for (int i=0; i<indent; i++)
+ tmp << " ";
+
+ tmp << "type=" << type_ << "(IAPREFIX) prefix=" << addr_.toText() << "/"
+ << prefix_len_ << ", preferred-lft=" << preferred_ << ", valid-lft="
+ << valid_ << endl;
+
+ for (OptionCollection::const_iterator opt=options_.begin();
+ opt!=options_.end();
+ ++opt) {
+ tmp << (*opt).second->toText(indent + 2);
+ }
+ return tmp.str();
+}
+
+uint16_t Option6IAPrefix::len() {
+
+ uint16_t length = OPTION6_HDR_LEN + OPTION6_IAPREFIX_LEN;
+
+ // length of all suboptions
+ for (Option::OptionCollection::const_iterator it = options_.begin();
+ it != options_.end(); ++it) {
+ length += (*it).second->len();
+ }
+ return (length);
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
diff --git a/src/lib/dhcp/option6_iaprefix.h b/src/lib/dhcp/option6_iaprefix.h
new file mode 100644
index 0000000..0a790be
--- /dev/null
+++ b/src/lib/dhcp/option6_iaprefix.h
@@ -0,0 +1,109 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION6_IAPREFIX_H
+#define OPTION6_IAPREFIX_H
+
+#include <asiolink/io_address.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option.h>
+
+namespace isc {
+namespace dhcp {
+
+
+/// @brief Class that represents IAPREFIX option in DHCPv6
+///
+/// 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 prefix, and
+/// a prefix length) 2 methods are used: getAddress() and getLength(). Although
+/// 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 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 {
+
+public:
+ /// length of the fixed part of the IAPREFIX option
+ static const size_t OPTION6_IAPREFIX_LEN = 25;
+
+ /// @brief Constructor, used for options constructed (during transmission).
+ ///
+ /// @param type option type
+ /// @param addr reference to an address
+ /// @param prefix_length length (1-128)
+ /// @param preferred address preferred lifetime (in seconds)
+ /// @param valid address valid lifetime (in seconds)
+ Option6IAPrefix(uint16_t type, const isc::asiolink::IOAddress& addr,
+ uint8_t prefix_length, uint32_t preferred, uint32_t valid);
+
+ /// @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
+ /// @param end iterator to end of option data (first byte after option end)
+ Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator begin,
+ OptionBuffer::const_iterator end);
+
+ /// @brief Writes option in wire-format.
+ ///
+ /// 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,
+ OptionBufferConstIter end);
+
+ /// Returns string representation of the option.
+ ///
+ /// @param indent number of spaces before printing text
+ ///
+ /// @return string with text representation.
+ virtual std::string toText(int indent = 0);
+
+ /// sets address in this option.
+ ///
+ /// @param addr address to be sent in this option
+ void setPrefix(const isc::asiolink::IOAddress& prefix,
+ uint8_t length) { addr_ = prefix; prefix_len_ = length; }
+
+ uint8_t getLength() const { return prefix_len_; }
+
+ /// returns data length (data length + DHCPv4/DHCPv6 option header)
+ virtual uint16_t len();
+
+protected:
+ uint8_t prefix_len_;
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif // OPTION_IA_H
diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h
index 00acdab..8ef33d0 100644
--- a/src/lib/dhcp/std_option_defs.h
+++ b/src/lib/dhcp/std_option_defs.h
@@ -214,7 +214,7 @@ RECORD_DECL(IA_NA_RECORDS, OPT_UINT32_TYPE, OPT_UINT32_TYPE, OPT_UINT32_TYPE);
RECORD_DECL(IA_PD_RECORDS, OPT_UINT32_TYPE, OPT_UINT32_TYPE, OPT_UINT32_TYPE);
// ia-prefix
RECORD_DECL(IA_PREFIX_RECORDS, OPT_UINT32_TYPE, OPT_UINT32_TYPE,
- OPT_UINT8_TYPE, OPT_BINARY_TYPE);
+ OPT_UINT8_TYPE, OPT_IPV6_ADDRESS_TYPE, OPT_BINARY_TYPE);
// lq-query
RECORD_DECL(LQ_QUERY_RECORDS, OPT_UINT8_TYPE, OPT_IPV6_ADDRESS_TYPE);
// lq-relay-data
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index 3baac04..3f40ddc 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -36,6 +36,7 @@ libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc
libdhcp___unittests_SOURCES += option6_client_fqdn_unittest.cc
libdhcp___unittests_SOURCES += option6_ia_unittest.cc
libdhcp___unittests_SOURCES += option6_iaaddr_unittest.cc
+libdhcp___unittests_SOURCES += option6_iaprefix_unittest.cc
libdhcp___unittests_SOURCES += option_int_unittest.cc
libdhcp___unittests_SOURCES += option_int_array_unittest.cc
libdhcp___unittests_SOURCES += option_data_types_unittest.cc
diff --git a/src/lib/dhcp/tests/option6_ia_unittest.cc b/src/lib/dhcp/tests/option6_ia_unittest.cc
index 071edb9..2a91505 100644
--- a/src/lib/dhcp/tests/option6_ia_unittest.cc
+++ b/src/lib/dhcp/tests/option6_ia_unittest.cc
@@ -18,6 +18,7 @@
#include <dhcp/option.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_iaprefix.h>
#include <util/buffer.h>
#include <boost/scoped_ptr.hpp>
@@ -43,71 +44,96 @@ public:
buf_[i] = 255 - i;
}
}
- OptionBuffer buf_;
- OutputBuffer outBuf_;
-};
-TEST_F(Option6IATest, basic) {
- buf_[0] = 0xa1; // iaid
- buf_[1] = 0xa2;
- buf_[2] = 0xa3;
- buf_[3] = 0xa4;
+ /// @brief performs basic checks on IA option
+ ///
+ /// Check that an option can be built based on incoming buffer and that
+ /// the option contains expected values.
+ /// @param type specifies option type (IA_NA or IA_PD)
+ void checkIA(uint16_t type) {
+ buf_[0] = 0xa1; // iaid
+ buf_[1] = 0xa2;
+ buf_[2] = 0xa3;
+ buf_[3] = 0xa4;
+
+ buf_[4] = 0x81; // T1
+ buf_[5] = 0x02;
+ buf_[6] = 0x03;
+ buf_[7] = 0x04;
+
+ buf_[8] = 0x84; // T2
+ buf_[9] = 0x03;
+ buf_[10] = 0x02;
+ buf_[11] = 0x01;
+
+ // Create an option
+ // unpack() is called from constructor
+ scoped_ptr<Option6IA> opt;
+ ASSERT_NO_THROW(opt.reset(new Option6IA(type, buf_.begin(),
+ buf_.begin() + 12)));
- buf_[4] = 0x81; // T1
- buf_[5] = 0x02;
- buf_[6] = 0x03;
- buf_[7] = 0x04;
+ EXPECT_EQ(Option::V6, opt->getUniverse());
+ EXPECT_EQ(type, opt->getType());
+ EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
+ EXPECT_EQ(0x81020304, opt->getT1());
+ EXPECT_EQ(0x84030201, opt->getT2());
- buf_[8] = 0x84; // T2
- buf_[9] = 0x03;
- buf_[10] = 0x02;
- buf_[11] = 0x01;
+ // Pack this option again in the same buffer, but in
+ // different place
- // Create an option
- // unpack() is called from constructor
- scoped_ptr<Option6IA> opt(new Option6IA(D6O_IA_NA,
- buf_.begin(),
- buf_.begin() + 12));
+ // Test for pack()
+ ASSERT_NO_THROW(opt->pack(outBuf_));
- EXPECT_EQ(Option::V6, opt->getUniverse());
- EXPECT_EQ(D6O_IA_NA, opt->getType());
- EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
- EXPECT_EQ(0x81020304, opt->getT1());
- EXPECT_EQ(0x84030201, opt->getT2());
+ // 12 bytes header + 4 bytes content
+ EXPECT_EQ(12, opt->len() - opt->getHeaderLen());
+ EXPECT_EQ(type, opt->getType());
- // Pack this option again in the same buffer, but in
- // different place
+ EXPECT_EQ(16, outBuf_.getLength()); // lenght(IA_NA) = 16
- // Test for pack()
- opt->pack(outBuf_);
+ // Check if pack worked properly:
+ InputBuffer out(outBuf_.getData(), outBuf_.getLength());
- // 12 bytes header + 4 bytes content
- EXPECT_EQ(12, opt->len() - opt->getHeaderLen());
- EXPECT_EQ(D6O_IA_NA, opt->getType());
+ // - if option type is correct
+ EXPECT_EQ(type, out.readUint16());
- EXPECT_EQ(16, outBuf_.getLength()); // lenght(IA_NA) = 16
+ // - if option length is correct
+ EXPECT_EQ(12, out.readUint16());
- // Check if pack worked properly:
- InputBuffer out(outBuf_.getData(), outBuf_.getLength());
+ // - if iaid is correct
+ EXPECT_EQ(0xa1a2a3a4, out.readUint32() );
- // - if option type is correct
- EXPECT_EQ(D6O_IA_NA, out.readUint16());
+ // - if T1 is correct
+ EXPECT_EQ(0x81020304, out.readUint32() );
- // - if option length is correct
- EXPECT_EQ(12, out.readUint16());
+ // - if T1 is correct
+ EXPECT_EQ(0x84030201, out.readUint32() );
- // - if iaid is correct
- EXPECT_EQ(0xa1a2a3a4, out.readUint32() );
+ EXPECT_NO_THROW(opt.reset());
+ }
- // - if T1 is correct
- EXPECT_EQ(0x81020304, out.readUint32() );
+ OptionBuffer buf_;
+ OutputBuffer outBuf_;
+};
- // - if T1 is correct
- EXPECT_EQ(0x84030201, out.readUint32() );
+TEST_F(Option6IATest, basic) {
+ checkIA(D6O_IA_NA);
+}
- EXPECT_NO_THROW(opt.reset());
+TEST_F(Option6IATest, pdBasic) {
+ checkIA(D6O_IA_PD);
}
+// Check that this class cannot be used for IA_TA (IA_TA has no T1, T2 fields
+// and people tend to think that if it's good for IA_NA and IA_PD, it can
+// be used for IA_TA as well and that is not true)
+TEST_F(Option6IATest, taForbidden) {
+ EXPECT_THROW(Option6IA(D6O_IA_TA, buf_.begin(), buf_.begin() + 50),
+ BadValue);
+
+ EXPECT_THROW(Option6IA(D6O_IA_TA, 123), BadValue);
+}
+
+// Check that getters/setters are working as expected.
TEST_F(Option6IATest, simple) {
scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_NA, 1234));
@@ -131,12 +157,8 @@ TEST_F(Option6IATest, simple) {
EXPECT_NO_THROW(ia.reset());
}
-
-// test if option can build suboptions
-TEST_F(Option6IATest, suboptions_pack) {
- buf_[0] = 0xff;
- buf_[1] = 0xfe;
- buf_[2] = 0xfc;
+// test if the option can build suboptions
+TEST_F(Option6IATest, suboptionsPack) {
scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_NA, 0x13579ace));
ia->setT1(0x2345);
@@ -154,6 +176,7 @@ TEST_F(Option6IATest, suboptions_pack) {
ASSERT_EQ(4, sub1->len());
ASSERT_EQ(48, ia->len());
+ // This contains expected on-wire format
uint8_t expected[] = {
D6O_IA_NA/256, D6O_IA_NA%256, // type
0, 44, // length
@@ -175,18 +198,69 @@ TEST_F(Option6IATest, suboptions_pack) {
};
ia->pack(outBuf_);
- ASSERT_EQ(48, outBuf_.getLength());
+ ASSERT_EQ(48, outBuf_.getLength());
EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 48));
-
EXPECT_NO_THROW(ia.reset());
}
+// test if IA_PD option can build IAPREFIX suboptions
+TEST_F(Option6IATest, pdSuboptionsPack) {
+
+ // Let's build IA_PD
+ scoped_ptr<Option6IA> ia;
+ ASSERT_NO_THROW(ia.reset(new Option6IA(D6O_IA_PD, 0x13579ace)));
+ ia->setT1(0x2345);
+ ia->setT2(0x3456);
+
+ // Put some dummy option in it
+ OptionPtr sub1(new Option(Option::V6, 0xcafe));
+
+ // Put a valid IAPREFIX option in it
+ boost::shared_ptr<Option6IAPrefix> addr1(
+ new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1234:5678::abcd"),
+ 91, 0x5000, 0x7000));
+
+ ia->addOption(sub1);
+ ia->addOption(addr1);
+
+ ASSERT_EQ(29, addr1->len());
+ ASSERT_EQ(4, sub1->len());
+ ASSERT_EQ(49, ia->len());
+
+ uint8_t expected[] = {
+ D6O_IA_PD/256, D6O_IA_PD%256, // type
+ 0, 45, // length
+ 0x13, 0x57, 0x9a, 0xce, // iaid
+ 0, 0, 0x23, 0x45, // T1
+ 0, 0, 0x34, 0x56, // T2
+
+ // iaprefix suboption
+ D6O_IAPREFIX/256, D6O_IAPREFIX%256, // type
+ 0, 25, // len
+ 0, 0, 0x50, 0, // preferred-lifetime
+ 0, 0, 0x70, 0, // valid-lifetime
+ 91, // prefix length
+ 0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
+ 0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
+
+ // suboption
+ 0xca, 0xfe, // type
+ 0, 0 // len
+ };
+
+ ia->pack(outBuf_);
+ ASSERT_EQ(49, outBuf_.getLength());
+
+ EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 49));
+
+ EXPECT_NO_THROW(ia.reset());
+}
// test if option can parse suboptions
TEST_F(Option6IATest, suboptions_unpack) {
// sizeof (expected) = 48 bytes
- uint8_t expected[] = {
+ const uint8_t expected[] = {
D6O_IA_NA / 256, D6O_IA_NA % 256, // type
0, 28, // length
0x13, 0x57, 0x9a, 0xce, // iaid
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
new file mode 100644
index 0000000..98014bb
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_iaprefix_unittest.cc
@@ -0,0 +1,188 @@
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp/option.h>
+#include <dhcp/option6_iaprefix.h>
+#include <util/buffer.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::util;
+using namespace isc::asiolink;
+
+namespace {
+class Option6IAPrefixTest : public ::testing::Test {
+public:
+ Option6IAPrefixTest() : buf_(255), outBuf_(255) {
+ for (int i = 0; i < 255; i++) {
+ 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) {
+
+ setExampleBuffer();
+
+ // Create an option (unpack content)
+ boost::scoped_ptr<Option6IAPrefix> opt;
+ ASSERT_NO_THROW(opt.reset(new Option6IAPrefix(D6O_IAPREFIX, buf_.begin(),
+ buf_.begin() + 25)));
+ ASSERT_TRUE(opt);
+
+ // Pack this option
+ opt->pack(outBuf_);
+ EXPECT_EQ(29, outBuf_.getLength());
+
+ checkOption(*opt, D6O_IAPREFIX);
+
+ checkOutputBuffer(D6O_IAPREFIX);
+
+ // Check that option can be disposed safely
+ EXPECT_NO_THROW(opt.reset());
+}
+
+// Checks whether a new option can be built correctly
+TEST_F(Option6IAPrefixTest, build) {
+
+ boost::scoped_ptr<Option6IAPrefix> opt;
+ setExampleBuffer();
+
+ ASSERT_NO_THROW(opt.reset(new Option6IAPrefix(12345,
+ IOAddress("2001:db8:1::dead:beef"), 77, 1000, 3000000000)));
+ ASSERT_TRUE(opt);
+
+ checkOption(*opt, 12345);
+
+ // 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