Kea 3.3.1
cfg_option.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <dhcp/libdhcp++.h>
10#include <dhcpsrv/cfg_option.h>
11#include <dhcp/dhcp6.h>
12#include <dhcp/option_space.h>
13#include <dhcpsrv/dhcpsrv_log.h>
14#include <util/encode/encode.h>
15#include <boost/algorithm/string/split.hpp>
16#include <boost/algorithm/string/classification.hpp>
17#include <boost/make_shared.hpp>
18#include <string>
19#include <sstream>
20#include <vector>
21
22using namespace isc::data;
23using namespace isc::log;
24
25namespace isc {
26namespace dhcp {
27
29OptionDescriptor::create(const OptionPtr& opt, bool persist, bool cancel,
30 const std::string& formatted_value,
31 ConstElementPtr user_context) {
32 return (boost::make_shared<OptionDescriptor>(opt, persist, cancel,
33 formatted_value,
34 user_context));
35}
36
38OptionDescriptor::create(bool persist, bool cancel) {
39 return (boost::make_shared<OptionDescriptor>(persist, cancel));
40}
41
44 return (boost::make_shared<OptionDescriptor>(desc));
45}
46
47bool
49 return ((persistent_ == other.persistent_) &&
50 (cancelled_ == other.cancelled_) &&
52 (space_name_ == other.space_name_) &&
53 ((option_ && other.option_) &&
54 option_->equals(other.option_)) &&
56}
57
58void
59OptionDescriptor::addClientClass(const std::string& class_name) {
60 std::string trimmed = util::str::trim(class_name);
61 if (!trimmed.empty()) {
62 client_classes_.insert(ClientClass(trimmed));
63 }
64}
65
70
71bool
73 if (client_classes_.empty()) {
74 return (true);
75 }
76
77 return (client_classes_.intersects(cclasses));
78}
79
80std::set<std::string> CfgOption::multiple_encapsulating_spaces_ = {
82};
83
85 : encapsulated_(false) {
86}
87
88bool
90 return (options_.empty() && vendor_options_.empty());
91}
92
93bool
94CfgOption::equals(const CfgOption& other) const {
95 return (options_.equals(other.options_) &&
96 vendor_options_.equals(other.vendor_options_));
97}
98
99void
101 const bool persistent,
102 const bool cancelled,
103 const std::string& option_space,
104 const uint64_t id) {
105 OptionDescriptor desc(option, persistent, cancelled);
106 if (id > 0) {
107 desc.setId(id);
108 }
109 add(desc, option_space);
110}
111
112void
113CfgOption::add(const OptionDescriptor& desc, const std::string& option_space) {
114 if (!desc.option_) {
115 isc_throw(isc::BadValue, "option being configured must not be NULL");
116
117 } else if (!OptionSpace::validateName(option_space)) {
118 isc_throw(isc::BadValue, "invalid option space name: '"
119 << option_space << "'");
120 }
121
122 const uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(option_space);
123 if (vendor_id) {
124 vendor_options_.addItem(desc, vendor_id);
125 } else {
126 options_.addItem(desc, option_space);
127 }
128}
129
130void
131CfgOption::replace(const OptionDescriptor& desc, const std::string& option_space) {
132 if (!desc.option_) {
133 isc_throw(isc::BadValue, "option being replaced must not be NULL");
134 }
135
136 // Check for presence of options.
137 OptionContainerPtr options = getAll(option_space);
138 if (!options) {
139 isc_throw(isc::BadValue, "option space " << option_space
140 << " does not exist");
141 }
142
143 // Find the option we want to replace.
144 auto& idx6 = options->get<6>();
145 auto const& od_itr = idx6.find(boost::make_tuple(desc.option_->getType(), desc.client_classes_));
146 if (od_itr == idx6.end()) {
147 isc_throw(isc::BadValue, "cannot replace option: "
148 << option_space << ":" << desc.option_->getType()
149 << ", client-classes: " << desc.client_classes_.toText()
150 << ", it does not exist");
151 }
152
153 idx6.replace(od_itr, desc);
154}
155
156std::list<std::string>
158 std::list<uint32_t> ids = getVendorIds();
159 std::list<std::string> names;
160 for (auto const& id : ids) {
161 std::ostringstream s;
162 // Vendor space name is constructed as "vendor-XYZ" where XYZ is an
163 // uint32_t value, without leading zeros.
164 s << "vendor-" << id;
165 names.push_back(s.str());
166 }
167 return (names);
168}
169
170void
172 // First we merge our options into other.
173 // This adds my options that are not
174 // in other, to other (i.e we skip over
175 // duplicates).
176 mergeTo(other);
177
178 // Create option instances based on the given definitions.
179 other.createOptions(cfg_def);
180
181 // Next we copy "other" on top of ourself.
182 other.copyTo(*this);
183
184 // If we copied new options we may need to populate the
185 // sub-options into the upper level options. The server
186 // expects that the top-level options have suitable
187 // suboptions appended.
188 encapsulate();
189}
190
191void
193 // Iterate over all the option descriptors in
194 // all the spaces and instantiate the options
195 // based on the given definitions.
196 for (auto const& space : getOptionSpaceNames()) {
197 for (auto opt_desc : *(getAll(space))) {
198 try {
199 if (createDescriptorOption(cfg_def, space, opt_desc)) {
200 // Option was recreated, let's replace the descriptor.
201 replace(opt_desc, space);
202 }
203 } catch (const InvalidOperation& ex) {
205 .arg(ex.what());
206 }
207 }
208 }
209}
210
211bool
212CfgOption::createDescriptorOption(CfgOptionDefPtr cfg_def, const std::string& space,
213 OptionDescriptor& opt_desc) {
214 if (!opt_desc.option_) {
216 "validateCreateOption: descriptor has no option instance");
217 }
218
219 Option::Universe universe = opt_desc.option_->getUniverse();
220 uint16_t code = opt_desc.option_->getType();
221
222 // Find the option's definition, if it has one.
223 // First, check for a standard definition.
225
226 // If there is no standard definition but the option is vendor specific,
227 // we should search the definition within the vendor option space.
228 if (!def && (space != DHCP4_OPTION_SPACE) && (space != DHCP6_OPTION_SPACE)) {
229 uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(space);
230 if (vendor_id > 0) {
231 def = LibDHCP::getVendorOptionDef(universe, vendor_id, code);
232 }
233 }
234
235 // Still haven't found the definition, so look for custom
236 // definition in the given set of configured definitions
237 if (!def) {
238 def = cfg_def->get(space, code);
239 }
240
241 // Finish with a last resort option definition.
242 if (!def) {
243 def = LibDHCP::getLastResortOptionDef(space, code);
244 }
245
246 std::string& formatted_value = opt_desc.formatted_value_;
247 if (!def) {
248 if (!formatted_value.empty()) {
249 isc_throw(InvalidOperation, "option: " << space << "." << code
250 << " has a formatted value: '" << formatted_value
251 << "' but no option definition");
252 }
253
254 // If there's no definition and no formatted string, we'll
255 // settle for the generic option already in the descriptor.
256 // Indicate no-change by returning false.
257 return (false);
258 }
259
260 try {
261 // Definition found. Let's replace the generic option in
262 // the descriptor with one created based on definition's factory.
263 if (formatted_value.empty()) {
264 // No formatted value, use data stored in the generic option.
265 opt_desc.option_ = def->optionFactory(universe, code, opt_desc.option_->getData());
266 } else {
267 // Spit the value specified in comma separated values format.
268 std::vector<std::string> split_vec;
269 boost::split(split_vec, formatted_value, boost::is_any_of(","));
270 opt_desc.option_ = def->optionFactory(universe, code, split_vec);
271 }
272 } catch (const std::exception& ex) {
273 isc_throw(InvalidOperation, "could not create option: " << space << "." << code
274 << " from data specified, reason: " << ex.what());
275 }
276
277 // Indicate we replaced the definition.
278 return (true);
279}
280
281void
283 // Merge non-vendor options.
284 mergeInternal(options_, other.options_);
285 // Merge vendor options.
286 mergeInternal(vendor_options_, other.vendor_options_);
287}
288
289void
291 // Remove any existing data in the destination.
292 other.options_.clearItems();
293 other.vendor_options_.clearItems();
294 mergeTo(other);
295 other.encapsulated_ = isEncapsulated();
296}
297
298void
300 // Append sub-options to the top level "dhcp4" option space.
301 encapsulateInternal(DHCP4_OPTION_SPACE);
302 // Append sub-options to the top level "dhcp6" option space.
303 encapsulateInternal(DHCP6_OPTION_SPACE);
304 encapsulated_ = true;
305}
306
307void
308CfgOption::encapsulateInternal(const std::string& option_space) {
309 // Get all options for the particular option space.
310 OptionContainerPtr options = getAll(option_space);
311 // For each option in the option space we will append sub-options
312 // from the option spaces they encapsulate.
313 for (auto const& opt : *options) {
314 encapsulateInternal(opt.option_);
315 }
316
317 for (auto const& vendor : getVendorIds()) {
318 OptionContainerPtr vendor_options = getAll(vendor);
319 // For each option in the option space we will append sub-options
320 // from the option spaces they encapsulate.
321 for (auto const& opt : *vendor_options) {
322 encapsulateInternal(opt.option_);
323 }
324 }
325}
326
327void
328CfgOption::encapsulateInternal(const OptionPtr& option) {
329 // Get encapsulated option space for the option.
330 const std::string& encap_space = option->getEncapsulatedSpace();
331 // Empty value means that no option space is encapsulated.
332 if (encap_space.empty()) {
333 return;
334 }
335 if (encap_space == DHCP4_OPTION_SPACE || encap_space == DHCP6_OPTION_SPACE) {
336 return;
337 }
338 // Handle multiple encapsulating spaces.
339 bool multiple_encapsulating = false;
340 if (multiple_encapsulating_spaces_.count(encap_space) > 0) {
341 multiple_encapsulating = true;
342 // Cleanup the option so encapsulate() can be called again.
343 decapsulateInternal(option);
344 }
345
346 // Retrieve all options from the encapsulated option space.
347 OptionContainerPtr encap_options = getAll(encap_space);
348 for (auto const& encap_opt : *encap_options) {
349 if (option.get() == encap_opt.option_.get()) {
350 // Avoid recursion by not adding options to themselves.
351 continue;
352 }
353
354 // Add sub-option if there isn't one added already, or
355 // if encapsulating space is a multiple exception.
356 if (multiple_encapsulating ||
357 !option->getOption(encap_opt.option_->getType())) {
358 option->addOption(encap_opt.option_);
359 }
360 encapsulateInternal(encap_opt.option_);
361 }
362}
363
364void
365CfgOption::decapsulateInternal(const OptionPtr& option) {
366 // Dereference any existing sub options.
367 auto sub_options = option->getOptions();
368 for (auto const& sub : sub_options) {
369 option->delOption(sub.second->getType());
370 }
371}
372
373template <typename Selector>
374void
375CfgOption::mergeInternal(const OptionSpaceContainer<OptionContainer,
376 OptionDescriptor, Selector>& src_container,
378 OptionDescriptor, Selector>& dest_container) const {
379 // Get all option spaces used in source container.
380 std::list<Selector> selectors = src_container.getOptionSpaceNames();
381
382 // For each space in the source container retrieve the actual options and
383 // match them with the options held in the destination container under
384 // the same space.
385 for (auto const& it : selectors) {
386 // Get all options in the destination container for the particular
387 // option space.
388 OptionContainerPtr dest_all = dest_container.getItems(it);
389 OptionContainerPtr src_all = src_container.getItems(it);
390 // For each option under this option space check if there is a
391 // corresponding option in the destination container. If not,
392 // add one.
393 for (auto const& src_opt : *src_all) {
394 const OptionContainerTypeIndex& idx = dest_all->get<1>();
395 const OptionContainerTypeRange& range =
396 idx.equal_range(src_opt.option_->getType());
397 // If there is no such option in the destination container,
398 // add one.
399 if (std::distance(range.first, range.second) == 0) {
400 dest_container.addItem(OptionDescriptor(src_opt), it);
401 }
402 }
403 }
404}
405
407CfgOption::getAll(const std::string& option_space) const {
408 return (options_.getItems(option_space));
409}
410
412CfgOption::getAll(const uint32_t vendor_id) const {
413 return (vendor_options_.getItems(vendor_id));
414}
415
417CfgOption::getAllCombined(const std::string& option_space) const {
418 auto vendor_id = LibDHCP::optionSpaceToVendorId(option_space);
419 if (vendor_id > 0) {
420 return (getAll(vendor_id));
421 }
422 return (getAll(option_space));
423}
424
425size_t
426CfgOption::del(const std::string& option_space, const uint16_t option_code) {
427 // Check for presence of options.
428 OptionContainerPtr options = getAll(option_space);
429 if (!options || options->empty()) {
430 // There are no options, so there is nothing to do.
431 return (0);
432 }
433
434 // If this is not top level option we may also need to delete the
435 // option instance from options encapsulating the particular option
436 // space.
437 if ((option_space != DHCP4_OPTION_SPACE) &&
438 (option_space != DHCP6_OPTION_SPACE)) {
439 // For each option space name iterate over the existing options.
440 auto option_space_names = getOptionSpaceNames();
441 for (auto const& option_space_from_list : option_space_names) {
442 // Get all options within the particular option space.
443 auto const& options_in_space = getAll(option_space_from_list);
444 for (auto const& option_it : *options_in_space) {
445
446 // Check if the option encapsulates our option space and
447 // it does, try to delete our option.
448 if (option_it.option_ &&
449 (option_it.option_->getEncapsulatedSpace() == option_space)) {
450 option_it.option_->delOption(option_code);
451 }
452 }
453 }
454 }
455
456 auto& idx = options->get<1>();
457 return (idx.erase(option_code));
458}
459
460size_t
461CfgOption::del(const std::string& option_space, const uint16_t option_code,
462 const ClientClasses& client_classes) {
463 // Check for presence of options.
464 OptionContainerPtr options = getAll(option_space);
465 if (!options || options->empty()) {
466 // There are no options, so there is nothing to do.
467 return (0);
468 }
469
470 // If this is not top level option we may also need to delete the
471 // option instance from options encapsulating the particular option
472 // space.
473 if ((option_space != DHCP4_OPTION_SPACE) &&
474 (option_space != DHCP6_OPTION_SPACE)) {
475 // For each option space name iterate over the existing options.
476 auto option_space_names = getOptionSpaceNames();
477 for (auto const& option_space_from_list : option_space_names) {
478 // Get all options within the particular option space.
479 auto const& options_in_space = getAll(option_space_from_list);
480 for (auto const& option_it : *options_in_space) {
481
482 // Check if the option encapsulates our option space and
483 // if it does, try to delete our option.
484 if (option_it.option_ &&
485 (option_it.option_->getEncapsulatedSpace() == option_space)) {
486 option_it.option_->delOption(option_code);
487 }
488 }
489 }
490 }
491
492 auto& idx6 = options->get<6>();
493 auto range = idx6.equal_range(boost::make_tuple(option_code, client_classes));
494 auto count = std::distance(range.first, range.second);
495 if (count) {
496 idx6.erase(range.first, range.second);
497 }
498
499 return (count);
500}
501
502size_t
503CfgOption::del(const uint32_t vendor_id, const uint16_t option_code) {
504 // Check for presence of options.
505 OptionContainerPtr vendor_options = getAll(vendor_id);
506 if (!vendor_options || vendor_options->empty()) {
507 // There are no options, so there is nothing to do.
508 return (0);
509 }
510
511 auto& idx = vendor_options->get<1>();
512 return (idx.erase(option_code));
513}
514
515size_t
516CfgOption::del(const uint64_t id) {
517 // Hierarchical nature of the options configuration requires that
518 // we go over all options and decapsulate them before removing
519 // any of them. Let's walk over the existing option spaces.
520 for (auto const& space_name : getOptionSpaceNames()) {
521 // Get all options for the option space.
522 auto const& options = getAll(space_name);
523 for (auto const& option_it : *options) {
524 if (option_it.option_) {
525 decapsulateInternal(option_it.option_);
526 }
527 }
528 }
529
530 // Now that we got rid of dependencies between the instances of the options
531 // we can delete all options having a specified id.
532 size_t num_deleted = options_.deleteItems(id) + vendor_options_.deleteItems(id);
533
534 // Let's encapsulate those options that remain in the configuration.
535 encapsulate();
536
537 // Return the number of deleted options.
538 return (num_deleted);
539}
540
543 return (toElementWithMetadata(false));
544}
545
548 return (toElementWithMetadata(false, cfg_option_def));
549}
550
552CfgOption::toElementWithMetadata(const bool include_metadata,
553 CfgOptionDefPtr cfg_option_def) const {
554 // option-data value is a list of maps
556 // Iterate first on options using space names
557 const std::list<std::string>& names = options_.getOptionSpaceNames();
558 for (auto const& name : names) {
559 OptionContainerPtr opts = getAll(name);
560 for (auto const& opt : *opts) {
561 // Get and fill the map for this option
563 // Set user context
564 opt.contextToElement(map);
565 // Set space from parent iterator
566 map->set("space", Element::create(name));
567 // Set the code
568 uint16_t code = opt.option_->getType();
569 map->set("code", Element::create(code));
570 // Set the name (always for standard options else when asked for)
572 if (cfg_option_def) {
573 def = cfg_option_def->get(name, code);
574 }
575 if (!def) {
576 def = LibDHCP::getOptionDef(name, code);
577 }
578 if (!def) {
579 def = LibDHCP::getRuntimeOptionDef(name, code);
580 }
581 if (!def) {
582 def = LibDHCP::getLastResortOptionDef(name, code);
583 }
584 if (def) {
585 map->set("name", Element::create(def->getName()));
586 }
587 // Set the data item
588 if (!opt.formatted_value_.empty()) {
589 map->set("csv-format", Element::create(true));
590 if (def && def->getType() == OPT_EMPTY_TYPE) {
591 map->set("data", Element::create(""));
592 } else {
593 map->set("data", Element::create(opt.formatted_value_));
594 }
595 } else {
596 std::vector<uint8_t> bin = opt.option_->toBinary();
597 if (!opt.cancelled_ || !bin.empty()) {
598 map->set("csv-format", Element::create(false));
599 if (def && def->getType() == OPT_EMPTY_TYPE) {
600 map->set("data", Element::create(""));
601 } else {
602 std::string repr = util::encode::encodeHex(bin);
603 map->set("data", Element::create(repr));
604 }
605 }
606 }
607 // Set the persistency flag
608 map->set("always-send", Element::create(opt.persistent_));
609 // Set the cancelled flag.
610 map->set("never-send", Element::create(opt.cancelled_));
611 // Include metadata if requested.
612 if (include_metadata) {
613 map->set("metadata", opt.getMetadata());
614 }
615
616 // Include client-classes if not empty.
617 if (!opt.client_classes_.empty()) {
618 map->set("client-classes", opt.client_classes_.toElement());
619 }
620
621 // Push on the list
622 result->add(map);
623 }
624 }
625 // Iterate first on vendor_options using vendor ids
626 const std::list<uint32_t>& ids = vendor_options_.getOptionSpaceNames();
627 for (auto const& id : ids) {
628 OptionContainerPtr opts = getAll(id);
629 for (auto const& opt : *opts) {
630 // Get and fill the map for this option
632 // Set user context
633 opt.contextToElement(map);
634 // Set space from parent iterator
635 std::ostringstream oss;
636 oss << "vendor-" << id;
637 map->set("space", Element::create(oss.str()));
638 // Set the code
639 uint16_t code = opt.option_->getType();
640 map->set("code", Element::create(code));
641 // Set the name
642 Option::Universe universe = opt.option_->getUniverse();
644 LibDHCP::getVendorOptionDef(universe, id, code);
645 if (!def) {
646 // vendor-XXX space is in oss
647 def = LibDHCP::getRuntimeOptionDef(oss.str(), code);
648 }
649 if (def) {
650 map->set("name", Element::create(def->getName()));
651 }
652 // Set the data item
653 if (!opt.formatted_value_.empty()) {
654 map->set("csv-format", Element::create(true));
655 if (def && def->getType() == OPT_EMPTY_TYPE) {
656 map->set("data", Element::create(""));
657 } else {
658 map->set("data", Element::create(opt.formatted_value_));
659 }
660 } else {
661 std::vector<uint8_t> bin = opt.option_->toBinary();
662 if (!opt.cancelled_ || !bin.empty()) {
663 map->set("csv-format", Element::create(false));
664 if (def && def->getType() == OPT_EMPTY_TYPE) {
665 map->set("data", Element::create(""));
666 } else {
667 std::string repr = util::encode::encodeHex(bin);
668 map->set("data", Element::create(repr));
669 }
670 }
671 }
672 // Set the persistency flag
673 map->set("always-send", Element::create(opt.persistent_));
674 // Set the cancellation flag
675 map->set("never-send", Element::create(opt.cancelled_));
676
677 // Include client-classes if not empty.
678 if (!opt.client_classes_.empty()) {
679 map->set("client-classes", opt.client_classes_.toElement());
680 }
681
682 // Push on the list
683 result->add(map);
684 }
685 }
686
687 return (result);
688}
689
690} // namespace dhcp
691} // namespace isc
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 function is called in a prohibited way.
void setId(const uint64_t id)
Sets element's database identifier.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:300
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:355
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:350
bool isEncapsulated() const
Checks if options have been encapsulated.
Definition cfg_option.h:603
OptionContainerPtr getAllCombined(const std::string &option_space) const
Returns all non-vendor or vendor options for the specified option space.
void encapsulate()
Appends encapsulated options to top-level options.
static std::set< std::string > multiple_encapsulating_spaces_
Option spaces which can encapsulate multiple sub-options of the same type.
Definition cfg_option.h:609
void replace(const OptionDescriptor &desc, const std::string &option_space)
Replaces the instance of an option within this collection.
static bool createDescriptorOption(CfgOptionDefPtr cfg_def, const std::string &space, OptionDescriptor &opt_desc)
Creates an option descriptor's option based on a set of option defs.
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
void createOptions(CfgOptionDefPtr cfg_def)
Re-create the option in each descriptor based on given definitions.
isc::data::ElementPtr toElementWithMetadata(const bool include_metadata, CfgOptionDefPtr cfg_option_def=CfgOptionDefPtr()) const
Unparse a configuration object with optionally including the metadata.
size_t del(const std::string &option_space, const uint16_t option_code)
Deletes option for the specified option space and option code.
std::list< std::string > getOptionSpaceNames() const
Returns a list of configured option space names.
Definition cfg_option.h:873
bool empty() const
Indicates the object is empty.
Definition cfg_option.cc:89
void mergeTo(CfgOption &other) const
Merges this configuration to another configuration.
void copyTo(CfgOption &other) const
Copies this configuration to another configuration.
CfgOption()
default constructor
Definition cfg_option.cc:84
std::list< std::string > getVendorIdsSpaceNames() const
Returns a list of option space names for configured vendor ids.
OptionContainerPtr getAll(const std::string &option_space) const
Returns all options for the specified option space.
void merge(CfgOptionDefPtr cfg_def, CfgOption &other)
Merges another option configuration into this one.
bool equals(const CfgOption &other) const
Check if configuration is equal to other configuration.
Definition cfg_option.cc:94
void add(const OptionPtr &option, const bool persistent, const bool cancelled, const std::string &option_space, const uint64_t id=0)
Adds instance of the option to the configuration.
std::list< uint32_t > getVendorIds() const
Returns a list of all configured vendor identifiers.
Definition cfg_option.h:878
Container for storing client class names.
Definition classify.h:111
std::string toText(const std::string &separator=", ") const
Returns all class names as text.
Definition classify.cc:77
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Definition libdhcp++.cc:132
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.
Definition libdhcp++.cc:174
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.
Definition libdhcp++.cc:195
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
Definition libdhcp++.cc:253
Option descriptor.
Definition cfg_option.h:50
OptionPtr option_
Option instance.
Definition cfg_option.h:53
void addClientClass(const std::string &class_name)
Adds new client class for which the option is allowed.
Definition cfg_option.cc:59
std::string space_name_
Option space name.
Definition cfg_option.h:93
OptionDescriptor(const OptionPtr &opt, bool persist, bool cancel, const std::string &formatted_value="", data::ConstElementPtr user_context=data::ConstElementPtr())
Constructor.
Definition cfg_option.h:106
bool equals(const OptionDescriptor &other) const
Checks if the one descriptor is equal to another.
Definition cfg_option.cc:48
bool allowedForClientClasses(const ClientClasses &cclasses) const
Validates an OptionDescriptor's client-classes against a list of classes.
Definition cfg_option.cc:72
ClientClassesPtr copyClientClasses() const
Get a copy of client classes.
Definition cfg_option.cc:67
bool cancelled_
Cancelled flag.
Definition cfg_option.h:67
std::string formatted_value_
Option value in textual (CSV) format.
Definition cfg_option.h:82
static OptionDescriptorPtr create(const OptionPtr &opt, bool persist, bool cancel, const std::string &formatted_value="", data::ConstElementPtr user_context=data::ConstElementPtr())
Factory function creating an instance of the OptionDescriptor.
Definition cfg_option.cc:29
ClientClasses client_classes_
Collection of classes for the which option is allowed.
Definition cfg_option.h:97
bool persistent_
Persistence flag.
Definition cfg_option.h:59
Simple container for option spaces holding various items.
void clearItems()
Remove all items from the container.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Universe
defines option universe DHCPv4 or DHCPv6
Definition option.h:90
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
std::string ClientClass
Defines a single class name.
Definition classify.h:45
boost::multi_index_container< OptionDescriptor, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::hashed_non_unique< KeyFromKeyExtractor< boost::multi_index::const_mem_fun< Option, uint16_t, &Option::getType >, boost::multi_index::member< OptionDescriptor, OptionPtr, &OptionDescriptor::option_ > > >, boost::multi_index::hashed_non_unique< boost::multi_index::member< OptionDescriptor, bool, &OptionDescriptor::persistent_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< OptionIdIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, uint64_t, &data::BaseStampedElement::getId > >, boost::multi_index::hashed_non_unique< boost::multi_index::member< OptionDescriptor, bool, &OptionDescriptor::cancelled_ > >, boost::multi_index::hashed_non_unique< boost::multi_index::composite_key< OptionDescriptor, KeyFromKeyExtractor< boost::multi_index::const_mem_fun< Option, uint16_t, &Option::getType >, boost::multi_index::member< OptionDescriptor, OptionPtr, &OptionDescriptor::option_ > >, boost::multi_index::member< OptionDescriptor, ClientClasses, &OptionDescriptor::client_classes_ > > > > > OptionContainer
Multi index container for DHCP option descriptors.
Definition cfg_option.h:348
std::pair< OptionContainerTypeIndex::const_iterator, OptionContainerTypeIndex::const_iterator > OptionContainerTypeRange
Pair of iterators to represent the range of options having the same option type value.
Definition cfg_option.h:358
OptionContainer::nth_index< 1 >::type OptionContainerTypeIndex
Type of the index #1 - option type.
Definition cfg_option.h:353
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< ClientClasses > ClientClassesPtr
Smart pointer to ClientClasses object.
Definition classify.h:304
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::shared_ptr< OptionDescriptor > OptionDescriptorPtr
A pointer to option descriptor.
Definition cfg_option.h:39
boost::shared_ptr< OptionContainer > OptionContainerPtr
Pointer to the OptionContainer object.
Definition cfg_option.h:351
const isc::log::MessageID DHCPSRV_CFGMGR_OPTION_DEFINITION_MISMATCH
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
Definition encode.cc:361
string trim(const string &input)
Trim leading and trailing spaces.
Definition str.cc:32
Defines the logger used by the top-level component of kea-lfc.
#define DHCP4_OPTION_SPACE
global std option spaces
#define V6_NTP_SERVER_SPACE
#define DHCP6_OPTION_SPACE