BIND 10 trac2304, updated. 273e195ef434e87ebf9838381d4b49e8a3081acb [2304] Added factory functions for IA_NA and IAADDR options.
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Oct 5 13:16:42 UTC 2012
The branch, trac2304 has been updated
via 273e195ef434e87ebf9838381d4b49e8a3081acb (commit)
via b2d0a03b1efe54b85736d22932f311fd376473ba (commit)
from 3c35688d9945077bceba65131bf0f9954181c7f4 (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 273e195ef434e87ebf9838381d4b49e8a3081acb
Author: Marcin Siodelski <marcin at isc.org>
Date: Fri Oct 5 15:16:26 2012 +0200
[2304] Added factory functions for IA_NA and IAADDR options.
commit b2d0a03b1efe54b85736d22932f311fd376473ba
Author: Marcin Siodelski <marcin at isc.org>
Date: Fri Oct 5 15:15:02 2012 +0200
[2304] Checking data types specified for Option6Int.
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/Makefile.am | 1 +
src/lib/dhcp/option6_int.h | 54 +++++++++---
src/lib/dhcp/option_data_types.h | 77 ++++++++++++++++
src/lib/dhcp/option_definition.cc | 27 ++++++
src/lib/dhcp/option_definition.h | 26 +++++-
src/lib/dhcp/tests/option_definition_unittest.cc | 103 ++++++++++++++++++++--
6 files changed, 270 insertions(+), 18 deletions(-)
create mode 100644 src/lib/dhcp/option_data_types.h
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index a041943..ef887d5 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -21,6 +21,7 @@ libb10_dhcp___la_SOURCES += iface_mgr_linux.cc
libb10_dhcp___la_SOURCES += iface_mgr_bsd.cc
libb10_dhcp___la_SOURCES += iface_mgr_sun.cc
libb10_dhcp___la_SOURCES += option.cc option.h
+libb10_dhcp___la_SOURCES += option_data_types.h
libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
libb10_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
libb10_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
diff --git a/src/lib/dhcp/option6_int.h b/src/lib/dhcp/option6_int.h
index 5c0a725..6531499 100644
--- a/src/lib/dhcp/option6_int.h
+++ b/src/lib/dhcp/option6_int.h
@@ -18,36 +18,68 @@
#include <stdint.h>
#include <limits>
#include <util/io_utilities.h>
+#include "dhcp/libdhcp++.h"
#include "dhcp/option.h"
+#include "dhcp/option_data_types.h"
namespace isc {
namespace dhcp {
+/// This template class represents DHCPv6 option with single value.
+/// This value is of integer type and can be any of the following:
+/// - uint8_t,
+/// - uint16_t,
+/// - uint32_t,
+/// - int8_t,
+/// - int16_t,
+/// - int32_t.
+///
+/// @param T data field type (see above).
template<typename T>
-class OptionInt6: public Option {
+class Option6Int: public Option {
public:
- OptionInt6(uint16_t type, T value)
+ /// @brief Constructor.
+ ///
+ /// @param type option type.
+ /// @param value option value.
+ Option6Int(uint16_t type, T value)
: Option(Option::V6, type), value_(value) {
+ if (!OptionDataTypes<T>::valid) {
+ isc_throw(dhcp::InvalidDataType, "non-numeric type");
+ }
}
- OptionInt6(uint16_t type, OptionBufferConstIter begin,
+ /// @brief Constructor.
+ ///
+ /// This constructor creates option from a buffer. This construtor
+ /// may throw exception if \ref unpack function throws during buffer
+ /// parsing.
+ ///
+ /// @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).
+ ///
+ /// @todo mention here what it throws.
+ Option6Int(uint16_t type, OptionBufferConstIter begin,
OptionBufferConstIter end)
: Option(Option::V6, type) {
+ if (!OptionDataTypes<T>::valid) {
+ isc_throw(dhcp::InvalidDataType, "non-numeric type");
+ }
unpack(begin, end);
}
/// Writes option in wire-format to buf, returns pointer to first unused
/// byte after stored option.
///
- /// @param buf buffer (option will be stored here)
+ /// @param [out] buf buffer (option will be stored here)
+ ///
+ /// @throw isc::BadValue if invalid option type has been provided.
void pack(isc::util::OutputBuffer& buf) {
- if (!std::numeric_limits<T>::is_integer) {
- isc_throw(isc::BadValue, "");
- }
buf.writeUint16(type_);
buf.writeUint16(len() - OPTION6_HDR_LEN);
- switch (sizeof(T)) {
+ switch (OptionDataTypes<T>::len) {
case 1:
buf.writeUint8(value_);
break;
@@ -58,7 +90,7 @@ public:
buf.writeUint32(value_);
break;
default:
- isc_throw(isc::BadValue, "");
+ isc_throw(dhcp::InvalidDataType, "non-numeric type");
}
}
@@ -73,7 +105,7 @@ public:
if (distance(begin, end) < sizeof(T)) {
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
- switch (sizeof(T)) {
+ switch (OptionDataTypes<T>::len) {
case 1:
value_ = *begin;
break;
@@ -84,7 +116,7 @@ public:
value_ = isc::util::readUint32( &(*begin) );
break;
default:
- isc_throw(isc::BadValue, "");
+ isc_throw(dhcp::InvalidDataType, "non-numeric type");
}
LibDHCP::unpackOptions6(OptionBuffer(begin, end), options_);
diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h
new file mode 100644
index 0000000..d23ae9b
--- /dev/null
+++ b/src/lib/dhcp/option_data_types.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2012 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 OPTION_DATA_TYPES_H_
+#define OPTION_DATA_TYPES_H_
+
+#include <exceptions/exceptions.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Exception to be thrown when invalid type specified as template parameter.
+class InvalidDataType : public Exception {
+public:
+ InvalidDataType(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief Numeric data types supported by DHCP option defintions.
+template<typename T>
+struct OptionDataTypes {
+ static const bool valid = false;
+ static const int len = 0;
+};
+
+template<>
+struct OptionDataTypes<int8_t> {
+ static const bool valid = true;
+ static const int len = 1;
+};
+
+template<>
+struct OptionDataTypes<int16_t> {
+ static const bool valid = true;
+ static const int len = 2;
+};
+
+template<>
+struct OptionDataTypes<int32_t> {
+ static const bool valid = true;
+ static const int len = 4;
+};
+
+template<>
+struct OptionDataTypes<uint8_t> {
+ static const bool valid = true;
+ static const int len = 1;
+};
+
+template<>
+struct OptionDataTypes<uint16_t> {
+ static const bool valid = true;
+ static const int len = 2;
+};
+
+template<>
+struct OptionDataTypes<uint32_t> {
+ static const bool valid = true;
+ static const int len = 4;
+};
+
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif /* OPTION_DATA_TYPES_H_ */
diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc
index 552ed73..fef7176 100644
--- a/src/lib/dhcp/option_definition.cc
+++ b/src/lib/dhcp/option_definition.cc
@@ -15,6 +15,8 @@
#include "dhcp/option_definition.h"
#include "dhcp/option4_addrlst.h"
#include "dhcp/option6_addrlst.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
#include "dhcp/option6_int.h"
using namespace std;
@@ -142,5 +144,30 @@ OptionDefinition::factoryEmpty(Option::Universe u, uint16_t type, const OptionBu
return (option);
}
+OptionPtr
+OptionDefinition::factoryIA6(Option::Universe u, uint16_t type, const OptionBuffer& buf) {
+ sanityCheckUniverse(u, Option::V6);
+ if (buf.size() != Option6IA::OPTION6_IA_LEN) {
+ isc_throw(isc::OutOfRange, "input option buffer has invalid size, expeted "
+ << Option6IA::OPTION6_IA_LEN << " bytes");
+ }
+ boost::shared_ptr<Option6IA> option(new Option6IA(type, buf.begin(),
+ buf.begin() + buf.size()));
+ return (option);
+}
+
+OptionPtr
+OptionDefinition::factoryIAAddr6(Option::Universe u, uint16_t type, const OptionBuffer& buf) {
+ sanityCheckUniverse(u, Option::V6);
+ if (buf.size() != Option6IAAddr::OPTION6_IAADDR_LEN) {
+ isc_throw(isc::OutOfRange, "input option buffer has invalid size, expeted "
+ << Option6IAAddr::OPTION6_IAADDR_LEN << " bytes");
+ }
+ boost::shared_ptr<Option6IAAddr> option(new Option6IAAddr(type, buf.begin(),
+ buf.begin() + buf.size()));
+ return (option);
+}
+
+
} // end of isc::dhcp namespace
} // end of isc namespace
diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h
index 5d1e6e8..73df860 100644
--- a/src/lib/dhcp/option_definition.h
+++ b/src/lib/dhcp/option_definition.h
@@ -230,6 +230,30 @@ public:
static OptionPtr factoryEmpty(Option::Universe u, uint16_t type,
const OptionBuffer& buf);
+ /// @brief Factory for IA-type of option.
+ ///
+ /// @param u universe (must be V6).
+ /// @param type option type.
+ /// @param buf option buffer.
+ ///
+ /// @throw isc::OutOfRange if provided option buffer is too short or
+ /// too long. Expected size is 12 bytes.
+ /// @throw isc::BadValue if specified universe value is not V6.
+ static OptionPtr factoryIA6(Option::Universe u, uint16_t type,
+ const OptionBuffer& buf);
+
+ /// @brief Factory for IAADDR-type of option.
+ ///
+ /// @param u universe (must be V6).
+ /// @param type option type.
+ /// @param buf option buffer.
+ ///
+ /// @throw isc::OutOfRange if provided option buffer is too short or
+ /// too long. Expected size is 24 bytes.
+ /// @throw isc::BadValue if specified universe value is not V6.
+ static OptionPtr factoryIAAddr6(Option::Universe u, uint16_t type,
+ const OptionBuffer& buf);
+
/// @brief Factory function to create option with integer value.
///
/// @param u universe (V6 or V4).
@@ -242,7 +266,7 @@ public:
isc_throw(isc::OutOfRange, "provided option buffer is too large, expected: "
<< sizeof(T) << " bytes");
}
- OptionPtr option(new OptionInt6<T>(type, buf.begin(), buf.begin() + buf.size()));
+ OptionPtr option(new Option6Int<T>(type, buf.begin(), buf.begin() + buf.size()));
return (option);
}
diff --git a/src/lib/dhcp/tests/option_definition_unittest.cc b/src/lib/dhcp/tests/option_definition_unittest.cc
index 0c75b6b..05536b0 100644
--- a/src/lib/dhcp/tests/option_definition_unittest.cc
+++ b/src/lib/dhcp/tests/option_definition_unittest.cc
@@ -26,6 +26,8 @@
#include "dhcp/dhcp6.h"
#include "dhcp/option4_addrlst.h"
#include "dhcp/option6_addrlst.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
#include "dhcp/option6_int.h"
#include "dhcp/option_definition.h"
@@ -235,6 +237,95 @@ TEST_F(OptionDefinitionTest, factoryEmpty) {
EXPECT_EQ(0, option_v4->getData().size());
}
+TEST_F(OptionDefinitionTest, factoryIA6) {
+ // This option consists of IAID, T1 and T2 fields (each 4 bytes long).
+ const int option6_ia_len = 12;
+ // This should work for DHCPv6 only, try passing invalid universe value.
+ EXPECT_THROW(
+ OptionDefinition::factoryIA6(Option::V4, D6O_IA_NA,
+ OptionBuffer(option6_ia_len)),
+ isc::BadValue
+ );
+ // The length of the buffer must be 12 bytes.
+ // Check too short buffer.
+ EXPECT_THROW(
+ OptionDefinition::factoryIA6(Option::V6, D6O_IA_NA,
+ OptionBuffer(option6_ia_len - 1)),
+ isc::OutOfRange
+ );
+ // Check too long buffer.
+ EXPECT_THROW(
+ OptionDefinition::factoryIA6(Option::V6, D6O_IA_NA,
+ OptionBuffer(option6_ia_len + 1)),
+ isc::OutOfRange
+ );
+ // Check the positive scenario.
+ OptionPtr option_v6;
+ OptionBuffer buf(12);
+ for (int i = 0; i < buf.size(); ++i) {
+ buf[i] = i;
+ }
+ EXPECT_NO_THROW(
+ option_v6 = OptionDefinition::factoryIA6(Option::V6, D6O_IA_NA, buf)
+ );
+ boost::shared_ptr<Option6IA> option_cast_v6 =
+ boost::static_pointer_cast<Option6IA>(option_v6);
+ EXPECT_EQ(0x00010203, option_cast_v6->getIAID());
+ EXPECT_EQ(0x04050607, option_cast_v6->getT1());
+ EXPECT_EQ(0x08090A0B, option_cast_v6->getT2());
+}
+
+TEST_F(OptionDefinitionTest, factoryIAAddr6) {
+ // This option consists of IPV6 Address (16 bytes) and preferred-lifetime and
+ // valid-lifetime fields (each 4 bytes long).
+ const int option6_iaaddr_len = 24;
+ // This should work for DHCPv6 only, try passing invalid universe value.
+ EXPECT_THROW(
+ OptionDefinition::factoryIAAddr6(Option::V4, D6O_IAADDR,
+ OptionBuffer(option6_iaaddr_len)),
+ isc::BadValue
+ );
+ // The length of the buffer must be 12 bytes.
+ // Check too short buffer.
+ EXPECT_THROW(
+ OptionDefinition::factoryIAAddr6(Option::V6, D6O_IAADDR,
+ OptionBuffer(option6_iaaddr_len - 1)),
+ isc::OutOfRange
+ );
+ // Check too long buffer.
+ EXPECT_THROW(
+ OptionDefinition::factoryIAAddr6(Option::V6, D6O_IAADDR,
+ OptionBuffer(option6_iaaddr_len + 1)),
+ isc::OutOfRange
+ );
+ // Check the positive scenario.
+ OptionPtr option_v6;
+ asiolink::IOAddress addr_v6("2001:0db8::ff00:0042:8329");
+ ASSERT_TRUE(addr_v6.getAddress().is_v6());
+ unsigned char* addr_bytes_v6 = addr_v6.getAddress().to_v6().to_bytes().data();
+ ASSERT_TRUE(addr_bytes_v6 != NULL);
+ OptionBuffer buf;
+ buf.insert(buf.end(), addr_bytes_v6, addr_bytes_v6 + asiolink::V6ADDRESS_LEN);
+ for (int i = 0; i < option6_iaaddr_len - asiolink::V6ADDRESS_LEN; ++i) {
+ buf.push_back(i);
+ }
+ EXPECT_NO_THROW(
+ option_v6 = OptionDefinition::factoryIAAddr6(Option::V6, D6O_IAADDR, buf);
+ );
+ boost::shared_ptr<Option6IAAddr> option_cast_v6 =
+ boost::static_pointer_cast<Option6IAAddr>(option_v6);
+ EXPECT_EQ(addr_v6, option_cast_v6->getAddress());
+ EXPECT_EQ(0x00010203, option_cast_v6->getPreferred());
+ EXPECT_EQ(0x04050607, option_cast_v6->getValid());
+}
+
+TEST_F(OptionDefinitionTest, factoryIntegerNegative) {
+ EXPECT_THROW(
+ OptionDefinition::factoryInteger<bool>(Option::V6, D6O_PREFERENCE, OptionBuffer(1)),
+ isc::dhcp::InvalidDataType
+ );
+}
+
TEST_F(OptionDefinitionTest, factoryInteger8) {
Option::Factory* f = OptionDefinition::factoryInteger<uint8_t>;
OptionPtr option_v6;
@@ -253,8 +344,8 @@ TEST_F(OptionDefinitionTest, factoryInteger8) {
option_v6 = f(Option::V6, D6O_PREFERENCE, OptionBuffer(1, 1));
);
// Validate the value.
- boost::shared_ptr<OptionInt6<uint8_t> > option_cast_v6 =
- boost::static_pointer_cast<OptionInt6<uint8_t> >(option_v6);
+ boost::shared_ptr<Option6Int<uint8_t> > option_cast_v6 =
+ boost::static_pointer_cast<Option6Int<uint8_t> >(option_v6);
EXPECT_EQ(1, option_cast_v6->getValue());
// @todo Add more cases for DHCPv4
@@ -281,8 +372,8 @@ TEST_F(OptionDefinitionTest, factoryInteger16) {
option_v6 = f(Option::V6, D6O_ELAPSED_TIME, buf);
);
// Validate the value.
- boost::shared_ptr<OptionInt6<uint16_t> > option_cast_v6 =
- boost::static_pointer_cast<OptionInt6<uint16_t> >(option_v6);
+ boost::shared_ptr<Option6Int<uint16_t> > option_cast_v6 =
+ boost::static_pointer_cast<Option6Int<uint16_t> >(option_v6);
EXPECT_EQ(0x0102, option_cast_v6->getValue());
// @todo Add more cases for DHCPv4
@@ -310,8 +401,8 @@ TEST_F(OptionDefinitionTest, factoryInteger32) {
option_v6 = f(Option::V6, D6O_CLT_TIME, buf);
);
// Validate the value.
- boost::shared_ptr<OptionInt6<uint32_t> > option_cast_v6 =
- boost::static_pointer_cast<OptionInt6<uint32_t> >(option_v6);
+ boost::shared_ptr<Option6Int<uint32_t> > option_cast_v6 =
+ boost::static_pointer_cast<Option6Int<uint32_t> >(option_v6);
EXPECT_EQ(0x01020304, option_cast_v6->getValue());
// @todo Add more cases for DHCPv4
More information about the bind10-changes
mailing list