// 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));
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));
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));
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));
}
if (!code) {
- const OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6,
+ const OptionDefinitionPtr def = LibDHCP::getOptionDef(DHCP6_OPTION_SPACE,
option_str);
if (def) {
code = def->getCode();
/// @param payload specified payload (0 = fill payload with repeating option code)
/// @return RSOO with nested options
OptionPtr createRSOO(const std::vector<uint16_t>& 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");
}
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);
}
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) {
}
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) {
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,
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);
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);
/// Map of factory functions.
typedef std::map<unsigned short, Option::Factory*> 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
/// @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
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
// 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.
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.
// 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);
}
// 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);
}
" 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 << "'");
// 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.
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);
}
}
// 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"));
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<OptionCustom>
+ (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.
#include <dhcp/option.h>
#include <dhcp/option_definition.h>
#include <dhcp/libdhcp++.h>
+#include <dhcp/option_space.h>
#include <eval/eval_context.h>
#include <eval/parser.h>
#include <exceptions/exceptions.h>
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);
}