/// @brief Constructor.
///
- /// @param param_name name of the parameter. Note, it is passed through
- /// but unused, parameter is currently always "Dhcp4/subnet4[X]/pool"
- /// @param pools storage container in which to store the parsed pool
- /// upon "commit"
- Pool4Parser(const std::string& param_name, PoolStoragePtr pools)
- :PoolParser(param_name, pools, AF_INET) {
+ /// @param pools storage container in which to store the parsed pool.
+ Pool4Parser(PoolStoragePtr pools) : PoolParser(pools) {
}
protected:
}
};
-class Pools4ListParser : public PoolsListParser {
+/// @brief Specialization of the pool list parser for DHCPv4
+class Pools4ListParser : PoolsListParser {
public:
- Pools4ListParser(const std::string& dummy, PoolStoragePtr pools)
- :PoolsListParser(dummy, pools) {
+ /// @brief Constructor.
+ ///
+ /// @param pools storage container in which to store the parsed pool.
+ Pools4ListParser(PoolStoragePtr pools) : PoolsListParser(pools) {
}
-protected:
- virtual ParserPtr poolParserMaker(PoolStoragePtr storage) {
- return (ParserPtr(new Pool4Parser("pool", storage)));
+ /// @brief parses the actual structure
+ ///
+ /// This method parses the actual list of pools.
+ ///
+ /// @param pools_list a list of pool structures
+ /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
+ void parse(isc::data::ConstElementPtr pools_list) {
+ BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
+ Pool4Parser parser(pools_);
+ parser.parse(pool, AF_INET);
+ }
}
};
///
/// @param subnet A new subnet being configured.
void build(ConstElementPtr subnet) {
+ /// Parse Pools first.
+ ConstElementPtr pools = subnet->get("pools");
+ if (pools) {
+ Pools4ListParser parser(pools_);
+ parser.parse(pools);
+ }
+
SubnetConfigParser::build(subnet);
if (subnet_) {
(config_id.compare("next-server") == 0) ||
(config_id.compare("reservation-mode") == 0)) {
parser = new StringParser(config_id, string_values_);
- } else if (config_id.compare("pools") == 0) {
- parser = new Pools4ListParser(config_id, pools_);
- // relay has been converted to SimpleParser already.
+ // pools has been converted to SimpleParser already.
+ // relay has been converted to SimpleParser already.
// option-data has been converted to SimpleParser already.
} else if (config_id.compare("match-client-id") == 0) {
parser = new BooleanParser(config_id, boolean_values_);
/// @brief Constructor.
///
- /// @param param_name name of the parameter. Note, it is passed through
- /// but unused, parameter is currently always "Dhcp6/subnet6[X]/pool"
- /// @param pools storage container in which to store the parsed pool
- /// upon "commit"
- Pool6Parser(const std::string& param_name, PoolStoragePtr pools)
- :PoolParser(param_name, pools, AF_INET6) {
+ /// @param pools storage container in which to store the parsed pool.
+ Pool6Parser(PoolStoragePtr pools) : PoolParser(pools) {
}
protected:
}
};
-class Pools6ListParser : public PoolsListParser {
+/// @brief Specialization of the pool list parser for DHCPv6
+class Pools6ListParser : PoolsListParser {
public:
- Pools6ListParser(const std::string& dummy, PoolStoragePtr pools)
- :PoolsListParser(dummy, pools) {
+ /// @brief Constructor.
+ ///
+ /// @param pools storage container in which to store the parsed pool.
+ Pools6ListParser(PoolStoragePtr pools) : PoolsListParser(pools) {
}
-protected:
- virtual ParserPtr poolParserMaker(PoolStoragePtr storage) {
- return (ParserPtr(new Pool6Parser("pool", storage)));
+ /// @brief parses the actual structure
+ ///
+ /// This method parses the actual list of pools.
+ ///
+ /// @param pools_list a list of pool structures
+ /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
+ void parse(isc::data::ConstElementPtr pools_list) {
+ BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
+ Pool6Parser parser(pools_);
+ parser.parse(pool, AF_INET6);
+ }
}
};
/// }
/// @endcode
///
-class PdPoolParser : public DhcpConfigParser {
+class PdPoolParser : public isc::data::SimpleParser {
public:
/// @brief Constructor.
///
- /// @param param_name name of the parameter. Note, it is passed through
- /// but unused, parameter is currently always "Dhcp6/subnet6[X]/pool"
- /// @param pools storage container in which to store the parsed pool
- /// upon "commit"
- PdPoolParser(const std::string&, PoolStoragePtr pools)
- : uint32_values_(new Uint32Storage()),
- string_values_(new StringStorage()), pools_(pools),
- options_(new CfgOption()) {
- if (!pools_) {
- isc_throw(isc::dhcp::DhcpConfigError,
- "PdPoolParser context storage may not be NULL");
- }
+ /// @param pools storage container in which to store the parsed pool.
+ PdPoolParser(PoolStoragePtr pools)
+ : pools_(pools), options_(new CfgOption()) {
}
/// @brief Builds a prefix delegation pool from the given configuration
/// that define a prefix delegation pool.
///
/// @throw DhcpConfigError if configuration parsing fails.
- virtual void build(ConstElementPtr pd_pool_) {
+ void parse(ConstElementPtr pd_pool_) {
+ std::string addr_str;
+ std::string excluded_prefix_str = "::";
+ int64_t prefix_len;
+ int64_t delegated_len;
+ int64_t excluded_prefix_len = 0;
+ bool got_prefix = false;
+ bool got_prefix_len = false;
+ bool got_delegated_len = false;
+
// Parse the elements that make up the option definition.
BOOST_FOREACH(ConfigPair param, pd_pool_->mapValue()) {
std::string entry(param.first);
- ParserPtr parser;
- if (entry == "prefix" || entry =="excluded-prefix") {
- StringParserPtr str_parser(new StringParser(entry,
- string_values_));
- parser = str_parser;
- } else if (entry == "prefix-len" || entry == "delegated-len" ||
- entry == "excluded-prefix-len") {
- Uint32ParserPtr code_parser(new Uint32Parser(entry,
- uint32_values_));
- parser = code_parser;
- } else if (entry == "option-data") {
- OptionDataListParser opts_parser(AF_INET6);
- opts_parser.parse(options_, param.second);
-
- // OptionDataListParser is converted to SimpleParser already,
- // no need to go through build/commit phases.
- continue;
- } else if (entry == "user-context") {
- user_context_ = param.second;
- continue; // no parser to remember, simply store the value
- } else {
- isc_throw(DhcpConfigError, "unsupported parameter: " << entry
- << " (" << param.second->getPosition() << ")");
+ ConstElementPtr value(param.second);
+ try {
+ if (entry == "prefix") {
+ addr_str = value->stringValue();
+ got_prefix = true;
+ } else if (entry == "excluded-prefix") {
+ excluded_prefix_str = value->stringValue();
+ } else if (entry == "prefix-len") {
+ prefix_len = value->intValue();
+ got_prefix_len = true;
+ } else if (entry == "delegated-len") {
+ delegated_len = value->intValue();
+ got_delegated_len = true;
+ } else if (entry == "excluded-prefix-len") {
+ excluded_prefix_len = value->intValue();
+ } else if (entry == "option-data") {
+ OptionDataListParser opts_parser(AF_INET6);
+ opts_parser.parse(options_, value);
+ } else if (entry == "user-context") {
+ user_context_ = value;
+ } else {
+ isc_throw(DhcpConfigError,
+ "unsupported parameter: " << entry
+ << " (" << value->getPosition() << ")");
+ }
+ } catch (const isc::data::TypeError&) {
+ isc_throw(isc::dhcp::DhcpConfigError,
+ "invalid value type specified for parameter '"
+ << entry << "' ("
+ << value->getPosition() << ")");
}
-
- parser->build(param.second);
- parser->commit();
}
- // Try to obtain the pool parameters. It will throw an exception if any
+ // Check the pool parameters. It will throw an exception if any
// of the required parameters are not present or invalid.
+ if (!got_prefix || !got_prefix_len || !got_delegated_len) {
+ isc_throw(isc::dhcp::DhcpConfigError,
+ "Missing parameter '"
+ << (!got_prefix ? "prefix" :
+ (!got_prefix_len ? "prefix-len" : "delegated-len"))
+ << "' (" << pd_pool_->getPosition() << ")");
+ }
try {
- const std::string addr_str = string_values_->getParam("prefix");
- const uint32_t prefix_len = uint32_values_->getParam("prefix-len");
- const uint32_t delegated_len = uint32_values_->getParam("delegated-len");
- const std::string excluded_prefix_str =
- string_values_->getOptionalParam("excluded-prefix", "::");
- const uint32_t excluded_prefix_len =
- uint32_values_->getOptionalParam("excluded-prefix-len", 0);
-
// Attempt to construct the local pool.
- pool_.reset(new Pool6(IOAddress(addr_str), prefix_len,
- delegated_len, IOAddress(excluded_prefix_str),
+ pool_.reset(new Pool6(IOAddress(addr_str),
+ prefix_len,
+ delegated_len,
+ IOAddress(excluded_prefix_str),
excluded_prefix_len));
// Merge options specified for a pool into pool configuration.
options_->copyTo(*pool_->getCfgOption());
if (user_context_) {
pool_->setUserContext(user_context_);
}
- }
- // @brief Commits the constructed local pool to the pool storage.
- virtual void commit() {
// Add the local pool to the external storage ptr.
pools_->push_back(pool_);
}
protected:
- /// Storage for subnet-specific integer values.
- Uint32StoragePtr uint32_values_;
-
- /// Storage for subnet-specific string values.
- StringStoragePtr string_values_;
-
- /// Parsers are stored here.
- ParserCollection parsers_;
/// Pointer to the created pool object.
isc::dhcp::Pool6Ptr pool_;
/// 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 PdPoolListParser : public DhcpConfigParser {
+class PdPoolListParser : public PoolsListParser {
public:
/// @brief Constructor.
///
- /// @param dummy first argument is ignored, all Parser constructors
- /// accept string as first argument.
/// @param storage is the pool storage in which to store the parsed
/// pools in this list
- /// @throw isc::dhcp::DhcpConfigError if storage is null.
- PdPoolListParser(const std::string&, PoolStoragePtr pools)
- : local_pools_(new PoolStorage()), pools_(pools) {
- if (!pools_) {
- isc_throw(isc::dhcp::DhcpConfigError,
- "PdPoolListParser pools storage may not be NULL");
- }
+ PdPoolListParser(PoolStoragePtr pools) : PoolsListParser(pools) {
}
/// @brief Parse configuration entries.
/// that define a prefix delegation pool.
///
/// @throw DhcpConfigError if configuration parsing fails.
- void build(isc::data::ConstElementPtr pd_pool_list) {
- // Make sure the local list is empty.
- local_pools_.reset(new PoolStorage());
-
- // Make sure we have a configuration elements to parse.
- if (!pd_pool_list) {
- isc_throw(DhcpConfigError,
- "PdPoolListParser: list of pool definitions is NULL");
- }
-
+ void parse(isc::data::ConstElementPtr pd_pool_list) {
// Loop through the list of pd pools.
BOOST_FOREACH(ConstElementPtr pd_pool, pd_pool_list->listValue()) {
- boost::shared_ptr<PdPoolParser>
- // Create the PdPool parser.
- parser(new PdPoolParser("pd-pool", local_pools_));
- // Build the pool instance
- parser->build(pd_pool);
- // Commit the pool to the local list of pools.
- parser->commit();
+ PdPoolParser parser(pools_);
+ parser.parse(pd_pool);
}
}
-
- /// @brief Commits the pools created to the external storage area.
- ///
- /// Note that this method adds the local list of pools to the storage area
- /// rather than replacing its contents. This permits other parsers to
- /// contribute to the set of pools.
- void commit() {
- // local_pools_ holds the values produced by the build function.
- // At this point parsing should have completed successfully so
- // we can append new data to the supplied storage.
- pools_->insert(pools_->end(), local_pools_->begin(),
- local_pools_->end());
- }
-
-private:
- /// @brief storage for local pools
- PoolStoragePtr local_pools_;
-
- /// @brief External storage where pools are stored upon list commit.
- PoolStoragePtr pools_;
};
/// @anchor Subnet6ConfigParser
///
/// @param subnet A new subnet being configured.
void build(ConstElementPtr subnet) {
+ /// Parse all pools first.
+ ConstElementPtr pools = subnet->get("pools");
+ if (pools) {
+ Pools6ListParser parser(pools_);
+ parser.parse(pools);
+ }
+ ConstElementPtr pd_pools = subnet->get("pd-pools");
+ if (pd_pools) {
+ PdPoolListParser parser(pools_);
+ parser.parse(pd_pools);
+ }
+
SubnetConfigParser::build(subnet);
if (subnet_) {
(config_id.compare("interface-id") == 0) ||
(config_id.compare("reservation-mode") == 0)) {
parser = new StringParser(config_id, string_values_);
- } else if (config_id.compare("pools") == 0) {
- parser = new Pools6ListParser(config_id, pools_);
+ // pools has been converted to SimpleParser.
// relay has been converted to SimpleParser.
- } else if (config_id.compare("pd-pools") == 0) {
- parser = new PdPoolListParser(config_id, pools_);
+ // pd-pools has been converted to SimpleParser.
// option-data was here, but it is now converted to SimpleParser
} else if (config_id.compare("rapid-commit") == 0) {
parser = new BooleanParser(config_id, boolean_values_);
*cfg = isc::dhcp::Subnet::RelayInfo(ip);
}
-//****************************** PoolsListParser ********************************
-PoolsListParser::PoolsListParser(const std::string&, 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);
-
- // Let's store the parser, but do not commit anything yet
- parsers_.push_back(parser);
- }
-}
-
-void PoolsListParser::commit() {
-
- // Commit each parser first. It will store the pool structure
- // in pools_.
- BOOST_FOREACH(ParserPtr parser, parsers_) {
- parser->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,
- const uint16_t address_family)
- :pools_(pools), options_(new CfgOption()),
- address_family_(address_family) {
+PoolParser::PoolParser(PoolStoragePtr pools) : pools_(pools) {
+}
- if (!pools_) {
- isc_throw(isc::dhcp::DhcpConfigError, "parser logic error: "
- << "storage may not be NULL");
- }
+PoolParser::~PoolParser() {
}
void
-PoolParser::build(ConstElementPtr pool_structure) {
+PoolParser::parse(ConstElementPtr pool_structure,
+ const uint16_t address_family) {
ConstElementPtr text_pool = pool_structure->get("pool");
}
pool = poolMaker(addr, len);
- local_pools_.push_back(pool);
+ pools_->push_back(pool);
// If there's user-context specified, store it.
ConstElementPtr user_context = pool_structure->get("user-context");
isc::asiolink::IOAddress max(txt.substr(pos + 1));
pool = poolMaker(min, max);
- local_pools_.push_back(pool);
+ pools_->push_back(pool);
}
}
if (option_data) {
try {
// Currently we don't support specifying options for the DHCPv4 server.
- if (address_family_ == AF_INET) {
+ if (address_family == AF_INET) {
isc_throw(DhcpConfigError, "option-data is not supported for DHCPv4"
" address pools");
}
CfgOptionPtr cfg = pool->getCfgOption();
- OptionDataListParser option_parser(address_family_);
+ OptionDataListParser option_parser(address_family);
option_parser.parse(cfg, option_data);
} catch (const std::exception& ex) {
isc_throw(isc::dhcp::DhcpConfigError, ex.what()
}
}
-void
-PoolParser::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());
- }
-}
-
//****************************** SubnetConfigParser *************************
SubnetConfigParser::SubnetConfigParser(const std::string&,
void
SubnetConfigParser::build(ConstElementPtr subnet) {
BOOST_FOREACH(ConfigPair param, subnet->mapValue()) {
+ // Pools has been converted to SimpleParser.
+ if (param.first == "pools") {
+ continue;
+ }
+
+ // PdPools has been converted to SimpleParser.
+ if ((param.first == "pd-pools") &&
+ (global_context_->universe_ == Option::V6)) {
+ continue;
+ }
+
// Host reservations must be parsed after subnet specific parameters.
// Note that the reservation parsing will be invoked by the build()
// in the derived classes, i.e. Subnet4ConfigParser and
/// and stored in chosen PoolStorage container.
///
/// It is useful for parsing Dhcp<4/6>/subnet<4/6>[X]/pools[X] structure.
-class PoolParser : public DhcpConfigParser {
+class PoolParser : public isc::data::SimpleParser {
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".
- /// @param address_family AF_INET (for DHCPv4) or AF_INET6 (for DHCPv6).
- /// @throw isc::dhcp::DhcpConfigError if storage is null.
- PoolParser(const std::string& dummy, PoolStoragePtr pools,
- const uint16_t address_family);
+ PoolParser(PoolStoragePtr pools);
+
+ /// @brief destructor.
+ virtual ~PoolParser();
/// @brief parses the actual structure
///
/// No validation is done at this stage, everything is interpreted as
/// interface name.
/// @param pool_structure a single entry on a list of pools
+ /// @param address_family AF_INET (for DHCPv4) or AF_INET6 (for DHCPv6).
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
- virtual void build(isc::data::ConstElementPtr pool_structure);
-
- /// @brief Stores the parsed values in a storage provided
- /// by an upper level parser.
- virtual void commit();
+ virtual void parse(isc::data::ConstElementPtr pool_structure,
+ const uint16_t address_family);
protected:
/// @brief Creates a Pool object given a IPv4 prefix and the prefix length.
/// @param ptype is the type of pool to create.
/// @return returns a PoolPtr to the new Pool object.
virtual PoolPtr poolMaker(isc::asiolink::IOAddress &addr, uint32_t len,
- int32_t ptype=0) = 0;
+ int32_t ptype = 0) = 0;
/// @brief Creates a Pool object given starting and ending IP addresses.
///
/// @param ptype is the type of pool to create (not used by all derivations)
/// @return returns a PoolPtr to the new Pool object.
virtual PoolPtr poolMaker(isc::asiolink::IOAddress &min,
- isc::asiolink::IOAddress &max, int32_t ptype=0) = 0;
+ isc::asiolink::IOAddress &max,
+ int32_t ptype = 0) = 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.
- PoolStorage local_pools_;
-
- /// A storage for pool specific option values.
- CfgOptionPtr options_;
-
- /// @brief Address family: AF_INET (for DHCPv4) or AF_INET6 for DHCPv6.
- uint16_t address_family_;
};
/// @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 {
+class PoolsListParser : public isc::data::SimpleParser {
public:
/// @brief constructor.
///
- /// @param dummy first argument is ignored, all Parser constructors
- /// accept a string as the 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);
+ /// @param pools is the storage in which to store the parsed pools.
+ PoolsListParser(PoolStoragePtr pools) : pools_(pools) {
+ }
+
+ /// @brief destructor.
+ virtual ~PoolsListParser() {
+ }
/// @brief parses the actual structure
///
- /// This method parses the actual list of pools. It creates a parser
- /// for each structure using poolParserMaker().
+ /// This method parses the actual list of pools.
///
/// @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 storage provided
- /// by an upper level parser.
- virtual void commit();
+ virtual void parse(isc::data::ConstElementPtr pools_list) = 0;
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 the
- /// storage where pools are stored by the build function.
- PoolStoragePtr local_pools_;
-
- /// Collection of parsers;
- ParserCollection parsers_;
};
/// @brief parser for additional relay information