From: Andrei Pavel Date: Mon, 13 Jun 2016 14:33:57 +0000 (+0300) Subject: added additional native option support and refactored option definitions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd6cb85522006c240d045dec034d3650d11a3c7c;p=thirdparty%2Fkea.git added additional native option support and refactored option definitions --- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index e2189d5242..a2aff70634 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -1010,7 +1010,7 @@ Dhcpv4Srv::appendRequestedOptions(Dhcpv4Exchange& ex) { // 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_); @@ -2459,7 +2459,7 @@ Dhcpv4Srv::vendorClassSpecificProcessing(const Dhcpv4Exchange& ex) { 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 boot = diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index afe3faa8f7..b64739051e 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -852,7 +852,7 @@ Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer, // 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_); diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 4cf6bb6204..b2a2790ac2 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -621,7 +621,8 @@ public: } 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 { diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h index 5969475461..bcc5cabc1f 100644 --- a/src/lib/dhcp/dhcp6.h +++ b/src/lib/dhcp/dhcp6.h @@ -79,7 +79,7 @@ #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 */ @@ -104,14 +104,14 @@ //#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 */ diff --git a/src/lib/dhcp/docsis3_option_defs.h b/src/lib/dhcp/docsis3_option_defs.h index 77368134ea..8f89b4a6fe 100644 --- a/src/lib/dhcp/docsis3_option_defs.h +++ b/src/lib/dhcp/docsis3_option_defs.h @@ -58,7 +58,8 @@ const OptionDefParams DOCSIS3_V6_DEFS[] = { }; /// 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; diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc index 116c61dc26..ee854b06f3 100644 --- a/src/lib/dhcp/libdhcp++.cc +++ b/src/lib/dhcp/libdhcp++.cc @@ -33,6 +33,30 @@ using namespace std; 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 LibDHCP::v4factories_; @@ -45,6 +69,9 @@ OptionDefContainerPtr LibDHCP::v4option_defs_(new OptionDefContainer()); // Static container with DHCPv6 option definitions. OptionDefContainerPtr LibDHCP::v6option_defs_(new OptionDefContainer()); +// Container that maps option spaces to option definitions. +std::map LibDHCP::option_defs_; + VendorOptionDefContainers LibDHCP::vendor4_defs_; VendorOptionDefContainers LibDHCP::vendor6_defs_; @@ -69,67 +96,38 @@ void initOptionSpace(OptionDefContainerPtr& 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); @@ -138,29 +136,29 @@ LibDHCP::getOptionDef(const Option::Universe u, const uint16_t code) { } 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); @@ -171,17 +169,17 @@ LibDHCP::getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, 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); @@ -312,19 +310,23 @@ size_t LibDHCP::unpackOptions6(const OptionBuffer& buf, 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. @@ -448,15 +450,23 @@ size_t LibDHCP::unpackOptions4(const OptionBuffer& buf, 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. @@ -560,14 +570,15 @@ size_t LibDHCP::unpackVendorOptions6(const uint32_t vendor_id, 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 @@ -652,12 +663,13 @@ size_t LibDHCP::unpackVendorOptions4(const uint32_t vendor_id, const OptionBuffe 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 @@ -830,29 +842,16 @@ void LibDHCP::OptionFactoryRegister(Option::Universe u, 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 diff --git a/src/lib/dhcp/libdhcp++.h b/src/lib/dhcp/libdhcp++.h index 2ac6ea49c0..decf75fbac 100644 --- a/src/lib/dhcp/libdhcp++.h +++ b/src/lib/dhcp/libdhcp++.h @@ -38,7 +38,8 @@ public: /// @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. @@ -49,7 +50,8 @@ public: /// @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. /// @@ -59,7 +61,8 @@ public: /// @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 /// @@ -248,21 +251,13 @@ public: 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. @@ -338,32 +333,7 @@ public: 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_; @@ -377,6 +347,9 @@ private: /// Container with DHCPv6 option definitions. static OptionDefContainerPtr v6option_defs_; + // Container that maps option spaces to option definitions. + static std::map option_defs_; + /// Container for v4 vendor option definitions static VendorOptionDefContainers vendor4_defs_; diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h index e7a5dc8ebd..4bb688f12c 100644 --- a/src/lib/dhcp/option_data_types.h +++ b/src/lib/dhcp/option_data_types.h @@ -53,12 +53,32 @@ enum OptionDataType { 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 @@ -221,7 +241,7 @@ public: /// /// @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. diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc index 22744b5f28..b40f8e0fe9 100644 --- a/src/lib/dhcp/option_definition.cc +++ b/src/lib/dhcp/option_definition.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include using namespace std; using namespace isc::util; @@ -565,6 +565,66 @@ OptionDefinition::writeToBuffer(const std::string& value, 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(txt_prefix); + } catch (...) { + isc_throw(BadDataTypeCast, "provided prefix " + << txt_prefix + << " is not valid."); + } + + // Write the prefix length + OptionDataTypeUtil::writeInt(len, buf); + + std::vector addrV6 = address.toBytes(); + boost::dynamic_bitset bits(addrV6.rbegin(), addrV6.rend()); + + uint8_t lenBytes = (len + 7) / 8; + for (size_t idx = 0; idx < lenBytes; idx++) { + boost::dynamic_bitset tmp = bits >> 120; + uint8_t val = static_cast(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(val, buf); + } + + return; + } case OPT_STRING_TYPE: OptionDataTypeUtil::writeString(value, buf); return; diff --git a/src/lib/dhcp/option_int.h b/src/lib/dhcp/option_int.h index 868ee3ca58..180316619e 100644 --- a/src/lib/dhcp/option_int.h +++ b/src/lib/dhcp/option_int.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,7 @@ public: if (!OptionDataTypeTraits::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. @@ -86,7 +87,7 @@ public: if (!OptionDataTypeTraits::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); } diff --git a/src/lib/dhcp/option_space.h b/src/lib/dhcp/option_space.h index c1867d930d..6fe92e48f3 100644 --- a/src/lib/dhcp/option_space.h +++ b/src/lib/dhcp/option_space.h @@ -13,8 +13,16 @@ #include #include -#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 { @@ -174,7 +182,7 @@ public: void setVendorSpace(const uint32_t enterprise_number); private: - + uint32_t enterprise_number_; ///< IANA assigned enterprise number. }; diff --git a/src/lib/dhcp/pkt4.cc b/src/lib/dhcp/pkt4.cc index 10542496b6..e6c79075ab 100644 --- a/src/lib/dhcp/pkt4.cc +++ b/src/lib/dhcp/pkt4.cc @@ -203,7 +203,7 @@ Pkt4::unpack() { // 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 diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc index 393cece498..6c1f5c8dcc 100644 --- a/src/lib/dhcp/pkt6.cc +++ b/src/lib/dhcp/pkt6.cc @@ -336,7 +336,7 @@ Pkt6::unpackMsg(OptionBuffer::const_iterator begin, // 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 @@ -386,7 +386,7 @@ Pkt6::unpackRelayMsg() { // 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 diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h index 10935453ba..1d6a68d03b 100644 --- a/src/lib/dhcp/std_option_defs.h +++ b/src/lib/dhcp/std_option_defs.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace isc { namespace dhcp { @@ -36,18 +37,6 @@ namespace { #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 @@ -72,7 +61,7 @@ RECORD_DECL(CLIENT_NDI_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE); 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, "" }, @@ -230,9 +219,8 @@ const OptionDefParams OPTION_DEF_PARAMS4[] = { }; /// 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 @@ -257,6 +245,13 @@ RECORD_DECL(LQ_QUERY_RECORDS, OPT_UINT8_TYPE, OPT_IPV6_ADDRESS_TYPE); 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 @@ -280,7 +275,7 @@ RECORD_DECL(CLIENT_NII_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE); /// 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), "" }, @@ -378,7 +373,11 @@ const OptionDefParams OPTION_DEF_PARAMS6[] = { { "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 @@ -386,8 +385,8 @@ const OptionDefParams OPTION_DEF_PARAMS6[] = { }; /// 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 @@ -395,12 +394,61 @@ const int OPTION_DEF_PARAMS_SIZE6 = /// /// @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 diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index 8c50d79a2f..215fba3959 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -1654,8 +1654,8 @@ TEST_F(LibDhcpTest, getOptionDefByName4) { // 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) { @@ -1670,8 +1670,8 @@ TEST_F(LibDhcpTest, getVendorOptionDefByName6) { // 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) { diff --git a/src/lib/dhcpsrv/cfg_option.cc b/src/lib/dhcpsrv/cfg_option.cc index b901d6030d..d874eb80c0 100644 --- a/src/lib/dhcpsrv/cfg_option.cc +++ b/src/lib/dhcpsrv/cfg_option.cc @@ -97,6 +97,26 @@ CfgOption::encapsulate() { 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. @@ -105,21 +125,7 @@ CfgOption::encapsulateInternal(const std::string& 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_); } } diff --git a/src/lib/dhcpsrv/cfg_option.h b/src/lib/dhcpsrv/cfg_option.h index 065316fa6a..6c920a0e82 100644 --- a/src/lib/dhcpsrv/cfg_option.h +++ b/src/lib/dhcpsrv/cfg_option.h @@ -409,6 +409,16 @@ private: /// 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 diff --git a/src/lib/dhcpsrv/cfg_option_def.cc b/src/lib/dhcpsrv/cfg_option_def.cc index ccc668ae85..66afa9c6fe 100644 --- a/src/lib/dhcpsrv/cfg_option_def.cc +++ b/src/lib/dhcpsrv/cfg_option_def.cc @@ -91,10 +91,10 @@ CfgOptionDef::add(const OptionDefinitionPtr& def, // 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 << "'"); diff --git a/src/lib/dhcpsrv/mysql_host_data_source.cc b/src/lib/dhcpsrv/mysql_host_data_source.cc index 7e2b3e423d..5c6dcf31b5 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.cc +++ b/src/lib/dhcpsrv/mysql_host_data_source.cc @@ -725,7 +725,7 @@ private: // 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 diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index 8c6ab3684f..fcc78e9edc 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -569,11 +569,7 @@ OptionDataParser::findOptionDefinition(const std::string& option_space, 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 diff --git a/src/lib/eval/eval_context.cc b/src/lib/eval/eval_context.cc index 059cb0fe63..54ad635185 100644 --- a/src/lib/eval/eval_context.cc +++ b/src/lib/eval/eval_context.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -78,19 +79,21 @@ uint16_t 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