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());
75namespace flex_option {
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();
141 if (options->empty()) {
144 for (
auto const& option : options->listValue()) {
145 parseOptionConfig(option);
159 for (
auto const& entry : option->mapValue()) {
160 if (OPTION_PARAMETERS.count(entry.first) == 0) {
164 if (entry.second->getType() == expected) {
169 <<
Element::typeToName(expected)
170 <<
": " << entry.second->str());
178 if (!code_elem && !name_elem) {
184 if (family == AF_INET) {
192 space = space_elem->stringValue();
200 int64_t value = code_elem->intValue();
202 if (family == AF_INET) {
203 max_code = numeric_limits<uint8_t>::max();
205 max_code = numeric_limits<uint16_t>::max();
207 if ((value < 0) || (value > max_code)) {
209 <<
" not in [0.." << max_code <<
"]");
214 "invalid 'code' value 0: reserved for PAD");
217 "invalid 'code' value 255: reserved for END");
224 code =
static_cast<uint16_t
>(value);
228 string name = name_elem->stringValue();
241 << space <<
"' space");
243 if (code_elem && (def->getCode() != code)) {
245 << def->getCode() <<
", not the specified code: "
248 code = def->getCode();
251 bool csv_format =
false;
252 if (csv_format_elem) {
253 csv_format = csv_format_elem->boolValue();
256 if (!csv_format && !sub_options) {
270 if (!def && csv_format) {
272 <<
"' in '" << space <<
"' space");
278 opt_cfg->setClass(class_elem->stringValue());
284 if (option->contains(
"add")) {
286 }
else if (option->contains(
"supersede")) {
287 action =
"supersede";
288 }
else if (option->contains(
"remove")) {
291 if (!action.empty()) {
293 <<
"incompatible in the same entry");
295 parseSubOptions(sub_options, opt_cfg, universe);
297 parseAction(option, opt_cfg, universe,
299 parseAction(option, opt_cfg, universe,
301 parseAction(option, opt_cfg, universe,
304 if (opt_cfg->getAction() ==
NONE) {
311 opt_lst.push_back(opt_cfg);
319 for (
auto const& sub_option : sub_options->listValue()) {
320 parseSubOption(sub_option, opt_cfg, universe);
335 for (
auto const& entry : sub_option->mapValue()) {
336 if (SUB_OPTION_PARAMETERS.count(entry.first) == 0) {
340 if (entry.second->getType() == expected) {
345 <<
Element::typeToName(expected)
346 <<
": " << entry.second->str());
353 if (!code_elem && !name_elem) {
355 << sub_option->str());
359 space = space_elem->stringValue();
368 space = opt_def->getEncapsulatedSpace();
376 int64_t value = code_elem->intValue();
379 max_code = numeric_limits<uint8_t>::max();
381 max_code = numeric_limits<uint16_t>::max();
383 if ((value < 0) || (value > max_code)) {
385 <<
" not in [0.." << max_code <<
"]");
387 code =
static_cast<uint16_t
>(value);
391 string name = name_elem->stringValue();
396 if (!def && vendor_id) {
404 << space <<
"' space");
406 if (code_elem && (def->getCode() != code)) {
408 <<
"' is defined as code: " << def->getCode()
409 <<
", not the specified code: " << code);
411 code = def->getCode();
414 bool csv_format =
false;
415 if (csv_format_elem) {
416 csv_format = csv_format_elem->boolValue();
427 if (!def && vendor_id) {
435 <<
"' in '" << space <<
"' space");
445 sub_cfg->setVendorId(vendor_id);
449 sub_cfg->setClass(class_elem->stringValue());
453 parseAction(sub_option, sub_cfg, universe,
455 parseAction(sub_option, sub_cfg, universe,
457 parseAction(sub_option, sub_cfg, universe,
460 if (sub_cfg->getAction() ==
NONE) {
465 ConstElementPtr container_remove = sub_option->get(
"container-remove");
466 if ((sub_cfg->getAction() ==
ADD) || (sub_cfg->getAction() ==
SUPERSEDE)) {
467 sub_cfg->setContainerAction(
ADD);
468 if (container_add && !container_add->boolValue()) {
469 sub_cfg->setContainerAction(
NONE);
471 }
else if (sub_cfg->getAction() ==
REMOVE) {
472 sub_cfg->setContainerAction(
REMOVE);
473 if (container_remove && !container_remove->boolValue()) {
474 sub_cfg->setContainerAction(
NONE);
480 uint16_t opt_code = opt_cfg->getCode();
482 if (sub_map.count(code)) {
484 <<
" was already specified");
486 sub_map[code] = sub_cfg;
500 const string& value) {
501 if (action ==
NONE) {
512 repr <<
"'" << value <<
"'";
515 for (
const char& ch : value) {
516 repr << setw(2) << setfill('0') << static_cast<unsigned>(ch);
534 uint32_t vendor_id) {
550 uint16_t container_code) {
555 .arg(container_code);
561 uint16_t container_code,
562 const string& value) {
563 if (action ==
NONE) {
570 .arg(container_code);
575 repr <<
"'" << value <<
"'";
578 for (
const char& ch : value) {
579 repr << setw(2) << setfill('0') << static_cast<unsigned>(ch);
599 OptionVendorPtr vendor = boost::dynamic_pointer_cast<OptionVendor>(opt);
600 bool ret = (!vendor || (vendor->getVendorId() == vendor_id));
605 .arg(vendor->getVendorId())
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
The Element class represents a piece of data, used by the command channel and configuration parts.
types
The types that an Element can hold.
static CfgMgr & instance()
returns a single instance of Configuration Manager
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
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.
static uint32_t optionSpaceToVendorId(const std::string &option_space)
Converts option space name to vendor id.
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Universe
defines option universe DHCPv4 or DHCPv6
Evaluation context, an interface to the expression evaluation.
ParserType
Specifies what type of expression the parser is expected to see.
@ PARSER_BOOL
expression is expected to evaluate to bool
@ PARSER_STRING
expression is expected to evaluate to string
Base option configuration.
virtual ~OptionConfig()
Destructor.
OptionConfig(uint16_t code, isc::dhcp::OptionDefinitionPtr def)
Constructor.
SubOptionConfig(uint16_t code, isc::dhcp::OptionDefinitionPtr def, OptionConfigPtr container)
Constructor.
virtual ~SubOptionConfig()
Destructor.
void configure(isc::data::ConstElementPtr options)
Configure the Flex Option implementation.
boost::shared_ptr< OptionConfig > OptionConfigPtr
The type of shared pointers to option config.
~FlexOptionImpl()
Destructor.
boost::shared_ptr< SubOptionConfig > SubOptionConfigPtr
The type of shared pointers to sub-option config.
static void logAction(Action action, uint16_t code, const std::string &value)
Log the action for option.
static void logSubClass(const isc::dhcp::ClientClass &client_class, uint16_t code, uint16_t container_code)
Log the client class for sub-option.
static void logSubAction(Action action, uint16_t code, uint16_t container_code, const std::string &value)
Log the action for sub-option.
FlexOptionImpl()
Constructor.
std::list< OptionConfigPtr > OptionConfigList
The type of lists of shared pointers to option config.
static bool checkVendor(isc::dhcp::OptionPtr opt, uint32_t vendor_id)
Check vendor option vendor id mismatch.
std::map< uint16_t, SubOptionConfigPtr > SubOptionConfigMap
The type of the sub-option config map.
static void logClass(const isc::dhcp::ClientClass &client_class, uint16_t code)
Log the client class for option.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
const isc::log::MessageID FLEX_OPTION_PROCESS_VENDOR_ID_MISMATCH
const isc::log::MessageID FLEX_OPTION_PROCESS_CLIENT_CLASS
const isc::log::MessageID FLEX_OPTION_PROCESS_ADD
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_SUPERSEDE
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_CLIENT_CLASS
const isc::log::MessageID FLEX_OPTION_PROCESS_REMOVE
const isc::log::MessageID FLEX_OPTION_PROCESS_SUPERSEDE
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_ADD
const isc::log::MessageID FLEX_OPTION_PROCESS_SUB_REMOVE
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< const Element > ConstElementPtr
std::map< std::string, isc::data::Element::types > SimpleKeywords
This specifies all accepted keywords with their types.
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
std::string ClientClass
Defines a single class name.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::shared_ptr< Expression > ExpressionPtr
std::vector< TokenPtr > Expression
This is a structure that holds an expression converted to RPN.
boost::shared_ptr< Option > OptionPtr
isc::log::Logger flex_option_logger("flex-option-hooks")
const int DBGLVL_TRACE_BASIC
Trace basic operations.
bool isPrintable(const string &content)
Check if a string is printable.
Defines the logger used by the top-level component of kea-lfc.
#define DHCP4_OPTION_SPACE
global std option spaces
#define DHCP6_OPTION_SPACE