// Iterate on the configured option list
for (CfgOptionList::const_iterator copts = co_list.begin();
copts != co_list.end(); ++copts) {
- OptionDescriptor desc = (*copts)->get("dhcp4", *opt);
+ OptionDescriptor desc = (*copts)->get(DHCP4_OPTION_SPACE, *opt);
// Got it: add it and jump to the outer loop
if (desc.option_) {
resp->addOption(desc.option_);
const CfgOptionList& co_list = ex.getCfgOptionList();
for (CfgOptionList::const_iterator copts = co_list.begin();
copts != co_list.end(); ++copts) {
- OptionDescriptor desc = (*copts)->get("dhcp4", DHO_BOOT_FILE_NAME);
+ OptionDescriptor desc = (*copts)->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
if (desc.option_) {
boost::shared_ptr<OptionString> boot =
// Iterate on the configured option list
for (CfgOptionList::const_iterator copts = co_list.begin();
copts != co_list.end(); ++copts) {
- OptionDescriptor desc = (*copts)->get("dhcp6", opt);
+ OptionDescriptor desc = (*copts)->get(DHCP6_OPTION_SPACE, opt);
// Got it: add it and jump to the outer loop
if (desc.option_) {
answer->addOption(desc.option_);
}
if (!code) {
- OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, option_str);
+ const OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6,
+ option_str, DHCP6_OPTION_SPACE);
if (def) {
code = def->getCode();
} else {
#define D6O_CLIENT_ARCH_TYPE 61 /* RFC5970 */
#define D6O_NII 62 /* RFC5970 */
//#define D6O_GEOLOCATION 63 /* RFC6225 */
-//#define D6O_AFTR_NAME 64 /* RFC6334 */
+#define D6O_AFTR_NAME 64 /* RFC6334 */
#define D6O_ERP_LOCAL_DOMAIN_NAME 65 /* RFC6440 */
#define D6O_RSOO 66 /* RFC6422 */
//#define D6O_PD_EXCLUDE 67 /* RFC6603 */
//#define D6O_V6_PCP_SERVER 86 /* RFC7291 */
#define D6O_DHCPV4_MSG 87 /* RFC7341 */
#define D6O_DHCPV4_O_DHCPV6_SERVER 88 /* RFC7341 */
-//#define D6O_S46_RULE 89 /* RFC7598 */
-//#define D6O_S46_BR 90 /* RFC7598 */
-//#define D6O_S46_DMR 91 /* RFC7598 */
-//#define D6O_S46_V4V6BIND 92 /* RFC7598 */
-//#define D6O_S46_PORTPARAMS 93 /* RFC7598 */
-//#define D6O_S46_CONT_MAPE 94 /* RFC7598 */
-//#define D6O_S46_CONT_MAPT 95 /* RFC7598 */
-//#define D6O_S46_CONT_LW 96 /* RFC7598 */
+#define D6O_S46_RULE 89 /* RFC7598 */
+#define D6O_S46_BR 90 /* RFC7598 */
+#define D6O_S46_DMR 91 /* RFC7598 */
+#define D6O_S46_V4V6BIND 92 /* RFC7598 */
+#define D6O_S46_PORTPARAMS 93 /* RFC7598 */
+#define D6O_S46_CONT_MAPE 94 /* RFC7598 */
+#define D6O_S46_CONT_MAPT 95 /* RFC7598 */
+#define D6O_S46_CONT_LW 96 /* RFC7598 */
//#define D6O_4RD 97 /* RFC7600 */
//#define D6O_4RD_MAP_RULE 98 /* RFC7600 */
//#define D6O_4RD_NON_MAP_RULE 99 /* RFC7600 */
};
/// Number of option definitions defined.
-const int DOCSIS3_V6_DEFS_SIZE = sizeof(DOCSIS3_V6_DEFS) / sizeof(OptionDefParams);
+const int DOCSIS3_V6_DEFS_SIZE =
+ sizeof(DOCSIS3_V6_DEFS) / sizeof(DOCSIS3_V6_DEFS[0]);
/// The class as specified in vendor-class option by the devices
extern const char* DOCSIS3_CLASS_EROUTER;
using namespace isc::dhcp;
using namespace isc::util;
+namespace isc {
+namespace dhcp {
+
+namespace {
+
+const OptionDefParamsEncapsulation OPTION_DEF_PARAMS[] = {
+ { STANDARD_V4_OPTION_DEFINITIONS, STANDARD_V4_OPTION_DEFINITIONS_SIZE, DHCP4_OPTION_SPACE },
+ { STANDARD_V6_OPTION_DEFINITIONS, STANDARD_V6_OPTION_DEFINITIONS_SIZE, DHCP6_OPTION_SPACE },
+ { DOCSIS3_V4_DEFS, DOCSIS3_V4_DEFS_SIZE, DOCSIS3_V4_OPTION_SPACE },
+ { DOCSIS3_V6_DEFS, DOCSIS3_V6_DEFS_SIZE, DOCSIS3_V6_OPTION_SPACE },
+ { ISC_V6_OPTION_DEFINITIONS, ISC_V6_OPTION_DEFINITIONS_SIZE, ISC_V6_OPTION_SPACE },
+ { MAPE_V6_OPTION_DEFINITIONS, MAPE_V6_OPTION_DEFINITIONS_SIZE, MAPE_V6_OPTION_SPACE },
+ { MAPT_V6_OPTION_DEFINITIONS, MAPT_V6_OPTION_DEFINITIONS_SIZE, MAPT_V6_OPTION_SPACE },
+ { LW_V6_OPTION_DEFINITIONS, LW_V6_OPTION_DEFINITIONS_SIZE, LW_V6_OPTION_SPACE },
+ { V4V6_RULE_OPTION_DEFINITIONS, V4V6_RULE_OPTION_DEFINITIONS_SIZE, V4V6_RULE_OPTION_SPACE },
+ { V4V6_BIND_OPTION_DEFINITIONS, V4V6_BIND_OPTION_DEFINITIONS_SIZE, V4V6_BIND_OPTION_SPACE },
+ { NULL, 0, "" }
+};
+
+} // unnamed namespace
+
+} // namespace dhcp
+} // namespace isc
+
// static array with factories for options
std::map<unsigned short, Option::Factory*> LibDHCP::v4factories_;
// Static container with DHCPv6 option definitions.
OptionDefContainerPtr LibDHCP::v6option_defs_(new OptionDefContainer());
+// Container that maps option spaces to option definitions.
+std::map<std::string, OptionDefContainerPtr> LibDHCP::option_defs_;
+
VendorOptionDefContainers LibDHCP::vendor4_defs_;
VendorOptionDefContainers LibDHCP::vendor6_defs_;
const OptionDefParams* params,
size_t params_size);
-const OptionDefContainerPtr&
-LibDHCP::getOptionDefs(const Option::Universe u) {
- switch (u) {
- case Option::V4:
- if (v4option_defs_->empty()) {
- initStdOptionDefs4();
- initVendorOptsDocsis4();
- }
- return (v4option_defs_);
- case Option::V6:
- if (v6option_defs_->empty()) {
- initStdOptionDefs6();
- initVendorOptsDocsis6();
- }
- return (v6option_defs_);
- default:
- isc_throw(isc::BadValue, "invalid universe " << u << " specified");
- }
-}
-
-const OptionDefContainerPtr&
-LibDHCP::getVendorOption4Defs(const uint32_t vendor_id) {
-
- if (vendor_id == VENDOR_ID_CABLE_LABS &&
- vendor4_defs_.find(VENDOR_ID_CABLE_LABS) == vendor4_defs_.end()) {
- initVendorOptsDocsis4();
- }
-
- VendorOptionDefContainers::const_iterator def = vendor4_defs_.find(vendor_id);
- if (def == vendor4_defs_.end()) {
- // No such vendor-id space
- return (null_option_def_container_);
+const OptionDefContainerPtr
+LibDHCP::getOptionDefs(const Option::Universe, const std::string& space) {
+ if (option_defs_.end() == option_defs_.find(space)) {
+ // First time initialization of the options for this space.
+ initStdOptionDefs(space);
}
- return (def->second);
+ return option_defs_[space];
}
-const OptionDefContainerPtr&
-LibDHCP::getVendorOption6Defs(const uint32_t vendor_id) {
-
- if (vendor_id == VENDOR_ID_CABLE_LABS &&
- vendor6_defs_.find(VENDOR_ID_CABLE_LABS) == vendor6_defs_.end()) {
- initVendorOptsDocsis6();
- }
-
- if (vendor_id == ENTERPRISE_ID_ISC &&
- vendor6_defs_.find(ENTERPRISE_ID_ISC) == vendor6_defs_.end()) {
- initVendorOptsIsc6();
- }
-
- VendorOptionDefContainers::const_iterator def = vendor6_defs_.find(vendor_id);
- if (def == vendor6_defs_.end()) {
- // No such vendor-id space
- return (null_option_def_container_);
+const OptionDefContainerPtr
+LibDHCP::getVendorOptionDefs(const Option::Universe u, const uint32_t vendor_id) {
+ if (Option::V4 == u) {
+ if (VENDOR_ID_CABLE_LABS == vendor_id) {
+ return getOptionDefs( Option::V4, DOCSIS3_V4_OPTION_SPACE );
+ }
+ } else if (Option::V6 == u) {
+ if (VENDOR_ID_CABLE_LABS == vendor_id) {
+ return getOptionDefs( Option::V6, DOCSIS3_V6_OPTION_SPACE );
+ } else if (ENTERPRISE_ID_ISC == vendor_id) {
+ return getOptionDefs( Option::V6, ISC_V6_OPTION_SPACE );
+ }
}
- return (def->second);
+ return OptionDefContainerPtr();
}
OptionDefinitionPtr
-LibDHCP::getOptionDef(const Option::Universe u, const uint16_t code) {
- const OptionDefContainerPtr& defs = getOptionDefs(u);
- const OptionDefContainerTypeIndex& idx = defs->get<1>();
+LibDHCP::getOptionDef(const Option::Universe u, const uint16_t code, const std::string& space) {
+ const OptionDefContainerPtr option_defs_ptr = getOptionDefs(u, space);
+ if (!option_defs_ptr) {
+ return (OptionDefinitionPtr());
+ }
+ const OptionDefContainerTypeIndex& idx = option_defs_ptr->get<1>();
const OptionDefContainerTypeRange& range = idx.equal_range(code);
if (range.first != range.second) {
return (*range.first);
}
OptionDefinitionPtr
-LibDHCP::getOptionDef(const Option::Universe u, const std::string& name) {
- const OptionDefContainerPtr defs = getOptionDefs(u);
- const OptionDefContainerNameIndex& idx = defs->get<2>();
+LibDHCP::getOptionDef(const Option::Universe u, const std::string& name, const std::string& space) {
+ const OptionDefContainerPtr option_defs_ptr = getOptionDefs(u, space);
+ if (!option_defs_ptr) {
+ return (OptionDefinitionPtr());
+ }
+ const OptionDefContainerNameIndex& idx = option_defs_ptr->get<2>();
const OptionDefContainerNameRange& range = idx.equal_range(name);
if (range.first != range.second) {
return (*range.first);
}
return (OptionDefinitionPtr());
-
}
-
OptionDefinitionPtr
LibDHCP::getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id,
const std::string& name) {
- OptionDefContainerPtr defs = (u == Option::V4 ? getVendorOption4Defs(vendor_id) :
- getVendorOption6Defs(vendor_id));
+ const OptionDefContainerPtr option_defs_ptr = getVendorOptionDefs(u, vendor_id);
- if (!defs) {
+ if (!option_defs_ptr) {
return (OptionDefinitionPtr());
}
- const OptionDefContainerNameIndex& idx = defs->get<2>();
+ const OptionDefContainerNameIndex& idx = option_defs_ptr->get<2>();
const OptionDefContainerNameRange& range = idx.equal_range(name);
if (range.first != range.second) {
return (*range.first);
OptionDefinitionPtr
LibDHCP::getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id,
const uint16_t code) {
- OptionDefContainerPtr defs = (u == Option::V4 ? getVendorOption4Defs(vendor_id) :
- getVendorOption6Defs(vendor_id));
+ const OptionDefContainerPtr option_defs_ptr =
+ getVendorOptionDefs(u, vendor_id);
- if (!defs) {
+ if (!option_defs_ptr) {
// Weird universe or unknown vendor_id. We don't care. No definitions
// one way or another
// What is it anyway?
return (OptionDefinitionPtr());
}
- const OptionDefContainerTypeIndex& idx = defs->get<1>();
+ const OptionDefContainerTypeIndex& idx = option_defs_ptr->get<1>();
const OptionDefContainerTypeRange& range = idx.equal_range(code);
if (range.first != range.second) {
return (*range.first);
size_t last_offset = 0;
// Get the list of standard option definitions.
- const OptionDefContainerPtr& option_defs = LibDHCP::getOptionDefs(Option::V6);
- // Runtime option definitions for non standard option space and if
- // the definition doesn't exist within the standard option definitions.
- const OptionDefContainerPtr& runtime_option_defs = LibDHCP::getRuntimeOptionDefs(option_space);
-
- // @todo Once we implement other option spaces we should add else clause
- // here and gather option definitions for them. For now leaving option_defs
- // empty will imply creation of generic Option.
+ OptionDefContainer option_defs;
+ const OptionDefContainerPtr option_defs_ptr
+ = LibDHCP::getOptionDefs(Option::V6, option_space);
+ OptionDefContainer runtime_option_defs;
+ const OptionDefContainerPtr runtime_option_defs_ptr
+ = LibDHCP::getRuntimeOptionDefs(option_space);
+ if (option_defs_ptr) {
+ option_defs = *option_defs_ptr;
+ }
+ if (runtime_option_defs_ptr) {
+ runtime_option_defs = *runtime_option_defs_ptr;
+ }
// Get the search indexes #1. It allows to search for option definitions
// using option code.
- const OptionDefContainerTypeIndex& idx = option_defs->get<1>();
- const OptionDefContainerTypeIndex& runtime_idx = runtime_option_defs->get<1>();
+ const OptionDefContainerTypeIndex& idx = option_defs.get<1>();
+ const OptionDefContainerTypeIndex& runtime_idx = runtime_option_defs.get<1>();
// The buffer being read comprises a set of options, each starting with
// a two-byte type code and a two-byte length field.
size_t last_offset = 0;
// Get the list of standard option definitions.
- const OptionDefContainerPtr& option_defs = LibDHCP::getOptionDefs(Option::V4);
- // Runtime option definitions for non standard option space and if
- // the definition doesn't exist within the standard option definitions.
- const OptionDefContainerPtr& runtime_option_defs = LibDHCP::getRuntimeOptionDefs(option_space);
+ OptionDefContainer option_defs;
+ const OptionDefContainerPtr option_defs_ptr
+ = LibDHCP::getOptionDefs(Option::V4, option_space);
+ OptionDefContainer runtime_option_defs;
+ const OptionDefContainerPtr runtime_option_defs_ptr
+ = LibDHCP::getRuntimeOptionDefs(option_space);
+ if (option_defs_ptr) {
+ option_defs = *option_defs_ptr;
+ }
+ if (runtime_option_defs_ptr) {
+ runtime_option_defs = *runtime_option_defs_ptr;
+ }
// Get the search indexes #1. It allows to search for option definitions
// using option code.
- const OptionDefContainerTypeIndex& idx = option_defs->get<1>();
- const OptionDefContainerTypeIndex& runtime_idx = runtime_option_defs->get<1>();
+ const OptionDefContainerTypeIndex& idx = option_defs.get<1>();
+ const OptionDefContainerTypeIndex& runtime_idx = runtime_option_defs.get<1>();
// The buffer being read comprises a set of options, each starting with
// a one-byte type code and a one-byte length field.
size_t length = buf.size();
// Get the list of option definitions for this particular vendor-id
- const OptionDefContainerPtr& option_defs = LibDHCP::getVendorOption6Defs(vendor_id);
+ const OptionDefContainerPtr option_defs_ptr =
+ LibDHCP::getVendorOptionDefs(Option::V6, vendor_id);
// Get the search index #1. It allows to search for option definitions
// using option code. If there's no such vendor-id space, we're out of luck
// anyway.
const OptionDefContainerTypeIndex* idx = NULL;
- if (option_defs) {
- idx = &(option_defs->get<1>());
+ if (option_defs_ptr) {
+ idx = &(option_defs_ptr->get<1>());
}
// The buffer being read comprises a set of options, each starting with
size_t offset = 0;
// Get the list of stdandard option definitions.
- const OptionDefContainerPtr& option_defs = LibDHCP::getVendorOption4Defs(vendor_id);
+ const OptionDefContainerPtr option_defs_ptr =
+ LibDHCP::getVendorOptionDefs(Option::V4, vendor_id);
// Get the search index #1. It allows to search for option definitions
// using option code.
const OptionDefContainerTypeIndex* idx = NULL;
- if (option_defs) {
- idx = &(option_defs->get<1>());
+ if (option_defs_ptr) {
+ idx = &(option_defs_ptr->get<1>());
}
// The buffer being read comprises a set of options, each starting with
return;
}
-void
-LibDHCP::initStdOptionDefs4() {
- initOptionSpace(v4option_defs_, OPTION_DEF_PARAMS4, OPTION_DEF_PARAMS_SIZE4);
-}
-
-void
-LibDHCP::initStdOptionDefs6() {
- initOptionSpace(v6option_defs_, OPTION_DEF_PARAMS6, OPTION_DEF_PARAMS_SIZE6);
-}
-
-void
-LibDHCP::initVendorOptsDocsis4() {
- initOptionSpace(vendor4_defs_[VENDOR_ID_CABLE_LABS], DOCSIS3_V4_DEFS, DOCSIS3_V4_DEFS_SIZE);
-}
-
-void
-LibDHCP::initVendorOptsDocsis6() {
- initOptionSpace(vendor6_defs_[VENDOR_ID_CABLE_LABS], DOCSIS3_V6_DEFS, DOCSIS3_V6_DEFS_SIZE);
-}
-
-void
-LibDHCP::initVendorOptsIsc6() {
- initOptionSpace(vendor6_defs_[ENTERPRISE_ID_ISC], ISC_V6_DEFS, ISC_V6_DEFS_SIZE);
+void LibDHCP::initStdOptionDefs(const std::string &space) {
+ if (option_defs_.end() == option_defs_.find(space)) {
+ option_defs_[space] = OptionDefContainerPtr(new OptionDefContainer);
+ for (int i = 0; OPTION_DEF_PARAMS[i].optionDefParams; i++) {
+ if (space == OPTION_DEF_PARAMS[i].space) {
+ initOptionSpace(option_defs_[space], OPTION_DEF_PARAMS[i].optionDefParams, OPTION_DEF_PARAMS[i].size);
+ break;
+ }
+ }
+ }
}
uint32_t
/// @param u universe of the options (V4 or V6).
///
/// @return Pointer to a collection of option definitions.
- static const OptionDefContainerPtr& getOptionDefs(const Option::Universe u);
+ static const OptionDefContainerPtr getOptionDefs(const Option::Universe u,
+ const std::string& space);
/// @brief Return the first option definition matching a
/// particular option code.
/// @return reference to an option definition being requested
/// or NULL pointer if option definition has not been found.
static OptionDefinitionPtr getOptionDef(const Option::Universe u,
- const uint16_t code);
+ const uint16_t code,
+ const std::string& space);
/// @brief Return the definition of option having a specified name.
///
/// @return Pointer to the option definition or NULL pointer if option
/// definition has not been found.
static OptionDefinitionPtr getOptionDef(const Option::Universe u,
- const std::string& name);
+ const std::string& name,
+ const std::string& space);
/// @brief Returns vendor option definition for a given vendor-id and code
///
uint16_t type,
Option::Factory * factory);
- /// @brief Returns v4 option definitions for a given vendor
+ /// @brief Returns option definitions for given universe and vendor
///
/// @param vendor_id enterprise-id of a given vendor
/// @return a container for a given vendor (or NULL if no option
/// definitions are defined)
- static const OptionDefContainerPtr&
- getVendorOption4Defs(const uint32_t vendor_id);
-
- /// @brief Returns v6 option definitions for a given vendor
- ///
- /// @param vendor_id enterprise-id of a given vendor
- /// @return a container for a given vendor (or NULL if no option
- /// definitions are defined)
- static const OptionDefContainerPtr&
- getVendorOption6Defs(const uint32_t vendor_id);
+ static const OptionDefContainerPtr
+ getVendorOptionDefs(Option::Universe u, const uint32_t vendor_id);
/// @brief Parses provided buffer as DHCPv6 vendor options and creates
/// Option objects.
static uint32_t optionSpaceToVendorId(const std::string& option_space);
private:
-
- /// Initialize standard DHCPv4 option definitions.
- ///
- /// The method creates option definitions for all DHCPv4 options.
- /// Currently this function is not implemented.
- ///
- /// @throw std::bad alloc if system went out of memory.
- /// @throw MalformedOptionDefinition if any of the definitions
- /// are incorrect. This is programming error.
- static void initStdOptionDefs4();
-
- /// Initialize standard DHCPv6 option definitions.
- ///
- /// The method creates option definitions for all DHCPv6 options.
- ///
- /// @throw std::bad_alloc if system went out of memory.
- /// @throw MalformedOptionDefinition if any of the definitions
- /// is incorrect. This is a programming error.
- static void initStdOptionDefs6();
-
- static void initVendorOptsDocsis4();
-
- static void initVendorOptsDocsis6();
-
- /// Initialize private DHCPv6 option definitions.
- static void initVendorOptsIsc6();
+ static void initStdOptionDefs(const std::string& space);
/// pointers to factories that produce DHCPv6 options
static FactoryMap v4factories_;
/// Container with DHCPv6 option definitions.
static OptionDefContainerPtr v6option_defs_;
+ // Container that maps option spaces to option definitions.
+ static std::map<std::string, OptionDefContainerPtr> option_defs_;
+
/// Container for v4 vendor option definitions
static VendorOptionDefContainers vendor4_defs_;
OPT_ANY_ADDRESS_TYPE,
OPT_IPV4_ADDRESS_TYPE,
OPT_IPV6_ADDRESS_TYPE,
+ OPT_IPV6_PREFIX_TYPE,
OPT_STRING_TYPE,
OPT_FQDN_TYPE,
OPT_RECORD_TYPE,
OPT_UNKNOWN_TYPE
};
+/// @brief Parameters being used to make up an option definition.
+struct OptionDefParams {
+ const char* name; // option name
+ uint16_t code; // option code
+ OptionDataType type; // data type
+ bool array; // is array
+ const OptionDataType* records; // record fields
+ size_t records_size; // number of fields in a record
+ const char* encapsulates; // option space encapsulated by the
+ // particular option.
+};
+
+/// @brief Encapsulation of option definition parameters and the structure size.
+struct OptionDefParamsEncapsulation {
+ const struct OptionDefParams* optionDefParams; // parameters structure
+ const int size; // structure size
+ const char* space; // option space
+};
+
/// @brief Trait class for data types supported in DHCP option definitions.
///
/// This is useful to check whether the type specified as template parameter
///
/// @param buf input buffer.
/// @param family address family: AF_INET or AF_INET6.
- ///
+ ///
/// @throw isc::dhcp::BadDataTypeCast when the data being read
/// is truncated.
/// @return address being read.
#include <dhcp/option_int.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_opaque_data_tuples.h>
-#include <dhcp/option_space.h>
#include <dhcp/option_string.h>
#include <dhcp/option_vendor.h>
#include <dhcp/option_vendor_class.h>
#include <util/strutil.h>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/dynamic_bitset.hpp>
using namespace std;
using namespace isc::util;
OptionDataTypeUtil::writeAddress(address, buf);
return;
}
+ case OPT_IPV6_PREFIX_TYPE:
+ {
+ std::string txt = value;
+
+ // first let's remove any whitespaces
+ boost::erase_all(txt, " "); // space
+ boost::erase_all(txt, "\t"); // tabulation
+
+ // Is this prefix/len notation?
+ size_t pos = txt.find("/");
+
+ if (pos == string::npos) {
+ isc_throw(BadDataTypeCast, "provided address/prefix "
+ << value
+ << " is not valid.");
+ }
+
+ std::string txt_address = txt.substr(0, pos);
+ isc::asiolink::IOAddress address = isc::asiolink::IOAddress(txt_address);
+ if (!address.isV6()) {
+ isc_throw(BadDataTypeCast, "provided address "
+ << txt_address
+ << " is not a valid IPv4 or IPv6 address.");
+ }
+
+ std::string txt_prefix = txt.substr(pos + 1);
+ uint8_t len = 0;
+ try {
+ // start with the first character after /
+ len = lexicalCastWithRangeCheck<uint8_t>(txt_prefix);
+ } catch (...) {
+ isc_throw(BadDataTypeCast, "provided prefix "
+ << txt_prefix
+ << " is not valid.");
+ }
+
+ // Write the prefix length
+ OptionDataTypeUtil::writeInt<uint8_t>(len, buf);
+
+ std::vector<uint8_t> addrV6 = address.toBytes();
+ boost::dynamic_bitset<uint8_t> bits(addrV6.rbegin(), addrV6.rend());
+
+ uint8_t lenBytes = (len + 7) / 8;
+ for (size_t idx = 0; idx < lenBytes; idx++) {
+ boost::dynamic_bitset<uint8_t> tmp = bits >> 120;
+ uint8_t val = static_cast<uint8_t>(tmp.to_ulong());
+
+ //Zero padded bits follow when the prefix len is not divided exactly by 8
+ if (idx == lenBytes - 1) {
+ uint8_t unusedBits = 0xFF;
+ unusedBits <<= (8 - (len % 8)) % 8;
+ val = val & unusedBits;
+ }
+ bits = bits << 8;
+ // Write prefix data
+ OptionDataTypeUtil::writeInt<uint8_t>(val, buf);
+ }
+
+ return;
+ }
case OPT_STRING_TYPE:
OptionDataTypeUtil::writeString(value, buf);
return;
#include <dhcp/libdhcp++.h>
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
+#include <dhcp/option_space.h>
#include <util/io_utilities.h>
#include <stdint.h>
if (!OptionDataTypeTraits<T>::integer_type) {
isc_throw(dhcp::InvalidDataType, "non-integer type");
}
- setEncapsulatedSpace(u == Option::V4 ? "dhcp4" : "dhcp6");
+ setEncapsulatedSpace(u == Option::V4 ? DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE);
}
/// @brief Constructor.
if (!OptionDataTypeTraits<T>::integer_type) {
isc_throw(dhcp::InvalidDataType, "non-integer type");
}
- setEncapsulatedSpace(u == Option::V4 ? "dhcp4" : "dhcp6");
+ setEncapsulatedSpace(u == Option::V4 ? DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE);
unpack(begin, end);
}
#include <stdint.h>
#include <string>
-#define DHCP4_OPTION_SPACE "dhcp4"
-#define DHCP6_OPTION_SPACE "dhcp6"
+#define DHCP4_OPTION_SPACE "dhcp4"
+#define DHCP6_OPTION_SPACE "dhcp6"
+#define DOCSIS3_V4_OPTION_SPACE "docsis3_v4"
+#define DOCSIS3_V6_OPTION_SPACE "docsis3_v6"
+#define ISC_V6_OPTION_SPACE "4o6"
+#define MAPE_V6_OPTION_SPACE "4over6-mape"
+#define MAPT_V6_OPTION_SPACE "4over6-mapt"
+#define LW_V6_OPTION_SPACE "4over6-lw"
+#define V4V6_RULE_OPTION_SPACE "v4v6rule"
+#define V4V6_BIND_OPTION_SPACE "v4v6bind"
namespace isc {
namespace dhcp {
void setVendorSpace(const uint32_t enterprise_number);
private:
-
+
uint32_t enterprise_number_; ///< IANA assigned enterprise number.
};
// a vector as an input.
buffer_in.readVector(opts_buffer, opts_len);
- size_t offset = LibDHCP::unpackOptions4(opts_buffer, "dhcp4", options_);
+ size_t offset = LibDHCP::unpackOptions4(opts_buffer, DHCP4_OPTION_SPACE, options_);
// If offset is not equal to the size and there is no DHO_END,
// then something is wrong here. We either parsed past input
// If custom option parsing function has been set, use this function
// to parse options. Otherwise, use standard function from libdhcp.
- size_t offset = LibDHCP::unpackOptions6(opt_buffer, "dhcp6", options_);
+ size_t offset = LibDHCP::unpackOptions6(opt_buffer, DHCP6_OPTION_SPACE, options_);
// If offset is not equal to the size, then something is wrong here. We
// either parsed past input buffer (bug in our code) or we haven't parsed
// If custom option parsing function has been set, use this function
// to parse options. Otherwise, use standard function from libdhcp.
- LibDHCP::unpackOptions6(opt_buffer, "dhcp6", relay.options_,
+ LibDHCP::unpackOptions6(opt_buffer, DHCP6_OPTION_SPACE, relay.options_,
&relay_msg_offset, &relay_msg_len);
/// @todo: check that each option appears at most once
#include <dhcp/option_data_types.h>
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
+#include <dhcp/option_space.h>
namespace isc {
namespace dhcp {
#define NO_RECORD_DEF 0, 0
#endif
-/// @brief Parameters being used to make up an option definition.
-struct OptionDefParams {
- const char* name; // option name
- uint16_t code; // option code
- OptionDataType type; // data type
- bool array; // is array
- const OptionDataType* records; // record fields
- size_t records_size; // number of fields in a record
- const char* encapsulates; // option space encapsulated by
- // the particular option.
-};
-
// fqdn option record fields.
//
// Note that the flags field indicates the type of domain
RECORD_DECL(UUID_GUID_RECORDS, OPT_UINT8_TYPE, OPT_BINARY_TYPE);
/// @brief Definitions of standard DHCPv4 options.
-const OptionDefParams OPTION_DEF_PARAMS4[] = {
+const OptionDefParams STANDARD_V4_OPTION_DEFINITIONS[] = {
{ "subnet-mask", DHO_SUBNET_MASK, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
{ "time-offset", DHO_TIME_OFFSET, OPT_INT32_TYPE, false, NO_RECORD_DEF, "" },
{ "routers", DHO_ROUTERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
};
/// Number of option definitions defined.
-const int OPTION_DEF_PARAMS_SIZE4 =
- sizeof(OPTION_DEF_PARAMS4) / sizeof(OPTION_DEF_PARAMS4[0]);
-
+const int STANDARD_V4_OPTION_DEFINITIONS_SIZE =
+ sizeof(STANDARD_V4_OPTION_DEFINITIONS) / sizeof(STANDARD_V4_OPTION_DEFINITIONS[0]);
/// Start Definition of DHCPv6 options
RECORD_DECL(LQ_RELAY_DATA_RECORDS, OPT_IPV6_ADDRESS_TYPE, OPT_BINARY_TYPE);
// remote-id
RECORD_DECL(REMOTE_ID_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE);
+// s46-rule
+RECORD_DECL(S46_RULE, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
+ OPT_IPV4_ADDRESS_TYPE, OPT_IPV6_PREFIX_TYPE);
+// s46-v4v6bind
+RECORD_DECL(S46_V4V6BIND, OPT_IPV4_ADDRESS_TYPE, OPT_IPV6_PREFIX_TYPE);
+// s46-portparams
+RECORD_DECL(S46_PORTPARAMS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT16_TYPE);
// status-code
RECORD_DECL(STATUS_CODE_RECORDS, OPT_UINT16_TYPE, OPT_STRING_TYPE);
// vendor-class
/// This however does not work on Solaris (GCC) which issues a
/// warning about lack of initializers for some struct members
/// causing build to fail.
-const OptionDefParams OPTION_DEF_PARAMS6[] = {
+const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
{ "clientid", D6O_CLIENTID, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
{ "serverid", D6O_SERVERID, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
{ "ia-na", D6O_IA_NA, OPT_RECORD_TYPE, false, RECORD_DEF(IA_NA_RECORDS), "" },
{ "signature", D6O_SIGNATURE, OPT_RECORD_TYPE, false,
RECORD_DEF(SIGNATURE_RECORDS), "" },
{ "timestamp", D6O_TIMESTAMP, OPT_BINARY_TYPE, false,
- NO_RECORD_DEF, "" }
+ NO_RECORD_DEF, "" },
+ { "aftr-name", D6O_AFTR_NAME, OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" },
+ { "s46-cont-mape", D6O_S46_CONT_MAPE, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, MAPE_V6_OPTION_SPACE },
+ { "s46-cont-mapt", D6O_S46_CONT_MAPT, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, MAPT_V6_OPTION_SPACE },
+ { "s46-cont-lw", D6O_S46_CONT_LW, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, LW_V6_OPTION_SPACE }
// @todo There is still a bunch of options for which we have to provide
// definitions but we don't do it because they are not really
};
/// Number of option definitions defined.
-const int OPTION_DEF_PARAMS_SIZE6 =
- sizeof(OPTION_DEF_PARAMS6) / sizeof(OPTION_DEF_PARAMS6[0]);
+const int STANDARD_V6_OPTION_DEFINITIONS_SIZE =
+ sizeof(STANDARD_V6_OPTION_DEFINITIONS) / sizeof(STANDARD_V6_OPTION_DEFINITIONS[0]);
/// @brief Definitions of vendor-specific DHCPv6 options, defined by ISC.
/// 4o6-* options are used for inter-process communication. For details, see
///
/// @todo: As those options are defined by ISC, they do not belong in std_option_defs.h.
/// We need to move them to a separate file, e.g. isc_option_defs.h
-const OptionDefParams ISC_V6_DEFS[] = {
+const OptionDefParams ISC_V6_OPTION_DEFINITIONS[] = {
{ "4o6-interface", ISC_V6_4O6_INTERFACE, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
{ "4o6-source-address", ISC_V6_4O6_SRC_ADDRESS, OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }
};
-const int ISC_V6_DEFS_SIZE = sizeof(ISC_V6_DEFS) / sizeof(OptionDefParams);
+const int ISC_V6_OPTION_DEFINITIONS_SIZE =
+ sizeof(ISC_V6_OPTION_DEFINITIONS) / sizeof(ISC_V6_OPTION_DEFINITIONS[0]);
+
+/// @brief MAPE option definitions
+/// @todo: Maybe move this to a separate file, e.g. mape_option_defs.h
+const OptionDefParams MAPE_V6_OPTION_DEFINITIONS[] = {
+ { "s46-br", D6O_S46_BR, OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
+ { "s46-rule", D6O_S46_RULE, OPT_RECORD_TYPE, false, RECORD_DEF(S46_RULE), V4V6_RULE_OPTION_SPACE }
+};
+
+const int MAPE_V6_OPTION_DEFINITIONS_SIZE =
+ sizeof(MAPE_V6_OPTION_DEFINITIONS) / sizeof(MAPE_V6_OPTION_DEFINITIONS[0]);
+
+/// @brief MAPT option definitions
+/// @todo: Maybe move this to a separate file, e.g. mapt_option_defs.h
+const OptionDefParams MAPT_V6_OPTION_DEFINITIONS[] = {
+ { "s46-rule", D6O_S46_RULE, OPT_RECORD_TYPE, false, RECORD_DEF(S46_RULE), V4V6_RULE_OPTION_SPACE },
+ { "s46-dmr", D6O_S46_DMR, OPT_IPV6_PREFIX_TYPE, false, NO_RECORD_DEF, "" },
+};
+
+const int MAPT_V6_OPTION_DEFINITIONS_SIZE =
+ sizeof(MAPT_V6_OPTION_DEFINITIONS) / sizeof(MAPT_V6_OPTION_DEFINITIONS[0]);
+
+/// @brief LW option definitions
+/// @todo: Maybe move this to a separate file, e.g. lw_option_defs.h
+const OptionDefParams LW_V6_OPTION_DEFINITIONS[] = {
+ { "s46-br", D6O_S46_BR, OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
+ { "s46-v4v6bind", D6O_S46_V4V6BIND, OPT_RECORD_TYPE, false, RECORD_DEF(S46_V4V6BIND), V4V6_BIND_OPTION_SPACE },
+};
+
+const int LW_V6_OPTION_DEFINITIONS_SIZE =
+ sizeof(LW_V6_OPTION_DEFINITIONS) / sizeof(LW_V6_OPTION_DEFINITIONS[0]);
+
+/// @brief Rule option definitions
+/// @todo: Maybe move this to a separate file, e.g. rule_option_defs.h
+const OptionDefParams V4V6_RULE_OPTION_DEFINITIONS[] = {
+ { "s46-portparams", D6O_S46_PORTPARAMS, OPT_RECORD_TYPE, false, RECORD_DEF(S46_PORTPARAMS), "" },
+};
+
+const int V4V6_RULE_OPTION_DEFINITIONS_SIZE =
+ sizeof(V4V6_RULE_OPTION_DEFINITIONS) / sizeof(V4V6_RULE_OPTION_DEFINITIONS[0]);
+
+/// @brief Bind option definitions
+/// @todo: Maybe move this to a separate file, e.g. bind_option_defs.h
+const OptionDefParams V4V6_BIND_OPTION_DEFINITIONS[] = {
+ { "s46-portparams", D6O_S46_PORTPARAMS, OPT_RECORD_TYPE, false, RECORD_DEF(S46_PORTPARAMS), "" }
+};
+
+const int V4V6_BIND_OPTION_DEFINITIONS_SIZE =
+ sizeof(V4V6_BIND_OPTION_DEFINITIONS) / sizeof(V4V6_BIND_OPTION_DEFINITIONS[0]);
} // unnamed namespace
// This test checks if the definition of the DHCPv6 vendor option can
// be searched by option name.
TEST_F(LibDhcpTest, getVendorOptionDefByName6) {
- const OptionDefContainerPtr& defs =
- LibDHCP::getVendorOption6Defs(VENDOR_ID_CABLE_LABS);
+ const OptionDefContainerPtr defs =
+ LibDHCP::getVendorOptionDefs(Option::V6, VENDOR_ID_CABLE_LABS);
ASSERT_TRUE(defs);
for (OptionDefContainer::const_iterator def = defs->begin();
def != defs->end(); ++def) {
// This test checks if the definition of the DHCPv4 vendor option can
// be searched by option name.
TEST_F(LibDhcpTest, getVendorOptionDefByName4) {
- const OptionDefContainerPtr& defs =
- LibDHCP::getVendorOption4Defs(VENDOR_ID_CABLE_LABS);
+ const OptionDefContainerPtr defs =
+ LibDHCP::getVendorOptionDefs(Option::V4, VENDOR_ID_CABLE_LABS);
ASSERT_TRUE(defs);
for (OptionDefContainer::const_iterator def = defs->begin();
def != defs->end(); ++def) {
encapsulateInternal(DHCP6_OPTION_SPACE);
}
+void
+CfgOption::encapsulateOptions(OptionPtr option) {
+ // Get encapsulated option space for the option.
+ const std::string& encap_space = option->getEncapsulatedSpace();
+ // Empty value means that no option space is encapsulated.
+ if (!encap_space.empty()) {
+ // Retrieve all options from the encapsulated option space.
+ OptionContainerPtr encap_options = getAll(encap_space);
+ for (OptionContainer::const_iterator encap_opt =
+ encap_options->begin(); encap_opt != encap_options->end();
+ ++encap_opt) {
+ // Add sub-option if there isn't one added already.
+ if (!option->getOption(encap_opt->option_->getType())) {
+ option->addOption(encap_opt->option_);
+ }
+ encapsulateOptions(encap_opt->option_);
+ }
+ }
+}
+
void
CfgOption::encapsulateInternal(const std::string& option_space) {
// Get all options for the particular option space.
// from the option spaces they encapsulate.
for (OptionContainer::const_iterator opt = options->begin();
opt != options->end(); ++opt) {
- // Get encapsulated option space for the option.
- const std::string& encap_space = opt->option_->getEncapsulatedSpace();
- // Empty value means that no option space is encapsulated.
- if (!encap_space.empty()) {
- // Retrieve all options from the encapsulated option space.
- OptionContainerPtr encap_options = getAll(encap_space);
- for (OptionContainer::const_iterator encap_opt =
- encap_options->begin(); encap_opt != encap_options->end();
- ++encap_opt) {
- // Add sub-option if there isn't one added already.
- if (!opt->option_->getOption(encap_opt->option_->getType())) {
- opt->option_->addOption(encap_opt->option_);
- }
- }
- }
+ encapsulateOptions(opt->option_);
}
}
/// which encapsulated options are appended.
void encapsulateInternal(const std::string& option_space);
+ /// @brief Appends encapsulated options from the option space
+ /// defined in the specific option.
+ ///
+ /// This function will go over all options belonging to the encapsulated space
+ /// and will check which option spaces they encapsulate recursively,
+ /// adding these options to the current option
+ ///
+ /// @param option which encapsulated options.
+ void encapsulateOptions(OptionPtr option);
+
/// @brief Merges data from two option containers.
///
/// This method merges options from one option container to another
// Must not override standard option definition.
} else if (((option_space == DHCP4_OPTION_SPACE) &&
LibDHCP::isStandardOption(Option::V4, def->getCode()) &&
- LibDHCP::getOptionDef(Option::V4, def->getCode())) ||
+ LibDHCP::getOptionDef(Option::V4, def->getCode(), option_space)) ||
((option_space == DHCP6_OPTION_SPACE) &&
LibDHCP::isStandardOption(Option::V6, def->getCode()) &&
- LibDHCP::getOptionDef(Option::V6, def->getCode()))) {
+ LibDHCP::getOptionDef(Option::V6, def->getCode(), option_space))) {
isc_throw(BadValue, "unable to override definition of option '"
<< def->getCode() << "' in standard option space '"
<< option_space << "'");
// definition created within libdhcp++.
OptionDefinitionPtr def;
if ((space == DHCP4_OPTION_SPACE) || (space == DHCP6_OPTION_SPACE)) {
- def = LibDHCP::getOptionDef(universe_, code_);
+ def = LibDHCP::getOptionDef(universe_, code_, space);
}
// Otherwise, we may check if this an option encapsulated within the
Option::V4 : Option::V6;
OptionDefinitionPtr def;
- if ((option_space == DHCP4_OPTION_SPACE) ||
- (option_space == DHCP6_OPTION_SPACE)) {
- def = LibDHCP::getOptionDef(u, search_key);
-
- }
+ def = LibDHCP::getOptionDef(u, search_key, option_space);
if (!def) {
// Check if this is a vendor-option. If it is, get vendor-specific
#include <dhcp/dhcp6.h>
#include <dhcp/option.h>
#include <dhcp/option_definition.h>
+#include <dhcp/option_space.h>
#include <dhcp/libdhcp++.h>
#include <eval/eval_context.h>
#include <eval/parser.h>
EvalContext::convertOptionName(const std::string& option_name,
const isc::eval::location& loc)
{
- OptionDefinitionPtr option_def = LibDHCP::getOptionDef(option_universe_,
- option_name);
- if (!option_def) {
- const std::string global_space =
- (option_universe_ == Option::V4) ? "dhcp4" : "dhcp6";
- option_def = LibDHCP::getRuntimeOptionDef(global_space, option_name);
+ const std::string global_space =
+ (Option::V4 == option_universe_) ? DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE;
+
+ OptionDefinitionPtr option_def_ptr =
+ LibDHCP::getOptionDef(option_universe_, option_name, global_space);
+
+ if (!option_def_ptr) {
+ option_def_ptr = LibDHCP::getRuntimeOptionDef(global_space, option_name);
}
- if (!option_def) {
+ if (!option_def_ptr) {
error(loc, "option '" + option_name + "' is not defined");
}
- return (option_def->getCode());
+ return (option_def_ptr->getCode());
}
uint8_t