2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-29 13:07:50 +00:00

[#3587] Updated kea-dhcp6 parser

Changes to be committed:
    doc/examples/kea6/all-keys.json
    doc/examples/kea6/classify2.json
    src/bin/admin/tests/mysql_tests.sh.in
    src/bin/dhcp6/dhcp6_lexer.cc
    src/bin/dhcp6/dhcp6_lexer.ll
    src/bin/dhcp6/dhcp6_parser.cc
    src/bin/dhcp6/dhcp6_parser.h
    src/bin/dhcp6/dhcp6_parser.yy
    src/bin/dhcp6/tests/config_parser_unittest.cc
This commit is contained in:
Thomas Markwalder 2024-10-17 13:39:15 -04:00
parent 3328540c76
commit 9acfe8732f
9 changed files with 4362 additions and 4003 deletions

View File

@ -67,10 +67,10 @@
// Boolean flag indicating whether the class expression is only evaluated
// when the class is required, e.g. the selected address pool configuration
// includes this class name in its "require-client-classes" list. The
// includes this class name in its "evaluate-additional-classes" list. The
// default value false means that the class test expression must
// always be evaluated.
"only-if-required": true,
"only-in-additional-list": true,
// Class selection expression.
"test": "member('ALL')"
@ -901,7 +901,7 @@
// List of client classes which must be evaluated when this shared
// network is selected for client assignments.
"require-client-classes": [ "late" ],
"evaluate-additional-classes": [ "late" ],
// Turn off storage of extended information (e.g. relay agent
// information) with each lease for this shared network.
@ -1043,7 +1043,7 @@
// List of client classes which must be evaluated
// when this prefix pool is selected for client assignments.
"require-client-classes": [],
"evaluate-additional-classes": [],
// PD-pool identifier used to enable statistics for this pd-pool.
// The pd-pool ID does not need to be unique within the subnet
@ -1080,7 +1080,7 @@
// List of client classes which must be evaluated when this pool
// is selected for client assignments.
"require-client-classes": [ "late" ]
"evaluate-additional-classes": [ "late" ]
},
{
// Restricts this pool to only be used for client
@ -1095,7 +1095,7 @@
// List of client classes which must be evaluated when this pool
// is selected for client assignments.
"require-client-classes": [],
"evaluate-additional-classes": [],
// Pool identifier used to enable statistics for this pool.
// The pool ID does not need to be unique within the subnet
@ -1195,7 +1195,7 @@
// List of client classes which must be evaluated when this subnet
// is selected for client assignments.
"require-client-classes": [ "late" ],
"evaluate-additional-classes": [ "late" ],
// Subnet prefix.
"subnet": "2001:db8::/32",

View File

@ -30,7 +30,7 @@
// is not yet defined.
{
"name": "second_subnet",
"only-if-required": true,
"only-in-additional-list": true,
"test": "member('ALL')",
"option-data": [{
"name": "dns-servers",
@ -86,7 +86,7 @@
"client-classes": [ "cable-modems" ]
} ],
"interface": "eth0",
"require-client-classes": [ "second_subnet" ]
"evaluate-additional-classes": [ "second_subnet" ]
},
// The following subnet contains a pool with a class constraint: only
// clients which belong to the class are allowed to use this pool.

View File

@ -961,10 +961,10 @@ mysql_upgrade_24_to_25_test() {
mysql_upgrade_25_to_26_test() {
# client_classes been added to dhcp4_options
check_table_column client_classes dhcp4_options;
check_table_column client_classes dhcp4_options
# client_classes been added to dhcp6_options
check_table_column client_classes dhcp6_options;
check_table_column client_classes dhcp6_options
# check rename of require_client_classes to evaluate_additaionl_classes.
check_table_column evaluate_additional_classes dhcp4_shared_network

File diff suppressed because it is too large Load Diff

View File

@ -1625,6 +1625,18 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
\"evaluate-additional-classes\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::POOLS:
case isc::dhcp::Parser6Context::PD_POOLS:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_EVALUATE_ADDITIONAL_CLASSES(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("evaluate-additional-classes", driver.loc_);
}
}
\"client-class\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::SUBNET6:
@ -1665,6 +1677,15 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
\"only-in-additional-list\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::CLIENT_CLASSES:
return isc::dhcp::Dhcp6Parser::make_ONLY_IN_ADDITIONAL_LIST(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("only-in-additional-list", driver.loc_);
}
}
\"reservations\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -177,9 +177,11 @@ using namespace std;
CLIENT_CLASSES "client-classes"
REQUIRE_CLIENT_CLASSES "require-client-classes"
EVALUATE_ADDITIONAL_CLASSES "evaluate-additional-classes"
TEST "test"
TEMPLATE_TEST "template-test"
ONLY_IF_REQUIRED "only-if-required"
ONLY_IN_ADDITIONAL_LIST "only-in-additional-list"
CLIENT_CLASS "client-class"
POOL_ID "pool-id"
@ -1617,6 +1619,7 @@ subnet6_param: preferred_lifetime
| rapid_commit
| client_class
| require_client_classes
| evaluate_additional_classes
| reservations
| reservations_global
| reservations_in_subnet
@ -1683,6 +1686,7 @@ client_class: CLIENT_CLASS {
ctx.leave();
};
// Deprecated.
require_client_classes: REQUIRE_CLIENT_CLASSES {
ctx.unique("require-client-classes", ctx.loc2pos(@1));
ElementPtr c(new ListElement(ctx.loc2pos(@1)));
@ -1694,6 +1698,18 @@ require_client_classes: REQUIRE_CLIENT_CLASSES {
ctx.leave();
};
evaluate_additional_classes: EVALUATE_ADDITIONAL_CLASSES {
ctx.unique("evaluate-additional-classes", ctx.loc2pos(@1));
ElementPtr c(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("evaluate-additional-classes", c);
ctx.stack_.push_back(c);
ctx.enter(ctx.NO_KEYWORD);
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
reservations_global: RESERVATIONS_GLOBAL COLON BOOLEAN {
ctx.unique("reservations-global", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
@ -1778,6 +1794,7 @@ shared_network_param: name
| reservations_out_of_pool
| client_class
| require_client_classes
| evaluate_additional_classes
| preferred_lifetime
| min_preferred_lifetime
| max_preferred_lifetime
@ -2143,6 +2160,7 @@ pool_param: pool_entry
| option_data_list
| client_class
| require_client_classes
| evaluate_additional_classes
| user_context
| comment
| unknown_map_entry
@ -2280,6 +2298,7 @@ pd_pool_param: pd_prefix
| option_data_list
| client_class
| require_client_classes
| evaluate_additional_classes
| excluded_prefix
| excluded_prefix_len
| user_context
@ -2535,6 +2554,7 @@ client_class_param: client_class_name
| client_class_test
| client_class_template_test
| only_if_required
| only_in_additional_list
| option_data_list
| user_context
| comment
@ -2567,12 +2587,19 @@ client_class_template_test: TEMPLATE_TEST {
ctx.leave();
};
// Deprecated
only_if_required: ONLY_IF_REQUIRED COLON BOOLEAN {
ctx.unique("only-if-required", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("only-if-required", b);
};
only_in_additional_list: ONLY_IN_ADDITIONAL_LIST COLON BOOLEAN {
ctx.unique("only-in-additional-list", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("only-in-additional-list", b);
};
// --- end of client classes ---------------------------------
// --- server-id ---------------------------------------------

View File

@ -9096,4 +9096,126 @@ TEST_F(Dhcp6ParserTest, optionClientClassesDuplicateCheck) {
EXPECT_EQ(*cclasses, "bar");
}
// This test verifies that require-client-classes gets translated
// to evaluate-additional-classes.
TEST_F(Dhcp6ParserTest, deprecatedRequireClientClassesCheck) {
std::string config = "{ " + genIfaceConfig() + ","
R"^(
"rebind-timer": 2000,
"renew-timer": 1000,
"subnet6": [{
"require-client-classes": [ "foo" ],
"pools": [{ "pool": "2001:db8::/64" }],
"id": 1,
"subnet": "2001:db8::/64"
}],
"valid-lifetime": 400
})^";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
ConstElementPtr status;
ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json));
checkResult(status, 0);
Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->
getCfgSubnets6()->selectSubnet(IOAddress("2001:db8::"));
ASSERT_TRUE(subnet);
const auto& cclass_list = subnet->getAdditionalClasses();
EXPECT_EQ(1, cclass_list.size());
auto cclasses = cclass_list.begin();
EXPECT_EQ(*cclasses, "foo");
}
// This test verifies that users cannot specify both
// require-client-classes and evaluate-addtional-classes.
TEST_F(Dhcp6ParserTest, deprecatedRequireClientClassesCheck2) {
std::string config = "{ " + genIfaceConfig() + ","
R"^(
"rebind-timer": 2000,
"renew-timer": 1000,
"subnet6": [{
"require-client-classes": [ "foo" ],
"evaluate-additional-classes": [ "foo" ],
"pools": [{ "pool": "2001:db8::/64" }],
"id": 1,
"subnet": "2001:db8::/64"
}],
"valid-lifetime": 400
})^";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
ConstElementPtr status;
ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json));
checkResult(status, 1,
"subnet configuration failed: cannot specify both 'require-client-classes'"
" and 'evaluate-additional-classes'. Use only the latter.");
}
// This test verifies that only-if-required gets translated
// to only-in-additional-list.
TEST_F(Dhcp6ParserTest, deprecatedOnlyIfRequiredCheck) {
std::string config = "{ " + genIfaceConfig() + ","
R"^(
"rebind-timer": 2000,
"renew-timer": 1000,
"client-classes": [{
"name": "foo",
"only-if-required": true
}],
"subnet6": [ ],
"valid-lifetime": 400
})^";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
ConstElementPtr status;
ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json));
checkResult(status, 0);
auto dictionary = CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
ASSERT_TRUE(dictionary);
EXPECT_EQ(1, dictionary->getClasses()->size());
ClientClassDefPtr class_def = dictionary->findClass("foo");
ASSERT_TRUE(class_def);
EXPECT_TRUE(class_def->getAdditional());
}
// This test verifies that users cannot specify both
// only-if-required and only-in-additional-list.
TEST_F(Dhcp6ParserTest, deprecatedOnlyIfRequiredCheck2) {
std::string config = "{ " + genIfaceConfig() + ","
R"^(
"rebind-timer": 2000,
"renew-timer": 1000,
"client-classes": [{
"name": "foo",
"only-if-required": true,
"only-in-additional-list": true
}],
"subnet6": [ ],
"valid-lifetime": 400
})^";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(config));
extractConfig(config);
ConstElementPtr status;
ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json));
checkResult(status, 1,
"cannot specify both 'only-if-required' and"
" 'only-in-additional-list'. Use only the latter.");
}
} // namespace