Browse Source

[3874] Added storage class for DUID configuration.

Marcin Siodelski 9 years ago
parent
commit
fe5f2029df

+ 1 - 0
src/lib/dhcpsrv/Makefile.am

@@ -78,6 +78,7 @@ libkea_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
 libkea_dhcpsrv_la_SOURCES += alloc_engine_log.cc alloc_engine_log.h
 libkea_dhcpsrv_la_SOURCES += base_host_data_source.h
 libkea_dhcpsrv_la_SOURCES += callout_handle_store.h
+libkea_dhcpsrv_la_SOURCES += cfg_duid.cc cfg_duid.h
 libkea_dhcpsrv_la_SOURCES += cfg_hosts.cc cfg_hosts.h
 libkea_dhcpsrv_la_SOURCES += cfg_iface.cc cfg_iface.h
 libkea_dhcpsrv_la_SOURCES += cfg_expiration.cc cfg_expiration.h

+ 58 - 0
src/lib/dhcpsrv/cfg_duid.cc

@@ -0,0 +1,58 @@
+// Copyright (C) 2015 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 <dhcpsrv/cfg_duid.h>
+#include <util/encode/hex.h>
+#include <util/strutil.h>
+#include <iostream>
+
+using namespace isc;
+using namespace isc::util::encode;
+using namespace isc::util::str;
+
+namespace isc {
+namespace dhcp {
+
+CfgDUID::CfgDUID()
+    : type_(DUID::DUID_LLT), identifier_(), htype_(0), time_(0),
+      enterprise_id_(0) {
+}
+
+void
+CfgDUID::setIdentifier(const std::string& identifier_as_hex) {
+    // Remove whitespaces.
+    const std::string identifier = trim(identifier_as_hex);
+    // Temporary result of parsing.
+    std::vector<uint8_t> binary;
+    if (!identifier.empty()) {
+        try {
+            // Decode identifier specified as a string of hexadecimal digits.
+            decodeHex(identifier, binary);
+            // All went ok, so let's replace identifier with a new value.
+            identifier_.swap(binary);
+        } catch (const std::exception& ex) {
+            isc_throw(BadValue, "identifier specified in the DUID"
+                      " configuration '" << identifier
+                      << "' is not a valid string of hexadecimal digits");
+        }
+
+    } else {
+         // If specified identifier is empty, clear our internal identifier.
+        identifier_.clear();
+    }
+}
+
+
+}
+}

+ 135 - 0
src/lib/dhcpsrv/cfg_duid.h

