17 #include <boost/foreach.hpp>
29 OptionDataParser::OptionDataParser(
const uint16_t address_family,
31 : address_family_(address_family), cfg_option_def_(cfg_option_def) {
34 std::pair<OptionDescriptor, std::string>
38 std::pair<OptionDescriptor, std::string> opt = createOption(single_option);
40 if (!opt.first.option_) {
43 "parser logic error: no option has been configured and"
44 " thus there is nothing to commit. Has build() been called?");
56 }
catch (
const std::exception&) {
63 isc_throw(DhcpConfigError,
"option code must not be zero "
66 }
else if (address_family_ == AF_INET &&
67 code > std::numeric_limits<uint8_t>::max()) {
68 isc_throw(DhcpConfigError,
"invalid option code '" << code
69 <<
"', it must not be greater than '"
70 <<
static_cast<int>(std::numeric_limits<uint8_t>::max())
74 }
else if (address_family_ == AF_INET6 &&
75 code > std::numeric_limits<uint16_t>::max()) {
76 isc_throw(DhcpConfigError,
"invalid option code '" << code
77 <<
"', it must not exceed '"
78 << std::numeric_limits<uint16_t>::max()
97 if (name.find(
" ") != std::string::npos) {
98 isc_throw(DhcpConfigError,
"invalid option name '" << name
99 <<
"', space character is not allowed ("
122 bool csv_format =
true;
124 csv_format =
getBoolean(parent,
"csv-format");
135 std::string space = address_family_ == AF_INET ?
146 isc_throw(DhcpConfigError,
"invalid option space name '"
152 <<
"' option space name is reserved for DHCPv4 server");
155 (address_family_ == AF_INET)) {
157 <<
"' option space name is reserved for DHCPv6 server");
160 }
catch (std::exception& ex) {
162 isc_throw(DhcpConfigError, ex.what() <<
" ("
171 bool persist =
false;
182 template<
typename SearchKey>
184 OptionDataParser::findOptionDefinition(
const std::string& option_space,
185 const SearchKey& search_key)
const {
187 if (cfg_option_def_) {
189 def = cfg_option_def_->get(option_space, search_key);
229 std::pair<OptionDescriptor, std::string>
238 std::string data_param = extractData(option_data);
239 std::string space_param = extractSpace(option_data);
244 isc_throw(DhcpConfigError,
"option data configuration requires one of"
245 " 'code' or 'name' parameters to be specified"
246 <<
" (" << option_data->getPosition() <<
")");
252 findOptionDefinition(space_param, code_param) :
253 findOptionDefinition(space_param, name_param);
260 if (csv_format_param.
isSpecified() && csv_format_param) {
261 isc_throw(DhcpConfigError,
"definition for the option '"
262 << space_param <<
"." << name_param
263 <<
"' having code '" << code_param
264 <<
"' does not exist ("
271 isc_throw(DhcpConfigError,
"definition for the option '"
272 << space_param <<
"." << name_param
273 <<
"' does not exist ("
280 std::vector<uint8_t> binary;
281 std::vector<std::string> data_tokens;
285 if (def && (!csv_format_param.
isSpecified() || csv_format_param)) {
302 if (!data_param.empty() && ((data_param.length() % 2) != 0)) {
303 data_param = data_param.insert(0,
"0");
307 isc_throw(DhcpConfigError,
"option data is not a valid"
308 <<
" string of hexadecimal digits: " << data_param
316 OptionDescriptor desc(
false);
324 OptionPtr option(
new Option(universe,
static_cast<uint16_t
>(code_param),
327 desc.option_ = option;
328 desc.persistent_ = persist_param.
isSpecified() && persist_param;
332 if (name_param.
isSpecified() && (def->getName() != name_param.
get())) {
333 isc_throw(DhcpConfigError,
"specified option name '"
334 << name_param <<
"' does not match the "
335 <<
"option definition: '" << space_param
336 <<
"." << def->getName() <<
"' ("
344 bool use_csv = !csv_format_param.
isSpecified() || csv_format_param;
346 def->optionFactory(universe, def->getCode(), data_tokens) :
347 def->optionFactory(universe, def->getCode(), binary);
348 desc.option_ = option;
349 desc.persistent_ = persist_param.
isSpecified() && persist_param;
351 desc.formatted_value_ = data_param;
354 isc_throw(DhcpConfigError,
"option data does not match"
355 <<
" option definition (space: " << space_param
356 <<
", code: " << def->getCode() <<
"): "
365 desc.setContext(user_context);
369 return make_pair(desc, space_param);
375 const uint16_t address_family,
377 : address_family_(address_family), cfg_option_def_(cfg_option_def) {
385 std::pair<OptionDescriptor, std::string> option =
386 option_parser.
parse(data);
388 cfg->add(option.first, option.second);