Commit 3e674fda authored by Francis Dupont's avatar Francis Dupont

[5097] Migrated (checkpoint as user-context are missing in flex/bison)

parent 91a546c3
......@@ -58,12 +58,8 @@ public:
/// @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:
......@@ -90,15 +86,26 @@ 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);
}
}
};
......@@ -123,6 +130,13 @@ public:
///
/// @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_) {
......@@ -186,9 +200,8 @@ protected:
(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_);
......
......@@ -75,12 +75,8 @@ 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"
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:
......@@ -113,15 +109,26 @@ 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);
}
}
};
......@@ -142,23 +149,14 @@ protected:
/// }
/// @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
......@@ -170,53 +168,67 @@ public:
/// 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());
......@@ -231,23 +243,12 @@ public:
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_;
......@@ -266,21 +267,13 @@ protected:
/// 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.
......@@ -292,47 +285,13 @@ public:
/// 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
......@@ -357,6 +316,18 @@ public:
///
/// @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_) {
......@@ -421,11 +392,9 @@ protected:
(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_);
......
......@@ -852,60 +852,16 @@ RelayInfoParser::parse(const isc::dhcp::Subnet::RelayInfoPtr& cfg,
*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");
......@@ -952,7 +908,7 @@ PoolParser::build(ConstElementPtr pool_structure) {
}
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");
......@@ -974,7 +930,7 @@ PoolParser::build(ConstElementPtr pool_structure) {
isc::asiolink::IOAddress max(txt.substr(pos + 1));
pool = poolMaker(min, max);
local_pools_.push_back(pool);
pools_->push_back(pool);
}
}
......@@ -991,13 +947,13 @@ PoolParser::build(ConstElementPtr pool_structure) {
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()
......@@ -1006,16 +962,6 @@ PoolParser::build(ConstElementPtr pool_structure) {
}
}
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&,
......@@ -1040,6 +986,17 @@ 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
......
......@@ -703,19 +703,16 @@ typedef boost::shared_ptr<PoolStorage> PoolStoragePtr;
/// 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
///
......@@ -723,12 +720,10 @@ public:
/// 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.
......@@ -738,7 +733,7 @@ protected:
/// @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.
///
......@@ -747,23 +742,14 @@ protected:
/// @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
......@@ -771,54 +757,34 @@ protected:
/// 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