]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2028] Parsers are replaceable
authorMarcin Siodelski <marcin@isc.org>
Wed, 15 Sep 2021 12:36:15 +0000 (14:36 +0200)
committerMarcin Siodelski <marcin@isc.org>
Wed, 22 Sep 2021 12:07:28 +0000 (14:07 +0200)
Added the virtual methods allowing for customizing parser chain. This
change is required to adopt the parsers to work with the config
backend.

src/lib/dhcpsrv/parsers/client_class_def_parser.cc
src/lib/dhcpsrv/parsers/client_class_def_parser.h
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.h
src/lib/dhcpsrv/parsers/option_data_parser.cc
src/lib/dhcpsrv/parsers/option_data_parser.h
src/lib/dhcpsrv/parsers/shared_network_parser.cc
src/lib/dhcpsrv/parsers/shared_network_parser.h

index 348694195ad9247eef13c86507d663b99f796625..4899f0a79f5257e09af27e821f952cbc4a76b65e 100644 (file)
@@ -10,7 +10,6 @@
 #include <dhcpsrv/client_class_def.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
-#include <dhcpsrv/parsers/option_data_parser.h>
 #include <dhcpsrv/parsers/simple_parser4.h>
 #include <dhcpsrv/parsers/simple_parser6.h>
 #include <eval/eval_context.h>
@@ -136,8 +135,8 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
     CfgOptionPtr options(new CfgOption());
     ConstElementPtr option_data = class_def_cfg->get("option-data");
     if (option_data) {
-        OptionDataListParser opts_parser(family, defs);
-        opts_parser.parse(options, option_data);
+        auto opts_parser = createOptionDataListParser(family, defs);
+        opts_parser->parse(options, option_data);
     }
 
     // Parse user context
@@ -294,6 +293,12 @@ ClientClassDefParser::checkParametersSupported(const ConstElementPtr& class_def_
     }
 }
 
+boost::shared_ptr<OptionDataListParser>
+ClientClassDefParser::createOptionDataListParser(const uint16_t address_family,
+                                                 CfgOptionDefPtr cfg_option_def) const {
+    auto parser = boost::make_shared<OptionDataListParser>(address_family, cfg_option_def);
+    return (parser);
+}
 
 // ****************** ClientClassDefListParser ************************
 
index 8350ba73e41723f97b89ff393897081dfc95c1fd..060ab10abcc1443983d9aff7b53f1ff3b066cc61 100644 (file)
@@ -11,6 +11,7 @@
 #include <cc/simple_parser.h>
 #include <eval/eval_context.h>
 #include <dhcpsrv/client_class_def.h>
+#include <dhcpsrv/parsers/option_data_parser.h>
 #include <functional>
 #include <list>
 
@@ -83,6 +84,10 @@ public:
 class ClientClassDefParser : public isc::data::SimpleParser {
 public:
 
+    /// @brief Virtual destructor.
+    virtual ~ClientClassDefParser() {
+    }
+
     /// @brief Parses an entry that describes single client class definition.
     ///
     /// Attempts to add the new class directly into the given dictionary.
@@ -115,6 +120,22 @@ public:
     /// @throw DhcpConfigError if any of the parameters is not supported.
     void checkParametersSupported(const isc::data::ConstElementPtr& class_def_cfg,
                                   const uint16_t family);
+
+protected:
+
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing the option-data structure.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @param address_family @c AF_INET (for DHCPv4) or @c AF_INET6 (for DHCPv6).
+    /// @param cfg_option_def structure holding option definitions.
+    ///
+    /// @return an instance of the @c OptionDataListParser.
+    virtual boost::shared_ptr<OptionDataListParser>
+    createOptionDataListParser(const uint16_t address_family,
+                               CfgOptionDefPtr cfg_option_def) const;
 };
 
 /// @brief Defines a pointer to a ClientClassDefParser
index 5e0bcc8a45225fab78d382b21acd8203019fdd7f..46c4e2eeb4a01723a30bb1e0ebbcbaade5971f1e 100644 (file)
@@ -24,6 +24,7 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/make_shared.hpp>
 #include <boost/scoped_ptr.hpp>
 
 #include <map>
@@ -87,32 +88,6 @@ void ControlSocketParser::parse(SrvConfig& srv_cfg, isc::data::ConstElementPtr v
     srv_cfg.setControlSocketInfo(value);
 }
 
-template<typename SearchKey>
-OptionDefinitionPtr
-OptionDataParser::findOptionDefinition(const std::string& option_space,
-                                       const SearchKey& search_key) const {
-    OptionDefinitionPtr def = LibDHCP::getOptionDef(option_space, search_key);
-
-    if (!def) {
-        // Check if this is a vendor-option. If it is, get vendor-specific
-        // definition.
-        uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(option_space);
-        if (vendor_id) {
-            const Option::Universe u = address_family_ == AF_INET ?
-                Option::V4 : Option::V6;
-            def = LibDHCP::getVendorOptionDef(u, vendor_id, search_key);
-        }
-    }
-
-    if (!def) {
-        // Check if this is an option specified by a user.
-        def = CfgMgr::instance().getStagingCfg()->getCfgOptionDef()
-            ->get(option_space, search_key);
-    }
-
-    return (def);
-}
-
 // ******************************** OptionDefParser ****************************
 
 OptionDefParser::OptionDefParser(const uint16_t address_family)
