#include <dhcp/option_definition.h>
#include <dhcpsrv/cfgmgr.h>
#include <util/encode/hex.h>
+#include <util/strutil.h>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
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)));
+ if (value_parser) {
+ value_parser->setStorage(&boolean_values_);
+ parser = value_parser;
+ }
} else {
isc_throw(Dhcp4ConfigError,
"Parser error: option-data parameter not supported: "
}
// 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<uint8_t> 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<std::string> 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.
<< " 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
// 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;
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_;
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));
}
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 <<
"\"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\" ],"
"\"option-data\": [ {"
" \"name\": \"option_foo\","
" \"code\": 56,"
- " \"data\": \"AB\""
+ " \"data\": \"AB\","
+ " \"csv-format\": False"
" } ],"
"\"subnet4\": [ { "
" \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
" \"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 }";
" \"option-data\": [ {"
" \"name\": \"option_foo\","
" \"code\": 56,"
- " \"data\": \"0102030405060708090A\""
+ " \"data\": \"0102030405060708090A\","
+ " \"csv-format\": False"
" } ]"
" },"
" {"
" \"option-data\": [ {"
" \"name\": \"option_foo2\","
" \"code\": 23,"
- " \"data\": \"FF\""
+ " \"data\": \"FF\","
+ " \"csv-format\": False"
" } ]"
" } ],"
"\"valid-lifetime\": 4000 }";