From: Marcin Siodelski Date: Fri, 21 Dec 2012 12:11:53 +0000 (+0100) Subject: [2545] Added new configuration parameter: csv-format for DHCPv4 server. X-Git-Tag: bind10-1.0.0-rc-release~99^2~21^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=caf95c197aa4abb916d8e27d3a5004ebed2e6108;p=thirdparty%2Fkea.git [2545] Added new configuration parameter: csv-format for DHCPv4 server. --- diff --git a/src/bin/dhcp4/config_parser.cc b/src/bin/dhcp4/config_parser.cc index 589bb3720e..1f03c9fa76 100644 --- a/src/bin/dhcp4/config_parser.cc +++ b/src/bin/dhcp4/config_parser.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -703,6 +704,13 @@ public: value_parser->setStorage(&string_values_); parser = value_parser; } + } else if (param.first == "csv-format") { + boost::shared_ptr + value_parser(dynamic_cast(BooleanParser::Factory(param.first))); + if (value_parser) { + value_parser->setStorage(&boolean_values_); + parser = value_parser; + } } else { isc_throw(Dhcp4ConfigError, "Parser error: option-data parameter not supported: " @@ -806,16 +814,27 @@ private: } // Get option data from the configuration database ('data' field). - // Option data is specified by the user as case insensitive string - // of hexadecimal digits for each option. - std::string option_data = getStringParam("data"); + const std::string option_data = getStringParam("data"); + const bool csv_format = getBooleanParam("csv-format"); // Transform string of hexadecimal digits into binary format. std::vector binary; - try { - util::encode::decodeHex(option_data, binary); - } catch (...) { - isc_throw(Dhcp4ConfigError, "Parser error: option data is not a valid" - << " string of hexadecimal digits: " << option_data); + std::vector data_tokens; + + if (csv_format) { + // If the option data is specified as a string of comma + // separated values then we need to split this string into + // individual values - each value will be used to initialize + // one data field of an option. + data_tokens = isc::util::str::tokens(option_data, ","); + } else { + // Otherwise, the option data is specified as a string of + // hexadecimal digits that we have to turn into binary format. + try { + util::encode::decodeHex(option_data, binary); + } catch (...) { + isc_throw(Dhcp4ConfigError, "Parser error: option data is not a valid" + << " string of hexadecimal digits: " << option_data); + } } // Get all existing DHCPv4 option definitions. The one that matches // our option will be picked and used to create it. @@ -835,6 +854,13 @@ private: << " for the same option code. This will be supported once" << " there option spaces are implemented."); } else if (num_defs == 0) { + if (csv_format) { + isc_throw(Dhcp4ConfigError, "the CSV option data format can be" + " used to specify values for an option that has a" + " definition. The option with code " << option_code + << " does not have a definition."); + } + // @todo We have a limited set of option definitions intiialized at the moment. // In the future we want to initialize option definitions for all options. // Consequently an error will be issued if an option definition does not exist @@ -852,7 +878,9 @@ private: // use it to create the option instance. const OptionDefinitionPtr& def = *(range.first); try { - OptionPtr option = def->optionFactory(Option::V4, option_code, binary); + OptionPtr option = csv_format ? + def->optionFactory(Option::V4, option_code, data_tokens) : + def->optionFactory(Option::V4, option_code, binary); Subnet::OptionDescriptor desc(option, false); option_descriptor_.option = option; option_descriptor_.persistent = false; @@ -890,10 +918,27 @@ private: return (param->second); } + /// @brief Get a parameter from the boolean values storage. + /// + /// @param param_id parameter identifier. + /// + /// @throw isc::dhcp::Dhcp6ConfigError if a parameter has not been found. + /// @return a value of the boolean parameter. + bool getBooleanParam(const std::string& param_id) const { + BooleanStorage::const_iterator param = boolean_values_.find(param_id); + if (param == boolean_values_.end()) { + isc_throw(isc::dhcp::Dhcp4ConfigError, "parser error: option-data parameter" + << " '" << param_id << "' not specified"); + } + return (param->second); + } + /// Storage for uint32 values (e.g. option code). Uint32Storage uint32_values_; /// Storage for string values (e.g. option name or data). StringStorage string_values_; + /// Storage for boolean values. + BooleanStorage boolean_values_; /// Pointer to options storage. This storage is provided by /// the calling class and is shared by all OptionDataParser objects. OptionStorage* options_; diff --git a/src/bin/dhcp4/dhcp4.spec b/src/bin/dhcp4/dhcp4.spec index 46192de7f8..7b4fc63cb5 100644 --- a/src/bin/dhcp4/dhcp4.spec +++ b/src/bin/dhcp4/dhcp4.spec @@ -61,6 +61,11 @@ "item_type": "string", "item_optional": false, "item_default": "" + }, + { "item_name": "csv-format", + "item_type": "boolean", + "item_optional": false, + "item_default": False } ] } }, @@ -141,6 +146,11 @@ "item_type": "string", "item_optional": false, "item_default": "" + }, + { "item_name": "csv-format", + "item_type": "bool", + "item_optional": false, + "item_default": False } ] } } ] diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc index 425fe9fdc8..6de7e94332 100644 --- a/src/bin/dhcp4/tests/config_parser_unittest.cc +++ b/src/bin/dhcp4/tests/config_parser_unittest.cc @@ -92,14 +92,22 @@ public: params["name"] = param_value; params["code"] = "56"; params["data"] = "AB CDEF0105"; + params["csv-format"] = "False"; } else if (parameter == "code") { params["name"] = "option_foo"; params["code"] = param_value; params["data"] = "AB CDEF0105"; + params["csv-format"] = "False"; } else if (parameter == "data") { params["name"] = "option_foo"; params["code"] = "56"; params["data"] = param_value; + params["csv-format"] = "False"; + } else if (parameter == "csv-format") { + params["name"] = "option_foo"; + params["code"] = "56"; + params["data"] = "AB CDEF0105"; + params["csv-format"] = param_value; } return (createConfigWithOption(params)); } @@ -136,6 +144,8 @@ public: stream << "\"code\": " << param.second << ""; } else if (param.first == "data") { stream << "\"data\": \"" << param.second << "\""; + } else if (param.first == "csv-format") { + stream << "\"csv-format\": " << param.second; } } stream << @@ -435,12 +445,14 @@ TEST_F(Dhcp4ParserTest, optionDataDefaults) { "\"option-data\": [ {" " \"name\": \"option_foo\"," " \"code\": 56," - " \"data\": \"AB CDEF0105\"" + " \"data\": \"AB CDEF0105\"," + " \"csv-format\": False" " }," " {" " \"name\": \"option_foo2\"," " \"code\": 23," - " \"data\": \"01\"" + " \"data\": \"01\"," + " \"csv-format\": False" " } ]," "\"subnet4\": [ { " " \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ]," @@ -498,7 +510,8 @@ TEST_F(Dhcp4ParserTest, optionDataInSingleSubnet) { "\"option-data\": [ {" " \"name\": \"option_foo\"," " \"code\": 56," - " \"data\": \"AB\"" + " \"data\": \"AB\"," + " \"csv-format\": False" " } ]," "\"subnet4\": [ { " " \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ]," @@ -506,12 +519,14 @@ TEST_F(Dhcp4ParserTest, optionDataInSingleSubnet) { " \"option-data\": [ {" " \"name\": \"option_foo\"," " \"code\": 56," - " \"data\": \"AB CDEF0105\"" + " \"data\": \"AB CDEF0105\"," + " \"csv-format\": False" " }," " {" " \"name\": \"option_foo2\"," " \"code\": 23," - " \"data\": \"01\"" + " \"data\": \"01\"," + " \"csv-format\": False" " } ]" " } ]," "\"valid-lifetime\": 4000 }"; @@ -567,7 +582,8 @@ TEST_F(Dhcp4ParserTest, optionDataInMultipleSubnets) { " \"option-data\": [ {" " \"name\": \"option_foo\"," " \"code\": 56," - " \"data\": \"0102030405060708090A\"" + " \"data\": \"0102030405060708090A\"," + " \"csv-format\": False" " } ]" " }," " {" @@ -576,7 +592,8 @@ TEST_F(Dhcp4ParserTest, optionDataInMultipleSubnets) { " \"option-data\": [ {" " \"name\": \"option_foo2\"," " \"code\": 23," - " \"data\": \"FF\"" + " \"data\": \"FF\"," + " \"csv-format\": False" " } ]" " } ]," "\"valid-lifetime\": 4000 }"; diff --git a/src/bin/dhcp6/config_parser.cc b/src/bin/dhcp6/config_parser.cc index 07aa7ec4c6..8e9e065f0e 100644 --- a/src/bin/dhcp6/config_parser.cc +++ b/src/bin/dhcp6/config_parser.cc @@ -858,9 +858,14 @@ private: std::vector binary; std::vector data_tokens; if (csv_format) { + // If the option data is specified as a string of comma + // separated values then we need to split this string into + // individual values - each value will be used to initialize + // one data field of an option. data_tokens = isc::util::str::tokens(option_data, ","); } else { - // Transform string of hexadecimal digits into binary format. + // Otherwise, the option data is specified as a string of + // hexadecimal digits that we have to turn into binary format. try { isc::util::encode::decodeHex(option_data, binary); } catch (...) {