From: Marcin Siodelski Date: Mon, 16 Nov 2015 17:17:48 +0000 (+0100) Subject: [3874] Added storage class for DUID configuration. X-Git-Tag: trac4231_base~39^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fe5f2029df0bcd09ac9fca4eac5f651854e8b849;p=thirdparty%2Fkea.git [3874] Added storage class for DUID configuration. --- diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am index e11aa31bd1..fbf237fefc 100644 --- a/src/lib/dhcpsrv/Makefile.am +++ b/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 diff --git a/src/lib/dhcpsrv/cfg_duid.cc b/src/lib/dhcpsrv/cfg_duid.cc new file mode 100644 index 0000000000..8c58bd3922 --- /dev/null +++ b/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 +#include +#include +#include + +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 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(); + } +} + + +} +} diff --git a/src/lib/dhcpsrv/cfg_duid.h b/src/lib/dhcpsrv/cfg_duid.h new file mode 100644 index 0000000000..f888543266 --- /dev/null +++ b/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 +#include +#include +#include + +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 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 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 CfgDUIDPtr; + +/// @brief Pointer to the const object. +typedef boost::shared_ptr ConstCfgDUIDPtr; + +//@} + +} +} + +#endif // CFG_DUID_H diff --git a/src/lib/dhcpsrv/srv_config.cc b/src/lib/dhcpsrv/srv_config.cc index b614ff5d2d..912459fb42 100644 --- a/src/lib/dhcpsrv/srv_config.cc +++ b/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) { } diff --git a/src/lib/dhcpsrv/srv_config.h b/src/lib/dhcpsrv/srv_config.h index da387c9a56..6a90d64fb1 100644 --- a/src/lib/dhcpsrv/srv_config.h +++ b/src/lib/dhcpsrv/srv_config.h @@ -15,6 +15,7 @@ #ifndef DHCPSRV_CONFIG_H #define DHCPSRV_CONFIG_H +#include #include #include #include @@ -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_; diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am index 11a1f3012f..69a91079a2 100644 --- a/src/lib/dhcpsrv/tests/Makefile.am +++ b/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 diff --git a/src/lib/dhcpsrv/tests/cfg_duid_unittest.cc b/src/lib/dhcpsrv/tests/cfg_duid_unittest.cc new file mode 100644 index 0000000000..31d62177bd --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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& 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