@@ -0,0 +1,135 @@
+// Copyright (C) 2015 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 CFG_DUID_H
+#define CFG_DUID_H
+
+#include <dhcp/duid.h>
+#include <boost/shared_ptr.hpp>
+#include <stdint.h>
+#include <vector>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Holds manual configuration of the server identifier (DUID).
+///
+/// The DHCPv6 server uses DHCPv6 Unique Identifier (DUID) to identify itself
+/// to the clients. Typically, the server generates the DUID on the first
+/// startup and writes it to the persistent storage so as it doesn't change
+/// across restarts of the server. RFC3315 and RFC6355 define different DUID
+/// types. Kea allows for selecting a type of DUID that the server should
+/// generate. It also allows for overriding entire default DUID or parts of
+/// it via configuration file. This class holds the DUID configuration
+/// specified in the server configuration file.
+class CfgDUID {
+public:
+
+    /// @brief Constructor.
+    CfgDUID();
+
+    /// @brief Returns DUID type.
+    DUID::DUIDType getType() const {
+        return (type_);
+    }
+
+    /// @brief Sets DUID type.
+    void setType(const DUID::DUIDType& type) {
+        type_ = type;
+    }
+
+    /// @brief Returns identifier.
+    ///
+    /// Identifier is a link layer address for the DUID-LLT and DUID-LL. It
+    /// is also a variable length identifier in DUID-EN. It may be used for
+    /// all other existing and future DUID types when there is a need to
+    /// represent some variable length identifier.
+    ///
+    /// @return Vector holding an identifier belonging to a particular
+    /// DUID type.
+    std::vector<uint8_t> getIdentifier() const {
+        return (identifier_);
+    }
+
+    /// @brief Sets new identifier as hex string.
+    ///
+    /// @param identifier_as_hex String of hexadecimal digits representing
+    /// variable length identifier within a DUID.
+    void setIdentifier(const std::string& identifier_as_hex);
+
+    /// @brief Returns hardware type for DUID-LLT and DUID-LL.
+    uint16_t getHType() const {
+        return (htype_);
+    }
+
+    /// @brief Sets new hardware type for DUID-LLT and DUID-LL.
+    void setHType(const uint16_t htype) {
+        htype_ = htype;
+    }
+
+    /// @brief Returns time for the DUID-LLT.
+    uint32_t getTime() const {
+        return (time_);
+    }
+
+    /// @brief Sets new time for DUID-LLT.
+    void setTime(const uint32_t new_time) {
+        time_ = new_time;
+    }
+
+    /// @brief Returns enterprise id for the DUID-EN.
+    uint32_t getEnterpriseId() const {
+        return (enterprise_id_);
+    }
+
+    /// @brief Sets new enterprise id.
+    ///
+    /// @param enterprise_id New enterprise id.
+    void setEnterpriseId(const uint32_t enterprise_id) {
+        enterprise_id_ = enterprise_id;
+    }
+
+private:
+
+    /// @brief DUID type.
+    DUID::DUIDType type_;
+
+    /// @brief Variable length identifier in a DUID.
+    std::vector<uint8_t> identifier_;
+
+    /// @brief Hardware type.
+    uint16_t htype_;
+
+    /// @brief Time used for DUID-LLT.
+    uint32_t time_;
+
+    /// @brief Enterprise id used for DUID-EN.
+    uint32_t enterprise_id_;
+
+};
+
+/// @name Pointers to the @c CfgDUID objects.
+//@{
+/// @brief Pointer to the Non-const object.
+typedef boost::shared_ptr<CfgDUID> CfgDUIDPtr;
+
+/// @brief Pointer to the const object.
+typedef boost::shared_ptr<const CfgDUID> ConstCfgDUIDPtr;
+
+//@}
+
+}
+}
+
+#endif // CFG_DUID_H

+ 2 - 2
src/lib/dhcpsrv/srv_config.cc

@@ -31,7 +31,7 @@ SrvConfig::SrvConfig()
       cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
       cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
       cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
-      cfg_expiration_(new CfgExpiration()),
+      cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()),
       decline_timer_(0) {
 }
 
@@ -40,7 +40,7 @@ SrvConfig::SrvConfig(const uint32_t sequence)
       cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
       cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
       cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
-      cfg_expiration_(new CfgExpiration()),
+      cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()),
       decline_timer_(0) {
 }
 

+ 16 - 0
src/lib/dhcpsrv/srv_config.h

@@ -15,6 +15,7 @@
 #ifndef DHCPSRV_CONFIG_H
 #define DHCPSRV_CONFIG_H
 
+#include <dhcpsrv/cfg_duid.h>
 #include <dhcpsrv/cfg_expiration.h>
 #include <dhcpsrv/cfg_hosts.h>
 #include <dhcpsrv/cfg_iface.h>
@@ -272,6 +273,18 @@ public:
         return (cfg_expiration_);
     }
 
+    /// @brief Returns pointer to the object holding configuration of the
+    /// server identifier.
+    CfgDUIDPtr getCfgDUID() {
+        return (cfg_duid_);
+    }
+
+    /// @brief Returns const pointer to the object holding configuration
+    /// of the server identifier.
+    ConstCfgDUIDPtr getCfgDUID() const {
+        return (cfg_duid_);
+    }
+
     //@}
 
     /// @brief Returns non-const reference to an array that stores
@@ -458,6 +471,9 @@ private:
     /// expired leases.
     CfgExpirationPtr cfg_expiration_;
 
+    /// @brief Pointer to the configuration of the server identifier.
+    CfgDUIDPtr cfg_duid_;
+
     /// @brief Pointer to the control-socket information
     isc::data::ConstElementPtr control_socket_;
 

+ 1 - 0
src/lib/dhcpsrv/tests/Makefile.am

@@ -65,6 +65,7 @@ libdhcpsrv_unittests_SOURCES += alloc_engine_hooks_unittest.cc
 libdhcpsrv_unittests_SOURCES += alloc_engine4_unittest.cc
 libdhcpsrv_unittests_SOURCES += alloc_engine6_unittest.cc
 libdhcpsrv_unittests_SOURCES += callout_handle_store_unittest.cc