@@ -494,8 +469,8 @@ PoolParser::parse(PoolStoragePtr pools,
     if (option_data) {
         try {
             CfgOptionPtr cfg = pool->getCfgOption();
-            OptionDataListParser option_parser(address_family);
-            option_parser.parse(cfg, option_data);
+            auto option_parser = createOptionDataListParser(address_family);
+            option_parser->parse(cfg, option_data);
         } catch (const std::exception& ex) {
             isc_throw(isc::dhcp::DhcpConfigError, ex.what()
                       << " (" << option_data->getPosition() << ")");
@@ -527,6 +502,12 @@ PoolParser::parse(PoolStoragePtr pools,
     }
 }
 
+boost::shared_ptr<OptionDataListParser>
+PoolParser::createOptionDataListParser(const uint16_t address_family) const {
+    auto parser =  boost::make_shared<OptionDataListParser>(address_family);
+    return (parser);
+}
+
 //****************************** Pool4Parser *************************
 
 PoolPtr
@@ -539,16 +520,22 @@ Pool4Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t) {
     return (PoolPtr(new Pool4(min, max)));
 }
 
-//****************************** Pool4ListParser *************************
+//****************************** Pools4ListParser *************************
 
 void
 Pools4ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list) {
     BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
-        Pool4Parser parser;
-        parser.parse(pools, pool, AF_INET);
+        auto parser = createPoolConfigParser();
+        parser->parse(pools, pool, AF_INET);
     }
 }
 
+boost::shared_ptr<PoolParser>
+Pools4ListParser::createPoolConfigParser() const {
+    auto parser = boost::make_shared<Pool4Parser>();
+    return (parser);
+}
+
 //****************************** SubnetConfigParser *************************
 
 SubnetConfigParser::SubnetConfigParser(uint16_t family, bool check_iface)
@@ -564,8 +551,8 @@ SubnetConfigParser::parse(ConstElementPtr subnet) {
 
     ConstElementPtr options_params = subnet->get("option-data");
     if (options_params) {
-        OptionDataListParser opt_parser(address_family_);
-        opt_parser.parse(options_, options_params);
+        auto opt_parser = createOptionDataListParser();
+        opt_parser->parse(options_, options_params);
     }
 
     ConstElementPtr relay_params = subnet->get("relay");
@@ -627,7 +614,7 @@ SubnetConfigParser::createSubnet(ConstElementPtr params) {
         ConstElementPtr elem = params->get("subnet");
         isc_throw(DhcpConfigError, "prefix length: '" <<
                   subnet_txt.substr(pos+1) << "' is not an integer ("
-                  << elem->getPosition() << ")");
+                   << elem->getPosition() << ")");
     }
 
     // Sanity check the prefix length
@@ -671,7 +658,12 @@ SubnetConfigParser::createSubnet(ConstElementPtr params) {
     subnet_->setFetchGlobalsFn([]() -> ConstElementPtr {
         return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
     });
+}
 
+boost::shared_ptr<OptionDataListParser>
+SubnetConfigParser::createOptionDataListParser() const {
+    auto parser = boost::make_shared<OptionDataListParser>(address_family_);
+    return (parser);
 }
 
 //****************************** Subnet4ConfigParser *************************
@@ -688,8 +680,8 @@ Subnet4ConfigParser::parse(ConstElementPtr subnet) {
     /// Parse Pools first.
     ConstElementPtr pools = subnet->get("pools");
     if (pools) {
-        Pools4ListParser parser;
-        parser.parse(pools_, pools);
+        auto parser = createPoolsListParser();
+        parser->parse(pools_, pools);
     }
 
     SubnetPtr generic = SubnetConfigParser::parse(subnet);
@@ -960,6 +952,12 @@ Subnet4ConfigParser::validateResv(const Subnet4Ptr& subnet, ConstHostPtr host) {
     }
 }
 
+boost::shared_ptr<PoolsListParser>
+Subnet4ConfigParser::createPoolsListParser() const {
+    auto parser = boost::make_shared<Pools4ListParser>();
+    return (parser);
+}
+
 //**************************** Subnets4ListConfigParser **********************
 
 Subnets4ListConfigParser::Subnets4ListConfigParser(bool check_iface)
