]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#571,!306] Added factory functions to objects used in MySQL CB.
authorMarcin Siodelski <marcin@isc.org>
Wed, 17 Apr 2019 12:56:47 +0000 (14:56 +0200)
committerMarcin Siodelski <marcin@isc.org>
Thu, 18 Apr 2019 19:02:07 +0000 (21:02 +0200)
20 files changed:
src/lib/database/audit_entry.cc
src/lib/database/audit_entry.h
src/lib/database/tests/audit_entry_unittest.cc
src/lib/dhcp/option.cc
src/lib/dhcp/option.h
src/lib/dhcp/option_definition.cc
src/lib/dhcp/option_definition.h
src/lib/dhcp/tests/option_definition_unittest.cc
src/lib/dhcp/tests/option_unittest.cc
src/lib/dhcpsrv/cfg_option.cc
src/lib/dhcpsrv/cfg_option.h
src/lib/dhcpsrv/pool.cc
src/lib/dhcpsrv/pool.h
src/lib/dhcpsrv/shared_network.cc
src/lib/dhcpsrv/shared_network.h
src/lib/dhcpsrv/subnet.cc
src/lib/dhcpsrv/subnet.h
src/lib/dhcpsrv/tests/cfg_option_unittest.cc
src/lib/dhcpsrv/tests/shared_network_unittest.cc
src/lib/dhcpsrv/tests/subnet_unittest.cc

index c4766487eef32208ee84ca6f1b93304ae60c4c5c..b44c15ab6216679ace431b6540e7fdde501768a0 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <database/audit_entry.h>
 #include <exceptions/exceptions.h>
