25#include <boost/lexical_cast.hpp>
26#include <boost/shared_array.hpp>
27#include <boost/shared_ptr.hpp>
37std::map<unsigned short, Option::Factory*> LibDHCP::v4factories_;
40std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
84 if (v4option_defs_->empty()) {
86 initVendorOptsDocsis4();
88 initVendorOptsDocsis6();
89 initLastResortOptionDefs();
93 return (v4option_defs_);
96 return (v6option_defs_);
99 OptionDefContainers::const_iterator container = option_defs_.find(space);
100 if (container != option_defs_.end()) {
101 return (container->second);
111 initVendorOptsDocsis4();
114 VendorOptionDefContainers::const_iterator def = vendor4_defs_.find(vendor_id);
115 if (def == vendor4_defs_.end()) {
119 return (def->second);
127 initVendorOptsDocsis6();
130 if (vendor_id == ENTERPRISE_ID_ISC &&
131 vendor6_defs_.find(ENTERPRISE_ID_ISC) == vendor6_defs_.end()) {
132 initVendorOptsIsc6();
135 VendorOptionDefContainers::const_iterator def = vendor6_defs_.find(vendor_id);
136 if (def == vendor6_defs_.end()) {
140 return (def->second);
148 if (range.first != range.second) {
149 return (*range.first);
159 if (range.first != range.second) {
160 return (*range.first);
167 const std::string& name) {
177 if (range.first != range.second) {
178 return (*range.first);
185 const uint16_t code) {
198 if (range.first != range.second) {
199 return (*range.first);
209 if (range.first != range.second) {
210 return (*range.first);
221 if (range.first != range.second) {
222 return (*range.first);
230 return (runtime_option_defs_.getValue().getItems(space));
237 for (std::list<std::string>::const_iterator name = option_space_names.begin();
238 name != option_space_names.end(); ++name) {
240 for (OptionDefContainer::const_iterator def = container->begin();
241 def != container->end(); ++def) {
243 defs_copy.
addItem(def_copy, *name);
246 runtime_option_defs_ = defs_copy;
251 runtime_option_defs_.reset();
256 runtime_option_defs_.revert();
261 runtime_option_defs_.commit();
269 if (range.first != range.second) {
270 return (*range.first);
281 if (range.first != range.second) {
282 return (*range.first);
291 return (lastresort_defs_);
300 ((code >= 224) && (code <= 254))));
307 FactoryMap::iterator it;
309 it = v4factories_.find(type);
310 if (it == v4factories_.end()) {
312 "for DHCP v4 option type " << type);
315 it = v6factories_.find(type);
316 if (it == v6factories_.end()) {
318 "for DHCPv6 option type " << type);
322 "Option::V4 or Option::V6");
324 return (it->second(u, type, buf));
329 const std::string& option_space,
331 size_t* relay_msg_offset ,
332 size_t* relay_msg_len ) {
334 size_t length = buf.size();
335 size_t last_offset = 0;
354 while (offset < length) {
356 last_offset = offset;
359 if (offset + 4 > length) {
361 return (last_offset);
371 if (offset + opt_len > length) {
380 return (last_offset);
383 if (opt_type ==
D6O_RELAY_MSG && relay_msg_offset && relay_msg_len) {
385 *relay_msg_offset = offset;
386 *relay_msg_len = opt_len;
394 if (offset + 4 > length) {
398 return (last_offset);
403 buf.begin() + offset + opt_len));
404 options.insert(std::make_pair(opt_type, vendor_opt));
421 range = idx.equal_range(opt_type);
422 num_defs = std::distance(range.first, range.second);
428 range = runtime_idx.equal_range(opt_type);
429 num_defs = std::distance(range.first, range.second);
436 " definitions for option type " << opt_type <<
437 " returned. Currently it is not supported to initialize"
438 " multiple option definitions for the same option code."
439 " This will be supported once support for option spaces"
441 }
else if (num_defs == 0) {
448 buf.begin() + offset,
449 buf.begin() + offset + opt_len));
455 opt = def->optionFactory(
Option::V6, opt_type,
456 buf.begin() + offset,
457 buf.begin() + offset + opt_len);
460 options.insert(std::make_pair(opt_type, opt));
464 last_offset = offset;
465 return (last_offset);
469 const std::string& option_space,
471 std::list<uint16_t>& deferred) {
473 size_t last_offset = 0;
488 while (offset < buf.size()) {
490 last_offset = offset;
493 uint8_t opt_type = buf[offset++];
500 return (last_offset);
508 if (offset + 1 > buf.size()) {
516 return (last_offset);
519 uint8_t opt_len = buf[offset++];
520 if (offset + opt_len > buf.size()) {
525 return (last_offset);
540 range = idx.equal_range(opt_type);
541 num_defs = std::distance(range.first, range.second);
547 range = runtime_idx.equal_range(opt_type);
548 num_defs = std::distance(range.first, range.second);
554 deferred.push_back(opt_type);
561 " definitions for option type " <<
562 static_cast<int>(opt_type) <<
563 " returned. Currently it is not supported to initialize"
564 " multiple option definitions for the same option code."
565 " This will be supported once support for option spaces"
567 }
else if (num_defs == 0) {
569 buf.begin() + offset,
570 buf.begin() + offset + opt_len));
577 opt = def->optionFactory(
Option::V4, opt_type,
578 buf.begin() + offset,
579 buf.begin() + offset + opt_len);
582 options.insert(std::make_pair(opt_type, opt));
585 last_offset = offset;
586 return (last_offset);
593 size_t length = buf.size();
603 idx = &(option_defs->get<1>());
608 while (offset < length) {
609 if (offset + 4 > length) {
611 "Vendor option parse failed: truncated header");
620 if (offset + opt_len > length) {
622 "Vendor option parse failed. Tried to parse "
623 << offset + opt_len <<
" bytes from " << length
624 <<
"-byte long buffer.");
638 idx->equal_range(opt_type);
641 size_t num_defs = std::distance(range.first, range.second);
647 " definitions for option type " << opt_type <<
648 " returned. Currently it is not supported to"
649 " initialize multiple option definitions for the"
650 " same option code. This will be supported once"
651 " support for option spaces is implemented");
652 }
else if (num_defs == 1) {
657 opt = def->optionFactory(
Option::V6, opt_type,
658 buf.begin() + offset,
659 buf.begin() + offset + opt_len);
670 buf.begin() + offset,
671 buf.begin() + offset + opt_len));
676 options.insert(std::make_pair(opt_type, opt));
694 idx = &(option_defs->get<1>());
699 while (offset < buf.size()) {
703 uint8_t data_len = buf[offset++];
705 if (offset + data_len > buf.size()) {
708 "Attempt to parse truncated vendor option");
711 uint8_t offset_end = offset + data_len;
714 while (offset < offset_end) {
715 uint8_t opt_type = buf[offset++];
719 if (offset + 1 > offset_end) {
724 "Attempt to parse truncated vendor option "
725 <<
static_cast<int>(opt_type));
728 uint8_t opt_len = buf[offset++];
729 if (offset + opt_len > offset_end) {
731 "Option parse failed. Tried to parse "
732 << offset + opt_len <<
" bytes from " << buf.size()
733 <<
"-byte long buffer.");
746 idx->equal_range(opt_type);
749 size_t num_defs = std::distance(range.first, range.second);
755 " option definitions for option type "
756 << opt_type <<
" returned. Currently it is"
757 " not supported to initialize multiple option"
758 " definitions for the same option code."
759 " This will be supported once support for"
760 " option spaces is implemented");
761 }
else if (num_defs == 1) {
766 opt = def->optionFactory(
Option::V4, opt_type,
767 buf.begin() + offset,
768 buf.begin() + offset + opt_len);
774 buf.begin() + offset,
775 buf.begin() + offset + opt_len));
778 options.insert(std::make_pair(opt_type, opt));
793 for (OptionCollection::const_iterator it = options.begin();
794 it != options.end(); ++it) {
805 it->second->pack(buf);
824 for (OptionCollection::const_iterator it = options.begin();
825 it != options.end(); ++it) {
826 it->second->pack(buf);
835 if (v6factories_.find(opt_type) != v6factories_.end()) {
837 <<
"for option type " << opt_type);
839 v6factories_[opt_type]=factory;
852 if (opt_type > 254) {
855 if (v4factories_.find(opt_type)!=v4factories_.end()) {
857 <<
"for option type " << opt_type);
859 v4factories_[opt_type]=factory;
870LibDHCP::initStdOptionDefs4() {
872 STANDARD_V4_OPTION_DEFINITIONS_SIZE);
876LibDHCP::initStdOptionDefs6() {
878 STANDARD_V6_OPTION_DEFINITIONS_SIZE);
880 MAPE_V6_OPTION_DEFINITIONS_SIZE);
882 MAPT_V6_OPTION_DEFINITIONS_SIZE);
884 LW_V6_OPTION_DEFINITIONS_SIZE);
886 V4V6_RULE_OPTION_DEFINITIONS_SIZE);
888 V4V6_BIND_OPTION_DEFINITIONS_SIZE);
892LibDHCP::initLastResortOptionDefs() {
894 LAST_RESORT_V4_OPTION_DEFINITIONS_SIZE);
898LibDHCP::initVendorOptsDocsis4() {
904LibDHCP::initVendorOptsDocsis6() {
910LibDHCP::initVendorOptsIsc6() {
911 initOptionSpace(vendor6_defs_[ENTERPRISE_ID_ISC], ISC_V6_OPTION_DEFINITIONS,
912 ISC_V6_OPTION_DEFINITIONS_SIZE);
918 if ((option_space.size() < 8) || (option_space.substr(0,7) !=
"vendor-")) {
925 std::string x = option_space.substr(7);
927 check = boost::lexical_cast<int64_t>(x);
929 }
catch (
const boost::bad_lexical_cast &) {
933 if ((check < 0) || (check > std::numeric_limits<uint32_t>::max())) {
938 return (
static_cast<uint32_t
>(check));
943 size_t params_size) {
954 for (
size_t i = 0; i < params_size; ++i) {
955 std::string encapsulates(params[i].encapsulates);
956 if (!encapsulates.empty() && params[i].
array) {
958 <<
"option with code '" << params[i].code
959 <<
"' may not encapsulate option space '"
960 << encapsulates <<
"' because the definition"
961 <<
" indicates that this option comprises an array"
969 if (encapsulates.empty()) {
980 params[i].encapsulates));
984 for (
size_t rec = 0; rec < params[i].
records_size; ++rec) {
985 definition->addRecordField(params[i].records[rec]);
989 definition->validate();
998 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 void OptionFactoryRegister(Option::Universe u, uint16_t type, Option::Factory *factory)
Registers factory method that produces options of specific option types.
static const OptionDefContainerPtr & getOptionDefs(const std::string &space)
Returns collection of option definitions.
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 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 void packOptions4(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv4 options in a buffer.
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 const OptionDefContainerPtr & getVendorOption4Defs(const uint32_t vendor_id)
Returns v4 option definitions for a given vendor.
static void clearRuntimeOptionDefs()
Removes runtime option definitions.
static void revertRuntimeOptionDefs()
Reverts uncommitted changes to runtime option definitions.
static const OptionDefContainerPtr & getVendorOption6Defs(const uint32_t vendor_id)
Returns v6 option definitions for a given vendor.
static size_t unpackOptions4(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, std::list< uint16_t > &deferred)
Parses provided buffer as DHCPv4 options and creates Option objects.
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.
Base class representing a DHCP option definition.
void addItem(const ItemType &item, const Selector &option_space)
Adds a new item to the option_space.
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,...
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
This class implements set/commit mechanism for a single object.
#define VENDOR_ID_CABLE_LABS
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void initOptionSpace(OptionDefContainerPtr &defs, const OptionDefParams *params, size_t params_size)
const OptionDefContainerPtr null_option_def_container_(new OptionDefContainer())
@ DHO_VENDOR_ENCAPSULATED_OPTIONS
const int DOCSIS3_V6_DEFS_SIZE
Number of option definitions defined.
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
const char * DOCSIS3_CLASS_EROUTER
The class as specified in vendor-class option by the devices.
std::map< uint32_t, OptionDefContainerPtr > VendorOptionDefContainers
Container that holds various vendor option containers.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
const OptionDefParams DOCSIS3_V6_DEFS[]
Definitions of standard DHCPv6 options.
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.
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 > > > > OptionDefContainer
Multi index container for DHCP option definitions.
const int DOCSIS3_V4_DEFS_SIZE
Number of option definitions defined.
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.
const OptionDefParams DOCSIS3_V4_DEFS[]
Definitions of standard DHCPv4 options.
OptionDefContainer::nth_index< 1 >::type OptionDefContainerTypeIndex
Type of the index #1 - option type.
boost::shared_ptr< Option > OptionPtr
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.
#define V4V6_BIND_OPTION_SPACE
#define DHCP4_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
Parameters being used to make up an option definition.