109 : code_(code), def_(def), action_(
NONE), class_(
""),
110 source_is_query_(true), dest_is_response_(true) {
119 :
OptionConfig(code, def), container_(container), vendor_id_(0),
120 container_action_(
NONE) {
133 sub_option_config_map_.clear();
134 option_config_map_.clear();
135 need_copy_classes_to_response_ =
false;
146 if (options->empty()) {
149 for (
auto const& option : options->listValue()) {
150 parseOptionConfig(option);
164 for (
auto const& entry : option->mapValue()) {
165 if (OPTION_PARAMETERS.count(entry.first) == 0) {
169 if (entry.second->getType() == expected) {
172 isc_throw(BadValue,
"'" << entry.first <<
"' must be "
175 <<
": " << entry.second->str());
185 if (!code_elem && !name_elem) {
186 isc_throw(BadValue,
"'code' or 'name' must be specified: "
191 if (family == AF_INET) {
199 space = space_elem->stringValue();
201 isc_throw(BadValue,
"'" << space <<
"' is not a valid space name");
207 int64_t value = code_elem->intValue();
209 if (family == AF_INET) {
210 max_code = numeric_limits<uint8_t>::max();
212 max_code = numeric_limits<uint16_t>::max();
214 if ((value < 0) || (value > max_code)) {
215 isc_throw(OutOfRange,
"invalid 'code' value " << value
216 <<
" not in [0.." << max_code <<
"]");
221 "invalid 'code' value 0: reserved for PAD");
224 "invalid 'code' value 255: reserved for END");
228 isc_throw(BadValue,
"invalid 'code' value 0: reserved");
231 code =
static_cast<uint16_t
>(value);
235 string name = name_elem->stringValue();
237 isc_throw(BadValue,
"'name' must not be empty");
247 isc_throw(BadValue,
"no known '" << name <<
"' option in '"
248 << space <<
"' space");
250 if (code_elem && (def->getCode() != code)) {
251 isc_throw(BadValue,
"option '" << name <<
"' is defined as code: "
252 << def->getCode() <<
", not the specified code: "
255 code = def->getCode();
258 bool csv_format =
false;
259 if (csv_format_elem) {
260 csv_format = csv_format_elem->boolValue();
263 if (!csv_format && !sub_options) {
277 if (!def && csv_format) {
278 isc_throw(BadValue,
"no known option with code '" << code
279 <<
"' in '" << space <<
"' space");
285 opt_cfg->setClass(class_elem->stringValue());
290 string source = source_elem->stringValue();
291 if (source ==
"query") {
292 opt_cfg->setSource(
true);
293 }
else if (source ==
"response") {
294 opt_cfg->setSource(
false);
296 isc_throw(BadValue,
"unknown source '" << source
297 <<
"', valid values are 'query' and 'response'");
303 string dest = dest_elem->stringValue();
304 if (dest ==
"query") {
305 opt_cfg->setDestination(
false);
306 }
else if (dest ==
"response") {
307 opt_cfg->setDestination(
true);
309 isc_throw(BadValue,
"unknown destination '" << dest
310 <<
"', valid values are 'response' and 'query'");
316 if (!opt_cfg->getDestination() && !opt_cfg->getSource()) {
317 isc_throw(BadValue,
"destination 'query' requires source 'query'");
322 if (!opt_cfg->getDestination() && !opt_cfg->getClass().empty()) {
325 .arg(opt_cfg->getClass());
331 if (option->contains(
"add")) {
333 }
else if (option->contains(
"supersede")) {
334 action =
"supersede";
335 }
else if (option->contains(
"remove")) {
338 if (!action.empty()) {
339 isc_throw(BadValue,
"'sub-options' and '" << action <<
"' are "
340 <<
"incompatible in the same entry");
342 parseSubOptions(sub_options, opt_cfg, universe);
344 parseAction(option, opt_cfg, universe,
346 parseAction(option, opt_cfg, universe,
348 parseAction(option, opt_cfg, universe,
351 if (opt_cfg->getAction() ==
NONE) {
352 isc_throw(BadValue,
"no action: " << option->str());
358 opt_lst.push_back(opt_cfg);
363 if (!opt_cfg->getDestination() && opt_cfg->getExpr()) {
364 for (
auto const& tok : *opt_cfg->getExpr()) {
365 if (boost::dynamic_pointer_cast<TokenMember>(tok)) {
368 .arg(opt_cfg->getText());
375 if (need_copy_classes_to_response_ ||
376 opt_cfg->getSource() ||
377 !opt_cfg->getExpr()) {
380 for (
auto const& tok : *opt_cfg->getExpr()) {
381 if (boost::dynamic_pointer_cast<TokenMember>(tok)) {
382 need_copy_classes_to_response_ =
true;
390 OptionConfigPtr opt_cfg,
392 for (
auto const& sub_option : sub_options->listValue()) {
393 parseSubOption(sub_option, opt_cfg, universe);
399 OptionConfigPtr opt_cfg,
402 isc_throw(BadValue,
"null sub-option element");
405 isc_throw(BadValue,
"sub-option element is not a map");
408 for (
auto const& entry : sub_option->mapValue()) {
409 if (SUB_OPTION_PARAMETERS.count(entry.first) == 0) {
410 isc_throw(BadValue,
"unknown parameter '" << entry.first <<
"'");
413 if (entry.second->getType() == expected) {
416 isc_throw(BadValue,
"'" << entry.first <<
"' must be "
419 <<
": " << entry.second->str());
426 if (!code_elem && !name_elem) {
427 isc_throw(BadValue,
"'code' or 'name' must be specified: "
428 << sub_option->str());
432 space = space_elem->stringValue();
434 isc_throw(BadValue,
"'" << space <<
"' is not a valid space name");
439 isc_throw(BadValue,
"container is not defined: can't get space");
441 space = opt_def->getEncapsulatedSpace();
443 isc_throw(BadValue,
"container does not encapsulate a space");
449 int64_t value = code_elem->intValue();
452 max_code = numeric_limits<uint8_t>::max();
454 max_code = numeric_limits<uint16_t>::max();
456 if ((value < 0) || (value > max_code)) {
457 isc_throw(OutOfRange,
"invalid 'code' value " << value
458 <<
" not in [0.." << max_code <<
"]");
460 code =
static_cast<uint16_t
>(value);
464 string name = name_elem->stringValue();
466 isc_throw(BadValue,
"'name' must not be empty");
469 if (!def && vendor_id) {
476 isc_throw(BadValue,
"no known '" << name <<
"' sub-option in '"
477 << space <<
"' space");
479 if (code_elem && (def->getCode() != code)) {
480 isc_throw(BadValue,
"sub-option '" << name
481 <<
"' is defined as code: " << def->getCode()
482 <<
", not the specified code: " << code);
484 code = def->getCode();
487 bool csv_format =
false;
488 if (csv_format_elem) {
489 csv_format = csv_format_elem->boolValue();
500 if (!def && vendor_id) {
507 isc_throw(BadValue,
"no known sub-option with code '" << code
508 <<
"' in '" << space <<
"' space");
518 sub_cfg->setVendorId(vendor_id);
522 sub_cfg->setClass(class_elem->stringValue());
526 sub_cfg->setSource(opt_cfg->getSource());
527 sub_cfg->setDestination(opt_cfg->getDestination());
531 if (!opt_cfg->getDestination() && !sub_cfg->getClass().empty()) {
534 .arg(opt_cfg->getCode())
535 .arg(sub_cfg->getClass());
539 parseAction(sub_option, sub_cfg, universe,
541 parseAction(sub_option, sub_cfg, universe,
543 parseAction(sub_option, sub_cfg, universe,
546 if (sub_cfg->getAction() ==
NONE) {
547 isc_throw(BadValue,
"no action: " << sub_option->str());
552 if (!opt_cfg->getDestination() && sub_cfg->getExpr()) {
553 for (
auto const& tok : *sub_cfg->getExpr()) {
554 if (boost::dynamic_pointer_cast<TokenMember>(tok)) {
558 .arg(opt_cfg->getCode())
559 .arg(sub_cfg->getText());
566 ConstElementPtr container_remove = sub_option->get(
"container-remove");
567 if ((sub_cfg->getAction() ==
ADD) || (sub_cfg->getAction() ==
SUPERSEDE)) {
568 sub_cfg->setContainerAction(
ADD);
569 if (container_add && !container_add->boolValue()) {
570 sub_cfg->setContainerAction(
NONE);
572 }
else if (sub_cfg->getAction() ==
REMOVE) {
573 sub_cfg->setContainerAction(
REMOVE);
574 if (container_remove && !container_remove->boolValue()) {
575 sub_cfg->setContainerAction(
NONE);
581 uint16_t opt_code = opt_cfg->getCode();
583 if (sub_map.count(code)) {
584 isc_throw(BadValue,
"sub-option " << code <<
" of option " << opt_code
585 <<
" was already specified");
587 sub_map[code] = sub_cfg;
590 if (need_copy_classes_to_response_ ||
591 opt_cfg->getSource() ||
592 !sub_cfg->getExpr()) {
595 for (
auto const& tok : *sub_cfg->getExpr()) {
596 if (boost::dynamic_pointer_cast<TokenMember>(tok)) {
597 need_copy_classes_to_response_ =
true;
614 const string& value) {
615 if (action ==
NONE) {
626 repr <<
"'" << value <<
"'";
629 for (
const char& ch : value) {
648 uint32_t vendor_id) {
664 uint16_t container_code) {
675 uint16_t container_code,
676 const string& value) {
677 if (action ==
NONE) {
684 .arg(container_code);
689 repr <<
"'" << value <<
"'";
692 for (
const char& ch : value) {
713 OptionVendorPtr vendor = boost::dynamic_pointer_cast<OptionVendor>(opt);
714 bool ret = (!vendor || (vendor->getVendorId() == vendor_id));
719 .arg(vendor->getVendorId())
Evaluation context, an interface to the expression evaluation.