Browse Source

[3464] PoolsListParser class added, PoolParser modified, DHCPv6 updated

Tomek Mrugalski 10 years ago
parent
commit
b7fb6a8c3d
3 changed files with 162 additions and 63 deletions
  1. 15 3
      src/bin/dhcp6/json_config_parser.cc
  2. 90 55
      src/lib/dhcpsrv/dhcp_parsers.cc
  3. 57 5
      src/lib/dhcpsrv/dhcp_parsers.h

+ 15 - 3
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) {

+ 90 - 55
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<int>(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 <min address-max address>"
-                  " or <prefix/len> ("
-                  << 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<int>(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 <min address-max address>"
+              " or <prefix/len> ("
+              << text_pool->getPosition() << ")");
 }
 
 void

+ 57 - 5
src/lib/dhcpsrv/dhcp_parsers.h

@@ -790,13 +790,13 @@ public:
 typedef std::vector<PoolPtr> PoolStorage;
 typedef boost::shared_ptr<PoolStorage> 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.