+#include <boost/make_shared.hpp>
 
 namespace isc {
 namespace db {
@@ -37,6 +38,28 @@ AuditEntry::AuditEntry(const std::string& object_type,
     validate();
 }
 
+AuditEntryPtr
+AuditEntry::create(const std::string& object_type,
+                   const uint64_t object_id,
+                   const ModificationType& modification_type,
+                   const boost::posix_time::ptime& modification_time,
+                   const std::string& log_message) {
+    return (boost::make_shared<AuditEntry>(object_type, object_id,
+                                           modification_type,
+                                           modification_time,
+                                           log_message));
+}
+
+AuditEntryPtr
+AuditEntry::create(const std::string& object_type,
+                   const uint64_t object_id,
+                   const ModificationType& modification_type,
+                   const std::string& log_message) {
+    return (boost::make_shared<AuditEntry>(object_type, object_id,
+                                           modification_type,
+                                           log_message));
+}
+
 void
 AuditEntry::validate() const {
     // object type can't be empty
index 70cc3dba5473c4ae8940edbf99d6de0562c9aa1a..47309cc9462912a7788a12467094af04547a9e1a 100644 (file)
 namespace isc {
 namespace db {
 
+class AuditEntry;
+
+/// @brief Pointer to the @c AuditEntry object.
+typedef boost::shared_ptr<AuditEntry> AuditEntryPtr;
+
 /// @brief Represents a single entry in the audit table.
 ///
 /// The audit tables are used in the databases to track incremental
@@ -93,6 +98,46 @@ public:
                const ModificationType& modification_type,
                const std::string& log_message);
 
+    /// @brief Factory function creating an instance of @c AuditEntry.
+    ///
+    /// This function should be used to create an instance of the shared
+    /// network within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param object_type name of the table where data was modified.
+    /// @param object_id identifier of the modified record in this table.
+    /// @param modification_type type of the modification, e.g. DELETE.
+    /// @param modification_time time of modification for that record.
+    /// @param log_message optional log message associated with the
+    /// modification.
+    ///
+    /// @return Pointer to the @c AuditEntry instance.
+    static AuditEntryPtr create(const std::string& object_type,
+                                const uint64_t object_id,
+                                const ModificationType& modification_type,
+                                const boost::posix_time::ptime& modification_time,
+                                const std::string& log_message);
+
+    /// @brief Factory function creating an instance of @c AuditEntry.
+    ///
+    /// This function should be used to create an instance of the shared
+    /// network within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param object_type name of the table where data was modified.
+    /// @param object_id identifier of the modified record in this table.
+    /// @param modification_type type of the modification, e.g. DELETE.
+    /// @param log_message optional log message associated with the
+    /// modification.
+    ///
+    /// @return Pointer to the @c AuditEntry instance.
+    static AuditEntryPtr create(const std::string& object_type,
+                                const uint64_t object_id,
+                                const ModificationType& modification_type,
+                                const std::string& log_message);
+
     /// @brief Returns object type.
     ///
     /// @return Name of the table in which the modification is present.
@@ -152,9 +197,6 @@ private:
     std::string log_message_;
 };
 
-/// @brief Pointer to the @c AuditEntry object.
-typedef boost::shared_ptr<AuditEntry> AuditEntryPtr;
-
 /// @brief Tag used to access index by object type.
 struct AuditEntryObjectTypeTag { };
 
index 83dad417b90e61a7752d6c6d9dfa3cbdd15024f2..a669949ab90e2ee3ce57c3fcff675ce99dae586e 100644 (file)
@@ -89,7 +89,7 @@ TEST_F(AuditEntryTest, create) {
     {
         SCOPED_TRACE("create with modification time");
 
-        ASSERT_NO_THROW(audit_entry = boost::make_shared<AuditEntry>
+        ASSERT_NO_THROW(audit_entry = AuditEntry::create
                         ("dhcp4_subnet", 10, AuditEntry::ModificationType::DELETE,
                          fixedTime(), "deleted subnet 10"));
         EXPECT_EQ("dhcp4_subnet", audit_entry->getObjectType());
@@ -102,7 +102,7 @@ TEST_F(AuditEntryTest, create) {
     {
         SCOPED_TRACE("create with default modification time");
 
-        ASSERT_NO_THROW(audit_entry = boost::make_shared<AuditEntry>
+        ASSERT_NO_THROW(audit_entry = AuditEntry::create
                         ("dhcp4_option", 123, AuditEntry::ModificationType::CREATE,
                          ""));
         EXPECT_EQ("dhcp4_option", audit_entry->getObjectType());
index 1fb18bfe4621004abbf351b2caacf2b42b7f5380..c2485eb5ef8ab9daba1cfee57a295b6cfea31238 100644 (file)
@@ -11,6 +11,8 @@
 #include <util/encode/hex.h>
 #include <util/io_utilities.h>
 
+#include <boost/make_shared.hpp>
+
 #include <iomanip>
 #include <list>
 #include <sstream>
@@ -56,6 +58,16 @@ Option::Option(const Option& option)
     option.getOptionsCopy(options_);
 }
 
+OptionPtr
+Option::create(Universe u, uint16_t type) {
+    return (boost::make_shared<Option>(u, type));
+}
+
+OptionPtr
+Option::create(Universe u, uint16_t type, const OptionBuffer& data) {
+    return (boost::make_shared<Option>(u, type, data));
+}
+
 Option&
 Option::operator=(const Option& rhs) {
     if (&rhs != this) {
index 992ac0fb5c38c796fa1cefa77aa8eb2ef2afb396..8907c1e341bbf31ea976f68b9ea7af6d467a1022 100644 (file)
@@ -165,6 +165,33 @@ public:
     /// @param source Option to be copied.
     Option(const Option& source);
 
+    /// @brief Factory function creating an instance of the @c Option.
+    ///
+    /// This function should be used to create an instance of the shared
+    /// network within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param u specifies universe (V4 or V6)
+    /// @param type option type (0-255 for V4 and 0-65535 for V6)
+    ///
+    /// @return Pointer to the @c Option instance.
+    static OptionPtr create(Universe u, uint16_t type);
+
+    /// @brief Factory function creating an instance of the @c Option.
+    ///
+    /// This function should be used to create an instance of the shared
+    /// network within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param u specifies universe (V4 or V6)
+    /// @param type option type (0-255 for V4 and 0-65535 for V6)
+    /// @param data content of the option
+    ///
+    /// @return Pointer to the @c Option instance.
+    static OptionPtr create(Universe u, uint16_t type, const OptionBuffer& data);
+
     /// @brief Assignment operator.
     ///
     /// The assignment operator performs a deep copy of the option and
index b353286477b46b2ed13351e314b2ef6a562d2607..c886e71222f3406ac8f156120ce624a7e833e727 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -32,6 +32,7 @@
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/dynamic_bitset.hpp>
+#include <boost/make_shared.hpp>
 #include <sstream>
 
 using namespace std;
@@ -100,6 +101,38 @@ OptionDefinition::OptionDefinition(const std::string& name,
       option_space_name_() {
 }
 
+OptionDefinitionPtr
+OptionDefinition::create(const std::string& name,
+                         const uint16_t code,
+                         const std::string& type,
+                         const bool array_type) {
+    return (boost::make_shared<OptionDefinition>(name, code, type, array_type));
+}
+
+OptionDefinitionPtr
+OptionDefinition::create(const std::string& name,
+                         const uint16_t code,
+                         const OptionDataType type,
+                         const bool array_type) {
+    return (boost::make_shared<OptionDefinition>(name, code, type, array_type));
+}
+
+OptionDefinitionPtr
+OptionDefinition::create(const std::string& name,
+                         const uint16_t code,
+                         const std::string& type,
+                         const char* encapsulated_space) {
+    return (boost::make_shared<OptionDefinition>(name, code, type, encapsulated_space));
+}
+
+OptionDefinitionPtr
+OptionDefinition::create(const std::string& name,
+                         const uint16_t code,
+                         const OptionDataType type,
+                         const char* encapsulated_space) {
+    return (boost::make_shared<OptionDefinition>(name, code, type, encapsulated_space));
+}
+
 bool
 OptionDefinition::equals(const OptionDefinition& other) const {
     return (name_ == other.name_ &&
index f644e6efb0e5654d61f6af22cc78ec8ad2384a4d..922f8e239a430bae523fdba9526cc95087a388c2 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -205,6 +205,81 @@ public:
                               const OptionDataType type,
                               const char* encapsulated_space);
 
+    /// @brief Factory function creating an instance of the @c OptionDefinition.
+    ///
+    /// This function should be used to create an instance of the option
+    /// definition within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param name option name.
+    /// @param code option code.
+    /// @param type option data type as string.
+    /// @param array_type array indicator, if true it indicates that the
+    /// option fields are the array.
+    ///
+    /// @return Pointer to the @c OptionDefinition instance.
+    static OptionDefinitionPtr create(const std::string& name,
+                                      const uint16_t code,
+                                      const std::string& type,
+                                      const bool array_type = false);
+
+    /// @brief Factory function creating an instance of the @c OptionDefinition.
+    ///
+    /// This function should be used to create an instance of the option
+    /// definition within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param name option name.
+    /// @param code option code.
+    /// @param type option data type.
+    /// @param array_type array indicator, if true it indicates that the
+    /// option fields are the array.
+    ///
+    /// @return Pointer to the @c OptionDefinition instance.
+    static OptionDefinitionPtr create(const std::string& name,
+                                      const uint16_t code,
+                                      const OptionDataType type,
+                                      const bool array_type = false);
+
+    /// @brief Factory function creating an instance of the @c OptionDefinition.
+    ///
+    /// This function should be used to create an instance of the option
+    /// definition within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param name option name.
+    /// @param code option code.
+    /// @param type option data type given as string.
+    /// @param encapsulated_space name of the option space being
+    /// encapsulated by this option.
+    ///
+    /// @return Pointer to the @c OptionDefinition instance.
+    static OptionDefinitionPtr create(const std::string& name,
+                                      const uint16_t code,
+                                      const std::string& type,
+                                      const char* encapsulated_space);
+
+    /// @brief Factory function creating an instance of the @c OptionDefinition.
+    ///
+    /// This function should be used to create an instance of the option
+    /// definition within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param name option name.
+    /// @param code option code.
+    /// @param type option data type.
+    /// @param encapsulated_space name of the option space being
+    /// encapsulated by this option.
+    ///
+    /// @return Pointer to the @c OptionDefinition instance.
+    static OptionDefinitionPtr create(const std::string& name,
+                                      const uint16_t code,
+                                      const OptionDataType type,
+                                      const char* encapsulated_space);
 
     /// @name Comparison functions and operators.
     ///
index 9854af2402cb14e27e6c4317d77f8917e24eeb50..778fd38f875551dc517dd089d431b2424048c122 100644 (file)
@@ -138,6 +138,58 @@ TEST_F(OptionDefinitionTest, copyConstructor) {
     EXPECT_EQ("isc", opt_def_copy2.getEncapsulatedSpace());
 }
 
+// This test checks that the factory function taking string option
+// data type as argument creates a valid instance.
+TEST_F(OptionDefinitionTest, createStringType) {
+    auto def = OptionDefinition::create("option-foo", 123, "uint16", "isc");
+    ASSERT_TRUE(def);
+
+    EXPECT_EQ("option-foo", def->getName());
+    EXPECT_EQ(123, def->getCode());
+    EXPECT_EQ(OPT_UINT16_TYPE, def->getType());
+    EXPECT_FALSE(def->getArrayType());
+    EXPECT_EQ("isc", def->getEncapsulatedSpace());
+}
+
+// This test checks that the factory function taking enum option
+// data type as argument creates a valid instance.
+TEST_F(OptionDefinitionTest, createEnumType) {
+    auto def = OptionDefinition::create("option-foo", 123, OPT_UINT16_TYPE, "isc");
+    ASSERT_TRUE(def);
+
+    EXPECT_EQ("option-foo", def->getName());
+    EXPECT_EQ(123, def->getCode());
+    EXPECT_EQ(OPT_UINT16_TYPE, def->getType());
+    EXPECT_FALSE(def->getArrayType());
+    EXPECT_EQ("isc", def->getEncapsulatedSpace());
+}
+
+// This test checks that the factory function creating an array and
+// taking string option data type as argument creates a valid instance.
+TEST_F(OptionDefinitionTest, createStringTypeArray) {
+    auto def = OptionDefinition::create("option-foo", 123, "uint16", true);
+    ASSERT_TRUE(def);
+
+    EXPECT_EQ("option-foo", def->getName());
+    EXPECT_EQ(123, def->getCode());
+    EXPECT_EQ(OPT_UINT16_TYPE, def->getType());
+    EXPECT_TRUE(def->getArrayType());
+    EXPECT_TRUE(def->getEncapsulatedSpace().empty());
+}
+
+// This test checks that the factory function creating an array and
+// taking enum option data type as argument creates a valid instance.
+TEST_F(OptionDefinitionTest, createEnumTypeArray) {
+    auto def = OptionDefinition::create("option-foo", 123, OPT_UINT16_TYPE, true);
+    ASSERT_TRUE(def);
+
+    EXPECT_EQ("option-foo", def->getName());
+    EXPECT_EQ(123, def->getCode());
+    EXPECT_EQ(OPT_UINT16_TYPE, def->getType());
+    EXPECT_TRUE(def->getArrayType());
+    EXPECT_TRUE(def->getEncapsulatedSpace().empty());
+}
+
 // This test checks that two option definitions may be compared for equality.
 TEST_F(OptionDefinitionTest, equality) {
     // Equal definitions.
index 62a69c5a88684cdcf9733fcc9de2486d49a33ada..adc08f18154ea054bb12a0ee230feab52ef6ccb6 100644 (file)
@@ -616,4 +616,23 @@ TEST_F(OptionTest, cloneInternal) {
     EXPECT_FALSE(clone);
 }
 
+// This test verifies that empty option factory function creates
+// a valid option instance.
+TEST_F(OptionTest, create) {
+    auto option = Option::create(Option::V4, 123);
+    ASSERT_TRUE(option);
+    EXPECT_EQ(Option::V4, option->getUniverse());
+    EXPECT_EQ(123, option->getType());
+}
+
+// This test verifies that option factory function creates a
+// valid option instance.
+TEST_F(OptionTest, createPayload) {
+    auto option = Option::create(Option::V4, 123, buf_);
+    ASSERT_TRUE(option);
+    EXPECT_EQ(Option::V4, option->getUniverse());
+    EXPECT_EQ(123, option->getType());
+    EXPECT_EQ(buf_, option->getData());
+}
+
 }
index f85914acbcfe62e85a5bb4b0933012019f3a9378..cde3ae31a90a9bfdbbea2b47e3422cfdefa06aba 100644 (file)
@@ -13,6 +13,7 @@
 #include <util/encode/hex.h>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string/classification.hpp>
+#include <boost/make_shared.hpp>
 #include <string>
 #include <sstream>
 #include <vector>
@@ -22,6 +23,24 @@ using namespace isc::data;
 namespace isc {
 namespace dhcp {
 
+OptionDescriptorPtr
+OptionDescriptor::create(const OptionPtr& opt, bool persist,
+                         const std::string& formatted_value,
+                         ConstElementPtr user_context) {
+    return (boost::make_shared<OptionDescriptor>(opt, persist, formatted_value,
+                                                 user_context));
+}
+
+OptionDescriptorPtr
+OptionDescriptor::create(bool persist) {
+    return (boost::make_shared<OptionDescriptor>(persist));
+}
+
+OptionDescriptorPtr
+OptionDescriptor::create(const OptionDescriptor& desc) {
+    return (boost::make_shared<OptionDescriptor>(desc));
+}
+
 bool
 OptionDescriptor::equals(const OptionDescriptor& other) const {
     return ((persistent_ == other.persistent_) &&
index 22c57227dc7630f2b775d4bd01f001d6dfcd0d3c..de3a849c50dc1e60b1f0c4f795ff7165ac961ba2 100644 (file)
 namespace isc {
 namespace dhcp {
 
+class OptionDescriptor;
+
+/// A pointer to option descriptor.
+typedef boost::shared_ptr<OptionDescriptor> OptionDescriptorPtr;
+
 /// @brief Option descriptor.
 ///
 /// Option descriptor holds instance of an option and additional information
@@ -73,11 +78,10 @@ public:
 
     /// @brief Constructor.
     ///
-    /// @param opt option
-    /// @param persist if true option is always sent.
-    /// @param formatted_value option value in the textual format. Default
+    /// @param opt option instance.
+    /// @param persist if true, option is always sent.
+    /// @param formatted_value option value in the textual format (optional).
     /// @param user_context user context (optional).
-    /// value is empty indicating that the value is not set.
     OptionDescriptor(const OptionPtr& opt, bool persist,
                      const std::string& formatted_value = "",
                      data::ConstElementPtr user_context = data::ConstElementPtr())
@@ -87,7 +91,7 @@ public:
         setContext(user_context);
     };
 
-    /// @brief Constructor
+    /// @brief Constructor.
     ///
     /// @param persist if true option is always sent.
     OptionDescriptor(bool persist)
@@ -96,7 +100,7 @@ public:
 
     /// @brief Constructor.
     ///
-    /// @param desc descriptor
+    /// @param desc option descriptor to be copied.
     OptionDescriptor(const OptionDescriptor& desc)
         : data::StampedElement(desc),
           option_(desc.option_),
@@ -106,6 +110,34 @@ public:
         setContext(desc.getContext());
     };
 
+    /// @brief Factory function creating an instance of the @c OptionDescriptor.
+    ///
+    /// @param opt option instance.
+    /// @param persist if true, option is always sent.
+    /// @param formatted_value option value in the textual format (optional).
+    /// @param user_context user context (optional).
+    ///
+    /// @return Pointer to the @c OptionDescriptor instance.
+    static OptionDescriptorPtr create(const OptionPtr& opt,
+                                      bool persist,
+                                      const std::string& formatted_value = "",
+                                      data::ConstElementPtr user_context =
+                                      data::ConstElementPtr());
+
+    /// @brief Factory function creating an instance of the @c OptionDescriptor.
+    ///
+    /// @param persist if true option is always sent.
+    ///
+    /// @return Pointer to the @c OptionDescriptor instance.
+    static OptionDescriptorPtr create(bool persist);
+
+    /// @brief Factory function creating an instance of the @c OptionDescriptor.
+    ///
+    /// @param desc option descriptor to be copied.
+    ///
+    /// @return Pointer to the @c OptionDescriptor instance.
+    static OptionDescriptorPtr create(const OptionDescriptor& desc);
+
     /// @brief Checks if the one descriptor is equal to another.
     ///
     /// @param other Other option descriptor to compare to.
@@ -132,9 +164,6 @@ public:
     }
 };
 
-/// A pointer to option descriptor.
-typedef boost::shared_ptr<OptionDescriptor> OptionDescriptorPtr;
-
 /// @brief Multi index container for DHCP option descriptors.
 ///
 /// This container comprises three indexes to access option
index 9a3306d264808e8a485aa38ce6e211aa39ed0d03..e672f437a98943225dd34a95ac82ec381108a8b8 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -9,6 +9,7 @@
 #include <asiolink/io_address.h>
 #include <asiolink/addr_utilities.h>
 #include <dhcpsrv/pool.h>
+#include <boost/make_shared.hpp>
 #include <sstream>
 
 using namespace isc::asiolink;
@@ -86,6 +87,16 @@ Pool4::Pool4( const isc::asiolink::IOAddress& prefix, uint8_t prefix_len)
     capacity_ = addrsInRange(prefix, last_);
 }
 
+Pool4Ptr
+Pool4::create(const IOAddress& first, const IOAddress& last) {
+    return (boost::make_shared<Pool4>(first, last));
+}
+
+Pool4Ptr
+Pool4::create(const IOAddress& prefix, uint8_t prefix_len) {
+    return (boost::make_shared<Pool4>(prefix, prefix_len));
+}
+
 data::ElementPtr
 Pool::toElement() const {
     // Prepare the map
@@ -244,6 +255,26 @@ Pool6::Pool6(const asiolink::IOAddress& prefix, const uint8_t prefix_len,
     }
 }
 
+Pool6Ptr
+Pool6::create(Lease::Type type, const IOAddress& first, const IOAddress& last) {
+    return (boost::make_shared<Pool6>(type, first, last));
+}
+
+Pool6Ptr
+Pool6::create(Lease::Type type, const IOAddress& prefix,
+              uint8_t prefix_len, uint8_t delegated_len) {
+    return (boost::make_shared<Pool6>(type, prefix, prefix_len, delegated_len));
+}
+
+Pool6Ptr
+Pool6::create(const IOAddress& prefix, const uint8_t prefix_len,
+              const uint8_t delegated_len, const IOAddress& excluded_prefix,
+              const uint8_t excluded_prefix_len) {
+    return (boost::make_shared<Pool6>(prefix, prefix_len,
+                                      delegated_len, excluded_prefix,
+                                      excluded_prefix_len));
+}
+
 void
 Pool6::init(const Lease::Type& type,
             const asiolink::IOAddress& prefix,
index 51488d4311d873cc51341a81764eaf7bcc56cdc6..f7cd0136544fe5586ee237efe1144ed7f3c4a91d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -236,6 +236,11 @@ protected:
     bool last_allocated_valid_;
 };
 
+class Pool4;
+
+/// @brief a pointer an IPv4 Pool
+typedef boost::shared_ptr<Pool4> Pool4Ptr;
+
 /// @brief Pool information for IPv4 addresses
 ///
 /// It holds information about pool4, i.e. a range of IPv4 address space that
@@ -256,14 +261,44 @@ public:
     Pool4(const isc::asiolink::IOAddress& prefix,
           uint8_t prefix_len);
 
+    /// @brief Factory function for creating an instance of the @c Pool4.
+    ///
+    /// This function should be used to create an instance of the pool
+    /// within a hooks library in cases when the library may be unloaded
+    /// before the object is destroyed. This ensures that the ownership
+    /// of the object by the Kea process is retained.
+    ///
+    /// @param first the first address in a pool
+    /// @param last the last address in a pool
+    ///
+    /// @return Pointer to the @c Pool4 instance.
+    static Pool4Ptr create(const isc::asiolink::IOAddress& first,
+                           const isc::asiolink::IOAddress& last);
+
+    /// @brief Factory function for creating an instance of the @c Pool4.
+    ///
+    /// This function should be used to create an instance of the pool
+    /// within a hooks library in cases when the library may be unloaded
+    /// before the object is destroyed. This ensures that the ownership
+    /// of the object by the Kea process is retained.
+    ///
+    /// @param prefix specifies prefix of the pool.
+    /// @param prefix_len specifies length of the prefix of the pool.
+    ///
+    /// @return Pointer to the @c Pool4 instance.
+    static Pool4Ptr create(const isc::asiolink::IOAddress& prefix,
+                           uint8_t prefix_len);
+
     /// @brief Unparse a Pool4 object.
     ///
     /// @return A pointer to unparsed Pool4 configuration.
     virtual data::ElementPtr toElement() const;
 };
 
-/// @brief a pointer an IPv4 Pool
-typedef boost::shared_ptr<Pool4> Pool4Ptr;
+class Pool6;
+
+/// @brief a pointer an IPv6 Pool
+typedef boost::shared_ptr<Pool6> Pool6Ptr;
 
 /// @brief Pool information for IPv6 addresses and prefixes
 ///
@@ -329,6 +364,60 @@ public:
           const asiolink::IOAddress& excluded_prefix,
           const uint8_t excluded_prefix_len);
 
+    /// @brief Factory function for creating an instance of the @c Pool6.
+    ///
+    /// This function should be used to create an instance of the pool
+    /// within a hooks library in cases when the library may be unloaded
+    /// before the object is destroyed. This ensures that the ownership
+    /// of the object by the Kea process is retained.
+    ///
+    /// @param type type of the pool (IA or TA)
+    /// @param first the first address in a pool
+    /// @param last the last address in a pool
+    ///
+    /// @return Pointer to the @c Pool6 instance.
+    static Pool6Ptr create(Lease::Type type,
+                           const isc::asiolink::IOAddress& first,
+                           const isc::asiolink::IOAddress& last);
+
+    /// @brief Factory function for creating an instance of the @c Pool6.
+    ///
+    /// This function should be used to create an instance of the pool
+    /// within a hooks library in cases when the library may be unloaded
+    /// before the object is destroyed. This ensures that the ownership
+    /// of the object by the Kea process is retained.
+    ///
+    /// @param type type of the pool (IA, TA or PD)
+    /// @param prefix specifies prefix of the pool
+    /// @param prefix_len specifies prefix length of the pool
+    /// @param delegated_len specifies length of the delegated prefixes
+    ///
+    /// @return Pointer to the @c Pool6 instance.
+    static Pool6Ptr create(Lease::Type type,
+                           const isc::asiolink::IOAddress& prefix,
+                           uint8_t prefix_len,
+                           uint8_t delegated_len = 128);
+
+    /// @brief Factory function for creating an instance of the @c Pool6.
+    ///
+    /// If @c excluded_prefix is equal to '::' and the @c excluded_prefix_len
+    /// is equal to 0, the excluded prefix is assumed to be unspecified for
+    /// the pool. In this case, the server will not send the Prefix Exclude
+    /// option to a client.
+    ///
+    /// @param prefix specifies a prefix of the pool.
+    /// @param prefix_len specifies prefix length of the pool.
+    /// @param delegated_len specifies length of the delegated prefixes.
+    /// @param excluded_prefix specifies an excluded prefix as per RFC6603.
+    /// @param excluded_prefix_len specifies length of an excluded prefix.
+    ///
+    /// @return Pointer to the @c Pool6 instance.
+    static Pool6Ptr create(const asiolink::IOAddress& prefix,
+                           const uint8_t prefix_len,
+                           const uint8_t delegated_len,
+                           const asiolink::IOAddress& excluded_prefix,
+                           const uint8_t excluded_prefix_len);
+
     /// @brief returns pool type
     ///
     /// @return pool type
@@ -398,9 +487,6 @@ private:
 
 };
 
-/// @brief a pointer an IPv6 Pool
-typedef boost::shared_ptr<Pool6> Pool6Ptr;
-
 /// @brief a pointer to either IPv4 or IPv6 Pool
 typedef boost::shared_ptr<Pool> PoolPtr;
 
index ff81a39d939c26310b87af648001c3a1f208f790..fcfcd117413b6951cb4602610aaf1ceedf1eeb62 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <exceptions/exceptions.h>
 #include <dhcpsrv/shared_network.h>
+#include <boost/make_shared.hpp>
 
 using namespace isc;
 using namespace isc::data;
@@ -244,6 +245,11 @@ public:
 namespace isc {
 namespace dhcp {
 
+SharedNetwork4Ptr
+SharedNetwork4::create(const std::string& name) {
+    return (boost::make_shared<SharedNetwork4>(name));
+}
+
 void
 SharedNetwork4::add(const Subnet4Ptr& subnet) {
     Impl::add(subnets_, subnet);
@@ -304,6 +310,11 @@ SharedNetwork4::toElement() const {
     return (map);
 }
 
+SharedNetwork6Ptr
+SharedNetwork6::create(const std::string& name) {
+    return (boost::make_shared<SharedNetwork6>(name));
+}
+
 void
 SharedNetwork6::add(const Subnet6Ptr& subnet) {
     Impl::add(subnets_, subnet);
index 041b2a0ce972b2cb6fba5aceb29407c15e491e0b..6ed825f3e15ccf659b1e8e7c536b605a6aa4f75d 100644 (file)
@@ -40,6 +40,11 @@ struct SharedNetworkServerIdIndexTag { };
 /// time.
 struct SharedNetworkModificationTimeIndexTag { };
 
+class SharedNetwork4;
+
+/// @brief Pointer to @ref SharedNetwork4 object.
+typedef boost::shared_ptr<SharedNetwork4> SharedNetwork4Ptr;
+
 /// @brief Shared network holding IPv4 subnets.
 ///
 /// Specialization of the @ref Network4 class for IPv4 shared networks.
@@ -50,10 +55,24 @@ public:
     /// @brief Constructor.
     ///
     /// Sets name of the shared network.
+    ///
+    /// @param name Name of the shared network.
     explicit SharedNetwork4(const std::string& name)
         : name_(name), subnets_() {
     }
 
+    /// @brief Factory function creating an instance of the @c SharedNetwork4.
+    ///
+    /// This function should be used to create an instance of the shared
+    /// network within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param name Name of the shared network.
+    ///
+    /// @return Pointer to the @c SharedNetwork4 instance.
+    static SharedNetwork4Ptr create(const std::string& name);
+
     /// @brief Returns a name of the shared network.
     std::string getName() const {
         return (name_);
@@ -157,9 +176,6 @@ private:
     Subnet4Collection subnets_;
 };
 
-/// @brief Pointer to @ref SharedNetwork4 object.
-typedef boost::shared_ptr<SharedNetwork4> SharedNetwork4Ptr;
-
 /// @brief Multi index container holding shared networks.
 ///
 /// This is multi index container can hold pointers to @ref SharedNetwork4
@@ -203,6 +219,11 @@ typedef boost::multi_index_container<
     >
 > SharedNetwork4Collection;
 
+class SharedNetwork6;
+
+/// @brief Pointer to @ref SharedNetwork6 object.
+typedef boost::shared_ptr<SharedNetwork6> SharedNetwork6Ptr;
+
 /// @brief Shared network holding IPv6 subnets.
 ///
 /// Specialization of the @ref Network6 class for IPv6 shared networks.
@@ -217,6 +238,18 @@ public:
         : name_(name), subnets_() {
     }
 
+    /// @brief Factory function creating an instance of the @c SharedNetwork6.
+    ///
+    /// This function should be used to create an instance of the shared
+    /// network within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param name Name of the shared network.
+    ///
+    /// @return Pointer to the @c SharedNetwork6 instance.
+    static SharedNetwork6Ptr create(const std::string& name);
+
     /// @brief Returns a name of the shared network.
     std::string getName() const {
         return (name_);
@@ -320,9 +353,6 @@ private:
     Subnet6Collection subnets_;
 };
 
-/// @brief Pointer to @ref SharedNetwork6 object.
-typedef boost::shared_ptr<SharedNetwork6> SharedNetwork6Ptr;
-
 /// @brief Multi index container holding shared networks.
 ///
 /// This is multi index container can hold pointers to @ref SharedNetwork6
index d676c2380c98f1992c9d055d242956244deb6e82..e3c3c0ae226c503fd7ebf4d38b3274ac5cab82d4 100644 (file)
@@ -12,6 +12,7 @@
 #include <dhcpsrv/shared_network.h>
 #include <dhcpsrv/subnet.h>
 #include <boost/lexical_cast.hpp>
+#include <boost/make_shared.hpp>
 #include <algorithm>
 #include <sstream>
 
@@ -244,7 +245,7 @@ void Subnet4::checkType(Lease::Type type) const {
     }
 }
 
-Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
+Subnet4::Subnet4(const IOAddress& prefix, uint8_t length,
                  const Triplet<uint32_t>& t1,
                  const Triplet<uint32_t>& t2,
                  const Triplet<uint32_t>& valid_lifetime,
@@ -261,6 +262,17 @@ Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
     setValid(valid_lifetime);
 }
 
+Subnet4Ptr
+Subnet4::create(const IOAddress& prefix, uint8_t length,
+                const Triplet<uint32_t>& t1,
+                const Triplet<uint32_t>& t2,
+                const Triplet<uint32_t>& valid_lifetime,
+                const SubnetID id) {
+    Subnet4Ptr subnet = boost::make_shared<Subnet4>
+        (prefix, length, t1, t2, valid_lifetime, id);
+    return (subnet);
+}
+
 Subnet4Ptr
 Subnet4::getNextSubnet(const Subnet4Ptr& first_subnet) const {
     SharedNetwork4Ptr network;
@@ -585,7 +597,7 @@ Subnet::poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const {
 }
 
 
-Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
+Subnet6::Subnet6(const IOAddress& prefix, uint8_t length,
                  const Triplet<uint32_t>& t1,
                  const Triplet<uint32_t>& t2,
                  const Triplet<uint32_t>& preferred_lifetime,
@@ -604,6 +616,18 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
     setValid(valid_lifetime);
 }
 
+Subnet6Ptr
+Subnet6::create(const IOAddress& prefix, uint8_t length,
+                const Triplet<uint32_t>& t1,
+                const Triplet<uint32_t>& t2,
+                const Triplet<uint32_t>& preferred_lifetime,
+                const Triplet<uint32_t>& valid_lifetime,
+                const SubnetID id) {
+    Subnet6Ptr subnet = boost::make_shared<Subnet6>
+        (prefix, length, t1, t2, preferred_lifetime, valid_lifetime, id);
+    return (subnet);
+}
+
 void Subnet6::checkType(Lease::Type type) const {
     if ( (type != Lease::TYPE_NA) && (type != Lease::TYPE_TA) &&
          (type != Lease::TYPE_PD)) {
index 676853b68fad84566bd5016c828adefcfe13eb38..b58fd350150d0ee2e8d23ad5a5709081c6d815e0 100644 (file)
@@ -476,6 +476,29 @@ public:
             const Triplet<uint32_t>& valid_lifetime,
             const SubnetID id = 0);
 
+    /// @brief Factory function creating an instance of the @c Subnet4.
+    ///
+    /// This function should be used to create an instance of the subnet
+    /// object within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param prefix Subnet4 prefix
+    /// @param length prefix length
+    /// @param t1 renewal timer (in seconds)
+    /// @param t2 rebind timer (in seconds)
+    /// @param valid_lifetime preferred lifetime of leases (in seconds)
+    /// @param id arbitrary subnet id, default value of 0 triggers
+    /// autogeneration of subnet id
+    ///
+    /// @return Pointer to the @c Subnet4 instance.
+    static Subnet4Ptr
+    create(const isc::asiolink::IOAddress& prefix, uint8_t length,
+           const Triplet<uint32_t>& t1,
+           const Triplet<uint32_t>& t2,
+           const Triplet<uint32_t>& valid_lifetime,
+           const SubnetID id = 0);
+
     /// @brief Returns next subnet within shared network.
     ///
     /// If the current subnet doesn't belong to any shared network or if
@@ -602,6 +625,31 @@ public:
             const Triplet<uint32_t>& valid_lifetime,
             const SubnetID id = 0);
 
+    /// @brief Factory function creating an instance of the @c Subnet4.
+    ///
+    /// This function should be used to create an instance of the subnet
+    /// object within a hooks library in cases when the library may be
+    /// unloaded before the object is destroyed. This ensures that the
+    /// ownership of the object by the Kea process is retained.
+    ///
+    /// @param prefix Subnet6 prefix
+    /// @param length prefix length
+    /// @param t1 renewal timer (in seconds)
+    /// @param t2 rebind timer (in seconds)
+    /// @param preferred_lifetime preferred lifetime of leases (in seconds)
+    /// @param valid_lifetime preferred lifetime of leases (in seconds)
+    /// @param id arbitrary subnet id, default value of 0 triggers
+    /// autogeneration of subnet id
+    ///
+    /// @return Pointer to the @c Subnet6 instance.
+    static Subnet6Ptr
+    create(const isc::asiolink::IOAddress& prefix, uint8_t length,
+           const Triplet<uint32_t>& t1,
+           const Triplet<uint32_t>& t2,
+           const Triplet<uint32_t>& preferred_lifetime,
+           const Triplet<uint32_t>& valid_lifetime,
+           const SubnetID id = 0);
+
     /// @brief Returns next subnet within shared network.
     ///
     /// If the current subnet doesn't belong to any shared network or if
index 52660d6faabfebcfebb54b8c8f81b3f5ef007910..5c67bd9427f5f68d2b65bd77faa8889e6e627c05 100644 (file)
@@ -5,6 +5,7 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 #include <config.h>
+#include <cc/data.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/option.h>
 #include <dhcp/option_custom.h>
 
 using namespace isc;
 using namespace isc::asiolink;
+using namespace isc::data;
 using namespace isc::dhcp;
 
 namespace {
 
+// This test verifies that the OptionDescriptor factory function creates a
+// valid instance.
+TEST(OptionDescriptorTest, create) {
+    OptionPtr option = Option::create(Option::V4, 234);
+    ElementPtr context = Element::createMap();
+    context->set("name", Element::create("value"));
+    auto desc = OptionDescriptor::create(option, true, "value", context);
+
+    ASSERT_TRUE(desc);
+    EXPECT_EQ(option, desc->option_);
+    EXPECT_TRUE(desc->persistent_);
+    EXPECT_EQ("value", desc->formatted_value_);
+    EXPECT_EQ(context, desc->getContext());
+}
+
+// This test verifies that the OptionDescriptor factory function variant
+// taking persistent flag as an argument creates valid instance.
+TEST(OptionDescriptorTest, createPersistent) {
+    auto desc = OptionDescriptor::create(true);
+    ASSERT_TRUE(desc);
+
+    EXPECT_FALSE(desc->option_);
+    EXPECT_TRUE(desc->persistent_);
+    EXPECT_TRUE(desc->formatted_value_.empty());
+    EXPECT_FALSE(desc->getContext());
+}
+
+// This test verifies that the OptionDescriptor factory function variant
+// copying a descriptor provided as an argument creates valid instance.
+TEST(OptionDescriptorTest, createCopy) {
+    OptionPtr option = Option::create(Option::V4, 234);
+    ElementPtr context = Element::createMap();
+    context->set("name", Element::create("value"));
+    auto desc = OptionDescriptor::create(option, true, "value", context);
+
+    auto desc_copy = OptionDescriptor::create(*desc);
+    ASSERT_TRUE(desc_copy);
+
+    ASSERT_TRUE(desc_copy);
+    EXPECT_EQ(option, desc_copy->option_);
+    EXPECT_TRUE(desc_copy->persistent_);
+    EXPECT_EQ("value", desc_copy->formatted_value_);
+    EXPECT_EQ(context, desc_copy->getContext());
+}
+
 /// This class fixture for testing @c CfgOption class, holding option
 /// configuration.
 class CfgOptionTest : public ::testing::Test {
index 490ada609a95d2f625d9de5f148aaebc7a2259d4..044692b6a5a73625040e24e65ac99577978f888a 100644 (file)
@@ -22,6 +22,14 @@ using namespace isc::dhcp;
 
 namespace {
 
+// This test verifies that the SharedNetwork4 factory function creates a
+// valid shared network instance.
+TEST(SharedNetwork4Test, create) {
+    auto network = SharedNetwork4::create("frog");
+    ASSERT_TRUE(network);
+    EXPECT_EQ("frog", network->getName());
+}
+
 // This test verifies the default values set for the shared
 // networks and verifies that the optional values are unspecified.
 TEST(SharedNetwork4Test, defaults) {
@@ -455,6 +463,14 @@ TEST(SharedNetwork4Test, delAll) {
     ASSERT_EQ(0, network->getAllSubnets()->size());
 }
 
+// This test verifies that the SharedNetwork6 factory function creates a
+// valid shared network instance.
+TEST(SharedNetwork6Test, create) {
+    auto network = SharedNetwork6::create("frog");
+    ASSERT_TRUE(network);
+    EXPECT_EQ("frog", network->getName());
+}
+
 // This test verifies the default values set for the shared
 // networks and verifies that the optional values are unspecified.
 TEST(SharedNetwork6Test, defaults) {
index a957f3b077e3c843e07f6dbe4018152f6c346dc1..65cced7fd9291f0932de89cb1140eadd13db87b3 100644 (file)
@@ -43,6 +43,20 @@ TEST(Subnet4Test, constructor) {
                 BadValue); // IPv6 addresses are not allowed in Subnet4
 }
 
+// This test verifies that the Subnet4 factory function creates a
+// valid subnet instance.
+TEST(Subnet4Test, create) {
+    auto subnet = Subnet4::create(IOAddress("192.0.2.2"), 16,
+                                  1, 2, 3, 10);
+    ASSERT_TRUE(subnet);
+
+    EXPECT_EQ("192.0.2.2/16", subnet->toText());
+    EXPECT_EQ(1, subnet->getT1().get());
+    EXPECT_EQ(2, subnet->getT2().get());
+    EXPECT_EQ(3, subnet->getValid().get());
+    EXPECT_EQ(10, subnet->getID());
+}
+
 // This test verifies the default values set for the subnets and verifies
 // that the optional values are unspecified.
 TEST(Subnet4Test, defaults) {
@@ -748,6 +762,21 @@ TEST(Subnet6Test, constructor) {
                 BadValue); // IPv4 addresses are not allowed in Subnet6
 }
 
+// This test verifies that the Subnet6 factory function creates a
+// valid subnet instance.
+TEST(Subnet6Test, create) {
+    auto subnet = Subnet6::create(IOAddress("2001:db8:1::"), 64,
+                                  1, 2, 3, 4, 10);
+    ASSERT_TRUE(subnet);
+
+    EXPECT_EQ("2001:db8:1::/64", subnet->toText());
+    EXPECT_EQ(1, subnet->getT1().get());
+    EXPECT_EQ(2, subnet->getT2().get());
+    EXPECT_EQ(3, subnet->getPreferred().get());
+    EXPECT_EQ(4, subnet->getValid().get());
+    EXPECT_EQ(10, subnet->getID());
+}
+
 // This test verifies the default values set for the shared
 // networks and verifies that the optional values are unspecified.
 TEST(SharedNetwork6Test, defaults) {