Browse Source

[2304] Added factory functions for IA_NA and IAADDR options.

Marcin Siodelski 12 years ago
parent
commit
273e195ef4

+ 27 - 0
src/lib/dhcp/option_definition.cc

@@ -15,6 +15,8 @@
 #include "dhcp/option_definition.h"
 #include "dhcp/option_definition.h"
 #include "dhcp/option4_addrlst.h"
 #include "dhcp/option4_addrlst.h"
 #include "dhcp/option6_addrlst.h"
 #include "dhcp/option6_addrlst.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
 #include "dhcp/option6_int.h"
 #include "dhcp/option6_int.h"
 
 
 using namespace std;
 using namespace std;
@@ -142,5 +144,30 @@ OptionDefinition::factoryEmpty(Option::Universe u, uint16_t type, const OptionBu
     return (option);
     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::dhcp namespace
 } // end of isc namespace
 } // end of isc namespace

+ 25 - 1
src/lib/dhcp/option_definition.h

@@ -230,6 +230,30 @@ public:
     static OptionPtr factoryEmpty(Option::Universe u, uint16_t type,
     static OptionPtr factoryEmpty(Option::Universe u, uint16_t type,
                                   const OptionBuffer& buf);
                                   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.
     /// @brief Factory function to create option with integer value.
     ///
     ///
     /// @param u universe (V6 or V4).
     /// @param u universe (V6 or V4).
@@ -242,7 +266,7 @@ public:
             isc_throw(isc::OutOfRange, "provided option buffer is too large, expected: "
             isc_throw(isc::OutOfRange, "provided option buffer is too large, expected: "
                       << sizeof(T) << " bytes");
                       << 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);
         return (option);
     }
     }
 
 

+ 97 - 6
src/lib/dhcp/tests/option_definition_unittest.cc

@@ -26,6 +26,8 @@
 #include "dhcp/dhcp6.h"
 #include "dhcp/dhcp6.h"
 #include "dhcp/option4_addrlst.h"
 #include "dhcp/option4_addrlst.h"
 #include "dhcp/option6_addrlst.h"
 #include "dhcp/option6_addrlst.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
 #include "dhcp/option6_int.h"
 #include "dhcp/option6_int.h"
 #include "dhcp/option_definition.h"
 #include "dhcp/option_definition.h"
 
 
@@ -235,6 +237,95 @@ TEST_F(OptionDefinitionTest, factoryEmpty) {
     EXPECT_EQ(0, option_v4->getData().size());
     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) {
 TEST_F(OptionDefinitionTest, factoryInteger8) {
     Option::Factory* f = OptionDefinition::factoryInteger<uint8_t>;
     Option::Factory* f = OptionDefinition::factoryInteger<uint8_t>;
     OptionPtr option_v6;
     OptionPtr option_v6;
@@ -253,8 +344,8 @@ TEST_F(OptionDefinitionTest, factoryInteger8) {
         option_v6 = f(Option::V6, D6O_PREFERENCE, OptionBuffer(1, 1));
         option_v6 = f(Option::V6, D6O_PREFERENCE, OptionBuffer(1, 1));
     );
     );
     // Validate the value.
     // 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());
     EXPECT_EQ(1, option_cast_v6->getValue());
 
 
     // @todo Add more cases for DHCPv4
     // @todo Add more cases for DHCPv4
@@ -281,8 +372,8 @@ TEST_F(OptionDefinitionTest, factoryInteger16) {
         option_v6 = f(Option::V6, D6O_ELAPSED_TIME, buf);
         option_v6 = f(Option::V6, D6O_ELAPSED_TIME, buf);
     );
     );
     // Validate the value.
     // 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());
     EXPECT_EQ(0x0102, option_cast_v6->getValue());
 
 
     // @todo Add more cases for DHCPv4
     // @todo Add more cases for DHCPv4
@@ -310,8 +401,8 @@ TEST_F(OptionDefinitionTest, factoryInteger32) {
         option_v6 = f(Option::V6, D6O_CLT_TIME, buf);
         option_v6 = f(Option::V6, D6O_CLT_TIME, buf);
     );
     );
     // Validate the value.
     // 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());
     EXPECT_EQ(0x01020304, option_cast_v6->getValue());
 
 
     // @todo Add more cases for DHCPv4
     // @todo Add more cases for DHCPv4