From: Marcin Siodelski Date: Fri, 5 Oct 2012 13:16:26 +0000 (+0200) Subject: [2304] Added factory functions for IA_NA and IAADDR options. X-Git-Tag: trac2402_base~5^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=273e195ef434e87ebf9838381d4b49e8a3081acb;p=thirdparty%2Fkea.git [2304] Added factory functions for IA_NA and IAADDR options. --- diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc index 552ed733b2..fef7176276 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 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 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 5d1e6e864b..73df8604a5 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(type, buf.begin(), buf.begin() + buf.size())); + OptionPtr option(new Option6Int(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 0c75b6b482..05536b09ac 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 option_cast_v6 = + boost::static_pointer_cast(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 option_cast_v6 = + boost::static_pointer_cast(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(Option::V6, D6O_PREFERENCE, OptionBuffer(1)), + isc::dhcp::InvalidDataType + ); +} + TEST_F(OptionDefinitionTest, factoryInteger8) { Option::Factory* f = OptionDefinition::factoryInteger; 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 > option_cast_v6 = - boost::static_pointer_cast >(option_v6); + boost::shared_ptr > option_cast_v6 = + boost::static_pointer_cast >(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 > option_cast_v6 = - boost::static_pointer_cast >(option_v6); + boost::shared_ptr > option_cast_v6 = + boost::static_pointer_cast >(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 > option_cast_v6 = - boost::static_pointer_cast >(option_v6); + boost::shared_ptr > option_cast_v6 = + boost::static_pointer_cast >(option_v6); EXPECT_EQ(0x01020304, option_cast_v6->getValue()); // @todo Add more cases for DHCPv4