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);
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
void parse(const CfgOptionPtr &cfg, isc::data::ConstElementPtr option_data_list)
Parses a list of options, instantiates them and stores in cfg.
Simple class representing an optional value.
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
std::pair< OptionDescriptor, std::string > parse(isc::data::ConstElementPtr single_option)
Parses ElementPtr containing option definition.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
#define DHCP6_OPTION_SPACE
boost::shared_ptr< Option > OptionPtr
Universe
defines option universe DHCPv4 or DHCPv6
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Indicate if an OptionalValue is is specified or not.
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
boost::shared_ptr< const Element > ConstElementPtr
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
T get() const
Retrieves the actual value.
vector< string > tokens(const std::string &text, const std::string &delim, bool escape)
Split String into Tokens.
#define DHCP4_OPTION_SPACE
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
static const data::Element::Position & getPosition(const std::string &name, const data::ConstElementPtr parent)
Utility method that returns position of an element.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
bool isSpecified() const
Checks if the value is specified or unspecified.
A generic exception that is thrown if a function is called in a prohibited way.
Parser for option data value.
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
OptionDataListParser(const uint16_t address_family, CfgOptionDefPtr cfg_option_def=CfgOptionDefPtr())
Constructor.
static uint32_t optionSpaceToVendorId(const std::string &option_space)
Converts option space name to vendor id.
static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, const uint16_t code)
Returns vendor option definition for a given vendor-id and code.