+libdhcpsrv_unittests_SOURCES += cfg_duid_unittest.cc
 libdhcpsrv_unittests_SOURCES += cfg_expiration_unittest.cc
 libdhcpsrv_unittests_SOURCES += cfg_hosts_unittest.cc
 libdhcpsrv_unittests_SOURCES += cfg_iface_unittest.cc

+ 108 - 0
src/lib/dhcpsrv/tests/cfg_duid_unittest.cc

@@ -0,0 +1,108 @@
+// Copyright (C) 2015 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/dhcp4.h>
+#include <dhcp/duid.h>
+#include <dhcpsrv/cfg_duid.h>
+#include <exceptions/exceptions.h>
+#include <util/encode/hex.h>
+#include <gtest/gtest.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief Converts vector to string of hexadecimal digits.
+///
+/// @param vec Input vector.
+/// @return String of hexadecimal digits converted from vector.
+std::string toString(const std::vector<uint8_t>& vec) {
+    try {
+        return (util::encode::encodeHex(vec));
+    } catch (...) {
+        ADD_FAILURE() << "toString: unable to encode vector to"
+            " hexadecimal string";
+    }
+    return ("");
+}
+
+
+// This test verifies default values of the DUID configuration.
+TEST(CfgDUIDTest, defaults) {
+    CfgDUID cfg_duid;
+    EXPECT_EQ(DUID::DUID_LLT, cfg_duid.getType());
+
+    EXPECT_TRUE(cfg_duid.getIdentifier().empty())
+        << "expected empty identifier, found: "
+        << toString(cfg_duid.getIdentifier());
+
+    EXPECT_EQ(0, cfg_duid.getHType());
+    EXPECT_EQ(0, cfg_duid.getTime());
+    EXPECT_EQ(0, cfg_duid.getEnterpriseId());
+}
+
+// This test verifies that it is possible to set values for the CfgDUID.
+TEST(CfgDUIDTest, setValues) {
+    CfgDUID cfg_duid;
+    // Set values.
+    ASSERT_NO_THROW(cfg_duid.setType(DUID::DUID_EN));
+    ASSERT_NO_THROW(cfg_duid.setIdentifier("ABCDEF"));
+    ASSERT_NO_THROW(cfg_duid.setHType(100));
+    ASSERT_NO_THROW(cfg_duid.setTime(32100));
+    ASSERT_NO_THROW(cfg_duid.setEnterpriseId(10));
+
+    // Check that values have been set correctly.
+    EXPECT_EQ(DUID::DUID_EN, cfg_duid.getType());
+    EXPECT_EQ("ABCDEF", toString(cfg_duid.getIdentifier()));
+    EXPECT_EQ(100, cfg_duid.getHType());
+    EXPECT_EQ(32100, cfg_duid.getTime());
+    EXPECT_EQ(10, cfg_duid.getEnterpriseId());
+}
+
+// This test checks positive scenarios for setIdentifier.
+TEST(CfgDUIDTest, setIdentifier) {
+    CfgDUID cfg_duid;
+    // Check that hexadecimal characters may be lower case.
+    ASSERT_NO_THROW(cfg_duid.setIdentifier("a1b2c3"));
+    EXPECT_EQ("A1B2C3", toString(cfg_duid.getIdentifier()));
+
+    // Check that whitespaces are allowed.
+    ASSERT_NO_THROW(cfg_duid.setIdentifier("  ABC  DEF    "));
+    EXPECT_EQ("ABCDEF", toString(cfg_duid.getIdentifier()));
+
+    // Check that identifier including only whitespaces is ignored.
+    ASSERT_NO_THROW(cfg_duid.setIdentifier("      "));
+    EXPECT_TRUE(cfg_duid.getIdentifier().empty())
+        << "expected empty identifier, found: "
+        << toString(cfg_duid.getIdentifier());
+}
+
+TEST(CfgDUIDTest, setInvalidIdentifier) {
+    CfgDUID cfg_duid;
+    // Check that hexadecimal characters may be lower case.
+    ASSERT_NO_THROW(cfg_duid.setIdentifier("a1b2c3"));
+    EXPECT_EQ("A1B2C3", toString(cfg_duid.getIdentifier()));
+
+    // Try to set invalid value. This should not modify original
+    // value.
+    ASSERT_THROW(cfg_duid.setIdentifier("hola!"), isc::BadValue);
+    EXPECT_EQ("A1B2C3", toString(cfg_duid.getIdentifier()));
+}
+
+} // end of anonymous namespace