@@ -972,8 +970,8 @@ Subnets4ListConfigParser::parse(SrvConfigPtr cfg,
     size_t cnt = 0;
     BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
 
-        Subnet4ConfigParser parser(check_iface_);
-        Subnet4Ptr subnet = parser.parse(subnet_json);
+        auto parser = createSubnetConfigParser();
+        Subnet4Ptr subnet = parser->parse(subnet_json);
         if (subnet) {
 
             // Adding a subnet to the Configuration Manager may fail if the
@@ -997,8 +995,8 @@ Subnets4ListConfigParser::parse(Subnet4Collection& subnets,
     size_t cnt = 0;
     BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
 
-        Subnet4ConfigParser parser(check_iface_);
-        Subnet4Ptr subnet = parser.parse(subnet_json);
+        auto parser = createSubnetConfigParser();
+        Subnet4Ptr subnet = parser->parse(subnet_json);
         if (subnet) {
             try {
                 auto ret = subnets.insert(subnet);
@@ -1016,6 +1014,11 @@ Subnets4ListConfigParser::parse(Subnet4Collection& subnets,
     return (cnt);
 }
 
+boost::shared_ptr<Subnet4ConfigParser>
+Subnets4ListConfigParser::createSubnetConfigParser() const {
+    auto parser = boost::make_shared<Subnet4ConfigParser>(check_iface_);
+    return (parser);
+}
 
 //**************************** Pool6Parser *********************************
 
@@ -1039,11 +1042,17 @@ Pool6Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t ptype)
 void
 Pools6ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list) {
     BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
-        Pool6Parser parser;
-        parser.parse(pools, pool, AF_INET6);
+        auto parser = createPoolConfigParser();
+        parser->parse(pools, pool, AF_INET6);
     }
 }
 
+boost::shared_ptr<PoolParser>
+Pools6ListParser::createPoolConfigParser() const {
+    auto parser = boost::make_shared<Pool6Parser>();
+    return (parser);
+}
+
 //**************************** PdPoolParser ******************************
 
 PdPoolParser::PdPoolParser() : options_(new CfgOption()) {
@@ -1071,8 +1080,8 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
 
     ConstElementPtr option_data = pd_pool_->get("option-data");
     if (option_data) {
-        OptionDataListParser opts_parser(AF_INET6);
-        opts_parser.parse(options_, option_data);
+        auto opts_parser = createOptionDataListParser();
+        opts_parser->parse(options_, option_data);
     }
 
     ConstElementPtr user_context = pd_pool_->get("user-context");
@@ -1134,17 +1143,29 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
     pools->push_back(pool_);
 }
 
+boost::shared_ptr<OptionDataListParser>
+PdPoolParser::createOptionDataListParser() const {
+    auto parser = boost::make_shared<OptionDataListParser>(AF_INET6);
+    return (parser);
+}
+
 //**************************** PdPoolsListParser ************************
 
 void
 PdPoolsListParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_list) {
     // Loop through the list of pd pools.
     BOOST_FOREACH(ConstElementPtr pd_pool, pd_pool_list->listValue()) {
-        PdPoolParser parser;
-        parser.parse(pools, pd_pool);
+        auto parser = createPdPoolConfigParser();
+        parser->parse(pools, pd_pool);
     }
 }
 
+boost::shared_ptr<PdPoolParser>
+PdPoolsListParser::createPdPoolConfigParser() const {
+    auto parser = boost::make_shared<PdPoolParser>();
+    return (parser);
+}
+
 //**************************** Subnet6ConfigParser ***********************
 
 Subnet6ConfigParser::Subnet6ConfigParser(bool check_iface)
@@ -1159,13 +1180,13 @@ Subnet6ConfigParser::parse(ConstElementPtr subnet) {
     /// Parse all pools first.
     ConstElementPtr pools = subnet->get("pools");
     if (pools) {
-        Pools6ListParser parser;
-        parser.parse(pools_, pools);
+        auto parser = createPoolsListParser();
+        parser->parse(pools_, pools);
     }
     ConstElementPtr pd_pools = subnet->get("pd-pools");
     if (pd_pools) {
-        PdPoolsListParser parser;
-        parser.parse(pools_, pd_pools);
+        auto parser = createPdPoolsListParser();
+        parser->parse(pools_, pd_pools);
     }
 
     SubnetPtr generic = SubnetConfigParser::parse(subnet);
@@ -1391,6 +1412,18 @@ Subnet6ConfigParser::validateResvs(const Subnet6Ptr& subnet, ConstHostPtr host)
     }
 }
 
+boost::shared_ptr<PoolsListParser>
+Subnet6ConfigParser::createPoolsListParser() const {
+    auto parser = boost::make_shared<Pools6ListParser>();
+    return (parser);
+}
+
+boost::shared_ptr<PdPoolsListParser>
+Subnet6ConfigParser::createPdPoolsListParser() const {
+    auto parser = boost::make_shared<PdPoolsListParser>();
+    return (parser);
+}
+
 //**************************** Subnet6ListConfigParser ********************
 
 Subnets6ListConfigParser::Subnets6ListConfigParser(bool check_iface)
