BIND 10 trac2545, updated. 890e0b0b7df76e61c1638744647a793143537722 [2545] Moved DhcpConfigParser abstract class to common header file.
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Jan 4 14:03:57 UTC 2013
The branch, trac2545 has been updated
via 890e0b0b7df76e61c1638744647a793143537722 (commit)
via d83fc2a12f36818bdd60c87e61d01be7a5dfa4e5 (commit)
from 36622df85e6b1b7ce4fc621fbfaa21d2b35003d8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 890e0b0b7df76e61c1638744647a793143537722
Author: Marcin Siodelski <marcin at isc.org>
Date: Fri Jan 4 14:15:40 2013 +0100
[2545] Moved DhcpConfigParser abstract class to common header file.
commit d83fc2a12f36818bdd60c87e61d01be7a5dfa4e5
Author: Marcin Siodelski <marcin at isc.org>
Date: Fri Jan 4 13:47:37 2013 +0100
[2545] Changes as a result of the review.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp4/config_parser.cc | 137 ++++++++++++--------
src/bin/dhcp4/config_parser.h | 92 +------------
src/bin/dhcp4/tests/config_parser_unittest.cc | 5 +-
src/bin/dhcp6/config_parser.cc | 106 ++++++++-------
src/bin/dhcp6/config_parser.h | 89 +------------
src/bin/dhcp6/tests/config_parser_unittest.cc | 6 +-
src/lib/dhcpsrv/Makefile.am | 1 +
.../dhcpsrv/dhcp_config_parser.h} | 68 ++--------
8 files changed, 165 insertions(+), 339 deletions(-)
copy src/{bin/dhcp6/config_parser.h => lib/dhcpsrv/dhcp_config_parser.h} (66%)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/config_parser.cc b/src/bin/dhcp4/config_parser.cc
index ede4268..193b1de 100644
--- a/src/bin/dhcp4/config_parser.cc
+++ b/src/bin/dhcp4/config_parser.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -18,6 +18,7 @@
#include <dhcp/libdhcp++.h>
#include <dhcp/option_definition.h>
#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/dhcp_config_parser.h>
#include <util/encode/hex.h>
#include <util/strutil.h>
#include <boost/foreach.hpp>
@@ -36,12 +37,11 @@ using namespace isc::asiolink;
namespace {
-
/// @brief auxiliary type used for storing element name and its parser
typedef pair<string, ConstElementPtr> ConfigPair;
/// @brief a factory method that will create a parser for a given element name
-typedef isc::dhcp::Dhcp4ConfigParser* ParserFactory(const std::string& config_id);
+typedef isc::dhcp::DhcpConfigParser* ParserFactory(const std::string& config_id);
/// @brief a collection of factories that creates parsers for specified element names
typedef std::map<std::string, ParserFactory*> FactoryMap;
@@ -81,12 +81,12 @@ OptionStorage option_defaults;
/// will accept any configuration and will just print it out
/// on commit. Useful for debugging existing configurations and
/// adding new ones.
-class DebugParser : public Dhcp4ConfigParser {
+class DebugParser : public DhcpConfigParser {
public:
/// @brief Constructor
///
- /// See @ref Dhcp4ConfigParser class for details.
+ /// See @ref DhcpConfigParser class for details.
///
/// @param param_name name of the parsed parameter
DebugParser(const std::string& param_name)
@@ -95,7 +95,7 @@ public:
/// @brief builds parameter value
///
- /// See @ref Dhcp4ConfigParser class for details.
+ /// See @ref DhcpConfigParser class for details.
///
/// @param new_config pointer to the new configuration
virtual void build(ConstElementPtr new_config) {
@@ -109,7 +109,7 @@ public:
/// This is a method required by base class. It pretends to apply the
/// configuration, but in fact it only prints the parameter out.
///
- /// See @ref Dhcp4ConfigParser class for details.
+ /// See @ref DhcpConfigParser class for details.
virtual void commit() {
// Debug message. The whole DebugParser class is used only for parser
// debugging, and is not used in production code. It is very convenient
@@ -121,7 +121,7 @@ public:
/// @brief factory that constructs DebugParser objects
///
/// @param param_name name of the parameter to be parsed
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* Factory(const std::string& param_name) {
return (new DebugParser(param_name));
}
@@ -138,7 +138,7 @@ private:
/// This parser handles configuration values of the boolean type.
/// Parsed values are stored in a provided storage. If no storage
/// is provided then the build function throws an exception.
-class BooleanParser : public Dhcp4ConfigParser {
+class BooleanParser : public DhcpConfigParser {
public:
/// @brief Constructor.
///
@@ -147,6 +147,11 @@ public:
: storage_(NULL),
param_name_(param_name),
value_(false) {
+ // Empty parameter name is invalid.
+ if (param_name_.empty()) {
+ isc_throw(isc::dhcp::Dhcp4ConfigError, "parser logic error:"
+ << "empty parameter name provided");
+ }
}
/// @brief Parse a boolean value.
@@ -184,7 +189,7 @@ public:
///
/// @param param_name name of the parameter for which the
/// parser is created.
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new BooleanParser(param_name));
}
@@ -214,11 +219,11 @@ private:
/// (uint32_defaults). If used in smaller scopes (e.g. to parse parameters
/// in subnet config), it can be pointed to a different storage, using
/// setStorage() method. This class follows the parser interface, laid out
-/// in its base class, @ref Dhcp4ConfigParser.
+/// in its base class, @ref DhcpConfigParser.
///
/// For overview of usability of this generic purpose parser, see
/// @ref dhcpv4ConfigInherit page.
-class Uint32Parser : public Dhcp4ConfigParser {
+class Uint32Parser : public DhcpConfigParser {
public:
/// @brief constructor for Uint32Parser
@@ -226,6 +231,11 @@ public:
Uint32Parser(const std::string& param_name)
: storage_(&uint32_defaults),
param_name_(param_name) {
+ // Empty parameter name is invalid.
+ if (param_name_.empty()) {
+ isc_throw(Dhcp4ConfigError, "parser logic error:"
+ << "empty parameter name provided");
+ }
}
/// @brief Parses configuration configuration parameter as uint32_t.
@@ -235,7 +245,7 @@ public:
/// or the parameter name is empty.
virtual void build(ConstElementPtr value) {
if (param_name_.empty()) {
- isc_throw(BadValue, "parser logic error:"
+ isc_throw(Dhcp4ConfigError, "parser logic error:"
<< "empty parameter name provided");
}
@@ -272,7 +282,7 @@ public:
/// @brief factory that constructs Uint32Parser objects
///
/// @param param_name name of the parameter to be parsed
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new Uint32Parser(param_name));
}
@@ -303,17 +313,22 @@ private:
/// (string_defaults). If used in smaller scopes (e.g. to parse parameters
/// in subnet config), it can be pointed to a different storage, using
/// setStorage() method. This class follows the parser interface, laid out
-/// in its base class, @ref Dhcp4ConfigParser.
+/// in its base class, @ref DhcpConfigParser.
///
/// For overview of usability of this generic purpose parser, see
/// @ref dhcpv4ConfigInherit page.
-class StringParser : public Dhcp4ConfigParser {
+class StringParser : public DhcpConfigParser {
public:
/// @brief constructor for StringParser
/// @param param_name name of the configuration parameter being parsed
StringParser(const std::string& param_name)
:storage_(&string_defaults), param_name_(param_name) {
+ // Empty parameter name is invalid.
+ if (param_name_.empty()) {
+ isc_throw(Dhcp4ConfigError, "parser logic error:"
+ << "empty parameter name provided");
+ }
}
/// @brief parses parameter value
@@ -339,7 +354,7 @@ public:
/// @brief factory that constructs StringParser objects
///
/// @param param_name name of the parameter to be parsed
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new StringParser(param_name));
}
@@ -372,7 +387,7 @@ private:
/// designates all interfaces.
///
/// It is useful for parsing Dhcp4/interface parameter.
-class InterfaceListConfigParser : public Dhcp4ConfigParser {
+class InterfaceListConfigParser : public DhcpConfigParser {
public:
/// @brief constructor
@@ -410,7 +425,7 @@ public:
/// @brief factory that constructs InterfaceListConfigParser objects
///
/// @param param_name name of the parameter to be parsed
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new InterfaceListConfigParser(param_name));
}
@@ -429,7 +444,7 @@ private:
/// before build(). Otherwise exception will be thrown.
///
/// It is useful for parsing Dhcp4/subnet4[X]/pool parameters.
-class PoolParser : public Dhcp4ConfigParser {
+class PoolParser : public DhcpConfigParser {
public:
/// @brief constructor.
@@ -537,7 +552,7 @@ public:
/// @brief factory that constructs PoolParser objects
///
/// @param param_name name of the parameter to be parsed
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new PoolParser(param_name));
}
@@ -565,7 +580,7 @@ private:
/// (see tickets #2319, #2314). When option spaces are implemented
/// there will be a way to reference the particular option using
/// its type (code) or option name.
-class OptionDataParser : public Dhcp4ConfigParser {
+class OptionDataParser : public DhcpConfigParser {
public:
/// @brief Constructor.
@@ -602,28 +617,28 @@ public:
ParserPtr parser;
if (param.first == "name") {
boost::shared_ptr<StringParser>
- name_parser(dynamic_cast<StringParser*>(StringParser::Factory(param.first)));
+ name_parser(dynamic_cast<StringParser*>(StringParser::factory(param.first)));
if (name_parser) {
name_parser->setStorage(&string_values_);
parser = name_parser;
}
} else if (param.first == "code") {
boost::shared_ptr<Uint32Parser>
- code_parser(dynamic_cast<Uint32Parser*>(Uint32Parser::Factory(param.first)));
+ code_parser(dynamic_cast<Uint32Parser*>(Uint32Parser::factory(param.first)));
if (code_parser) {
code_parser->setStorage(&uint32_values_);
parser = code_parser;
}
} else if (param.first == "data") {
boost::shared_ptr<StringParser>
- value_parser(dynamic_cast<StringParser*>(StringParser::Factory(param.first)));
+ value_parser(dynamic_cast<StringParser*>(StringParser::factory(param.first)));
if (value_parser) {
value_parser->setStorage(&string_values_);
parser = value_parser;
}
} else if (param.first == "csv-format") {
boost::shared_ptr<BooleanParser>
- value_parser(dynamic_cast<BooleanParser*>(BooleanParser::Factory(param.first)));
+ value_parser(dynamic_cast<BooleanParser*>(BooleanParser::factory(param.first)));
if (value_parser) {
value_parser->setStorage(&boolean_values_);
parser = value_parser;
@@ -869,7 +884,7 @@ private:
/// data for a particular subnet and creates a collection of options.
/// If parsing is successful, all these options are added to the Subnet
/// object.
-class OptionDataListParser : public Dhcp4ConfigParser {
+class OptionDataListParser : public DhcpConfigParser {
public:
/// @brief Constructor.
@@ -926,7 +941,7 @@ public:
/// @param param_name param name.
///
/// @return DhcpConfigParser object.
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new OptionDataListParser(param_name));
}
@@ -945,7 +960,7 @@ public:
///
/// This class parses the whole subnet definition. It creates parsers
/// for received configuration parameters as needed.
-class Subnet4ConfigParser : public Dhcp4ConfigParser {
+class Subnet4ConfigParser : public DhcpConfigParser {
public:
/// @brief constructor
@@ -1059,18 +1074,32 @@ private:
isc_throw(Dhcp4ConfigError,
"Mandatory subnet definition in subnet missing");
}
+ // Remove any spaces or tabs.
string subnet_txt = it->second;
boost::erase_all(subnet_txt, " ");
boost::erase_all(subnet_txt, "\t");
+ // The subnet format is prefix/len. We are going to extract
+ // the prefix portion of a subnet string to create IOAddress
+ // object from it. IOAddress will be passed to the Subnet's
+ // constructor later on. In order to extract the prefix we
+ // need to get all characters preceding "/".
size_t pos = subnet_txt.find("/");
if (pos == string::npos) {
isc_throw(Dhcp4ConfigError,
"Invalid subnet syntax (prefix/len expected):" << it->second);
}
+
+ // Try to create the address object. It also validates that
+ // the address syntax is ok.
IOAddress addr(subnet_txt.substr(0, pos));
uint8_t len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1));
+ // Get all 'time' parameters using inheritance.
+ // If the subnet-specific value is defined then use it, else
+ // use the global value. The global value must always be
+ // present. If it is not, it is an internal error and exception
+ // is thrown.
Triplet<uint32_t> t1 = getParam("renew-timer");
Triplet<uint32_t> t2 = getParam("rebind-timer");
Triplet<uint32_t> valid = getParam("valid-lifetime");
@@ -1130,15 +1159,15 @@ private:
/// @param config_id name od the entry
/// @return parser object for specified entry name
/// @throw NotImplemented if trying to create a parser for unknown config element
- Dhcp4ConfigParser* createSubnet4ConfigParser(const std::string& config_id) {
+ DhcpConfigParser* createSubnet4ConfigParser(const std::string& config_id) {
FactoryMap factories;
- factories["valid-lifetime"] = Uint32Parser::Factory;
- factories["renew-timer"] = Uint32Parser::Factory;
- factories["rebind-timer"] = Uint32Parser::Factory;
- factories["subnet"] = StringParser::Factory;
- factories["pool"] = PoolParser::Factory;
- factories["option-data"] = OptionDataListParser::Factory;
+ factories["valid-lifetime"] = Uint32Parser::factory;
+ factories["renew-timer"] = Uint32Parser::factory;
+ factories["rebind-timer"] = Uint32Parser::factory;
+ factories["subnet"] = StringParser::factory;
+ factories["pool"] = PoolParser::factory;
+ factories["option-data"] = OptionDataListParser::factory;
FactoryMap::iterator f = factories.find(config_id);
if (f == factories.end()) {
@@ -1209,7 +1238,7 @@ private:
/// This is a wrapper parser that handles the whole list of Subnet4
/// definitions. It iterates over all entries and creates Subnet4ConfigParser
/// for each entry.
-class Subnets4ListConfigParser : public Dhcp4ConfigParser {
+class Subnets4ListConfigParser : public DhcpConfigParser {
public:
/// @brief constructor
@@ -1257,7 +1286,7 @@ public:
/// @brief Returns Subnet4ListConfigParser object
/// @param param_name name of the parameter
/// @return Subnets4ListConfigParser object
- static Dhcp4ConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new Subnets4ListConfigParser(param_name));
}
@@ -1279,16 +1308,16 @@ namespace dhcp {
/// @param config_id pointer to received global configuration entry
/// @return parser for specified global DHCPv4 parameter
/// @throw NotImplemented if trying to create a parser for unknown config element
-Dhcp4ConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id) {
+DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id) {
FactoryMap factories;
- factories["valid-lifetime"] = Uint32Parser::Factory;
- factories["renew-timer"] = Uint32Parser::Factory;
- factories["rebind-timer"] = Uint32Parser::Factory;
- factories["interface"] = InterfaceListConfigParser::Factory;
- factories["subnet4"] = Subnets4ListConfigParser::Factory;
- factories["option-data"] = OptionDataListParser::Factory;
- factories["version"] = StringParser::Factory;
+ factories["valid-lifetime"] = Uint32Parser::factory;
+ factories["renew-timer"] = Uint32Parser::factory;
+ factories["rebind-timer"] = Uint32Parser::factory;
+ factories["interface"] = InterfaceListConfigParser::factory;
+ factories["subnet4"] = Subnets4ListConfigParser::factory;
+ factories["option-data"] = OptionDataListParser::factory;
+ factories["version"] = StringParser::factory;
FactoryMap::iterator f = factories.find(config_id);
if (f == factories.end()) {
@@ -1327,12 +1356,12 @@ configureDhcp4Server(Dhcpv4Srv& , ConstElementPtr config_set) {
ParserCollection dependent_parsers;
// The subnet parsers implement data inheritance by directly
- // accesing global storages. For this reason the global data
+ // accessing global storage. For this reason the global data
// parsers must store the parsed data into global storages
- // immediatelly. This may cause data inconsistency if the
- // parsing operation fails after the global storage have been
- // already modified. We need to preserve the original global
- // data here so as we can rollback changes when an error occurs.
+ // immediately. This may cause data inconsistency if the
+ // parsing operation fails after the global storage has been
+ // modified. We need to preserve the original global data here
+ // so as we can rollback changes when an error occurs.
Uint32Storage uint32_local(uint32_defaults);
StringStorage string_local(string_defaults);
OptionStorage option_local(option_defaults);
@@ -1345,11 +1374,11 @@ configureDhcp4Server(Dhcpv4Srv& , ConstElementPtr config_set) {
try {
- // Iterate over all independent parsers first (all but subnet6)
+ // Iterate over all independent parsers first (all but subnet4)
// and try to parse the data.
BOOST_FOREACH(ConfigPair config_pair, config_set->mapValue()) {
- ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first));
if (config_pair.first != "subnet4") {
+ ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first));
independent_parsers.push_back(parser);
parser->build(config_pair.second);
// The commit operation here may modify the global storage
@@ -1361,8 +1390,8 @@ configureDhcp4Server(Dhcpv4Srv& , ConstElementPtr config_set) {
// Process dependent configuration data.
BOOST_FOREACH(ConfigPair config_pair, config_set->mapValue()) {
- ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first));
if (config_pair.first == "subnet4") {
+ ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first));
dependent_parsers.push_back(parser);
parser->build(config_pair.second);
}
diff --git a/src/bin/dhcp4/config_parser.h b/src/bin/dhcp4/config_parser.h
index e24ae75..3247241 100644
--- a/src/bin/dhcp4/config_parser.h
+++ b/src/bin/dhcp4/config_parser.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -42,96 +42,6 @@ public:
: isc::Exception(file, line, what) {}
};
-/// @brief Forward declaration to Dhcp4ConfigParser class.
-///
-/// It is only needed here to define types that are
-/// based on this class before the class definition.
-class Dhcp4ConfigParser;
-
-/// @brief a pointer to configuration parser
-typedef boost::shared_ptr<Dhcp4ConfigParser> ParserPtr;
-
-/// @brief a collection of parsers
-///
-/// This container is used to store pointer to parsers for a given scope.
-typedef std::vector<ParserPtr> ParserCollection;
-
-/// @brief Base abstract class for all DHCPv4 parsers
-///
-/// Each instance of a class derived from this class parses one specific config
-/// element. Sometimes elements are simple (e.g. a string) and sometimes quite
-/// complex (e.g. a subnet). In such case, it is likely that a parser will
-/// spawn child parsers to parse child elements in the configuration.
-/// @todo: Merge this class with DhcpConfigParser in src/bin/dhcp6
-class Dhcp4ConfigParser {
- ///
- /// @name Constructors and Destructor
- ///
- /// Note: The copy constructor and the assignment operator are
- /// intentionally defined as private to make it explicit that this is a
- /// pure base class.
- //@{
-private:
-
- // Private construtor and assignment operator assures that nobody
- // will be able to copy or assign a parser. There are no defined
- // bodies for them.
- Dhcp4ConfigParser(const Dhcp4ConfigParser& source);
- Dhcp4ConfigParser& operator=(const Dhcp4ConfigParser& source);
-protected:
- /// @brief The default constructor.
- ///
- /// This is intentionally defined as @c protected as this base class should
- /// never be instantiated (except as part of a derived class).
- Dhcp4ConfigParser() {}
-public:
- /// The destructor.
- virtual ~Dhcp4ConfigParser() {}
- //@}
-
- /// @brief Prepare configuration value.
- ///
- /// This method parses the "value part" of the configuration identifier
- /// that corresponds to this derived class and prepares a new value to
- /// apply to the server.
- ///
- /// This method must validate the given value both in terms of syntax
- /// and semantics of the configuration, so that the server will be
- /// validly configured at the time of @c commit(). Note: the given
- /// configuration value is normally syntactically validated, but the
- /// @c build() implementation must also expect invalid input. If it
- /// detects an error it may throw an exception of a derived class
- /// of @c isc::Exception.
- ///
- /// Preparing a configuration value will often require resource
- /// allocation. If it fails, it may throw a corresponding standard
- /// exception.
- ///
- /// This method is not expected to be called more than once in the
- /// life of the object. Although multiple calls are not prohibited
- /// by the interface, the behavior is undefined.
- ///
- /// @param config_value The configuration value for the identifier
- /// corresponding to the derived class.
- virtual void build(isc::data::ConstElementPtr config_value) = 0;
-
- /// @brief Apply the prepared configuration value to the server.
- ///
- /// This method is expected to be exception free, and, as a consequence,
- /// it should normally not involve resource allocation.
- /// Typically it would simply perform exception free assignment or swap
- /// operation on the value prepared in @c build().
- /// In some cases, however, it may be very difficult to meet this
- /// condition in a realistic way, while the failure case should really
- /// be very rare. In such a case it may throw, and, if the parser is
- /// called via @c configureDhcp4Server(), the caller will convert the
- /// exception as a fatal error.
- ///
- /// This method is expected to be called after @c build(), and only once.
- /// The result is undefined otherwise.
- virtual void commit() = 0;
-};
-
/// @brief Configure DHCPv4 server (@c Dhcpv4Srv) with a set of configuration values.
///
/// This function parses configuration information stored in @c config_set
diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc
index baf550d..498cedb 100644
--- a/src/bin/dhcp4/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp4/tests/config_parser_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -78,7 +78,8 @@ public:
/// @brief Create the simple configuration with single option.
///
/// This function allows to set one of the parameters that configure
- /// option value. These parameters are: "name", "code" and "data".
+ /// option value. These parameters are: "name", "code", "data" and
+ /// "csv-format".
///
/// @param param_value string holiding option parameter value to be
/// injected into the configuration string.
diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc
index 8a4c26c..aec182a 100644
--- a/src/bin/dhcp6/config_parser.cc
+++ b/src/bin/dhcp6/config_parser.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -19,6 +19,7 @@
#include <dhcp6/config_parser.h>
#include <dhcp6/dhcp6_log.h>
#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/dhcp_config_parser.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/triplet.h>
@@ -131,7 +132,7 @@ public:
/// @brief factory that constructs DebugParser objects
///
/// @param param_name name of the parameter to be parsed
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new DebugParser(param_name));
}
@@ -158,6 +159,11 @@ public:
: storage_(NULL),
param_name_(param_name),
value_(false) {
+ // Empty parameter name is invalid.
+ if (param_name_.empty()) {
+ isc_throw(isc::dhcp::Dhcp6ConfigError, "parser logic error:"
+ << "empty parameter name provided");
+ }
}
/// @brief Parse a boolean value.
@@ -195,7 +201,7 @@ public:
///
/// @param param_name name of the parameter for which the
/// parser is created.
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new BooleanParser(param_name));
}
@@ -241,6 +247,11 @@ public:
Uint32Parser(const std::string& param_name)
: storage_(&uint32_defaults),
param_name_(param_name) {
+ // Empty parameter name is invalid.
+ if (param_name_.empty()) {
+ isc_throw(Dhcp6ConfigError, "parser logic error:"
+ << "empty parameter name provided");
+ }
}
/// @brief Parses configuration configuration parameter as uint32_t.
@@ -297,7 +308,7 @@ public:
/// @brief Factory that constructs Uint32Parser objects.
///
/// @param param_name name of the parameter to be parsed.
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new Uint32Parser(param_name));
}
@@ -339,6 +350,11 @@ public:
StringParser(const std::string& param_name)
: storage_(&string_defaults),
param_name_(param_name) {
+ // Empty parameter name is invalid.
+ if (param_name_.empty()) {
+ isc_throw(Dhcp6ConfigError, "parser logic error:"
+ << "empty parameter name provided");
+ }
}
/// @brief parses parameter value
@@ -368,7 +384,7 @@ public:
/// @brief Factory that constructs StringParser objects
///
/// @param param_name name of the parameter to be parsed
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new StringParser(param_name));
}
@@ -436,7 +452,7 @@ public:
/// @brief factory that constructs InterfaceListConfigParser objects
///
/// @param param_name name of the parameter to be parsed
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new InterfaceListConfigParser(param_name));
}
@@ -474,8 +490,6 @@ public:
/// (setStorage() not called)
void build(ConstElementPtr pools_list) {
- using namespace isc::dhcp;
-
// setStorage() should have been called before build
if (!pools_) {
isc_throw(isc::InvalidOperation, "parser logic error: no pool storage set,"
@@ -566,7 +580,7 @@ public:
/// @brief factory that constructs PoolParser objects
///
/// @param param_name name of the parameter to be parsed
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new PoolParser(param_name));
}
@@ -625,8 +639,6 @@ public:
/// @throw isc::BadValue if option data storage is invalid.
virtual void build(ConstElementPtr option_data_entries) {
- using namespace isc::dhcp;
-
if (options_ == NULL) {
isc_throw(isc::InvalidOperation, "Parser logic error: storage must be set before "
"parsing option data.");
@@ -635,28 +647,28 @@ public:
ParserPtr parser;
if (param.first == "name") {
boost::shared_ptr<StringParser>
- name_parser(dynamic_cast<StringParser*>(StringParser::Factory(param.first)));
+ name_parser(dynamic_cast<StringParser*>(StringParser::factory(param.first)));
if (name_parser) {
name_parser->setStorage(&string_values_);
parser = name_parser;
}
} else if (param.first == "code") {
boost::shared_ptr<Uint32Parser>
- code_parser(dynamic_cast<Uint32Parser*>(Uint32Parser::Factory(param.first)));
+ code_parser(dynamic_cast<Uint32Parser*>(Uint32Parser::factory(param.first)));
if (code_parser) {
code_parser->setStorage(&uint32_values_);
parser = code_parser;
}
} else if (param.first == "data") {
boost::shared_ptr<StringParser>
- value_parser(dynamic_cast<StringParser*>(StringParser::Factory(param.first)));
+ value_parser(dynamic_cast<StringParser*>(StringParser::factory(param.first)));
if (value_parser) {
value_parser->setStorage(&string_values_);
parser = value_parser;
}
} else if (param.first == "csv-format") {
boost::shared_ptr<BooleanParser>
- value_parser(dynamic_cast<BooleanParser*>(BooleanParser::Factory(param.first)));
+ value_parser(dynamic_cast<BooleanParser*>(BooleanParser::factory(param.first)));
if (value_parser) {
value_parser->setStorage(&boolean_values_);
parser = value_parser;
@@ -740,8 +752,6 @@ private:
/// are invalid.
void createOption() {
- using namespace isc::dhcp;
-
// Option code is held in the uint32_t storage but is supposed to
// be uint16_t value. We need to check that value in the configuration
// does not exceed range of uint16_t and is not zero.
@@ -963,7 +973,7 @@ public:
/// @param param_name param name.
///
/// @return DhcpConfigParser object.
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new OptionDataListParser(param_name));
}
@@ -998,8 +1008,6 @@ public:
/// @throw isc::Dhcp6ConfigError if subnet configuration parsing failed.
void build(ConstElementPtr subnet) {
- using namespace isc::dhcp;
-
BOOST_FOREACH(ConfigPair param, subnet->mapValue()) {
ParserPtr parser(createSubnet6ConfigParser(param.first));
// The actual type of the parser is unknown here. We have to discover
@@ -1091,8 +1099,6 @@ private:
/// @throw isc::dhcp::Dhcp6ConfigError if subnet configuration parsing failed.
void createSubnet() {
- using namespace isc::dhcp;
-
// Find a subnet string.
StringStorage::const_iterator it = string_values_.find("subnet");
if (it == string_values_.end()) {
@@ -1103,7 +1109,11 @@ private:
string subnet_txt = it->second;
boost::erase_all(subnet_txt, " ");
boost::erase_all(subnet_txt, "\t");
- // Get the address portion (without length).
+ // The subnet format is prefix/len. We are going to extract
+ // the prefix portion of a subnet string to create IOAddress
+ // object from it. IOAddress will be passed to the Subnet's
+ // constructor later on. In order to extract the prefix we
+ // need to get all characters preceding "/".
size_t pos = subnet_txt.find("/");
if (pos == string::npos) {
isc_throw(Dhcp6ConfigError,
@@ -1117,7 +1127,9 @@ private:
// Get all 'time' parameters using inheritance.
// If the subnet-specific value is defined then use it, else
- // use the global value.
+ // use the global value. The global value must always be
+ // present. If it is not, it is an internal error and exception
+ // is thrown.
Triplet<uint32_t> t1 = getParam("renew-timer");
Triplet<uint32_t> t2 = getParam("rebind-timer");
Triplet<uint32_t> pref = getParam("preferred-lifetime");
@@ -1185,13 +1197,13 @@ private:
DhcpConfigParser* createSubnet6ConfigParser(const std::string& config_id) {
FactoryMap factories;
- factories["preferred-lifetime"] = Uint32Parser::Factory;
- factories["valid-lifetime"] = Uint32Parser::Factory;
- factories["renew-timer"] = Uint32Parser::Factory;
- factories["rebind-timer"] = Uint32Parser::Factory;
- factories["subnet"] = StringParser::Factory;
- factories["pool"] = PoolParser::Factory;
- factories["option-data"] = OptionDataListParser::Factory;
+ factories["preferred-lifetime"] = Uint32Parser::factory;
+ factories["valid-lifetime"] = Uint32Parser::factory;
+ factories["renew-timer"] = Uint32Parser::factory;
+ factories["rebind-timer"] = Uint32Parser::factory;
+ factories["subnet"] = StringParser::factory;
+ factories["pool"] = PoolParser::factory;
+ factories["option-data"] = OptionDataListParser::factory;
FactoryMap::iterator f = factories.find(config_id);
if (f == factories.end()) {
@@ -1311,7 +1323,7 @@ public:
/// @brief Returns Subnet6ListConfigParser object
/// @param param_name name of the parameter
/// @return Subnets6ListConfigParser object
- static DhcpConfigParser* Factory(const std::string& param_name) {
+ static DhcpConfigParser* factory(const std::string& param_name) {
return (new Subnets6ListConfigParser(param_name));
}
@@ -1335,14 +1347,14 @@ namespace dhcp {
DhcpConfigParser* createGlobalDhcpConfigParser(const std::string& config_id) {
FactoryMap factories;
- factories["preferred-lifetime"] = Uint32Parser::Factory;
- factories["valid-lifetime"] = Uint32Parser::Factory;
- factories["renew-timer"] = Uint32Parser::Factory;
- factories["rebind-timer"] = Uint32Parser::Factory;
- factories["interface"] = InterfaceListConfigParser::Factory;
- factories["subnet6"] = Subnets6ListConfigParser::Factory;
- factories["option-data"] = OptionDataListParser::Factory;
- factories["version"] = StringParser::Factory;
+ factories["preferred-lifetime"] = Uint32Parser::factory;
+ factories["valid-lifetime"] = Uint32Parser::factory;
+ factories["renew-timer"] = Uint32Parser::factory;
+ factories["rebind-timer"] = Uint32Parser::factory;
+ factories["interface"] = InterfaceListConfigParser::factory;
+ factories["subnet6"] = Subnets6ListConfigParser::factory;
+ factories["option-data"] = OptionDataListParser::factory;
+ factories["version"] = StringParser::factory;
FactoryMap::iterator f = factories.find(config_id);
if (f == factories.end()) {
@@ -1381,12 +1393,12 @@ configureDhcp6Server(Dhcpv6Srv& , ConstElementPtr config_set) {
ParserCollection dependent_parsers;
// The subnet parsers implement data inheritance by directly
- // accesing global storages. For this reason the global data
+ // accessing global storages. For this reason the global data
// parsers must store the parsed data into global storages
- // immediatelly. This may cause data inconsistency if the
- // parsing operation fails after the global storage have been
- // already modified. We need to preserve the original global
- // data here so as we can rollback changes when an error occurs.
+ // immediately. This may cause data inconsistency if the
+ // parsing operation fails after the global storage has been
+ // modified. We need to preserve the original global data here
+ // so as we can rollback changes when an error occurs.
Uint32Storage uint32_local(uint32_defaults);
StringStorage string_local(string_defaults);
OptionStorage option_local(option_defaults);
@@ -1400,8 +1412,8 @@ configureDhcp6Server(Dhcpv6Srv& , ConstElementPtr config_set) {
// Iterate over all independent parsers first (all but subnet6)
// and try to parse the data.
BOOST_FOREACH(ConfigPair config_pair, config_set->mapValue()) {
- ParserPtr parser(createGlobalDhcpConfigParser(config_pair.first));
if (config_pair.first != "subnet6") {
+ ParserPtr parser(createGlobalDhcpConfigParser(config_pair.first));
independent_parsers.push_back(parser);
parser->build(config_pair.second);
// The commit operation here may modify the global storage
@@ -1413,8 +1425,8 @@ configureDhcp6Server(Dhcpv6Srv& , ConstElementPtr config_set) {
// Process dependent configuration data.
BOOST_FOREACH(ConfigPair config_pair, config_set->mapValue()) {
- ParserPtr parser(createGlobalDhcpConfigParser(config_pair.first));
if (config_pair.first == "subnet6") {
+ ParserPtr parser(createGlobalDhcpConfigParser(config_pair.first));
dependent_parsers.push_back(parser);
parser->build(config_pair.second);
}
diff --git a/src/bin/dhcp6/config_parser.h b/src/bin/dhcp6/config_parser.h
index 5394ede..408d01f 100644
--- a/src/bin/dhcp6/config_parser.h
+++ b/src/bin/dhcp6/config_parser.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -41,93 +41,6 @@ public:
: isc::Exception(file, line, what) {}
};
-/// @brief Forward declaration to DhcpConfigParser class.
-///
-/// It is only needed here to define types that are
-/// based on this class before the class definition.
-class DhcpConfigParser;
-
-/// @brief a pointer to configuration parser
-typedef boost::shared_ptr<DhcpConfigParser> ParserPtr;
-
-/// @brief Collection of parsers.
-///
-/// This container is used to store pointer to parsers for a given scope.
-typedef std::vector<ParserPtr> ParserCollection;
-
-/// @brief Base abstract class for all DHCPv6 parsers
-///
-/// Each instance of a class derived from this class parses one specific config
-/// element. Sometimes elements are simple (e.g. a string) and sometimes quite
-/// complex (e.g. a subnet). In such case, it is likely that a parser will
-/// spawn child parsers to parse child elements in the configuration.
-/// @todo: Merge this class with Dhcp4ConfigParser in src/bin/dhcp4
-class DhcpConfigParser {
-
- /// @name Constructors and Destructor
- ///
- /// Note: The copy constructor and the assignment operator are
- /// intentionally defined as private to make it explicit that this is a
- /// pure base class.
- //@{
-private:
- DhcpConfigParser(const DhcpConfigParser& source);
- DhcpConfigParser& operator=(const DhcpConfigParser& source);
-
-protected:
- /// @brief The default constructor.
- ///
- /// This is intentionally defined as @c protected as this base class should
- /// never be instantiated (except as part of a derived class).
- DhcpConfigParser() {}
-public:
- /// The destructor.
- virtual ~DhcpConfigParser() {}
- //@}
-
- /// \brief Prepare configuration value.
- ///
- /// This method parses the "value part" of the configuration identifier
- /// that corresponds to this derived class and prepares a new value to
- /// apply to the server.
- ///
- /// This method must validate the given value both in terms of syntax
- /// and semantics of the configuration, so that the server will be
- /// validly configured at the time of @c commit(). Note: the given
- /// configuration value is normally syntactically validated, but the
- /// @c build() implementation must also expect invalid input. If it
- /// detects an error it may throw an exception of a derived class
- /// of @c isc::Exception.
- ///
- /// Preparing a configuration value will often require resource
- /// allocation. If it fails, it may throw a corresponding standard
- /// exception.
- ///
- /// This method is not expected to be called more than once in the
- /// life of the object. Although multiple calls are not prohibited
- /// by the interface, the behavior is undefined.
- ///
- /// @param config_value The configuration value for the identifier
- /// corresponding to the derived class.
- virtual void build(isc::data::ConstElementPtr config_value) = 0;
-
- /// @brief Apply the prepared configuration value to the server.
- ///
- /// This method is expected to be exception free, and, as a consequence,
- /// it should normally not involve resource allocation.
- /// Typically it would simply perform exception free assignment or swap
- /// operation on the value prepared in @c build().
- /// In some cases, however, it may be very difficult to meet this
- /// condition in a realistic way, while the failure case should really
- /// be very rare. In such a case it may throw, and, if the parser is
- /// called via @c configureDhcp6Server(), the caller will convert the
- /// exception as a fatal error.
- ///
- /// This method is expected to be called after @c build(), and only once.
- /// The result is undefined otherwise.
- virtual void commit() = 0;
-};
-
/// @brief Configures DHCPv6 server
///
/// This function is called every time a new configuration is received. The extra
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index 9774270..8beb548 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -56,7 +56,8 @@ public:
/// @brief Create the simple configuration with single option.
///
/// This function allows to set one of the parameters that configure
- /// option value. These parameters are: "name", "code" and "data".
+ /// option value. These parameters are: "name", "code", "data" and
+ /// "csv-format".
///
/// @param param_value string holiding option parameter value to be
/// injected into the configuration string.
@@ -720,7 +721,6 @@ TEST_F(Dhcp6ParserTest, optionDataLowerCase) {
EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
- std::cout << comment_->str() << std::endl;
ASSERT_EQ(0, rcode_);
Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"));
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
index b44fa7d..f819839 100644
--- a/src/lib/dhcpsrv/Makefile.am
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -21,6 +21,7 @@ libb10_dhcpsrv_la_SOURCES =
libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
libb10_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
libb10_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
+libb10_dhcpsrv_la_SOURCES += dhcp_config_parser.h
libb10_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h
libb10_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
diff --git a/src/lib/dhcpsrv/dhcp_config_parser.h b/src/lib/dhcpsrv/dhcp_config_parser.h
new file mode 100644
index 0000000..7077552
--- /dev/null
+++ b/src/lib/dhcpsrv/dhcp_config_parser.h
@@ -0,0 +1,114 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef DHCP_CONFIG_PARSER_H
+#define DHCP_CONFIG_PARSER_H
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Forward declaration to DhcpConfigParser class.
+///
+/// It is only needed here to define types that are
+/// based on this class before the class definition.
+class DhcpConfigParser;
+
+/// @brief a pointer to configuration parser
+typedef boost::shared_ptr<DhcpConfigParser> ParserPtr;
+
+/// @brief Collection of parsers.
+///
+/// This container is used to store pointer to parsers for a given scope.
+typedef std::vector<ParserPtr> ParserCollection;
+
+/// @brief Base abstract class for all DHCP parsers
+///
+/// Each instance of a class derived from this class parses one specific config
+/// element. Sometimes elements are simple (e.g. a string) and sometimes quite
+/// complex (e.g. a subnet). In such case, it is likely that a parser will
+/// spawn child parsers to parse child elements in the configuration.
+class DhcpConfigParser {
+ ///
+ /// @name Constructors and Destructor
+ ///
+ /// Note: The copy constructor and the assignment operator are
+ /// intentionally defined as private to make it explicit that this is a
+ /// pure base class.
+ //@{
+private:
+
+ // Private construtor and assignment operator assures that nobody
+ // will be able to copy or assign a parser. There are no defined
+ // bodies for them.
+ DhcpConfigParser(const DhcpConfigParser& source);
+ DhcpConfigParser& operator=(const DhcpConfigParser& source);
+protected:
+ /// @brief The default constructor.
+ ///
+ /// This is intentionally defined as @c protected as this base class should
+ /// never be instantiated (except as part of a derived class).
+ DhcpConfigParser() {}
+public:
+ /// The destructor.
+ virtual ~DhcpConfigParser() {}
+ //@}
+
+ /// @brief Prepare configuration value.
+ ///
+ /// This method parses the "value part" of the configuration identifier
+ /// that corresponds to this derived class and prepares a new value to
+ /// apply to the server.
+ ///
+ /// This method must validate the given value both in terms of syntax
+ /// and semantics of the configuration, so that the server will be
+ /// validly configured at the time of @c commit(). Note: the given
+ /// configuration value is normally syntactically validated, but the
+ /// @c build() implementation must also expect invalid input. If it
+ /// detects an error it may throw an exception of a derived class
+ /// of @c isc::Exception.
+ ///
+ /// Preparing a configuration value will often require resource
+ /// allocation. If it fails, it may throw a corresponding standard
+ /// exception.
+ ///
+ /// This method is not expected to be called more than once in the
+ /// life of the object. Although multiple calls are not prohibited
+ /// by the interface, the behavior is undefined.
+ ///
+ /// @param config_value The configuration value for the identifier
+ /// corresponding to the derived class.
+ virtual void build(isc::data::ConstElementPtr config_value) = 0;
+
+ /// @brief Apply the prepared configuration value to the server.
+ ///
+ /// This method is expected to be exception free, and, as a consequence,
+ /// it should normally not involve resource allocation.
+ /// Typically it would simply perform exception free assignment or swap
+ /// operation on the value prepared in @c build().
+ /// In some cases, however, it may be very difficult to meet this
+ /// condition in a realistic way, while the failure case should really
+ /// be very rare. In such a case it may throw, and, if the parser is
+ /// called via @c configureDhcp4Server(), the caller will convert the
+ /// exception as a fatal error.
+ ///
+ /// This method is expected to be called after @c build(), and only once.
+ /// The result is undefined otherwise.
+ virtual void commit() = 0;
+};
+
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif // DHCP_CONFIG_PARSER_H
More information about the bind10-changes
mailing list