51 string expr_text = elem->stringValue();
52 if (expr_text.empty()) {
58 opt_cfg->setAction(action);
59 opt_cfg->setText(expr_text);
62 eval_ctx.parseString(expr_text, parser_type);
64 opt_cfg->setExpr(expr);
65 }
catch (
const std::exception& ex) {
67 << expr_text <<
"] error: " << ex.
what());
75 namespace flex_option {
104 FlexOptionImpl::OptionConfig::OptionConfig(uint16_t code,
106 :
code_(code), def_(def), action_(
NONE), class_(
"") {
115 :
OptionConfig(code, def), container_(container), vendor_id_(0),
116 container_action_(
NONE) {
129 sub_option_config_map_.clear();
130 option_config_map_.clear();
138 if (options->getType() != Element::list) {
141 if (options->empty()) {
144 for (
auto option : options->listValue()) {
145 parseOptionConfig(option);
151 uint16_t family = CfgMgr::instance().getFamily();
155 if (option->getType() != Element::map) {
159 for (
auto entry : option->mapValue()) {
160 if (OPTION_PARAMETERS.count(entry.first) == 0) {
164 if (entry.second->getType() == expected) {
168 << (expected == Element::integer ?
"an " :
"a ")
169 << Element::typeToName(expected)
170 <<
": " << entry.second->str());
178 if (!code_elem && !name_elem) {
184 if (family == AF_INET) {
186 universe = Option::V4;
189 universe = Option::V6;
192 space = space_elem->stringValue();
193 if (!OptionSpace::validateName(space)) {
199 int64_t value = code_elem->intValue();
201 if (family == AF_INET) {
202 max_code = numeric_limits<uint8_t>::max();
204 max_code = numeric_limits<uint16_t>::max();
206 if ((value < 0) || (value > max_code)) {
208 <<
" not in [0.." << max_code <<
"]");
213 "invalid 'code' value 0: reserved for PAD");
216 "invalid 'code' value 255: reserved for END");
223 code =
static_cast<uint16_t
>(value);
227 string name = name_elem->stringValue();
231 def = LibDHCP::getOptionDef(space, name);
233 def = LibDHCP::getRuntimeOptionDef(space, name);
236 def = LibDHCP::getLastResortOptionDef(space, name);
240 << space <<
"' space");
242 if (code_elem && (def->getCode() != code)) {
244 << def->getCode() <<
", not the specified code: " 247 code = def->getCode();
250 bool csv_format =
false;
251 if (csv_format_elem) {
252 csv_format = csv_format_elem->boolValue();
255 if (!csv_format && !sub_options) {
269 if (!def && csv_format) {
271 <<
"' in '" << space <<
"' space");
277 opt_cfg->setClass(class_elem->stringValue());
283 if (option->contains(
"add")) {
285 }
else if (option->contains(
"supersede")) {
286 action =
"supersede";
287 }
else if (option->contains(
"remove")) {
290 if (!action.empty()) {
292 <<
"incompatible in the same entry");
294 parseSubOptions(sub_options, opt_cfg, universe);
296 parseAction(option, opt_cfg, universe,
297 "add",
ADD, EvalContext::PARSER_STRING);
298 parseAction(option, opt_cfg, universe,
299 "supersede",
SUPERSEDE, EvalContext::PARSER_STRING);
300 parseAction(option, opt_cfg, universe,
301 "remove",
REMOVE, EvalContext::PARSER_BOOL);
303 if (opt_cfg->getAction() ==
NONE) {
310 opt_lst.push_back(opt_cfg);
319 parseSubOption(sub_option, opt_cfg, universe);
330 if (sub_option->getType() != Element::map) {
334 for (
auto entry : sub_option->mapValue()) {
335 if (SUB_OPTION_PARAMETERS.count(entry.first) == 0) {
339 if (entry.second->getType() == expected) {
343 << (expected == Element::integer ?
"an " :
"a ")
344 << Element::typeToName(expected)
345 <<
": " << entry.second->str());
352 if (!code_elem && !name_elem) {
354 << sub_option->str());
358 space = space_elem->stringValue();
359 if (!OptionSpace::validateName(space)) {
367 space = opt_def->getEncapsulatedSpace();
372 uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(space);
375 int64_t value = code_elem->intValue();
377 if (universe == Option::V4) {
378 max_code = numeric_limits<uint8_t>::max();
380 max_code = numeric_limits<uint16_t>::max();
382 if ((value < 0) || (value > max_code)) {
384 <<
" not in [0.." << max_code <<
"]");
386 code =
static_cast<uint16_t
>(value);
390 string name = name_elem->stringValue();
394 def = LibDHCP::getOptionDef(space, name);
395 if (!def && vendor_id) {
396 def = LibDHCP::getVendorOptionDef(universe, vendor_id, name);
399 def = LibDHCP::getRuntimeOptionDef(space, name);
403 << space <<
"' space");
405 if (code_elem && (def->getCode() != code)) {
407 <<
"' is defined as code: " << def->getCode()
408 <<
", not the specified code: " << code);
410 code = def->getCode();
413 bool csv_format =
false;
414 if (csv_format_elem) {
415 csv_format = csv_format_elem->boolValue();
426 if (!def && vendor_id) {
427 def = LibDHCP::getVendorOptionDef(universe, vendor_id, code);
434 <<
"' in '" << space <<
"' space");
440 if (((universe == Option::V4) &&
442 ((universe == Option::V6) &&
444 sub_cfg->setVendorId(vendor_id);
448 sub_cfg->setClass(class_elem->stringValue());
452 parseAction(sub_option, sub_cfg, universe,
453 "add",
ADD, EvalContext::PARSER_STRING);
454 parseAction(sub_option, sub_cfg, universe,
455 "supersede",
SUPERSEDE, EvalContext::PARSER_STRING);
456 parseAction(sub_option, sub_cfg, universe,
457 "remove",
REMOVE, EvalContext::PARSER_BOOL);
459 if (sub_cfg->getAction() ==
NONE) {
464 ConstElementPtr container_remove = sub_option->get(
"container-remove");
465 if ((sub_cfg->getAction() ==
ADD) || (sub_cfg->getAction() ==
SUPERSEDE)) {
466 sub_cfg->setContainerAction(
ADD);
467 if (container_add && !container_add->boolValue()) {
468 sub_cfg->setContainerAction(
NONE);
470 }
else if (sub_cfg->getAction() ==
REMOVE) {
471 sub_cfg->setContainerAction(
REMOVE);
472 if (container_remove && !container_remove->boolValue()) {
473 sub_cfg->setContainerAction(
NONE);
479 uint16_t opt_code = opt_cfg->getCode();
481 if (sub_map.count(code)) {
483 <<
" was already specified");
485 sub_map[code] = sub_cfg;
499 const string& value) {
500 if (action ==
NONE) {
511 repr <<
"'" << value <<
"'";
514 for (
const char& ch : value) {
515 repr << setw(2) << setfill('0') << static_cast<unsigned>(ch);
533 uint32_t vendor_id) {
549 uint16_t container_code) {
554 .arg(container_code);
560 uint16_t container_code,
561 const string& value) {
562 if (action ==
NONE) {
569 .arg(container_code);
574 repr <<
"'" << value <<
"'";
577 for (
const char& ch : value) {
578 repr << setw(2) << setfill('0') << static_cast<unsigned>(ch);
599 bool ret = (!vendor || (vendor->getVendorId() == vendor_id));
604 .arg(vendor->getVendorId())
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
const isc::log::MessageID FLEX_OPTION_PROCESS_SUPERSEDE
const isc::log::MessageID FLEX_OPTION_PROCESS_VENDOR_ID_MISMATCH
const int DBGLVL_TRACE_BASIC
Trace basic operations.
isc::log::Logger flex_option_logger("flex-option-hooks")
std::map< std::string, isc::data::Element::types > SimpleKeywords
This specifies all accepted keywords with their types.
static bool checkVendor(isc::dhcp::OptionPtr opt, uint32_t vendor_id)
Check vendor option vendor id mismatch.
const isc::log::MessageID FLEX_OPTION_PROCESS_ADD
OptionConfig(uint16_t code, isc::dhcp::OptionDefinitionPtr def)
Constructor.
boost::shared_ptr< Option > OptionPtr
~FlexOptionImpl()
Destructor.
Universe
defines option universe DHCPv4 or DHCPv6
boost::shared_ptr< OptionConfig > OptionConfigPtr
The type of shared pointers to option config.
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_SUPERSEDE
std::map< uint16_t, SubOptionConfigPtr > SubOptionConfigMap
The type of the sub-option config map.
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.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
void configure(isc::data::ConstElementPtr options)
Configure the Flex Option implementation.
FlexOptionImpl()
Constructor.
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_ADD
A generic exception that is thrown when an unexpected error condition occurs.
SubOptionConfig(uint16_t code, isc::dhcp::OptionDefinitionPtr def, OptionConfigPtr container)
Constructor.
Evaluation context, an interface to the expression evaluation.
boost::shared_ptr< const Element > ConstElementPtr
const isc::log::MessageID FLEX_OPTION_PROCESS_REMOVE
const isc::log::MessageID FLEX_OPTION_PROCESS_CLIENT_CLASS
static void logAction(Action action, uint16_t code, const std::string &value)
Log the action for option.
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Defines the logger used by the top-level component of kea-lfc.
std::vector< TokenPtr > Expression
This is a structure that holds an expression converted to RPN.
std::list< OptionConfigPtr > OptionConfigList
The type of lists of shared pointers to option config.
static void logSubClass(const isc::dhcp::ClientClass &client_class, uint16_t code, uint16_t container_code)
Log the client class for sub-option.
#define DHCP6_OPTION_SPACE
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_CLIENT_CLASS
#define DHCP4_OPTION_SPACE
global std option spaces
boost::shared_ptr< SubOptionConfig > SubOptionConfigPtr
The type of shared pointers to sub-option config.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
ParserType
Specifies what type of expression the parser is expected to see.
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
static void logSubAction(Action action, uint16_t code, uint16_t container_code, const std::string &value)
Log the action for sub-option.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
virtual ~OptionConfig()
Destructor.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
virtual ~SubOptionConfig()
Destructor.
static void logClass(const isc::dhcp::ClientClass &client_class, uint16_t code)
Log the client class for option.
std::string ClientClass
Defines a single class name.
Base option configuration.
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
bool isPrintable(const std::string &content)
Check if a string is printable.
boost::shared_ptr< Expression > ExpressionPtr
This class represents vendor-specific information option.
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_REMOVE