mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[2314] Configure encapsulated option space for DHCPv6 options.
This commit is contained in:
parent
45b03507d6
commit
f16d079d34
@ -880,6 +880,7 @@ private:
|
||||
<< ", code: " << option_code << "): "
|
||||
<< ex.what());
|
||||
}
|
||||
|
||||
}
|
||||
// All went good, so we can set the option space name.
|
||||
option_space_ = option_space;
|
||||
@ -1139,7 +1140,7 @@ private:
|
||||
}
|
||||
} catch (const Exception& ex) {
|
||||
isc_throw(DhcpConfigError, "invalid record type values"
|
||||
<< " specified for the option definition: "
|
||||
<< " specified for the option definition: "
|
||||
<< ex.what());
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,6 @@ OptionStorage option_defaults;
|
||||
/// @brief Global storage for option definitions.
|
||||
OptionDefStorage option_def_intermediate;
|
||||
|
||||
|
||||
/// @brief a dummy configuration parser
|
||||
///
|
||||
/// This is a debugging parser. It does not configure anything,
|
||||
@ -1037,8 +1036,8 @@ public:
|
||||
BOOST_FOREACH(ConfigPair param, option_def->mapValue()) {
|
||||
std::string entry(param.first);
|
||||
ParserPtr parser;
|
||||
if (entry == "name" || entry == "type" ||
|
||||
entry == "record-types" || entry == "space") {
|
||||
if (entry == "name" || entry == "type" || entry == "record-types" ||
|
||||
entry == "space" || entry == "encapsulate") {
|
||||
StringParserPtr
|
||||
str_parser(dynamic_cast<StringParser*>(StringParser::factory(entry)));
|
||||
if (str_parser) {
|
||||
@ -1122,9 +1121,36 @@ private:
|
||||
uint32_t code = getParam<uint32_t>("code", uint32_values_);
|
||||
std::string type = getParam<std::string>("type", string_values_);
|
||||
bool array_type = getParam<bool>("array", boolean_values_);
|
||||
std::string encapsulates = getParam<std::string>("encapsulate",
|
||||
string_values_);
|
||||
|
||||
// Create option definition.
|
||||
OptionDefinitionPtr def;
|
||||
// We need to check if user has set encapsulated option space
|
||||
// name. If so, different constructor will be used.
|
||||
if (!encapsulates.empty()) {
|
||||
// Arrays can't be used together with sub-options.
|
||||
if (array_type) {
|
||||
isc_throw(DhcpConfigError, "option '" << space << "."
|
||||
<< "name" << "', comprising an array of data"
|
||||
<< " fields may not encapsulate any option space");
|
||||
|
||||
} else if (encapsulates == space) {
|
||||
isc_throw(DhcpConfigError, "option must not encapsulate"
|
||||
<< " an option space it belongs to: '"
|
||||
<< space << "." << name << "' is set to"
|
||||
<< " encapsulate '" << space << "'");
|
||||
|
||||
} else {
|
||||
def.reset(new OptionDefinition(name, code, type,
|
||||
encapsulates.c_str()));
|
||||
}
|
||||
|
||||
} else {
|
||||
def.reset(new OptionDefinition(name, code, type, array_type));
|
||||
|
||||
}
|
||||
|
||||
OptionDefinitionPtr def(new OptionDefinition(name, code,
|
||||
type, array_type));
|
||||
// The record-types field may carry a list of comma separated names
|
||||
// of data types that form a record.
|
||||
std::string record_types = getParam<std::string>("record-types",
|
||||
@ -1142,7 +1168,7 @@ private:
|
||||
}
|
||||
} catch (const Exception& ex) {
|
||||
isc_throw(DhcpConfigError, "invalid record type values"
|
||||
<< " specified for the option definition: "
|
||||
<< " specified for the option definition: "
|
||||
<< ex.what());
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +86,12 @@
|
||||
"item_type": "string",
|
||||
"item_optional": false,
|
||||
"item_default": ""
|
||||
},
|
||||
|
||||
{ "item_name": "encapsulate",
|
||||
"item_type": "string",
|
||||
"item_optional": false,
|
||||
"item_default": ""
|
||||
} ]
|
||||
}
|
||||
},
|
||||
|
@ -461,7 +461,8 @@ TEST_F(Dhcp6ParserTest, optionDefIpv6Address) {
|
||||
" \"type\": \"ipv6-address\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -499,7 +500,8 @@ TEST_F(Dhcp6ParserTest, optionDefRecord) {
|
||||
" \"type\": \"record\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"uint16, ipv4-address, ipv6-address, string\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -546,7 +548,8 @@ TEST_F(Dhcp6ParserTest, optionDefMultiple) {
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"foo-2\","
|
||||
@ -554,7 +557,8 @@ TEST_F(Dhcp6ParserTest, optionDefMultiple) {
|
||||
" \"type\": \"ipv4-address\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -604,7 +608,8 @@ TEST_F(Dhcp6ParserTest, optionDefDuplicate) {
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"foo-2\","
|
||||
@ -612,7 +617,8 @@ TEST_F(Dhcp6ParserTest, optionDefDuplicate) {
|
||||
" \"type\": \"ipv4-address\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -640,7 +646,8 @@ TEST_F(Dhcp6ParserTest, optionDefArray) {
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": True,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -666,6 +673,47 @@ TEST_F(Dhcp6ParserTest, optionDefArray) {
|
||||
EXPECT_TRUE(def->getArrayType());
|
||||
}
|
||||
|
||||
// The purpose of this test to verify that encapsulated option
|
||||
// space name may be specified.
|
||||
TEST_F(Dhcp6ParserTest, optionDefEncapsulate) {
|
||||
|
||||
// Configuration string. Included the encapsulated
|
||||
// option space name.
|
||||
std::string config =
|
||||
"{ \"option-def\": [ {"
|
||||
" \"name\": \"foo\","
|
||||
" \"code\": 100,"
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"sub-opts-space\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
|
||||
// Make sure that the particular option definition does not exist.
|
||||
OptionDefinitionPtr def = CfgMgr::instance().getOptionDef("isc", 100);
|
||||
ASSERT_FALSE(def);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
ASSERT_TRUE(status);
|
||||
checkResult(status, 0);
|
||||
|
||||
// The option definition should now be available in the CfgMgr.
|
||||
def = CfgMgr::instance().getOptionDef("isc", 100);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Check the option data.
|
||||
EXPECT_EQ("foo", def->getName());
|
||||
EXPECT_EQ(100, def->getCode());
|
||||
EXPECT_EQ(OPT_UINT32_TYPE, def->getType());
|
||||
EXPECT_FALSE(def->getArrayType());
|
||||
EXPECT_EQ("sub-opts-space", def->getEncapsulatedSpace());
|
||||
}
|
||||
|
||||
/// The purpose of this test is to verify that the option definition
|
||||
/// with invalid name is not accepted.
|
||||
TEST_F(Dhcp6ParserTest, optionDefInvalidName) {
|
||||
@ -678,7 +726,8 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidName) {
|
||||
" \"type\": \"string\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -703,7 +752,8 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidType) {
|
||||
" \"type\": \"sting\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -728,7 +778,8 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidRecordType) {
|
||||
" \"type\": \"record\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"uint32,uint8,sting\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -741,6 +792,85 @@ TEST_F(Dhcp6ParserTest, optionDefInvalidRecordType) {
|
||||
checkResult(status, 1);
|
||||
}
|
||||
|
||||
/// The goal of this test is to verify that the invalid encapsulated
|
||||
/// option space name is not accepted.
|
||||
TEST_F(Dhcp6ParserTest, optionDefInvalidEncapsulatedSpace) {
|
||||
// Configuration string. The encapsulated option space
|
||||
// name is invalid (% character is not allowed).
|
||||
std::string config =
|
||||
"{ \"option-def\": [ {"
|
||||
" \"name\": \"foo\","
|
||||
" \"code\": 100,"
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"invalid%space%name\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
ASSERT_TRUE(status);
|
||||
// Expecting parsing error (error code 1).
|
||||
checkResult(status, 1);
|
||||
}
|
||||
|
||||
/// The goal of this test is to verify that the encapsulated
|
||||
/// option space name can't be specified for the option that
|
||||
/// comprises an array of data fields.
|
||||
TEST_F(Dhcp6ParserTest, optionDefEncapsulatedSpaceAndArray) {
|
||||
// Configuration string. The encapsulated option space
|
||||
// name is set to non-empty value and the array flag
|
||||
// is set.
|
||||
std::string config =
|
||||
"{ \"option-def\": [ {"
|
||||
" \"name\": \"foo\","
|
||||
" \"code\": 100,"
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": True,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"valid-space-name\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
ASSERT_TRUE(status);
|
||||
// Expecting parsing error (error code 1).
|
||||
checkResult(status, 1);
|
||||
}
|
||||
|
||||
/// The goal of this test is to verify that the option may not
|
||||
/// encapsulate option space it belongs to.
|
||||
TEST_F(Dhcp6ParserTest, optionDefEncapsulateOwnSpace) {
|
||||
// Configuration string. Option is set to encapsulate
|
||||
// option space it belongs to.
|
||||
std::string config =
|
||||
"{ \"option-def\": [ {"
|
||||
" \"name\": \"foo\","
|
||||
" \"code\": 100,"
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"isc\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
|
||||
// Use the configuration string to create new option definition.
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
ASSERT_TRUE(status);
|
||||
// Expecting parsing error (error code 1).
|
||||
checkResult(status, 1);
|
||||
}
|
||||
|
||||
/// The purpose of this test is to verify that it is not allowed
|
||||
/// to override the standard option (that belongs to dhcp6 option
|
||||
@ -759,7 +889,8 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
|
||||
" \"type\": \"string\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"dhcp6\""
|
||||
" \"space\": \"dhcp6\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
ElementPtr json = Element::fromJSON(config);
|
||||
@ -794,7 +925,8 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
|
||||
" \"type\": \"string\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"dhcp6\""
|
||||
" \"space\": \"dhcp6\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ]"
|
||||
"}";
|
||||
json = Element::fromJSON(config);
|
||||
@ -916,7 +1048,8 @@ TEST_F(Dhcp6ParserTest, optionDataTwoSpaces) {
|
||||
" \"type\": \"uint32\","
|
||||
" \"array\": False,"
|
||||
" \"record-types\": \"\","
|
||||
" \"space\": \"isc\""
|
||||
" \"space\": \"isc\","
|
||||
" \"encapsulate\": \"\""
|
||||
" } ],"
|
||||
"\"subnet6\": [ { "
|
||||
" \"pool\": [ \"2001:db8:1::/80\" ],"
|
||||
|
Loading…
x
Reference in New Issue
Block a user