From: Marcin Siodelski Date: Fri, 14 Oct 2016 11:40:51 +0000 (+0200) Subject: [github24] Definitions of encapsulated options available thru libdhcp++. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe328fa3cd4e6a47d4b04a5cfd54d11ad72ee7cf;p=thirdparty%2Fkea.git [github24] Definitions of encapsulated options available thru libdhcp++. --- diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index b8e5575019..cc045a4656 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -402,7 +402,7 @@ TEST_F(Dhcpv4SrvTest, initResponse) { // client-id echo is optional // rai echo is done in relayAgentInfoEcho // Do subnet selection option - OptionDefinitionPtr sbnsel_def = LibDHCP::getOptionDef(Option::V4, + OptionDefinitionPtr sbnsel_def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, DHO_SUBNET_SELECTION); ASSERT_TRUE(sbnsel_def); OptionCustomPtr sbnsel(new OptionCustom(*sbnsel_def, Option::V4)); @@ -2165,7 +2165,7 @@ TEST_F(Dhcpv4SrvTest, relayLinkSelect) { dis->addOption(clientid); // Let's create a Relay Agent Information option - OptionDefinitionPtr rai_def = LibDHCP::getOptionDef(Option::V4, + OptionDefinitionPtr rai_def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, DHO_DHCP_AGENT_OPTIONS); ASSERT_TRUE(rai_def); OptionCustomPtr rai(new OptionCustom(*rai_def, Option::V4)); @@ -2192,7 +2192,7 @@ TEST_F(Dhcpv4SrvTest, relayLinkSelect) { EXPECT_TRUE(subnet2 == srv_.selectSubnet(dis)); // Subnet select option has a lower precedence - OptionDefinitionPtr sbnsel_def = LibDHCP::getOptionDef(Option::V4, + OptionDefinitionPtr sbnsel_def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, DHO_SUBNET_SELECTION); ASSERT_TRUE(sbnsel_def); OptionCustomPtr sbnsel(new OptionCustom(*sbnsel_def, Option::V4)); @@ -2275,7 +2275,7 @@ TEST_F(Dhcpv4SrvTest, subnetSelect) { dis->addOption(clientid); // Let's create a Subnet Selection option - OptionDefinitionPtr sbnsel_def = LibDHCP::getOptionDef(Option::V4, + OptionDefinitionPtr sbnsel_def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, DHO_SUBNET_SELECTION); ASSERT_TRUE(sbnsel_def); OptionCustomPtr sbnsel(new OptionCustom(*sbnsel_def, Option::V4)); diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 99f8bed7f4..6ed6c1d8e7 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -627,7 +627,7 @@ public: } if (!code) { - const OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, + const OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP6_OPTION_SPACE, option_str); if (def) { code = def->getCode(); diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc index 82fcaf6163..fae9873b80 100644 --- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc @@ -2333,7 +2333,7 @@ TEST_F(Dhcpv6SrvTest, relayOverrideAndClientClass) { /// @param payload specified payload (0 = fill payload with repeating option code) /// @return RSOO with nested options OptionPtr createRSOO(const std::vector& codes, uint8_t payload = 0) { - OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, D6O_RSOO); + OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP6_OPTION_SPACE, D6O_RSOO); if (!def) { isc_throw(BadValue, "Can't find RSOO definition"); } diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc index c4b64c5d8d..033a66e2f6 100644 --- a/src/lib/dhcp/libdhcp++.cc +++ b/src/lib/dhcp/libdhcp++.cc @@ -75,32 +75,21 @@ void initOptionSpace(OptionDefContainerPtr& defs, 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"); +LibDHCP::getOptionDefs(const std::string& space) { + // If any of the containers is not initialized, it means that we haven't + // initialized option definitions at all. + if (v4option_defs_->empty()) { + initStdOptionDefs4(); + initVendorOptsDocsis4(); + initStdOptionDefs6(); + initVendorOptsDocsis6(); } -} -const OptionDefContainerPtr& -LibDHCP::getOptionDefs(const std::string& space) { if (space == DHCP4_OPTION_SPACE) { - return (getOptionDefs(Option::V4)); + return (v4option_defs_); } else if (space == DHCP6_OPTION_SPACE) { - return (getOptionDefs(Option::V6)); + return (v6option_defs_); } OptionDefContainers::const_iterator container = option_defs_.find(space); @@ -148,8 +137,8 @@ LibDHCP::getVendorOption6Defs(const uint32_t vendor_id) { } OptionDefinitionPtr -LibDHCP::getOptionDef(const Option::Universe u, const uint16_t code) { - const OptionDefContainerPtr& defs = getOptionDefs(u); +LibDHCP::getOptionDef(const std::string& space, const uint16_t code) { + const OptionDefContainerPtr& defs = getOptionDefs(space); const OptionDefContainerTypeIndex& idx = defs->get<1>(); const OptionDefContainerTypeRange& range = idx.equal_range(code); if (range.first != range.second) { @@ -159,18 +148,16 @@ 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); +LibDHCP::getOptionDef(const std::string& space, const std::string& name) { + const OptionDefContainerPtr defs = getOptionDefs(space); const OptionDefContainerNameIndex& idx = defs->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) { @@ -270,34 +257,6 @@ LibDHCP::commitRuntimeOptionDefs() { runtime_option_defs_.commit(); } -bool -LibDHCP::isStandardOption(const Option::Universe u, const uint16_t code) { - if (u == Option::V6) { - if (code < 79 && - code != 10 && - code != 35) { - return (true); - } - - } else if (u == Option::V4) { - if (!(code == 84 || - code == 96 || - (code > 101 && code < 112) || - code == 115 || - code == 126 || - code == 127 || - (code > 146 && code < 150) || - (code > 177 && code < 208) || - (code > 213 && code < 220) || - (code > 221 && code < 255))) { - return (true); - } - - } - - return (false); -} - OptionPtr LibDHCP::optionFactory(Option::Universe u, uint16_t type, @@ -333,7 +292,7 @@ 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); + const OptionDefContainerPtr& option_defs = LibDHCP::getOptionDefs(option_space); // 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); @@ -469,7 +428,7 @@ 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); + const OptionDefContainerPtr& option_defs = LibDHCP::getOptionDefs(option_space); // 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); diff --git a/src/lib/dhcp/libdhcp++.h b/src/lib/dhcp/libdhcp++.h index 4d9179aba3..31c589803b 100644 --- a/src/lib/dhcp/libdhcp++.h +++ b/src/lib/dhcp/libdhcp++.h @@ -27,19 +27,6 @@ public: /// Map of factory functions. typedef std::map FactoryMap; - /// @brief Return collection of option definitions. - /// - /// Method returns the collection of DHCP standard DHCP - /// option definitions. - /// @todo DHCPv4 option definitions are not implemented. For now - /// this function will throw isc::NotImplemented in case of attempt - /// to get option definitions for V4 universe. - /// - /// @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); - /// @brief Returns collection of option definitions. /// /// This method returns a collection of option definitions for a specified @@ -53,22 +40,22 @@ public: /// @brief Return the first option definition matching a /// particular option code. /// - /// @param u universe (V4 or V6) + /// @param space option space. /// @param code 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, + static OptionDefinitionPtr getOptionDef(const std::string& space, const uint16_t code); /// @brief Return the definition of option having a specified name. /// - /// @param u universe (v4 or V6) + /// @param space option space. /// @param name Option name. /// /// @return Pointer to the option definition or NULL pointer if option /// definition has not been found. - static OptionDefinitionPtr getOptionDef(const Option::Universe u, + static OptionDefinitionPtr getOptionDef(const std::string& option_space, const std::string& name); /// @brief Returns vendor option definition for a given vendor-id and code @@ -125,21 +112,6 @@ public: static OptionDefContainerPtr getRuntimeOptionDefs(const std::string& space); - /// @brief Check if the specified option is a standard option. - /// - /// @param u universe (V4 or V6) - /// @param code option code. - /// - /// @return true if the specified option is a standard option. - /// @todo We already create option definitions for the subset if - /// standard options. We are aiming that this function checks - /// the presence of the standard option definition and if it finds - /// it, then the true value is returned. However, at this point - /// this is not doable because some of the definitions (for less - /// important options) are not created yet. - static bool isStandardOption(const Option::Universe u, - const uint16_t code); - /// @brief Factory function to create instance of option. /// /// Factory method creates instance of specified option. The option diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index 45889d327c..227bf8e1fa 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -707,7 +707,7 @@ TEST_F(LibDhcpTest, packOptions4) { // Get the option definition for RAI option. This option is represented // by OptionCustom which requires a definition to be passed to // the constructor. - OptionDefinitionPtr rai_def = LibDHCP::getOptionDef(Option::V4, + OptionDefinitionPtr rai_def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, DHO_DHCP_AGENT_OPTIONS); ASSERT_TRUE(rai_def); // Create RAI option. @@ -1039,69 +1039,6 @@ TEST_F(LibDhcpTest, unpackSubOptions4) { EXPECT_EQ(0x0, option_bar->getValue()); } -TEST_F(LibDhcpTest, isStandardOption4) { - // Get all option codes that are not occupied by standard options. - const uint16_t unassigned_codes[] = { 84, 96, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 115, 126, 127, 147, 148, 149, - 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 214, 215, 216, 217, 218, 219, - 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254 }; - const size_t unassigned_num = sizeof(unassigned_codes) / sizeof(unassigned_codes[0]); - - // Try all possible option codes. - for (size_t i = 0; i < 256; ++i) { - // Some ranges of option codes are unassigned and thus the isStandardOption - // should return false for them. - bool check_unassigned = false; - // Check the array of unassigned options to find out whether option code - // is assigned to standard option or unassigned. - for (size_t j = 0; j < unassigned_num; ++j) { - // If option code is found within the array of unassigned options - // we the isStandardOption function should return false. - if (unassigned_codes[j] == i) { - check_unassigned = true; - EXPECT_FALSE(LibDHCP::isStandardOption(Option::V4, - unassigned_codes[j])) - << "Test failed for option code " << unassigned_codes[j]; - break; - } - } - // If the option code belongs to the standard option then the - // isStandardOption should return true. - if (!check_unassigned) { - EXPECT_TRUE(LibDHCP::isStandardOption(Option::V4, i)) - << "Test failed for the option code " << i; - } - } -} - -TEST_F(LibDhcpTest, isStandardOption6) { - // All option codes in the range from 0 to 78 (except 10 and 35) - // identify the standard options. - for (uint16_t code = 0; code < 79; ++code) { - if (code != 10 && code != 35) { - EXPECT_TRUE(LibDHCP::isStandardOption(Option::V6, code)) - << "Test failed for option code " << code; - } - } - - // Check the option codes 10 and 35. They are unassigned. - EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, 10)); - EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, 35)); - - // Check a range of option codes above 78. Those are option codes - // identifying non-standard options. - for (uint16_t code = 79; code < 512; ++code) { - EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, code)) - << "Test failed for option code " << code; - } -} - TEST_F(LibDhcpTest, stdOptionDefs4) { // Create a buffer that holds dummy option data. @@ -1679,12 +1616,12 @@ TEST_F(LibDhcpTest, stdOptionDefs6) { // an option name. TEST_F(LibDhcpTest, getOptionDefByName6) { // Get all definitions. - const OptionDefContainerPtr defs = LibDHCP::getOptionDefs(Option::V6); + const OptionDefContainerPtr defs = LibDHCP::getOptionDefs(DHCP6_OPTION_SPACE); // For each definition try to find it using option name. for (OptionDefContainer::const_iterator def = defs->begin(); def != defs->end(); ++def) { OptionDefinitionPtr def_by_name = - LibDHCP::getOptionDef(Option::V6, (*def)->getName()); + LibDHCP::getOptionDef(DHCP6_OPTION_SPACE, (*def)->getName()); ASSERT_TRUE(def_by_name); ASSERT_TRUE(**def == *def_by_name); } @@ -1695,12 +1632,12 @@ TEST_F(LibDhcpTest, getOptionDefByName6) { // an option name. TEST_F(LibDhcpTest, getOptionDefByName4) { // Get all definitions. - const OptionDefContainerPtr defs = LibDHCP::getOptionDefs(Option::V4); + const OptionDefContainerPtr defs = LibDHCP::getOptionDefs(DHCP4_OPTION_SPACE); // For each definition try to find it using option name. for (OptionDefContainer::const_iterator def = defs->begin(); def != defs->end(); ++def) { OptionDefinitionPtr def_by_name = - LibDHCP::getOptionDef(Option::V4, (*def)->getName()); + LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, (*def)->getName()); ASSERT_TRUE(def_by_name); ASSERT_TRUE(**def == *def_by_name); } diff --git a/src/lib/dhcpsrv/cfg_option_def.cc b/src/lib/dhcpsrv/cfg_option_def.cc index ccc668ae85..1dd51a5729 100644 --- a/src/lib/dhcpsrv/cfg_option_def.cc +++ b/src/lib/dhcpsrv/cfg_option_def.cc @@ -89,12 +89,7 @@ CfgOptionDef::add(const OptionDefinitionPtr& def, " space '" << option_space << "'"); // 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())) || - ((option_space == DHCP6_OPTION_SPACE) && - LibDHCP::isStandardOption(Option::V6, def->getCode()) && - LibDHCP::getOptionDef(Option::V6, def->getCode()))) { + } else if (LibDHCP::getOptionDef(option_space, def->getCode())) { 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..f420273be4 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.cc +++ b/src/lib/dhcpsrv/mysql_host_data_source.cc @@ -720,13 +720,8 @@ private: // class, using option definition. Thus, we need to find the // option definition for this option code and option space. - // If the option space is a standard DHCPv4 or DHCPv6 option space, - // this is most likely a standard option, for which we have a - // definition created within libdhcp++. - OptionDefinitionPtr def; - if ((space == DHCP4_OPTION_SPACE) || (space == DHCP6_OPTION_SPACE)) { - def = LibDHCP::getOptionDef(universe_, code_); - } + // Check if this is a standard option. + OptionDefinitionPtr def = LibDHCP::getOptionDef(space, code_); // Otherwise, we may check if this an option encapsulated within the // vendor space. diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index 748163823e..26796c4702 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -566,21 +566,15 @@ template OptionDefinitionPtr OptionDataParser::findOptionDefinition(const std::string& option_space, const SearchKey& search_key) const { - const Option::Universe u = address_family_ == AF_INET ? - Option::V4 : Option::V6; - OptionDefinitionPtr def; - - if ((option_space == DHCP4_OPTION_SPACE) || - (option_space == DHCP6_OPTION_SPACE)) { - def = LibDHCP::getOptionDef(u, search_key); - - } + OptionDefinitionPtr def = LibDHCP::getOptionDef(option_space, search_key); if (!def) { // Check if this is a vendor-option. If it is, get vendor-specific // definition. uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(option_space); if (vendor_id) { + const Option::Universe u = address_family_ == AF_INET ? + Option::V4 : Option::V6; def = LibDHCP::getVendorOptionDef(u, vendor_id, search_key); } } diff --git a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc index 67a0e22a03..cb77858781 100644 --- a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc @@ -182,7 +182,7 @@ TEST(CfgOptionDefTest, get) { // Check that an option definition can be added to the standard // (dhcp4 and dhcp6) option spaces when the option code is not // reserved by the standard option. - OptionDefinitionPtr def6(new OptionDefinition("option-foo", 79, "uint16")); + OptionDefinitionPtr def6(new OptionDefinition("option-foo", 1000, "uint16")); EXPECT_NO_THROW(cfg.add(def6, DHCP6_OPTION_SPACE)); OptionDefinitionPtr def4(new OptionDefinition("option-foo", 222, "uint16")); diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc index 83cbdc458f..471d41874c 100644 --- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc +++ b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc @@ -766,6 +766,28 @@ TEST_F(ParseConfigTest, optionDataCSVFormatWithOptionDef) { EXPECT_EQ("192.0.2.0", addr_opt->readAddress().toText()); } +TEST_F(ParseConfigTest, encapsulatedOptionData) { + std::string config = + "{ \"option-data\": [ {" + " \"space\": \"s46-cont-mape-options\"," + " \"name\": \"s46-rule\"," + " \"data\": \"1, 0, 24, 192.0.2.0, 2001:db8:1::/64\"" + " } ]" + "}"; + + // The default universe is V6. We need to change it to use dhcp4 option + // space. + parser_context_->universe_ = Option::V6; + int rcode = 0; + ASSERT_NO_THROW(rcode = parseConfiguration(config)); + ASSERT_EQ(0, rcode); + + // Verify that the option data is correct. + OptionCustomPtr s46_rule = boost::dynamic_pointer_cast + (getOptionPtr(MAPE_V6_OPTION_SPACE, D6O_S46_RULE)); + ASSERT_TRUE(s46_rule); +} + // This test checks behavior of the configuration parser for option data // for different values of csv-format parameter and when there is no // option definition. diff --git a/src/lib/eval/eval_context.cc b/src/lib/eval/eval_context.cc index 059cb0fe63..5ee9272f78 100644 --- a/src/lib/eval/eval_context.cc +++ b/src/lib/eval/eval_context.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -78,11 +79,12 @@ uint16_t EvalContext::convertOptionName(const std::string& option_name, const isc::eval::location& loc) { - OptionDefinitionPtr option_def = LibDHCP::getOptionDef(option_universe_, + const std::string global_space = (option_universe_ == Option::V4) ? + DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE; + + OptionDefinitionPtr option_def = LibDHCP::getOptionDef(global_space, option_name); if (!option_def) { - const std::string global_space = - (option_universe_ == Option::V4) ? "dhcp4" : "dhcp6"; option_def = LibDHCP::getRuntimeOptionDef(global_space, option_name); }