@@ -1403,8 +1436,8 @@ Subnets6ListConfigParser::parse(SrvConfigPtr cfg,
     size_t cnt = 0;
     BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
 
-        Subnet6ConfigParser parser(check_iface_);
-        Subnet6Ptr subnet = parser.parse(subnet_json);
+        auto parser = createSubnetConfigParser();
+        Subnet6Ptr subnet = parser->parse(subnet_json);
 
         // Adding a subnet to the Configuration Manager may fail if the
         // subnet id is invalid (duplicate). Thus, we catch exceptions
@@ -1426,8 +1459,8 @@ Subnets6ListConfigParser::parse(Subnet6Collection& subnets,
     size_t cnt = 0;
     BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
 
-        Subnet6ConfigParser parser(check_iface_);
-        Subnet6Ptr subnet = parser.parse(subnet_json);
+        auto parser = createSubnetConfigParser();
+        Subnet6Ptr subnet = parser->parse(subnet_json);
         if (subnet) {
             try {
                 auto ret = subnets.insert(subnet);
@@ -1445,6 +1478,11 @@ Subnets6ListConfigParser::parse(Subnet6Collection& subnets,
     return (cnt);
 }
 
+boost::shared_ptr<Subnet6ConfigParser>
+Subnets6ListConfigParser::createSubnetConfigParser() const {
+    auto parser = boost::make_shared<Subnet6ConfigParser>(check_iface_);
+    return (parser);
+}
 
 //**************************** D2ClientConfigParser **********************
 
index ba040773a37fa3c17b4e88af0b00ba1b74a0253a..b5c5053e2bd735a8f741864d043a81e4aeafe81e 100644 (file)
@@ -20,6 +20,7 @@
 #include <dhcpsrv/cfg_mac_source.h>
 #include <dhcpsrv/srv_config.h>
 #include <dhcpsrv/parsers/base_network_parser.h>
+#include <dhcpsrv/parsers/option_data_parser.h>
 #include <cc/simple_parser.h>
 #include <exceptions/exceptions.h>
 #include <util/optional.h>
@@ -325,6 +326,18 @@ protected:
     virtual PoolPtr poolMaker(isc::asiolink::IOAddress &min,
                               isc::asiolink::IOAddress &max,
                               int32_t ptype = 0) = 0;
+
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing the option-data structure.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @param address_family AF_INET (for DHCPv4) or AF_INET6 (for DHCPv6).
+    ///
+    /// @return an instance of the @c OptionDataListParser.
+    virtual boost::shared_ptr<OptionDataListParser>
+    createOptionDataListParser(const uint16_t address_family) const;
 };
 
 /// @brief Parser for IPv4 pool definitions.
@@ -379,10 +392,21 @@ public:
     /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
     virtual void parse(PoolStoragePtr pools,
                        isc::data::ConstElementPtr pools_list) = 0;
+
+protected:
+
+    /// @brief Returns an instance of the @c PoolParser to be used in
+    /// parsing the address pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c PoolParser.
+    virtual boost::shared_ptr<PoolParser> createPoolConfigParser() const = 0;
 };
 
 /// @brief Specialization of the pool list parser for DHCPv4
-class Pools4ListParser : PoolsListParser {
+class Pools4ListParser : public PoolsListParser {
 public:
 
     /// @brief parses the actual structure
@@ -393,6 +417,17 @@ public:
     /// @param pools_list a list of pool structures
     /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
     void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list);
+
+protected:
+
+    /// @brief Returns an instance of the @c Pool4Parser to be used in
+    /// parsing the address pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c Pool4Parser.
+    virtual boost::shared_ptr<PoolParser> createPoolConfigParser() const;
 };
 
 /// @brief parser for additional relay information
@@ -499,7 +534,7 @@ protected:
     virtual void initSubnet(isc::data::ConstElementPtr params,
                             isc::asiolink::IOAddress addr, uint8_t len) = 0;
 
-private:
+protected:
 
     /// @brief Create a new subnet using a data from child parsers.
     ///
@@ -508,7 +543,24 @@ private:
     /// failed.
     void createSubnet(isc::data::ConstElementPtr data);
 
-protected:
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing the option-data structure.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @return an instance of the @c OptionDataListParser.
+    virtual boost::shared_ptr<OptionDataListParser> createOptionDataListParser() const;
+
+    /// @brief Returns an instance of the @c PoolsListParser to be used
+    /// in parsing the address pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c PoolsListParser.
+    virtual boost::shared_ptr<PoolsListParser>
+    createPoolsListParser() const = 0;
 
     /// Storage for pools belonging to this subnet.
     PoolStoragePtr pools_;
@@ -569,6 +621,16 @@ protected:
     /// @param host pointer to the host reservation
     /// @throw DhcpConfigError when the address is not in the subnet range.
     void validateResv(const Subnet4Ptr& subnet, ConstHostPtr host);
+
+    /// @brief Returns an instance of the @c Pools4ListParser to be used
+    /// in parsing the address pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c Pools4ListParser.
+    virtual boost::shared_ptr<PoolsListParser>
+    createPoolsListParser() const;
 };
 
 /// @brief this class parses list of DHCP4 subnets
@@ -585,6 +647,10 @@ public:
     /// the system.
     Subnets4ListConfigParser(bool check_iface = true);
 
+    /// @brief Virtual destructor.
+    virtual ~Subnets4ListConfigParser() {
+    }
+
     /// @brief parses contents of the list
     ///
     /// Iterates over all entries on the list, parses its content
@@ -606,6 +672,15 @@ public:
 
 protected:
 
+    /// @brief Returns an instance of the @c Subnet4ConfigParser to be
+    /// used in parsing the subnets.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the subnets.
+    ///
+    /// @return an instance of the @c Subnet4ConfigParser.
+    virtual boost::shared_ptr<Subnet4ConfigParser> createSubnetConfigParser() const;
+
     /// Check if the specified interface exists in the system.
     bool check_iface_;
 };
