24 #include <boost/lexical_cast.hpp>
25 #include <boost/shared_array.hpp>
26 #include <boost/shared_ptr.hpp>
44 { STANDARD_V4_OPTION_DEFINITIONS, STANDARD_V4_OPTION_DEFINITIONS_SIZE,
DHCP4_OPTION_SPACE },
45 { STANDARD_V6_OPTION_DEFINITIONS, STANDARD_V6_OPTION_DEFINITIONS_SIZE,
DHCP6_OPTION_SPACE },
64 std::map<unsigned short, Option::Factory*> LibDHCP::v4factories_;
67 std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
92 bool LibDHCP::initialized_ = LibDHCP::initOptionDefs();
95 LibDHCP::getOptionDefs(
const std::string& space) {
96 OptionDefContainers::const_iterator container = option_defs_.find(space);
97 if (container != option_defs_.end()) {
98 return (container->second);
106 if (Option::V4 == u) {
110 }
else if (Option::V6 == u) {
113 }
else if (ENTERPRISE_ID_ISC == vendor_id) {
122 LibDHCP::getOptionDef(
const std::string& space,
const uint16_t code) {
126 if (range.first != range.second) {
127 return (*range.first);
134 LibDHCP::getOptionDef(
const std::string& space,
const std::string& name) {
138 if (range.first != range.second) {
139 return (*range.first);
147 const std::string& name) {
156 if (range.first != range.second) {
157 return (*range.first);
165 const uint16_t code) {
177 if (range.first != range.second) {
178 return (*range.first);
185 LibDHCP::getRuntimeOptionDef(
const std::string& space,
const uint16_t code) {
189 if (range.first != range.second) {
190 return (*range.first);
197 LibDHCP::getRuntimeOptionDef(
const std::string& space,
const std::string& name) {
201 if (range.first != range.second) {
202 return (*range.first);
209 LibDHCP::getRuntimeOptionDefs(
const std::string& space) {
210 return (runtime_option_defs_.getValue().getItems(space));
217 for (std::list<std::string>::const_iterator name = option_space_names.begin();
218 name != option_space_names.end(); ++name) {
220 for (OptionDefContainer::const_iterator def = container->begin();
221 def != container->end(); ++def) {
226 runtime_option_defs_ = defs_copy;
230 LibDHCP::clearRuntimeOptionDefs() {
231 runtime_option_defs_.reset();
235 LibDHCP::revertRuntimeOptionDefs() {
236 runtime_option_defs_.revert();
240 LibDHCP::commitRuntimeOptionDefs() {
241 runtime_option_defs_.commit();
245 LibDHCP::getLastResortOptionDef(
const std::string& space,
const uint16_t code) {
249 if (range.first != range.second) {
250 return (*range.first);
257 LibDHCP::getLastResortOptionDef(
const std::string& space,
const std::string& name) {
261 if (range.first != range.second) {
262 return (*range.first);
269 LibDHCP::getLastResortOptionDefs(
const std::string& space) {
278 LibDHCP::shouldDeferOptionUnpack(
const std::string& space,
const uint16_t code) {
281 ((code >= 224) && (code <= 254))));
288 FactoryMap::iterator it;
289 if (u == Option::V4) {
290 it = v4factories_.find(type);
291 if (it == v4factories_.end()) {
293 "for DHCP v4 option type " << type);
295 }
else if (u == Option::V6) {
296 it = v6factories_.find(type);
297 if (it == v6factories_.end()) {
299 "for DHCPv6 option type " << type);
303 "Option::V4 or Option::V6");
305 return (it->second(u, type, buf));
311 const std::string& option_space,
313 size_t* relay_msg_offset ,
314 size_t* relay_msg_len ) {
316 size_t length = buf.size();
317 size_t last_offset = 0;
336 while (offset < length) {
338 last_offset = offset;
341 if (offset + 4 > length) {
343 return (last_offset);
353 if (offset + opt_len > length) {
362 return (last_offset);
365 if (opt_type ==
D6O_RELAY_MSG && relay_msg_offset && relay_msg_len) {
367 *relay_msg_offset = offset;
368 *relay_msg_len = opt_len;
376 if (offset + 4 > length) {
380 return (last_offset);
385 buf.begin() + offset + opt_len));
386 options.insert(std::make_pair(opt_type, vendor_opt));
403 range = idx.equal_range(opt_type);
404 num_defs = std::distance(range.first, range.second);
410 range = runtime_idx.equal_range(opt_type);
411 num_defs = std::distance(range.first, range.second);
418 " definitions for option type " << opt_type <<
419 " returned. Currently it is not supported to initialize"
420 " multiple option definitions for the same option code."
421 " This will be supported once support for option spaces"
423 }
else if (num_defs == 0) {
430 buf.begin() + offset,
431 buf.begin() + offset + opt_len));
438 opt = def->optionFactory(Option::V6, opt_type,
439 buf.begin() + offset,
440 buf.begin() + offset + opt_len);
448 options.insert(std::make_pair(opt_type, opt));
454 last_offset = offset;
455 return (last_offset);
460 const std::string& option_space,
462 std::list<uint16_t>& deferred,
463 bool flexible_pad_end) {
465 size_t last_offset = 0;
482 bool flex_pad = (flexible_pad_end && (runtime_idx.count(
DHO_PAD) == 0));
483 bool flex_end = (flexible_pad_end && (runtime_idx.count(
DHO_END) == 0));
487 while (offset < buf.size()) {
489 last_offset = offset;
492 uint8_t opt_type = buf[offset++];
497 if ((opt_type ==
DHO_END) && (space_is_dhcp4 || flex_end)) {
501 return (last_offset);
508 if ((opt_type ==
DHO_PAD) && (space_is_dhcp4 || flex_pad)) {
512 if (offset + 1 > buf.size()) {
520 return (last_offset);
523 uint8_t opt_len = buf[offset++];
524 if (offset + opt_len > buf.size()) {
529 return (last_offset);
537 if (space_is_dhcp4 && opt_len == 0 && opt_type ==
DHO_HOST_NAME) {
553 range = idx.equal_range(opt_type);
554 num_defs = std::distance(range.first, range.second);
560 range = runtime_idx.equal_range(opt_type);
561 num_defs = std::distance(range.first, range.second);
565 if (shouldDeferOptionUnpack(option_space, opt_type)) {
567 deferred.push_back(opt_type);
574 " definitions for option type " <<
575 static_cast<int>(opt_type) <<
576 " returned. Currently it is not supported to initialize"
577 " multiple option definitions for the same option code."
578 " This will be supported once support for option spaces"
580 }
else if (num_defs == 0) {
582 buf.begin() + offset,
583 buf.begin() + offset + opt_len));
591 opt = def->optionFactory(Option::V4, opt_type,
592 buf.begin() + offset,
593 buf.begin() + offset + opt_len);
601 options.insert(std::make_pair(opt_type, opt));
606 last_offset = offset;
607 return (last_offset);
611 LibDHCP::unpackVendorOptions6(
const uint32_t vendor_id,
615 size_t length = buf.size();
619 LibDHCP::getVendorOptionDefs(Option::V6, vendor_id);
626 idx = &(option_defs->get<1>());
631 while (offset < length) {
632 if (offset + 4 > length) {
634 "Vendor option parse failed: truncated header");
643 if (offset + opt_len > length) {
645 "Vendor option parse failed. Tried to parse "
646 << offset + opt_len <<
" bytes from " << length
647 <<
"-byte long buffer.");
661 idx->equal_range(opt_type);
664 size_t num_defs = std::distance(range.first, range.second);
670 " definitions for option type " << opt_type <<
671 " returned. Currently it is not supported to"
672 " initialize multiple option definitions for the"
673 " same option code. This will be supported once"
674 " support for option spaces is implemented");
675 }
else if (num_defs == 1) {
680 opt = def->optionFactory(Option::V6, opt_type,
681 buf.begin() + offset,
682 buf.begin() + offset + opt_len);
693 buf.begin() + offset,
694 buf.begin() + offset + opt_len));
699 options.insert(std::make_pair(opt_type, opt));
708 LibDHCP::unpackVendorOptions4(
const uint32_t vendor_id,
const OptionBuffer& buf,
714 LibDHCP::getVendorOptionDefs(Option::V4, vendor_id);
719 idx = &(option_defs->get<1>());
724 while (offset < buf.size()) {
728 uint8_t data_len = buf[offset++];
730 if (offset + data_len > buf.size()) {
733 "Attempt to parse truncated vendor option");
736 uint8_t offset_end = offset + data_len;
739 while (offset < offset_end) {
740 uint8_t opt_type = buf[offset++];
744 if (offset + 1 > offset_end) {
749 "Attempt to parse truncated vendor option "
750 << static_cast<int>(opt_type));
753 uint8_t opt_len = buf[offset++];
754 if (offset + opt_len > offset_end) {
756 "Option parse failed. Tried to parse "
757 << offset + opt_len <<
" bytes from " << buf.size()
758 <<
"-byte long buffer.");
771 idx->equal_range(opt_type);
774 size_t num_defs = std::distance(range.first, range.second);
780 " option definitions for option type "
781 << opt_type <<
" returned. Currently it is"
782 " not supported to initialize multiple option"
783 " definitions for the same option code."
784 " This will be supported once support for"
785 " option spaces is implemented");
786 }
else if (num_defs == 1) {
791 opt = def->optionFactory(Option::V4, opt_type,
792 buf.begin() + offset,
793 buf.begin() + offset + opt_len);
799 buf.begin() + offset,
800 buf.begin() + offset + opt_len));
803 options.insert(std::make_pair(opt_type, opt));
826 if (x != options.end()) {
827 x->second->pack(buf);
831 for (OptionCollection::const_iterator it = options.begin();
832 it != options.end(); ++it) {
845 it->second->pack(buf);
864 for (OptionCollection::const_iterator it = options.begin();
865 it != options.end(); ++it) {
866 it->second->pack(buf);
873 Option::Factory* factory) {
877 if (v6factories_.find(opt_type) != v6factories_.end()) {
879 <<
"for option type " << opt_type);
881 v6factories_[opt_type] = factory;
894 if (opt_type > 254) {
897 if (v4factories_.find(opt_type) != v4factories_.end()) {
899 <<
"for option type " << opt_type);
901 v4factories_[opt_type] = factory;
912 LibDHCP::initOptionDefs() {
913 for (uint32_t i = 0; OPTION_DEF_PARAMS[i].optionDefParams; ++i) {
914 std::string space = OPTION_DEF_PARAMS[i].space;
917 OPTION_DEF_PARAMS[i].optionDefParams,
918 OPTION_DEF_PARAMS[i].size);
925 LibDHCP::optionSpaceToVendorId(
const std::string& option_space) {
927 if ((option_space.size() < 8) || (option_space.substr(0,7) !=
"vendor-")) {
934 std::string x = option_space.substr(7);
936 check = boost::lexical_cast<int64_t>(x);
937 }
catch (
const boost::bad_lexical_cast &) {
941 if ((check < 0) || (check > std::numeric_limits<uint32_t>::max())) {
946 return (static_cast<uint32_t>(check));
952 size_t params_size) {
962 for (
size_t i = 0; i < params_size; ++i) {
963 std::string encapsulates(params[i].encapsulates);
964 if (!encapsulates.empty() && params[i].
array) {
966 <<
"option with code '" << params[i].code
967 <<
"' may not encapsulate option space '"
968 << encapsulates <<
"' because the definition"
969 <<
" indicates that this option comprises an array"
977 if (encapsulates.empty()) {
990 params[i].encapsulates));
994 for (
size_t rec = 0; rec < params[i].
records_size; ++rec) {
995 definition->addRecordField(params[i].records[rec]);
999 definition->validate();
1011 static_cast<void>(defs->push_back(definition));
Encapsulation of option definition parameters and the structure size.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
Base class representing a DHCP option definition.
void addItem(const OptionDefinitionPtr &def)
Adds a new option definition to the container.
#define V4V6_BIND_OPTION_SPACE
Exception thrown during option unpacking This exception is thrown when an error has occurred...
#define V4V6_RULE_OPTION_SPACE
std::list< Selector > getOptionSpaceNames() const
Get a list of existing option spaces.
OptionDefContainer::nth_index< 1 >::type OptionDefContainerTypeIndex
Type of the index #1 - option type.
boost::shared_ptr< Option > OptionPtr
Universe
defines option universe DHCPv4 or DHCPv6
Parameters being used to make up an option definition.
#define DOCSIS3_V4_OPTION_SPACE
global docsis3 option spaces
boost::multi_index_container< OptionDefinitionPtr, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::hashed_non_unique< boost::multi_index::const_mem_fun< OptionDefinition, uint16_t,&OptionDefinition::getCode > >, boost::multi_index::hashed_non_unique< boost::multi_index::const_mem_fun< OptionDefinition, std::string,&OptionDefinition::getName > >, boost::multi_index::ordered_non_unique< boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime,&data::StampedElement::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 > > >> OptionDefContainer
Multi index container for DHCP option definitions.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
std::pair< OptionDefContainerTypeIndex::const_iterator, OptionDefContainerTypeIndex::const_iterator > OptionDefContainerTypeRange
Pair of iterators to represent the range of options definitions having the same option type value...
#define LW_V6_OPTION_SPACE
Class of option definition space container.
const OptionDefParams DOCSIS3_V6_OPTION_DEFINITIONS[]
Definitions of standard DHCPv6 options.
#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...
#define MAPT_V6_OPTION_SPACE
#define MAPE_V6_OPTION_SPACE
const char * DOCSIS3_CLASS_MODEM
DOCSIS3.0 compatible cable modem.
A generic exception that is thrown when an unexpected error condition occurs.
#define ISC_V6_OPTION_SPACE
const char * DOCSIS3_CLASS_EROUTER
The class as specified in vendor-class option by the devices.
#define LAST_RESORT_V4_OPTION_SPACE
boost::shared_ptr< OptionDefContainer > OptionDefContainerPtr
Pointer to an option definition container.
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
const OptionDefParams DOCSIS3_V4_OPTION_DEFINITIONS[]
Definitions of standard DHCPv4 options.
std::map< std::string, OptionDefContainerPtr > OptionDefContainers
Container that holds option definitions for various option spaces.
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.
const int DOCSIS3_V6_OPTION_DEFINITIONS_SIZE
Number of option definitions defined.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
#define DHCP6_OPTION_SPACE
#define DHCP4_OPTION_SPACE
global std option spaces
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
Exception thrown during option unpacking This exception is thrown when an error has occurred unpackin...
#define DOCSIS3_V6_OPTION_SPACE
const OptionDefContainerPtr null_option_def_container_(new OptionDefContainer())
#define VENDOR_ID_CABLE_LABS
This class implements set/commit mechanism for a single object.
ItemsContainerPtr getItems(const Selector &option_space) const
Get all items for the particular option space.
This class represents vendor-specific information option.
void initOptionSpace(OptionDefContainerPtr &defs, const OptionDefParams *params, size_t params_size)
OptionDefContainer::nth_index< 2 >::type OptionDefContainerNameIndex
Type of the index #2 - option name.
const int DOCSIS3_V4_OPTION_DEFINITIONS_SIZE
Number of option definitions defined.
std::pair< OptionDefContainerNameIndex::const_iterator, OptionDefContainerNameIndex::const_iterator > OptionDefContainerNameRange
Pair of iterators to represent the range of options definitions having the same option name...