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 },
64std::map<unsigned short, Option::Factory*> LibDHCP::v4factories_;
67std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
92bool LibDHCP::initialized_ = LibDHCP::initOptionDefs();
95LibDHCP::getOptionDefs(
const std::string& space) {
96 OptionDefContainers::const_iterator container = option_defs_.find(space);
97 if (container != option_defs_.end()) {
98 return (container->second);
113 }
else if (ENTERPRISE_ID_ISC == vendor_id) {
126 if (range.first != range.second) {
127 return (*range.first);
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);
189 if (range.first != range.second) {
190 return (*range.first);
201 if (range.first != range.second) {
202 return (*range.first);
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;
231 runtime_option_defs_.reset();
236 runtime_option_defs_.revert();
241 runtime_option_defs_.commit();
249 if (range.first != range.second) {
250 return (*range.first);
261 if (range.first != range.second) {
262 return (*range.first);
281 ((code >= 224) && (code <= 254))));
288 FactoryMap::iterator it;
290 it = v4factories_.find(type);
291 if (it == v4factories_.end()) {
293 "for DHCP v4 option type " << type);
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);
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);
615 size_t length = buf.size();
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));
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);
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;
912LibDHCP::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);
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));
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
A generic exception that is thrown when an unexpected error condition occurs.
static size_t unpackOptions4(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, std::list< uint16_t > &deferred, bool flexible_pad_end=false)
Parses provided buffer as DHCPv4 options and creates Option objects.
static void OptionFactoryRegister(Option::Universe u, uint16_t type, Option::Factory *factory)
Registers factory method that produces options of specific option types.
static size_t unpackVendorOptions6(const uint32_t vendor_id, const OptionBuffer &buf, isc::dhcp::OptionCollection &options)
Parses provided buffer as DHCPv6 vendor options and creates Option objects.
static const OptionDefContainerPtr getOptionDefs(const std::string &space)
Returns collection of option definitions.
static bool shouldDeferOptionUnpack(const std::string &space, const uint16_t code)
Checks if an option unpacking has to be deferred.
static isc::dhcp::OptionPtr optionFactory(isc::dhcp::Option::Universe u, uint16_t type, const OptionBuffer &buf)
Factory function to create instance of option.
static void setRuntimeOptionDefs(const OptionDefSpaceContainer &defs)
Copies option definitions created at runtime.
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 OptionDefContainerPtr getLastResortOptionDefs(const std::string &space)
Returns last resort option definitions for specified option space name.
static OptionDefContainerPtr getRuntimeOptionDefs(const std::string &space)
Returns runtime (non-standard) option definitions for specified option space name.
static void commitRuntimeOptionDefs()
Commits runtime option definitions.
static void clearRuntimeOptionDefs()
Removes runtime option definitions.
static void packOptions4(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options, bool top=false)
Stores DHCPv4 options in a buffer.
static void revertRuntimeOptionDefs()
Reverts uncommitted changes to runtime option definitions.
static const OptionDefContainerPtr getVendorOptionDefs(Option::Universe u, const uint32_t vendor_id)
Returns option definitions for given universe and vendor.
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 size_t unpackOptions6(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, size_t *relay_msg_offset=0, size_t *relay_msg_len=0)
Parses provided buffer as DHCPv6 options and creates Option objects.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
static size_t unpackVendorOptions4(const uint32_t vendor_id, const OptionBuffer &buf, isc::dhcp::OptionCollection &options)
Parses provided buffer as DHCPv4 vendor options and creates Option objects.
Class of option definition space container.
void addItem(const OptionDefinitionPtr &def)
Adds a new option definition to the container.
Base class representing a DHCP option definition.
std::list< Selector > getOptionSpaceNames() const
Get a list of existing option spaces.
ItemsContainerPtr getItems(const Selector &option_space) const
Get all items for the particular option space.
This class represents vendor-specific information option.
Universe
defines option universe DHCPv4 or DHCPv6
OptionPtr Factory(Option::Universe u, uint16_t type, const OptionBuffer &buf)
a factory function prototype
Exception thrown during option unpacking This exception is thrown when an error has occurred,...
Exception thrown during option unpacking This exception is thrown when an error has occurred unpackin...
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
This class implements set/commit mechanism for a single object.
#define DOCSIS3_V6_OPTION_SPACE
#define VENDOR_ID_CABLE_LABS
#define DOCSIS3_V4_OPTION_SPACE
global docsis3 option spaces
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
void initOptionSpace(OptionDefContainerPtr &defs, const OptionDefParams *params, size_t params_size)
const OptionDefContainerPtr null_option_def_container_(new OptionDefContainer())
@ DHO_VENDOR_ENCAPSULATED_OPTIONS
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
const OptionDefParams DOCSIS3_V4_OPTION_DEFINITIONS[]
Definitions of standard DHCPv4 options.
const char * DOCSIS3_CLASS_EROUTER
The class as specified in vendor-class option by the devices.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
const int DOCSIS3_V6_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.
const char * DOCSIS3_CLASS_MODEM
DOCSIS3.0 compatible cable modem.
std::map< std::string, OptionDefContainerPtr > OptionDefContainers
Container that holds option definitions for various option spaces.
OptionDefContainer::nth_index< 2 >::type OptionDefContainerNameIndex
Type of the index #2 - option name.
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.
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.
const int DOCSIS3_V4_OPTION_DEFINITIONS_SIZE
Number of option definitions defined.
OptionDefContainer::nth_index< 1 >::type OptionDefContainerTypeIndex
Type of the index #1 - option type.
boost::shared_ptr< Option > OptionPtr
const OptionDefParams DOCSIS3_V6_OPTION_DEFINITIONS[]
Definitions of standard DHCPv6 options.
boost::shared_ptr< OptionDefContainer > OptionDefContainerPtr
Pointer to an option definition container.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Defines the logger used by the top-level component of kea-lfc.
#define V4V6_BIND_OPTION_SPACE
#define LAST_RESORT_V4_OPTION_SPACE
#define DHCP4_OPTION_SPACE
global std option spaces
#define ISC_V6_OPTION_SPACE
#define V4V6_RULE_OPTION_SPACE
#define MAPE_V6_OPTION_SPACE
#define LW_V6_OPTION_SPACE
#define DHCP6_OPTION_SPACE
#define MAPT_V6_OPTION_SPACE
Encapsulation of option definition parameters and the structure size.
Parameters being used to make up an option definition.