@@ -643,7 +718,7 @@ protected:
 };
 
 /// @brief Specialization of the pool list parser for DHCPv6
-class Pools6ListParser : PoolsListParser {
+class Pools6ListParser : public PoolsListParser {
 public:
 
     /// @brief parses the actual structure
@@ -654,6 +729,17 @@ public:
     /// @param pools_list a list of pool structures
     /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
     void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list);
+
+protected:
+
+    /// @brief Returns an instance of the @c Pool6Parser to be used in
+    /// parsing the address pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c Pool6Parser.
+    virtual boost::shared_ptr<PoolParser> createPoolConfigParser() const;
 };
 
 /// @brief Parser for IPv6 prefix delegation definitions.
@@ -680,6 +766,10 @@ public:
     ///
     PdPoolParser();
 
+    /// @brief Virtual destructor.
+    virtual ~PdPoolParser() {
+    }
+
     /// @brief Builds a prefix delegation pool from the given configuration
     ///
     /// This function parses configuration entries and creates an instance
@@ -692,7 +782,17 @@ public:
     /// @throw DhcpConfigError if configuration parsing fails.
     void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_);
 
-private:
+protected:
+
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing the option-data structure.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @return an instance of the @c OptionDataListParser.
+    virtual boost::shared_ptr<OptionDataListParser>
+    createOptionDataListParser() const;
 
     /// Pointer to the created pool object.
     isc::dhcp::Pool6Ptr pool_;
@@ -716,9 +816,13 @@ private:
 /// This parser iterates over a list of prefix delegation pool entries and
 /// creates pool instances for each one. If the parsing is successful, the
 /// collection of pools is committed to the provided storage.
-class PdPoolsListParser : public PoolsListParser {
+class PdPoolsListParser : public isc::data::SimpleParser {
 public:
 
+    /// @brief Virtual destructor.
+    virtual ~PdPoolsListParser() {
+    }
+
     /// @brief Parse configuration entries.
     ///
     /// This function parses configuration entries and creates instances
@@ -730,6 +834,18 @@ public:
     ///
     /// @throw DhcpConfigError if configuration parsing fails.
     void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_list);
+
+protected:
+
+    /// @brief Returns an instance of the @c PdPoolParser to be used in
+    /// parsing the prefix delegation pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c PdPool6Parser.
+    virtual boost::shared_ptr<PdPoolParser>
+    createPdPoolConfigParser() const;
 };
 
 /// @anchor Subnet6ConfigParser
@@ -782,6 +898,26 @@ protected:
     /// @param host pointer to the host reservation
     /// @throw DhcpConfigError when an address is not in the subnet range.
     void validateResvs(const Subnet6Ptr& subnet, ConstHostPtr host);
+
+    /// @brief Returns an instance of the @c Pools6ListParser to be used
+    /// in parsing the address pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c Pools6ListParser.
+    virtual boost::shared_ptr<PoolsListParser>
+    createPoolsListParser() const;
+
+    /// @brief Returns an instance of the @c PdPools6ListParser to be used
+    /// in parsing the prefix delegation pools.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the pools.
+    ///
+    /// @return an instance of the @c PdPools6ListParser.
+    virtual boost::shared_ptr<PdPoolsListParser>
+    createPdPoolsListParser() const;
 };
 
 
@@ -799,6 +935,10 @@ public:
     /// the system.
     Subnets6ListConfigParser(bool check_iface = true);
 
+    /// @brief Virtual destructor.
+    virtual ~Subnets6ListConfigParser() {
+    }
+
     /// @brief parses contents of the list
     ///
     /// Iterates over all entries on the list, parses its content
@@ -820,6 +960,15 @@ public:
 
 protected:
 
