From: Tomek Mrugalski Date: Mon, 28 Jul 2014 01:43:45 +0000 (-0400) Subject: [3464] PoolsListParser class added, PoolParser modified, DHCPv6 updated X-Git-Tag: trac3482_base~53^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b7fb6a8c3d627e0770ee4d07cd1b9b23db3261ee;p=thirdparty%2Fkea.git [3464] PoolsListParser class added, PoolParser modified, DHCPv6 updated --- diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 79365bdfef..1ed76f2558 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -122,7 +122,7 @@ protected: } }; -/// @brief Parser for IPv4 pool definitions. +/// @brief Parser for IPv6 pool definitions. /// /// This is the IPv6 derivation of the PoolParser class and handles pool /// definitions, i.e. a list of entries of one of two syntaxes: min-max and @@ -173,6 +173,18 @@ protected: } }; +class Pools6ListParser : public PoolsListParser { +public: + Pools6ListParser(const std::string& dummy, PoolStoragePtr pools) + :PoolsListParser(dummy, pools) { + } + +protected: + virtual ParserPtr poolParserMaker(PoolStoragePtr storage) { + return (ParserPtr(new Pool6Parser("pool", storage))); + } +}; + /// @brief Parser for IPv6 prefix delegation definitions. /// /// This class handles prefix delegation pool definitions for IPv6 subnets @@ -436,8 +448,8 @@ protected: (config_id.compare("client-class") == 0) || (config_id.compare("interface-id") == 0)) { parser = new StringParser(config_id, string_values_); - } else if (config_id.compare("pool") == 0) { - parser = new Pool6Parser(config_id, pools_); + } else if (config_id.compare("pools") == 0) { + parser = new Pools6ListParser(config_id, pools_); } else if (config_id.compare("relay") == 0) { parser = new RelayInfoParser(config_id, relay_info_, Option::V6); } else if (config_id.compare("pd-pools") == 0) { diff --git a/src/lib/dhcpsrv/dhcp_parsers.cc b/src/lib/dhcpsrv/dhcp_parsers.cc index 37a567841f..856b0ec955 100644 --- a/src/lib/dhcpsrv/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/dhcp_parsers.cc @@ -943,6 +943,40 @@ RelayInfoParser::commit() { *storage_ = local_; } +//****************************** PoolsListParser ******************************** +PoolsListParser::PoolsListParser(const std::string& dummy, PoolStoragePtr pools) + :pools_(pools), local_pools_(new PoolStorage()) { + if (!pools_) { + isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:" + << "storage may not be NULL"); + } +} + +void +PoolsListParser::build(ConstElementPtr pools) { + BOOST_FOREACH(ConstElementPtr pool, pools->listValue()) { + + // Iterate over every structure on the pools list and invoke + // a separate parser for it. + ParserPtr parser = poolParserMaker(local_pools_); + + parser->build(pool); + + // Before we can create a pool, we need to ask the pool parser + // to create it. + parser->commit(); + } +} + +void PoolsListParser::commit() { + if (pools_) { + // local_pools_ holds the values produced by the build function. + // At this point parsing should have completed successfuly so + // we can append new data to the supplied storage. + pools_->insert(pools_->end(), local_pools_->begin(), local_pools_->end()); + } +} + //****************************** PoolParser ******************************** PoolParser::PoolParser(const std::string&, PoolStoragePtr pools) :pools_(pools) { @@ -954,66 +988,67 @@ PoolParser::PoolParser(const std::string&, PoolStoragePtr pools) } void -PoolParser::build(ConstElementPtr pools_list) { - BOOST_FOREACH(ConstElementPtr text_pool, pools_list->listValue()) { - // That should be a single pool representation. It should contain - // text is form prefix/len or first - last. Note that spaces - // are allowed - string txt = text_pool->stringValue(); - - // first let's remove any whitespaces - boost::erase_all(txt, " "); // space - boost::erase_all(txt, "\t"); // tabulation - - // Is this prefix/len notation? - size_t pos = txt.find("/"); - if (pos != string::npos) { - isc::asiolink::IOAddress addr("::"); - uint8_t len = 0; - try { - addr = isc::asiolink::IOAddress(txt.substr(0, pos)); - - // start with the first character after / - string prefix_len = txt.substr(pos + 1); - - // It is lexical cast to int and then downcast to uint8_t. - // Direct cast to uint8_t (which is really an unsigned char) - // will result in interpreting the first digit as output - // value and throwing exception if length is written on two - // digits (because there are extra characters left over). - - // No checks for values over 128. Range correctness will - // be checked in Pool4 constructor. - len = boost::lexical_cast(prefix_len); - } catch (...) { - isc_throw(DhcpConfigError, "Failed to parse pool " - "definition: " << text_pool->stringValue() - << " (" << text_pool->getPosition() << ")"); - } +PoolParser::build(ConstElementPtr pool_structure) { - PoolPtr pool(poolMaker(addr, len)); - local_pools_.push_back(pool); - continue; - } + ConstElementPtr text_pool = pool_structure->get("pool"); - // Is this min-max notation? - pos = txt.find("-"); - if (pos != string::npos) { - // using min-max notation - isc::asiolink::IOAddress min(txt.substr(0,pos)); - isc::asiolink::IOAddress max(txt.substr(pos + 1)); + // That should be a single pool representation. It should contain + // text is form prefix/len or first - last. Note that spaces + // are allowed + string txt = text_pool->stringValue(); - PoolPtr pool(poolMaker(min, max)); - local_pools_.push_back(pool); - continue; - } + // first let's remove any whitespaces + boost::erase_all(txt, " "); // space + boost::erase_all(txt, "\t"); // tabulation - isc_throw(DhcpConfigError, "invalid pool definition: " - << text_pool->stringValue() << - ". There are two acceptable formats " - " or (" - << text_pool->getPosition() << ")"); + // Is this prefix/len notation? + size_t pos = txt.find("/"); + if (pos != string::npos) { + isc::asiolink::IOAddress addr("::"); + uint8_t len = 0; + try { + addr = isc::asiolink::IOAddress(txt.substr(0, pos)); + + // start with the first character after / + string prefix_len = txt.substr(pos + 1); + + // It is lexical cast to int and then downcast to uint8_t. + // Direct cast to uint8_t (which is really an unsigned char) + // will result in interpreting the first digit as output + // value and throwing exception if length is written on two + // digits (because there are extra characters left over). + + // No checks for values over 128. Range correctness will + // be checked in Pool4 constructor. + len = boost::lexical_cast(prefix_len); + } catch (...) { + isc_throw(DhcpConfigError, "Failed to parse pool " + "definition: " << text_pool->stringValue() + << " (" << text_pool->getPosition() << ")"); } + + PoolPtr pool(poolMaker(addr, len)); + local_pools_.push_back(pool); + return; + } + + // Is this min-max notation? + pos = txt.find("-"); + if (pos != string::npos) { + // using min-max notation + isc::asiolink::IOAddress min(txt.substr(0,pos)); + isc::asiolink::IOAddress max(txt.substr(pos + 1)); + + PoolPtr pool(poolMaker(min, max)); + local_pools_.push_back(pool); + return; + } + + isc_throw(DhcpConfigError, "invalid pool definition: " + << text_pool->stringValue() << + ". There are two acceptable formats " + " or (" + << text_pool->getPosition() << ")"); } void diff --git a/src/lib/dhcpsrv/dhcp_parsers.h b/src/lib/dhcpsrv/dhcp_parsers.h index 3ca074e76e..55bf33d220 100644 --- a/src/lib/dhcpsrv/dhcp_parsers.h +++ b/src/lib/dhcpsrv/dhcp_parsers.h @@ -790,13 +790,13 @@ public: typedef std::vector PoolStorage; typedef boost::shared_ptr PoolStoragePtr; -/// @brief parser for pool definition +/// @brief parser for a signle pool definition /// /// This abstract parser handles pool definitions, i.e. a list of entries of one /// of two syntaxes: min-max and prefix/len. Pool objects are created /// and stored in chosen PoolStorage container. /// -/// It is useful for parsing Dhcp<4/6>/subnet<4/6>[X]/pool parameters. +/// It is useful for parsing Dhcp<4/6>/subnet<4/6>[X]/pools[X] structure. class PoolParser : public DhcpConfigParser { public: @@ -809,14 +809,14 @@ public: /// @throw isc::dhcp::DhcpConfigError if storage is null. PoolParser(const std::string& dummy, PoolStoragePtr pools); - /// @brief parses the actual list + /// @brief parses the actual structure /// /// This method parses the actual list of interfaces. /// No validation is done at this stage, everything is interpreted as /// interface name. - /// @param pools_list list of pools defined for a subnet + /// @param pool_structure a signle entry on a list of pools /// @throw isc::dhcp::DhcpConfigError when pool parsing fails - virtual void build(isc::data::ConstElementPtr pools_list); + virtual void build(isc::data::ConstElementPtr pool_structure); /// @brief Stores the parsed values in a storage provided /// by an upper level parser. @@ -852,6 +852,58 @@ protected: PoolStorage local_pools_; }; +/// @brief Parser for a list of pools +/// +/// This parser parses a list pools. Each element on that list gets its own +/// parser, created with poolParserMaker() method. That method must be specified +/// for each protocol family (v4 or v6) separately. +/// +/// This class is not intended to be used directly. Instead, derived classes +/// should implement poolParserMaker() method. +class PoolsListParser : public DhcpConfigParser { +public: + + /// @brief constructor. + /// + /// @param dummy first argument is ignored, all Parser constructors + /// accept string as first argument. + /// @param pools is the storage in which to store the parsed pool + /// upon "commit". + /// @throw isc::dhcp::DhcpConfigError if storage is null. + PoolsListParser(const std::string& dummy, PoolStoragePtr pools); + + /// @brief parses the actual structure + /// + /// This method parses the actual list of pools. It creates a parser + /// for each structure using poolParserMaker(). + /// + /// @param pools_list a list of pool structures + /// @throw isc::dhcp::DhcpConfigError when pool parsing fails + virtual void build(isc::data::ConstElementPtr pools_list); + + /// @brief Stores the parsed values in a storage provided + /// by an upper level parser. + virtual void commit(); + +protected: + + /// @brief Creates a PoolParser object + /// + /// Instantiates appropriate (v4 or v6) PoolParser object. + /// @param storage parameter that is passed to ParserMaker() constructor. + virtual ParserPtr poolParserMaker(PoolStoragePtr storage) = 0; + + /// @brief pointer to the actual Pools storage + /// + /// That is typically a storage somewhere in Subnet parser + /// (an upper level parser). + PoolStoragePtr pools_; + + /// A temporary storage for pools configuration. It is a + /// storage where pools are stored by build function. + PoolStoragePtr local_pools_; +}; + /// @brief parser for additional relay information /// /// This concrete parser handles RelayInfo structure defintions.