]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
added additional native option support and refactored option definitions
authorAndrei Pavel <andrei.pavel@qualitance.com>
Mon, 13 Jun 2016 14:33:57 +0000 (17:33 +0300)
committerAndrei Pavel <andrei.pavel@qualitance.com>
Mon, 13 Jun 2016 15:35:20 +0000 (18:35 +0300)
21 files changed:
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/json_config_parser.cc
src/lib/dhcp/dhcp6.h
src/lib/dhcp/docsis3_option_defs.h
src/lib/dhcp/libdhcp++.cc
src/lib/dhcp/libdhcp++.h
src/lib/dhcp/option_data_types.h
src/lib/dhcp/option_definition.cc
src/lib/dhcp/option_int.h
src/lib/dhcp/option_space.h
src/lib/dhcp/pkt4.cc
src/lib/dhcp/pkt6.cc
src/lib/dhcp/std_option_defs.h
src/lib/dhcp/tests/libdhcp++_unittest.cc
src/lib/dhcpsrv/cfg_option.cc
src/lib/dhcpsrv/cfg_option.h
src/lib/dhcpsrv/cfg_option_def.cc
src/lib/dhcpsrv/mysql_host_data_source.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/eval/eval_context.cc

index e2189d52427248e9a90f1c05dcf369425870d505..a2aff70634657e082f24f4dc3070d311d2bde848 100644 (file)
@@ -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<OptionString> boot =
index afe3faa8f73027dd7095e8825e9af7685f8a6f6a..b64739051e15134e47717404d13ffc1fd72d896f 100644 (file)
@@ -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_);
index 4cf6bb6204abc5a147a71e1a6d19e1054a264128..b2a2790ac2d186cdbed243e9c050551d6003db35 100644 (file)
@@ -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 {
index 596947546159d95bfd3028e1aeef5f50871ca897..bcc5cabc1fd0664581eaf9c2f929f25c734be190 100644 (file)
@@ -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 */
 //#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 */
index 77368134ea59da0a3cc10131d88ed36c9ebf4386..8f89b4a6fe2b79237b14c1cffb06649f4a5f2974 100644 (file)
@@ -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;
index 116c61dc2671837c27316cb602b36623e846cdd9..ee854b06f3df4d106c498de1ec7d7dc3dbc0151e 100644 (file)
@@ -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<unsigned short, Option::Factory*> 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<std::string, OptionDefContainerPtr> 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
index 2ac6ea49c063546d8e27d95eee19e85ff98da944..decf75fbac9142410f7ae38224972dcbba581f85 100644 (file)
@@ -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<std::string, OptionDefContainerPtr> option_defs_;
+
     /// Container for v4 vendor option definitions
     static VendorOptionDefContainers vendor4_defs_;
 
index e7a5dc8ebd25309ab29de6cff0032be4b3aec6d3..4bb688f12c4e961c6ff396b34d2e3a18b1909031 100644 (file)
@@ -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.
index 22744b5f2836ef8be56674357f46ea9fec1f7c8e..b40f8e0fe9750773116803de9a1e59994f7fe5a6 100644 (file)
@@ -20,7 +20,6 @@
 #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>
@@ -28,6 +27,7 @@
 #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;
@@ -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<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;
index 868ee3ca582c711cd12f1d6d07c8c237f6849b85..180316619ee8b4ce2a18e353fb4c11b53019ebae 100644 (file)
@@ -10,6 +10,7 @@
 #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>
@@ -62,7 +63,7 @@ public:
         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.
@@ -86,7 +87,7 @@ public:
         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);
     }
 
index c1867d930d8a82e94a429c4b624d9d8ff3609488..6fe92e48f31745c7a70fee9522f6ee1c54c0931c 100644 (file)
 #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 {
@@ -174,7 +182,7 @@ public:
     void setVendorSpace(const uint32_t enterprise_number);
 
 private:
-    
+
     uint32_t enterprise_number_; ///< IANA assigned enterprise number.
 };
 
index 10542496b6f8ce70ab3a077d125a38bd67f443c6..e6c79075ab68cb0f9ebf94139edd957449a4c579 100644 (file)
@@ -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
index 393cece498693484c0657c5579455a7ff271d966..6c1f5c8dcc8280fa945b5188a9798a589901c7fe 100644 (file)
@@ -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
index 10935453ba236f6fd143117e6bc858a25760cf35..1d6a68d03b4efa073595f5ccdc92291ba2f1c3aa 100644 (file)
@@ -10,6 +10,7 @@
 #include <dhcp/option_data_types.h>
 #include <dhcp/dhcp4.h>
 #include <dhcp/dhcp6.h>
+#include <dhcp/option_space.h>
 
 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
 
index 8c50d79a2f78c5354718f479d5b9e44200c16188..215fba395952b2e67460a5e409f6a9a5431dd6f4 100644 (file)
@@ -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) {
index b901d6030d0eb5a4b2ab47069c3aec405e38f078..d874eb80c05b8b2296af9d8d99714db41d5201e8 100644 (file)
@@ -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_);
     }
 }
 
index 065316fa6a59489e3766dd234e0e080b2f6d8095..6c920a0e82609f1b377a2d8d05f0ac2c3893164b 100644 (file)
@@ -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
index ccc668ae85f0cce3555ea2f3b66dc22d55d353c2..66afa9c6fe9caf9c1cd4eb0a0f2f39e8510c6709 100644 (file)
@@ -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 << "'");
index 7e2b3e423df51d9ff9efbb5848b83762d9217b19..5c6dcf31b5707a01df4be9a0724b47ed11be5ac4 100644 (file)
@@ -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
index 8c6ab3684f39f915b9b8fa1bf9ae2b821b07643b..fcc78e9edccfada8544b38bdbfe030559dd35927 100644 (file)
@@ -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
index 059cb0fe63ed4b03984cfe12c87df78c25c2ac6f..54ad635185c78fc9917c082811bda94b1549a5b6 100644 (file)
@@ -7,6 +7,7 @@
 #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>
@@ -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