+    /// @brief Returns an instance of the @c Subnet6ConfigParser to be
+    /// used in parsing the subnets.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the subnets.
+    ///
+    /// @return an instance of the @c Subnet6ConfigParser.
+    virtual boost::shared_ptr<Subnet6ConfigParser> createSubnetConfigParser() const;
+
     /// Check if the specified interface exists in the system.
     bool check_iface_;
 };
index 80808ffdbedb37da490f66632259c7657e4551f6..5b45ce1e6209659163a2e0fb8ad4f52ee8c4222e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2021 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
@@ -18,6 +18,7 @@
 #include <util/encode/hex.h>
 #include <util/strutil.h>
 #include <boost/foreach.hpp>
+#include <boost/make_shared.hpp>
 #include <limits>
 #include <vector>
 
@@ -185,19 +186,27 @@ OptionDataParser::extractPersistent(ConstElementPtr parent) const {
     return (Optional<bool>(persist));
 }
 
-template<typename SearchKey>
 OptionDefinitionPtr
 OptionDataParser::findOptionDefinition(const std::string& option_space,
-                                       const SearchKey& search_key) const {
+                                       const Optional<uint32_t>& option_code,
+                                       const Optional<std::string>& option_name) const {
     OptionDefinitionPtr def;
     if (cfg_option_def_) {
         // Check if the definition was given in the constructor
-        def = cfg_option_def_->get(option_space, search_key);
+        if (option_code.unspecified()) {
+            def = cfg_option_def_->get(option_space, option_name);
+        } else {
+            def = cfg_option_def_->get(option_space, option_code);
+        }
     }
 
     if (!def) {
         // Check if this is a standard option.
-        def = LibDHCP::getOptionDef(option_space, search_key);
+        if (option_code.unspecified()) {
+            def = LibDHCP::getOptionDef(option_space, option_name);
+        } else {
+            def = LibDHCP::getOptionDef(option_space, option_code);
+        }
     }
 
     if (!def) {
@@ -207,7 +216,11 @@ OptionDataParser::findOptionDefinition(const std::string& option_space,
         if (vendor_id) {
             const Option::Universe u = address_family_ == AF_INET ?
                 Option::V4 : Option::V6;
-            def = LibDHCP::getVendorOptionDef(u, vendor_id, search_key);
+            if (option_code.unspecified()) {
+                def = LibDHCP::getVendorOptionDef(u, vendor_id, option_name);
+            } else {
+                def = LibDHCP::getVendorOptionDef(u, vendor_id, option_code);
+            }
         }
     }
 
@@ -221,12 +234,20 @@ OptionDataParser::findOptionDefinition(const std::string& option_space,
         // the definitions from the current configuration in case there is
         // no staging configuration (after configuration commit). In other
         // words, runtime options are always the ones that we need here.
-        def = LibDHCP::getRuntimeOptionDef(option_space, search_key);
+        if (option_code.unspecified()) {
+            def = LibDHCP::getRuntimeOptionDef(option_space, option_name);
+        } else {
+            def = LibDHCP::getRuntimeOptionDef(option_space, option_code);
+        }
     }
 
     if (!def) {
         // Finish by last resort definitions.
-        def = LibDHCP::getLastResortOptionDef(option_space, search_key);
+        if (option_code.unspecified()) {
+            def = LibDHCP::getLastResortOptionDef(option_space, option_name);
+        } else {
+            def = LibDHCP::getLastResortOptionDef(option_space, option_code);
+        }
     }
 
     return (def);
@@ -254,9 +275,7 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
 
     // Try to find a corresponding option definition using option code or
     // option name.
-    OptionDefinitionPtr def = code_param.unspecified() ?
-        findOptionDefinition(space_param, name_param) :
-        findOptionDefinition(space_param, code_param);
+    OptionDefinitionPtr def = findOptionDefinition(space_param, code_param, name_param);
 
     // If there is no definition, the user must not explicitly enable the
     // use of csv-format.
@@ -407,15 +426,21 @@ OptionDataListParser::OptionDataListParser(//const std::string&,
 
 void OptionDataListParser::parse(const CfgOptionPtr& cfg,
                                  isc::data::ConstElementPtr option_data_list) {
-    OptionDataParser option_parser(address_family_, cfg_option_def_);
+    auto option_parser = createOptionDataParser();
     BOOST_FOREACH(ConstElementPtr data, option_data_list->listValue()) {
         std::pair<OptionDescriptor, std::string> option =
-            option_parser.parse(data);
+            option_parser->parse(data);
         // Use the option description to keep the formatted value
         cfg->add(option.first, option.second);
         cfg->encapsulate();
     }
 }
 
+boost::shared_ptr<OptionDataParser>
+OptionDataListParser::createOptionDataParser() const {
+    auto parser = boost::make_shared<OptionDataParser>(address_family_, cfg_option_def_);
+    return (parser);
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc
index 4d576483d89da918d2ec1837b942b17db1feba8c..a0e0c507582a13811f5a9b1972877a80324bbf3b 100644 (file)
@@ -12,6 +12,7 @@
 #include <dhcp/option_definition.h>
 #include <dhcpsrv/cfg_option.h>
 #include <dhcpsrv/cfg_option_def.h>
+#include <boost/shared_ptr.hpp>
 #include <util/optional.h>
 #include <cstdint>
 #include <string>
@@ -47,6 +48,10 @@ public:
     OptionDataParser(const uint16_t address_family,
                      CfgOptionDefPtr cfg_option_def = CfgOptionDefPtr());
 
+    /// @brief Virtual destructor.
+    virtual ~OptionDataParser() {
+    }
+
     /// @brief Parses ElementPtr containing option definition
     ///
     /// This method parses ElementPtr containing the option definition,
@@ -65,7 +70,7 @@ public:
     std::pair<OptionDescriptor, std::string>
     parse(isc::data::ConstElementPtr single_option);
 
-private:
+protected:
 
     /// @brief Finds an option definition within an option space
     ///
@@ -73,18 +78,19 @@ private:
     /// option definition within the option definition storage.
     ///
     /// @param option_space name of the parameter option space
-    /// @param search_key an option code or name to be used to lookup the
-    /// option definition.
-    /// @tparam A numeric type for searching using an option code or the
-    /// string for searching using the option name.
+    /// @param option_code option code to be used to find the option
+    /// definition, if the option name is unspecified.
+    /// @param option_name option name to be used to lookup the option
+    /// definition.
     ///
     /// @return OptionDefinitionPtr of the option definition or an
     /// empty OptionDefinitionPtr if not found.
     /// @throw DhcpConfigError if the option space requested is not valid
     /// for this server.
-    template<typename SearchKey>
-    OptionDefinitionPtr findOptionDefinition(const std::string& option_space,
-                                             const SearchKey& search_key) const;
+    virtual OptionDefinitionPtr
+    findOptionDefinition(const std::string& option_space,
+                         const util::Optional<uint32_t>& option_code,
+                         const util::Optional<std::string>& option_name) const;
 
     /// @brief Create option instance.
     ///
@@ -185,6 +191,10 @@ public:
     OptionDataListParser(const uint16_t address_family,
                          CfgOptionDefPtr cfg_option_def = CfgOptionDefPtr());
 
+    /// @brief Virtual destructor.
+    virtual ~OptionDataListParser() {
+    }
+
     /// @brief Parses a list of options, instantiates them and stores in cfg
     ///
     /// This method expects to get a list of options in option_data_list,
@@ -195,7 +205,17 @@ public:
     /// @param option_data_list configuration that describes the options
     void parse(const CfgOptionPtr& cfg,
                isc::data::ConstElementPtr option_data_list);
-private:
+protected:
+
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing options.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @return an instance of the @c OptionDataListParser.
+    virtual boost::shared_ptr<OptionDataParser> createOptionDataParser() const;
+
     /// @brief Address family: @c AF_INET or @c AF_INET6
     uint16_t address_family_;
 
index 1eb7c8710216d0eec2ab0f2336f6350d349085b7..98c136f9d8c998f09d27833170e9d099744e21ee 100644 (file)
 #include <cc/data.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/cfg_option.h>
-#include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dhcpsrv/parsers/option_data_parser.h>
 #include <dhcpsrv/parsers/shared_network_parser.h>
 #include <dhcpsrv/parsers/simple_parser4.h>
 #include <dhcpsrv/parsers/simple_parser6.h>
 #include <dhcpsrv/shared_network.h>
+#include <boost/make_shared.hpp>
 #include <boost/pointer_cast.hpp>
 #include <string>
 
@@ -74,17 +74,17 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
             auto json = shared_network_data->get("option-data");
             // Create parser instance for option-data.
             CfgOptionPtr cfg_option = shared_network->getCfgOption();
-            OptionDataListParser parser(AF_INET);
-            parser.parse(cfg_option, json);
+            auto parser = createOptionDataListParser();
+            parser->parse(cfg_option, json);
         }
 
         if (shared_network_data->contains("subnet4")) {
             auto json = shared_network_data->get("subnet4");
 
             // Create parser instance of subnet4.
-            Subnets4ListConfigParser parser(check_iface_);
+            auto parser = createSubnetsListParser();
             Subnet4Collection subnets;
-            parser.parse(subnets, json);
+            parser->parse(subnets, json);
 
             // Add all returned subnets into shared network.
             for (auto subnet = subnets.cbegin(); subnet != subnets.cend();
@@ -215,6 +215,18 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
     return (shared_network);
 }
 
+boost::shared_ptr<OptionDataListParser>
+SharedNetwork4Parser::createOptionDataListParser() const {
+    auto parser = boost::make_shared<OptionDataListParser>(AF_INET);
+    return (parser);
+}
+
+boost::shared_ptr<Subnets4ListConfigParser>
+SharedNetwork4Parser::createSubnetsListParser() const {
+    auto parser = boost::make_shared<Subnets4ListConfigParser>(check_iface_);
+    return (parser);
+}
+
 SharedNetwork6Parser::SharedNetwork6Parser(bool check_iface)
     : check_iface_(check_iface) {
 }
@@ -303,8 +315,8 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
             auto json = shared_network_data->get("option-data");
             // Create parser instance for option-data.
             CfgOptionPtr cfg_option = shared_network->getCfgOption();
-            OptionDataListParser parser(AF_INET6);
-            parser.parse(cfg_option, json);
+            auto parser = createOptionDataListParser();
+            parser->parse(cfg_option, json);
         }
 
         if (shared_network_data->contains("client-class")) {
@@ -337,9 +349,9 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
             auto json = shared_network_data->get("subnet6");
 
             // Create parser instance of subnet6.
-            Subnets6ListConfigParser parser(check_iface_);
+            auto parser = createSubnetsListParser();
             Subnet6Collection subnets;
-            parser.parse(subnets, json);
+            parser->parse(subnets, json);
 
             // Add all returned subnets into shared network.
             for (auto subnet = subnets.cbegin(); subnet != subnets.cend();
@@ -380,5 +392,17 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
     return (shared_network);
 }
 
+boost::shared_ptr<OptionDataListParser>
+SharedNetwork6Parser::createOptionDataListParser() const {
+    auto parser = boost::make_shared<OptionDataListParser>(AF_INET6);
+    return (parser);
+}
+
+boost::shared_ptr<Subnets6ListConfigParser>
+SharedNetwork6Parser::createSubnetsListParser() const {
+    auto parser = boost::make_shared<Subnets6ListConfigParser>(check_iface_);
+    return (parser);
+}
+
 } // end of namespace isc::dhcp
 } // end of namespace isc
index 1603f856634ad2d1190ce1da12c117e4d7111ede..8b4ea01ec30d44da9953a84adc314038ca24059e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2021 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
@@ -13,6 +13,9 @@
 #include <dhcpsrv/cfg_subnets6.h>
 #include <dhcpsrv/shared_network.h>
 #include <dhcpsrv/parsers/base_network_parser.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
+#include <dhcpsrv/parsers/option_data_parser.h>
+#include <boost/shared_ptr.hpp>
 
 namespace isc {
 namespace dhcp {
@@ -26,6 +29,10 @@ public:
     /// the system.
     SharedNetwork4Parser(bool check_iface = true);
 
+    /// @brief Virtual destructor.
+    virtual ~SharedNetwork4Parser() {
+    }
+
     /// @brief Parses shared configuration information for IPv4 shared network.
     ///
     /// @param shared_network_data Data element holding shared network
@@ -37,6 +44,25 @@ public:
     parse(const data::ConstElementPtr& shared_network_data);
 
 protected:
+
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing the option-data structure.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @return an instance of the @c OptionDataListParser(AF_INET).
+    virtual boost::shared_ptr<OptionDataListParser> createOptionDataListParser() const;
+
+    /// @brief Returns an instance of the @c Subnets4ListConfigParser
+    /// to be used for parsing the subnets within the shared network.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the subnets.
+    ///
+    /// @return an instance of the @c Subnets4ListConfigParser.
+    virtual boost::shared_ptr<Subnets4ListConfigParser> createSubnetsListParser() const;
+
     /// Check if the specified interface exists in the system.
     bool check_iface_;
 };
@@ -50,6 +76,10 @@ public:
     /// the system.
     SharedNetwork6Parser(bool check_iface = true);
 
+    /// @brief Virtual destructor.
+    virtual ~SharedNetwork6Parser() {
+    }
+
     /// @brief Parses shared configuration information for IPv6 shared network.
     ///
     /// @param shared_network_data Data element holding shared network
@@ -61,6 +91,25 @@ public:
     parse(const data::ConstElementPtr& shared_network_data);
 
 protected:
+
+    /// @brief Returns an instance of the @c OptionDataListParser to
+    /// be used in parsing the option-data structure.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for option data.
+    ///
+    /// @return an instance of the @c OptionDataListParser(AF_INET6).
+    virtual boost::shared_ptr<OptionDataListParser> createOptionDataListParser() const;
+
+    /// @brief Returns an instance of the @c Subnets6ListConfigParser
+    /// to be used for parsing the subnets within the shared network.
+    ///
+    /// This function can be overridden in the child classes to supply
+    /// a custom parser for the subnets.
+    ///
+    /// @return an instance of the @c Subnets6ListConfigParser.
+    virtual boost::shared_ptr<Subnets6ListConfigParser> createSubnetsListParser() const;
+
     /// Check if the specified interface exists in the system.
     bool check_iface_;
 };