summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRazvan Becheriu <razvan@isc.org>2022-10-18 14:07:53 +0200
committerRazvan Becheriu <razvan@isc.org>2022-10-24 19:49:34 +0200
commit80e8c44897d6c28e49267ab623b1203db97c75fb (patch)
tree71eec5961abe7a2de6755002ad257fe06dd00e0e /src
parent[#248] using same add/get class interface (diff)
downloadkea-80e8c44897d6c28e49267ab623b1203db97c75fb.tar.xz
kea-80e8c44897d6c28e49267ab623b1203db97c75fb.zip
[#248] template classes can add regular classes
Diffstat (limited to 'src')
-rw-r--r--src/bin/d2/parser_context.cc20
-rw-r--r--src/bin/dhcp4/dhcp4_lexer.ll6
-rw-r--r--src/bin/dhcp4/dhcp4_parser.yy15
-rw-r--r--src/bin/dhcp4/dhcp4_srv.cc4
-rw-r--r--src/bin/dhcp4/tests/config_parser_unittest.cc4
-rw-r--r--src/bin/dhcp4/tests/fqdn_unittest.cc6
-rw-r--r--src/bin/dhcp4/tests/simple_parser4_unittest.cc6
-rw-r--r--src/bin/dhcp6/dhcp6_lexer.ll6
-rw-r--r--src/bin/dhcp6/dhcp6_parser.yy15
-rw-r--r--src/bin/dhcp6/dhcp6_srv.cc4
-rw-r--r--src/bin/dhcp6/tests/config_parser_unittest.cc4
-rw-r--r--src/bin/dhcp6/tests/fqdn_unittest.cc2
-rw-r--r--src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc24
-rw-r--r--src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc2
-rw-r--r--src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc2
-rw-r--r--src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc2
-rw-r--r--src/hooks/dhcp/run_script/tests/run_script_unittests.cc2
-rw-r--r--src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc4
-rw-r--r--src/hooks/dhcp/user_chk/pkt_send_co.cc4
-rw-r--r--src/hooks/dhcp/user_chk/user_file.cc2
-rw-r--r--src/lib/database/dbaccess_parser.cc1
-rw-r--r--src/lib/dhcp/classify.h28
-rw-r--r--src/lib/dhcp/pkt.cc18
-rw-r--r--src/lib/dhcp/pkt.h14
-rw-r--r--src/lib/dhcp/tests/pkt4_unittest.cc9
-rw-r--r--src/lib/dhcp/tests/pkt6_unittest.cc9
-rw-r--r--src/lib/dhcpsrv/alloc_engine.cc22
-rw-r--r--src/lib/dhcpsrv/client_class_def.cc8
-rw-r--r--src/lib/dhcpsrv/memfile_lease_mgr.cc20
-rw-r--r--src/lib/dhcpsrv/parsers/client_class_def_parser.cc40
-rw-r--r--src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc73
-rw-r--r--src/lib/dhcpsrv/tests/client_class_def_unittest.cc7
32 files changed, 215 insertions, 168 deletions
diff --git a/src/bin/d2/parser_context.cc b/src/bin/d2/parser_context.cc
index 703460a6de..f27a628c6a 100644
--- a/src/bin/d2/parser_context.cc
+++ b/src/bin/d2/parser_context.cc
@@ -169,25 +169,25 @@ D2ParserContext::contextName()
case TSIG_KEYS:
return ("tsig-keys");
case ALGORITHM:
- return ("algorithm");
+ return("algorithm");
case DIGEST_BITS:
- return ("digest-bits");
+ return("digest-bits");
case SECRET:
- return ("secret");
+ return("secret");
case FORWARD_DDNS:
- return ("forward-ddns");
+ return("forward-ddns");
case REVERSE_DDNS:
- return ("reverse-ddns");
+ return("reverse-ddns");
case DDNS_DOMAIN:
- return ("ddns-domain");
+ return("ddns-domain");
case DDNS_DOMAINS:
- return ("ddns-domains");
+ return("ddns-domains");
case DNS_SERVER:
- return ("dns-server");
+ return("dns-server");
case DNS_SERVERS:
- return ("dns-servers");
+ return("dns-servers");
case CONTROL_SOCKET:
- return ("control-socket");
+ return("control-socket");
case LOGGERS:
return ("loggers");
case OUTPUT_OPTIONS:
diff --git a/src/bin/dhcp4/dhcp4_lexer.ll b/src/bin/dhcp4/dhcp4_lexer.ll
index 1aebaf1551..ccd6a72530 100644
--- a/src/bin/dhcp4/dhcp4_lexer.ll
+++ b/src/bin/dhcp4/dhcp4_lexer.ll
@@ -1279,12 +1279,12 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
-\"template-class\" {
+\"template-test\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::CLIENT_CLASSES:
- return isc::dhcp::Dhcp4Parser::make_TEMPLATE_CLASS(driver.loc_);
+ return isc::dhcp::Dhcp4Parser::make_TEMPLATE_TEST(driver.loc_);
default:
- return isc::dhcp::Dhcp4Parser::make_STRING("template-class", driver.loc_);
+ return isc::dhcp::Dhcp4Parser::make_STRING("template-test", driver.loc_);
}
}
diff --git a/src/bin/dhcp4/dhcp4_parser.yy b/src/bin/dhcp4/dhcp4_parser.yy
index 9783cc9d18..f5c04dc8ce 100644
--- a/src/bin/dhcp4/dhcp4_parser.yy
+++ b/src/bin/dhcp4/dhcp4_parser.yy
@@ -170,7 +170,7 @@ using namespace std;
CLIENT_CLASSES "client-classes"
REQUIRE_CLIENT_CLASSES "require-client-classes"
TEST "test"
- TEMPLATE_CLASS "template-class"
+ TEMPLATE_TEST "template-test"
ONLY_IF_REQUIRED "only-if-required"
CLIENT_CLASS "client-class"
@@ -2336,7 +2336,7 @@ not_empty_client_class_params: client_class_param
client_class_param: client_class_name
| client_class_test
- | client_class_template_class
+ | client_class_template_test
| only_if_required
| option_def_list
| option_data_list
@@ -2362,10 +2362,13 @@ client_class_test: TEST {
ctx.leave();
};
-client_class_template_class: TEMPLATE_CLASS COLON BOOLEAN {
- ctx.unique("template-class", ctx.loc2pos(@1));
- ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
- ctx.stack_.back()->set("template-class", b);
+client_class_template_test: TEMPLATE_TEST {
+ ctx.unique("template-test", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr template_test(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("template-test", template_test);
+ ctx.leave();
};
only_if_required: ONLY_IF_REQUIRED COLON BOOLEAN {
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 017affde7f..df0b100047 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -250,7 +250,7 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
// Perform second pass of classification.
evaluateClasses(query, true);
- const ClientClasses& classes = query_->getClassesAndSubClasses();
+ const ClientClasses& classes = query_->getClasses();
if (!classes.empty()) {
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
.arg(query_->getLabel())
@@ -2489,7 +2489,7 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
Lease4Ptr lease;
- auto const& classes = query->getClassesAndSubClasses();
+ auto const& classes = query->getClasses();
// We used to issue a separate query (two actually: one for client-id
// and another one for hw-addr for) each subnet in the shared network.
diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc
index a263daf940..f80a8d6d64 100644
--- a/src/bin/dhcp4/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp4/tests/config_parser_unittest.cc
@@ -6103,11 +6103,11 @@ TEST_F(Dhcp4ParserTest, templateClientClassValidLifetime) {
" \"min-valid-lifetime\": 1000, \n"
" \"valid-lifetime\": 2000, \n"
" \"max-valid-lifetime\": 3000, \n"
- " \"template-class\": true, \n"
+ " \"template-test\": \"''\" \n"
" }, \n"
" { \n"
" \"name\": \"two\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" } \n"
"], \n"
"\"subnet4\": [ { \n"
diff --git a/src/bin/dhcp4/tests/fqdn_unittest.cc b/src/bin/dhcp4/tests/fqdn_unittest.cc
index 2caf0ec6dd..2a275c6041 100644
--- a/src/bin/dhcp4/tests/fqdn_unittest.cc
+++ b/src/bin/dhcp4/tests/fqdn_unittest.cc
@@ -398,7 +398,7 @@ public:
return (DdnsParamsPtr(new DdnsParams()));
}
- return (CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_));
+ return(CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_));
}
// Create a lease to be used by various tests.
@@ -457,8 +457,8 @@ public:
/// @return An std::string contained the generated FQDN.
std::string generatedNameFromAddress(const IOAddress& addr,
const bool trailing_dot = true) {
- return (CfgMgr::instance().getD2ClientMgr()
- .generateFqdn(addr, *getDdnsParams(), trailing_dot));
+ return(CfgMgr::instance().getD2ClientMgr()
+ .generateFqdn(addr, *getDdnsParams(), trailing_dot));
}
// Get the Client FQDN Option from the given message.
diff --git a/src/bin/dhcp4/tests/simple_parser4_unittest.cc b/src/bin/dhcp4/tests/simple_parser4_unittest.cc
index df104f8293..6ac157a99c 100644
--- a/src/bin/dhcp4/tests/simple_parser4_unittest.cc
+++ b/src/bin/dhcp4/tests/simple_parser4_unittest.cc
@@ -210,6 +210,6 @@ TEST_F(SimpleParser4Test, optionDefDefaults4) {
checkBoolValue(def, "array", false);
}
-}
-}
-}
+};
+};
+};
diff --git a/src/bin/dhcp6/dhcp6_lexer.ll b/src/bin/dhcp6/dhcp6_lexer.ll
index e9577eec15..6e6340a6fa 100644
--- a/src/bin/dhcp6/dhcp6_lexer.ll
+++ b/src/bin/dhcp6/dhcp6_lexer.ll
@@ -1611,12 +1611,12 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
-\"template-class\" {
+\"template-test\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::CLIENT_CLASSES:
- return isc::dhcp::Dhcp6Parser::make_TEMPLATE_CLASS(driver.loc_);
+ return isc::dhcp::Dhcp6Parser::make_TEMPLATE_TEST(driver.loc_);
default:
- return isc::dhcp::Dhcp6Parser::make_STRING("template-class", driver.loc_);
+ return isc::dhcp::Dhcp6Parser::make_STRING("template-test", driver.loc_);
}
}
diff --git a/src/bin/dhcp6/dhcp6_parser.yy b/src/bin/dhcp6/dhcp6_parser.yy
index 23d12eb637..18e90b911d 100644
--- a/src/bin/dhcp6/dhcp6_parser.yy
+++ b/src/bin/dhcp6/dhcp6_parser.yy
@@ -168,7 +168,7 @@ using namespace std;
CLIENT_CLASSES "client-classes"
REQUIRE_CLIENT_CLASSES "require-client-classes"
TEST "test"
- TEMPLATE_CLASS "template-class"
+ TEMPLATE_TEST "template-test"
ONLY_IF_REQUIRED "only-if-required"
CLIENT_CLASS "client-class"
@@ -2408,7 +2408,7 @@ not_empty_client_class_params: client_class_param
client_class_param: client_class_name
| client_class_test
- | client_class_template_class
+ | client_class_template_test
| only_if_required
| option_data_list
| user_context
@@ -2433,10 +2433,13 @@ client_class_test: TEST {
ctx.leave();
};
-client_class_template_class: TEMPLATE_CLASS COLON BOOLEAN {
- ctx.unique("template-class", ctx.loc2pos(@1));
- ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
- ctx.stack_.back()->set("template-class", b);
+client_class_template_test: TEMPLATE_TEST {
+ ctx.unique("template-test", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr template_test(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("template-test", template_test);
+ ctx.leave();
};
only_if_required: ONLY_IF_REQUIRED COLON BOOLEAN {
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 34f08986f6..dfad23ba04 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -569,7 +569,7 @@ Dhcpv6Srv::initContext(const Pkt6Ptr& pkt,
// Perform second pass of classification.
evaluateClasses(pkt, true);
- const ClientClasses& classes = pkt->getClassesAndSubClasses();
+ const ClientClasses& classes = pkt->getClasses();
if (!classes.empty()) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED)
.arg(pkt->getLabel())
@@ -4056,7 +4056,7 @@ Dhcpv6Srv::setReservedClientClasses(const Pkt6Ptr& pkt,
}
}
- const ClientClasses& classes = pkt->getClassesAndSubClasses();
+ const ClientClasses& classes = pkt->getClasses();
if (!classes.empty()) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED)
.arg(pkt->getLabel())
diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc
index cc3c6a8989..33b64c02b4 100644
--- a/src/bin/dhcp6/tests/config_parser_unittest.cc
+++ b/src/bin/dhcp6/tests/config_parser_unittest.cc
@@ -8169,11 +8169,11 @@ TEST_F(Dhcp6ParserTest, templateClientClassValidPreferredLifetime) {
" \"min-preferred-lifetime\": 4000, \n"
" \"preferred-lifetime\": 5000, \n"
" \"max-preferred-lifetime\": 6000, \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" }, \n"
" { \n"
" \"name\": \"two\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" } \n"
"], \n"
"\"subnet6\": [ { \n"
diff --git a/src/bin/dhcp6/tests/fqdn_unittest.cc b/src/bin/dhcp6/tests/fqdn_unittest.cc
index a26c0b7e8c..683a71cf62 100644
--- a/src/bin/dhcp6/tests/fqdn_unittest.cc
+++ b/src/bin/dhcp6/tests/fqdn_unittest.cc
@@ -145,7 +145,7 @@ public:
return (DdnsParamsPtr(new DdnsParams()));
}
- return (CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_));
+ return(CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_));
}
/// @brief Construct the DHCPv6 Client FQDN option using flags and
diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc b/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc
index b284aaab3f..7d431b40dd 100644
--- a/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc
+++ b/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc
@@ -34,7 +34,7 @@ extern "C" {
/// 1 otherwise.
int lease4_add(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.leaseAddHandler(handle));
+ return(lease_cmds.leaseAddHandler(handle));
}
/// @brief This is a command callout for 'lease6-add' command.
@@ -45,7 +45,7 @@ int lease4_add(CalloutHandle& handle) {
/// 1 otherwise.
int lease6_add(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.leaseAddHandler(handle));
+ return(lease_cmds.leaseAddHandler(handle));
}
/// @brief This is a command callout for 'lease6-bulk-apply' command.
@@ -67,7 +67,7 @@ int lease6_bulk_apply(CalloutHandle& handle) {
/// 1 otherwise.
int lease4_get(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.leaseGetHandler(handle));
+ return(lease_cmds.leaseGetHandler(handle));
}
/// @brief This is a command callout for 'lease6-get' command.
@@ -78,7 +78,7 @@ int lease4_get(CalloutHandle& handle) {
/// 1 otherwise.
int lease6_get(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.leaseGetHandler(handle));
+ return(lease_cmds.leaseGetHandler(handle));
}
/// @brief This is a command callout for 'lease4-get-all' command.
@@ -188,7 +188,7 @@ int lease6_get_by_hostname(CalloutHandle& handle) {
/// 1 otherwise.
int lease4_del(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease4DelHandler(handle));
+ return(lease_cmds.lease4DelHandler(handle));
}
/// @brief This is a command callout for 'lease6-del' command.
@@ -199,7 +199,7 @@ int lease4_del(CalloutHandle& handle) {
/// 1 otherwise.
int lease6_del(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease6DelHandler(handle));
+ return(lease_cmds.lease6DelHandler(handle));
}
/// @brief This is a command callout for 'lease4-update' command.
@@ -210,7 +210,7 @@ int lease6_del(CalloutHandle& handle) {
/// 1 otherwise.
int lease4_update(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease4UpdateHandler(handle));
+ return(lease_cmds.lease4UpdateHandler(handle));
}
/// @brief This is a command callout for 'lease6-update' command.
@@ -221,7 +221,7 @@ int lease4_update(CalloutHandle& handle) {
/// 1 otherwise.
int lease6_update(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease6UpdateHandler(handle));
+ return(lease_cmds.lease6UpdateHandler(handle));
}
/// @brief This is a command callout for 'lease4-wipe' command.
@@ -232,7 +232,7 @@ int lease6_update(CalloutHandle& handle) {
/// 1 otherwise.
int lease4_wipe(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease4WipeHandler(handle));
+ return(lease_cmds.lease4WipeHandler(handle));
}
/// @brief This is a command callout for 'lease6-wipe' command.
@@ -243,7 +243,7 @@ int lease4_wipe(CalloutHandle& handle) {
/// 1 otherwise.
int lease6_wipe(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease6WipeHandler(handle));
+ return(lease_cmds.lease6WipeHandler(handle));
}
/// @brief This is a command callout for 'lease4-resend-ddns' command.
@@ -254,7 +254,7 @@ int lease6_wipe(CalloutHandle& handle) {
/// 1 otherwise.
int lease4_resend_ddns(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease4ResendDdnsHandler(handle));
+ return(lease_cmds.lease4ResendDdnsHandler(handle));
}
/// @brief This is a command callout for 'lease6-resend-ddns' command.
@@ -265,7 +265,7 @@ int lease4_resend_ddns(CalloutHandle& handle) {
/// 1 otherwise.
int lease6_resend_ddns(CalloutHandle& handle) {
LeaseCmds lease_cmds;
- return (lease_cmds.lease6ResendDdnsHandler(handle));
+ return(lease_cmds.lease6ResendDdnsHandler(handle));
}
/// @brief This is a command callout for 'lease4-write' command.
diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc
index d70fa258c1..afaceced64 100644
--- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc
+++ b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc
@@ -4525,7 +4525,7 @@ PgSqlConfigBackendDHCPv4Impl::getStatement(size_t index) const {
<< index << ", is invalid");
}
- return (tagged_statements[index]);
+ return(tagged_statements[index]);
}
PgSqlConfigBackendDHCPv4::PgSqlConfigBackendDHCPv4(const DatabaseConnection::ParameterMap& parameters)
diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc
index b78b4d63e3..5ad7e43188 100644
--- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc
+++ b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc
@@ -4994,7 +4994,7 @@ PgSqlConfigBackendDHCPv6Impl::getStatement(size_t index) const {
<< index << ", is invalid");
}
- return (tagged_statements[index]);
+ return(tagged_statements[index]);
}
PgSqlConfigBackendDHCPv6::PgSqlConfigBackendDHCPv6(const DatabaseConnection::ParameterMap& parameters)
diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc
index c04eb74c14..4399cb08a2 100644
--- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc
+++ b/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc
@@ -50,7 +50,7 @@ PgSqlConfigBackendImpl::insertQuery(size_t index,
uint64_t
PgSqlConfigBackendImpl::updateDeleteQuery(size_t index,
const PsqlBindArray& in_bindings) {
- return (conn_.updateDeleteQuery(getStatement(index), in_bindings));
+ return(conn_.updateDeleteQuery(getStatement(index), in_bindings));
}
PgSqlConfigBackendImpl::ScopedAuditRevision::ScopedAuditRevision(
diff --git a/src/hooks/dhcp/run_script/tests/run_script_unittests.cc b/src/hooks/dhcp/run_script/tests/run_script_unittests.cc
index 7ca5babee7..46d9c8d277 100644
--- a/src/hooks/dhcp/run_script/tests/run_script_unittests.cc
+++ b/src/hooks/dhcp/run_script/tests/run_script_unittests.cc
@@ -156,7 +156,7 @@ generateLease4() {
Lease4Ptr lease4(new Lease4(IOAddress("192.168.0.1"), hwaddr, clientid,
2, 3, 4, false, false, "test.hostname"));
- return (lease4);
+ return(lease4);
}
/// @brief Generate a valid Lease6.
diff --git a/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc b/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc
index df90c55fe1..228772f981 100644
--- a/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc
+++ b/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc
@@ -32,7 +32,7 @@ extern "C" {
/// 1 otherwise.
int stat_lease4_get(CalloutHandle& handle) {
StatCmds stat_cmds;
- return (stat_cmds.statLease4GetHandler(handle));
+ return(stat_cmds.statLease4GetHandler(handle));
}
/// @brief This is a command callout for 'stat-lease6-get' command.
@@ -43,7 +43,7 @@ int stat_lease4_get(CalloutHandle& handle) {
/// 1 otherwise.
int stat_lease6_get(CalloutHandle& handle) {
StatCmds stat_cmds;
- return (stat_cmds.statLease6GetHandler(handle));
+ return(stat_cmds.statLease6GetHandler(handle));
}
/// @brief This function is called when the library is loaded.
diff --git a/src/hooks/dhcp/user_chk/pkt_send_co.cc b/src/hooks/dhcp/user_chk/pkt_send_co.cc
index 788d133022..740bc4b6c3 100644
--- a/src/hooks/dhcp/user_chk/pkt_send_co.cc
+++ b/src/hooks/dhcp/user_chk/pkt_send_co.cc
@@ -402,7 +402,7 @@ void generate_output_record(const std::string& id_type_str,
std::string getV6AddrStr(Pkt6Ptr response) {
OptionPtr tmp = response->getOption(D6O_IA_NA);
if (tmp) {
- return (getAddrStrIA_NA(tmp));
+ return(getAddrStrIA_NA(tmp));
}
// IA_NA not there so try IA_PD
@@ -411,7 +411,7 @@ std::string getV6AddrStr(Pkt6Ptr response) {
isc_throw (isc::BadValue, "Response has neither IA_NA nor IA_PD");
}
- return (getAddrStrIA_PD(tmp));
+ return(getAddrStrIA_PD(tmp));
}
/// @brief Stringify the lease address in an D6O_IA_NA option set
diff --git a/src/hooks/dhcp/user_chk/user_file.cc b/src/hooks/dhcp/user_chk/user_file.cc
index e324bcb2b0..96cb6a0fc4 100644
--- a/src/hooks/dhcp/user_chk/user_file.cc
+++ b/src/hooks/dhcp/user_chk/user_file.cc
@@ -54,7 +54,7 @@ UserFile::readNextUser() {
// We got something, try to make a user out of it.
if (file_.gcount() > 0) {
- return (makeUser(buf));
+ return(makeUser(buf));
}
}
diff --git a/src/lib/database/dbaccess_parser.cc b/src/lib/database/dbaccess_parser.cc
index 76ba13799e..caee236282 100644
--- a/src/lib/database/dbaccess_parser.cc
+++ b/src/lib/database/dbaccess_parser.cc
@@ -91,7 +91,6 @@ DbAccessParser::parse(std::string& access_string,
max_row_errors = param.second->intValue();
values_copy[param.first] =
boost::lexical_cast<std::string>(max_row_errors);
-
} else {
// all remaining string parameters
diff --git a/src/lib/dhcp/classify.h b/src/lib/dhcp/classify.h
index 0c857048ea..f7d38c4c39 100644
--- a/src/lib/dhcp/classify.h
+++ b/src/lib/dhcp/classify.h
@@ -64,9 +64,9 @@ namespace dhcp {
> ClientClassContainer;
/// @brief Defines a single subclass (template class instantiation).
- struct SubClass {
+ struct SubClassRelation {
/// @brief Constructor.
- SubClass(const ClientClass& template_class, const ClientClass& subclass) :
+ SubClassRelation(const ClientClass& template_class, const ClientClass& subclass) :
template_class_(template_class), subclass_(subclass) {
}
@@ -77,6 +77,30 @@ namespace dhcp {
ClientClass subclass_;
};
+ /// @brief Tag for the sequence index.
+ struct TemplateClassSequenceTag { };
+
+ /// @brief Tag for the name index.
+ struct TemplateClassNameTag { };
+
+ /// @brief the subclass multi-index.
+ typedef boost::multi_index_container<
+ SubClassRelation,
+ boost::multi_index::indexed_by<
+ // First index is the sequence one.
+ boost::multi_index::sequenced<
+ boost::multi_index::tag<TemplateClassSequenceTag>
+ >,
+ // Second index is the name hash one.
+ boost::multi_index::hashed_unique<
+ boost::multi_index::tag<TemplateClassNameTag>,
+ boost::multi_index::member<SubClassRelation,
+ ClientClass,
+ &SubClassRelation::template_class_>
+ >
+ >
+ > SubClassRelationContainer;
+
/// @brief Container for storing client class names
///
/// Both a list to iterate on it in insert order and unordered
diff --git a/src/lib/dhcp/pkt.cc b/src/lib/dhcp/pkt.cc
index f70043edf2..fa85b0070b 100644
--- a/src/lib/dhcp/pkt.cc
+++ b/src/lib/dhcp/pkt.cc
@@ -77,10 +77,7 @@ Pkt::delOption(uint16_t type) {
bool
Pkt::inClass(const ClientClass& client_class) {
- if (classes_.contains(client_class)) {
- return (true);
- }
- return (subclasses_.contains(client_class));
+ return (classes_.contains(client_class));
}
void
@@ -92,9 +89,7 @@ Pkt::addClass(const ClientClass& client_class, bool required) {
ClientClasses& classes = !required ? classes_ : required_classes_;
if (!classes.contains(client_class)) {
classes.insert(client_class);
- if (!subclasses_.empty()) {
- subclasses_.insert(client_class);
- }
+ static_cast<void>(subclasses_.push_back(SubClassRelation(client_class, client_class)));
}
}
@@ -105,11 +100,12 @@ Pkt::addSubClass(const ClientClass& template_class, const ClientClass& subclass)
classes_.insert("ALL");
}
if (!classes_.contains(template_class)) {
- if (subclasses_.empty()) {
- subclasses_ = classes_;
- }
classes_.insert(template_class);
- subclasses_.insert(subclass);
+ static_cast<void>(subclasses_.push_back(SubClassRelation(template_class, subclass)));
+ }
+ if (!classes_.contains(subclass)) {
+ classes_.insert(subclass);
+ static_cast<void>(subclasses_.push_back(SubClassRelation(subclass, subclass)));
}
}
diff --git a/src/lib/dhcp/pkt.h b/src/lib/dhcp/pkt.h
index 89cfb4c39c..dd1e395f39 100644
--- a/src/lib/dhcp/pkt.h
+++ b/src/lib/dhcp/pkt.h
@@ -327,13 +327,6 @@ public:
return (!required ? classes_ : required_classes_);
}
- /// @brief Returns true if the subclass set is not empty
- ///
- /// @return true if there is at least one subclass associated with the packet.
- bool hasSubClasses() const {
- return (!subclasses_.empty());
- }
-
/// @brief Returns the class set including template classes associated with
/// subclasses
///
@@ -343,10 +336,7 @@ public:
/// @return if required is false (the default) the classes the
/// packet belongs to else the classes which are required to be
/// evaluated.
- const ClientClasses getClassesAndSubClasses() const {
- if (subclasses_.empty()) {
- return (classes_);
- }
+ const SubClassRelationContainer& getSubClassesRelations() const {
return (subclasses_);
}
@@ -662,7 +652,7 @@ public:
/// iterate over existing classes. Having it public also solves the problem
/// of returned reference lifetime. It is preferred to use @ref inClass and
/// @ref addSubClass to operate on this field.
- ClientClasses subclasses_;
+ SubClassRelationContainer subclasses_;
/// @brief Collection of options present in this message.
///
diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc
index 1bd45b5ce6..4687835a87 100644
--- a/src/lib/dhcp/tests/pkt4_unittest.cc
+++ b/src/lib/dhcp/tests/pkt4_unittest.cc
@@ -933,14 +933,12 @@ TEST_F(Pkt4Test, clientClasses) {
EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_EROUTER));
EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM));
EXPECT_TRUE(pkt.getClasses().empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to the first class
pkt.addClass(DOCSIS3_CLASS_EROUTER);
EXPECT_TRUE(pkt.inClass(DOCSIS3_CLASS_EROUTER));
EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM));
ASSERT_FALSE(pkt.getClasses().empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to a second class
pkt.addClass(DOCSIS3_CLASS_MODEM);
@@ -951,7 +949,6 @@ TEST_F(Pkt4Test, clientClasses) {
EXPECT_NO_THROW(pkt.addClass("foo"));
EXPECT_NO_THROW(pkt.addClass("foo"));
EXPECT_NO_THROW(pkt.addClass("foo"));
- EXPECT_FALSE(pkt.hasSubClasses());
// Check that the packet belongs to 'foo'
EXPECT_TRUE(pkt.inClass("foo"));
@@ -964,17 +961,14 @@ TEST_F(Pkt4Test, deferredClientClasses) {
// Default values (do not belong to any class)
EXPECT_TRUE(pkt.getClasses(true).empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to the first class
pkt.addClass(DOCSIS3_CLASS_EROUTER, true);
EXPECT_EQ(1, pkt.getClasses(true).size());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to a second class
pkt.addClass(DOCSIS3_CLASS_MODEM, true);
EXPECT_EQ(2, pkt.getClasses(true).size());
- EXPECT_FALSE(pkt.hasSubClasses());
EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_EROUTER));
EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_MODEM));
EXPECT_FALSE(pkt.getClasses(true).contains("foo"));
@@ -983,7 +977,6 @@ TEST_F(Pkt4Test, deferredClientClasses) {
EXPECT_NO_THROW(pkt.addClass("foo", true));
EXPECT_NO_THROW(pkt.addClass("foo", true));
EXPECT_NO_THROW(pkt.addClass("foo", true));
- EXPECT_FALSE(pkt.hasSubClasses());
// Check that the packet belongs to 'foo'
EXPECT_TRUE(pkt.getClasses(true).contains("foo"));
@@ -998,14 +991,12 @@ TEST_F(Pkt4Test, templateClasses) {
EXPECT_FALSE(pkt.inClass("eth0"));
EXPECT_FALSE(pkt.inClass("interface-id0"));
EXPECT_TRUE(pkt.getClasses().empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to the first subclass
pkt.addSubClass("template-interface-name", "eth0");
EXPECT_TRUE(pkt.inClass("eth0"));
EXPECT_FALSE(pkt.inClass("interface-id0"));
ASSERT_FALSE(pkt.getClasses().empty());
- EXPECT_TRUE(pkt.hasSubClasses());
// Add to a second subclass
pkt.addSubClass("template-interface-id", "interface-id0");
diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc
index f92f4168f5..f433bae6b6 100644
--- a/src/lib/dhcp/tests/pkt6_unittest.cc
+++ b/src/lib/dhcp/tests/pkt6_unittest.cc
@@ -1307,14 +1307,12 @@ TEST_F(Pkt6Test, clientClasses) {
EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_EROUTER));
EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM));
EXPECT_TRUE(pkt.getClasses().empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to the first class
pkt.addClass(DOCSIS3_CLASS_EROUTER);
EXPECT_TRUE(pkt.inClass(DOCSIS3_CLASS_EROUTER));
EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM));
ASSERT_FALSE(pkt.getClasses().empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to a second class
pkt.addClass(DOCSIS3_CLASS_MODEM);
@@ -1325,7 +1323,6 @@ TEST_F(Pkt6Test, clientClasses) {
EXPECT_NO_THROW(pkt.addClass("foo"));
EXPECT_NO_THROW(pkt.addClass("foo"));
EXPECT_NO_THROW(pkt.addClass("foo"));
- EXPECT_FALSE(pkt.hasSubClasses());
// Check that the packet belongs to 'foo'
EXPECT_TRUE(pkt.inClass("foo"));
@@ -1338,17 +1335,14 @@ TEST_F(Pkt6Test, deferredClientClasses) {
// Default values (do not belong to any class)
EXPECT_TRUE(pkt.getClasses(true).empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to the first class
pkt.addClass(DOCSIS3_CLASS_EROUTER, true);
EXPECT_EQ(1, pkt.getClasses(true).size());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to a second class
pkt.addClass(DOCSIS3_CLASS_MODEM, true);
EXPECT_EQ(2, pkt.getClasses(true).size());
- EXPECT_FALSE(pkt.hasSubClasses());
EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_EROUTER));
EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_MODEM));
EXPECT_FALSE(pkt.getClasses(true).contains("foo"));
@@ -1357,7 +1351,6 @@ TEST_F(Pkt6Test, deferredClientClasses) {
EXPECT_NO_THROW(pkt.addClass("foo", true));
EXPECT_NO_THROW(pkt.addClass("foo", true));
EXPECT_NO_THROW(pkt.addClass("foo", true));
- EXPECT_FALSE(pkt.hasSubClasses());
// Check that the packet belongs to 'foo'
EXPECT_TRUE(pkt.getClasses(true).contains("foo"));
@@ -1372,14 +1365,12 @@ TEST_F(Pkt6Test, templateClasses) {
EXPECT_FALSE(pkt.inClass("eth0"));
EXPECT_FALSE(pkt.inClass("interface-id0"));
EXPECT_TRUE(pkt.getClasses().empty());
- EXPECT_FALSE(pkt.hasSubClasses());
// Add to the first subclass
pkt.addSubClass("template-interface-name", "eth0");
EXPECT_TRUE(pkt.inClass("eth0"));
EXPECT_FALSE(pkt.inClass("interface-id0"));
ASSERT_FALSE(pkt.getClasses().empty());
- EXPECT_TRUE(pkt.hasSubClasses());
// Add to a second subclass
pkt.addSubClass("template-interface-id", "interface-id0");
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index b514055669..9fcdcce2ec 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -425,7 +425,7 @@ inAllowedPool(AllocEngine::ClientContext6& ctx, const Lease::Type& lease_type,
// If the subnet belongs to a shared network we will be iterating
// over the subnets that belong to this shared network.
Subnet6Ptr current_subnet = ctx.subnet_;
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
while (current_subnet) {
if (current_subnet->clientSupported(classes)) {
@@ -658,7 +658,7 @@ AllocEngine::findReservation(ClientContext6& ctx) {
}
}
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
// We can only search for the reservation if a subnet has been selected.
while (subnet) {
@@ -919,7 +919,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
CalloutHandle::CalloutNextStep callout_status = CalloutHandle::NEXT_STEP_CONTINUE;
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
if (!subnet->clientSupported(classes)) {
@@ -1360,7 +1360,7 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx,
// There is no lease for a reservation in this IA. So, let's now iterate
// over reservations specified and try to allocate one of them for the IA.
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
for (Subnet6Ptr subnet = ctx.subnet_; subnet;
subnet = subnet->getNextSubnet(ctx.subnet_)) {
@@ -2259,7 +2259,7 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) {
// is not permitted by subnet client classification, delete it.
if (!(ctx.hasGlobalReservation(makeIPv6Resrv(*lease))) &&
(((lease->type_ != Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
- !ctx.subnet_->clientSupported(ctx.query_->getClassesAndSubClasses()))) {
+ !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
// Oh dear, the lease is no longer valid. We need to get rid of it.
// Remove this lease from LeaseMgr
@@ -3290,7 +3290,7 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) {
// No address reservation found here, so let's try another subnet
// within the same shared network.
- subnet = subnet->getNextSubnet(ctx.subnet_, ctx.query_->getClassesAndSubClasses());
+ subnet = subnet->getNextSubnet(ctx.subnet_, ctx.query_->getClasses());
}
return (false);
@@ -3316,7 +3316,7 @@ void findClientLease(AllocEngine::ClientContext4& ctx, Lease4Ptr& client_lease)
Subnet4Ptr original_subnet = ctx.subnet_;
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
// Client identifier is optional. First check if we can try to lookup
// by client-id.
@@ -3401,7 +3401,7 @@ inAllowedPool(AllocEngine::ClientContext4& ctx, const IOAddress& address) {
// If the subnet belongs to a shared network we will be iterating
// over the subnets that belong to this shared network.
Subnet4Ptr current_subnet = ctx.subnet_;
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
while (current_subnet) {
if (current_subnet->inPool(Lease::TYPE_V4, address, classes)) {
@@ -3513,7 +3513,7 @@ AllocEngine::allocateLease4(ClientContext4& ctx) {
// subnets allowed for this client within the shared network, we
// can't allocate a lease.
Subnet4Ptr subnet = ctx.subnet_;
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
if (subnet && !subnet->clientSupported(classes)) {
ctx.subnet_ = subnet->getNextSubnet(subnet, classes);
}
@@ -3604,7 +3604,7 @@ AllocEngine::findReservation(ClientContext4& ctx) {
}
}
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
// We can only search for the reservation if a subnet has been selected.
while (subnet) {
@@ -4411,7 +4411,7 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
// no matching pools for the client.
uint64_t subnets_with_unavail_pools = 0;
- auto const& classes = ctx.query_->getClassesAndSubClasses();
+ auto const& classes = ctx.query_->getClasses();
while (subnet) {
ClientIdPtr client_id;
diff --git a/src/lib/dhcpsrv/client_class_def.cc b/src/lib/dhcpsrv/client_class_def.cc
index 53e229994d..53e382bde9 100644
--- a/src/lib/dhcpsrv/client_class_def.cc
+++ b/src/lib/dhcpsrv/client_class_def.cc
@@ -294,7 +294,13 @@ ClientClassDef::toElement() const {
ElementPtr
TemplateClientClassDef::toElement() const {
auto const& result = ClientClassDef::toElement();
- result->set("template-class", Element::create(true));
+ auto const& test = result->get("test");
+ if (test) {
+ result->set("template-test", test);
+ result->remove("test");
+ } else {
+ result->set("template-test", Element::create(""));
+ }
return (result);
}
diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc
index 61c8ce8747..c62fe59610 100644
--- a/src/lib/dhcpsrv/memfile_lease_mgr.cc
+++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc
@@ -1882,7 +1882,7 @@ Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename,
lease_file.reset(new LeaseFileType(filename));
LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage,
max_row_errors, false);
- conversion_needed = conversion_needed || lease_file->needsConversion();
+ conversion_needed = conversion_needed || lease_file->needsConversion();
return (conversion_needed);
}
@@ -2006,7 +2006,7 @@ Memfile_LeaseMgr::startLeaseStatsQuery4() {
query->start();
}
- return (query);
+ return(query);
}
LeaseStatsQueryPtr
@@ -2019,7 +2019,7 @@ Memfile_LeaseMgr::startSubnetLeaseStatsQuery4(const SubnetID& subnet_id) {
query->start();
}
- return (query);
+ return(query);
}
LeaseStatsQueryPtr
@@ -2034,7 +2034,7 @@ Memfile_LeaseMgr::startSubnetRangeLeaseStatsQuery4(const SubnetID& first_subnet_
query->start();
}
- return (query);
+ return(query);
}
LeaseStatsQueryPtr
@@ -2047,7 +2047,7 @@ Memfile_LeaseMgr::startLeaseStatsQuery6() {
query->start();
}
- return (query);
+ return(query);
}
LeaseStatsQueryPtr
@@ -2060,7 +2060,7 @@ Memfile_LeaseMgr::startSubnetLeaseStatsQuery6(const SubnetID& subnet_id) {
query->start();
}
- return (query);
+ return(query);
}
LeaseStatsQueryPtr
@@ -2075,7 +2075,7 @@ Memfile_LeaseMgr::startSubnetRangeLeaseStatsQuery6(const SubnetID& first_subnet_
query->start();
}
- return (query);
+ return(query);
}
size_t
@@ -2163,15 +2163,15 @@ Memfile_LeaseMgr::getClassLeaseCount(const ClientClass& client_class,
const Lease::Type& ltype /* = Lease::TYPE_V4*/) const {
if (MultiThreadingMgr::instance().getMode()) {
std::lock_guard<std::mutex> lock(*mutex_);
- return (class_lease_counter_.getClassCount(client_class, ltype));
+ return(class_lease_counter_.getClassCount(client_class, ltype));
} else {
- return (class_lease_counter_.getClassCount(client_class, ltype));
+ return(class_lease_counter_.getClassCount(client_class, ltype));
}
}
void
Memfile_LeaseMgr::clearClassLeaseCounts() {
- return (class_lease_counter_.clear());
+ return(class_lease_counter_.clear());
}
std::string
diff --git a/src/lib/dhcpsrv/parsers/client_class_def_parser.cc b/src/lib/dhcpsrv/parsers/client_class_def_parser.cc
index 8c48a9afbc..99e6692571 100644
--- a/src/lib/dhcpsrv/parsers/client_class_def_parser.cc
+++ b/src/lib/dhcpsrv/parsers/client_class_def_parser.cc
@@ -50,6 +50,12 @@ ExpressionParser::parse(ExpressionPtr& expression,
// by str() enclosed in quotes.
std::string value;
expression_cfg->getValue(value);
+
+ if (parser_type == EvalContext::PARSER_STRING && value.empty()) {
+ isc_throw(DhcpConfigError, "expression can not be empty at ("
+ << expression_cfg->getPosition() << ")");
+ }
+
try {
EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6,
check_defined);
@@ -83,29 +89,33 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
EvalContext::ParserType parser_type = EvalContext::PARSER_BOOL;
- // Let's try to parse the template-class flag
+ // Let's try to parse the template-test expression
bool is_template = false;
- if (class_def_cfg->contains("template-class")) {
- is_template = getBoolean(class_def_cfg, "template-class");
- if (is_template) {
- parser_type = EvalContext::PARSER_STRING;
- }
- }
// Parse matching expression
ExpressionPtr match_expr;
ConstElementPtr test_cfg = class_def_cfg->get("test");
+ ConstElementPtr template_test_cfg = class_def_cfg->get("template-test");
+ if (test_cfg && template_test_cfg) {
+ isc_throw(DhcpConfigError, "expected either 'test' or 'template-test' ("
+ << test_cfg->getPosition() << ") and ("
+ << template_test_cfg->getPosition() << ")");
+ }
std::string test;
bool depend_on_known = false;
+ EvalContext::CheckDefined check_defined = EvalContext::acceptAll;
+ if (template_test_cfg) {
+ test_cfg = template_test_cfg;
+ parser_type = EvalContext::PARSER_STRING;
+ is_template = true;
+ } else {
+ check_defined = [&class_dictionary, &depend_on_known, check_dependencies](const ClientClass& cclass) {
+ return (!check_dependencies || isClientClassDefined(class_dictionary, depend_on_known, cclass));
+ };
+ }
+
if (test_cfg) {
ExpressionParser parser;
- auto check_defined =
- [&class_dictionary, &depend_on_known, check_dependencies]
- (const ClientClass& cclass) {
- return (!check_dependencies || isClientClassDefined(class_dictionary,
- depend_on_known,
- cclass));
- };
parser.parse(match_expr, test_cfg, family, check_defined, parser_type);
test = test_cfg->stringValue();
}
@@ -285,7 +295,7 @@ ClientClassDefParser::checkParametersSupported(const ConstElementPtr& class_def_
"valid-lifetime",
"min-valid-lifetime",
"max-valid-lifetime",
- "template-class"};
+ "template-test"};
// The v4 client class supports additional parameters.
static std::set<std::string> supported_params_v4 = { "option-def",
diff --git a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
index 305d024c52..0ca5f0450a 100644
--- a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
+++ b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
@@ -378,7 +378,7 @@ TEST_F(ClientClassDefParserTest, checkAllSupported4) {
" \"min-valid-lifetime\": 1000,\n"
" \"max-valid-lifetime\": 1000,\n"
" \"next-server\": \"192.0.2.3\",\n"
- " \"template-class\": true,\n"
+ " \"template-test\": \"\",\n"
" \"server-hostname\": \"myhost\",\n"
" \"boot-file-name\": \"efi\""
"}\n";
@@ -400,7 +400,7 @@ TEST_F(ClientClassDefParserTest, checkAllSupported6) {
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
" \"only-if-required\": false,\n"
- " \"template-class\": true,\n"
+ " \"template-test\": \"\",\n"
" \"preferred-lifetime\": 800,\n"
" \"min-preferred-lifetime\": 800,\n"
" \"max-preferred-lifetime\": 800\n"
@@ -638,8 +638,7 @@ TEST_F(ClientClassDefParserTest, templateNameAndExpressionClass4) {
std::string cfg_text =
"{ \n"
" \"name\": \"class_one\", \n"
- " \"template-class\": true, \n"
- " \"test\": \"" + test + "\" \n"
+ " \"template-test\": \"" + test + "\" \n"
"} \n";
ClientClassDefPtr cclass;
@@ -730,8 +729,7 @@ TEST_F(ClientClassDefParserTest, templateNameAndExpressionClass6) {
std::string cfg_text =
"{ \n"
" \"name\": \"class_one\", \n"
- " \"template-class\": true, \n"
- " \"test\": \"" + test + "\" \n"
+ " \"template-test\": \"" + test + "\" \n"
"} \n";
ClientClassDefPtr cclass;
@@ -894,8 +892,7 @@ TEST_F(ClientClassDefParserTest, templateBasicValidClass4) {
std::string cfg_text =
"{ \n"
" \"name\": \"MICROSOFT\", \n"
- " \"test\": \"" + test + "\", \n"
- " \"template-class\": true, \n"
+ " \"template-test\": \"" + test + "\", \n"
" \"option-data\": [ \n"
" { \n"
" \"name\": \"domain-name-servers\", \n"
@@ -994,8 +991,7 @@ TEST_F(ClientClassDefParserTest, templateBasicValidClass6) {
std::string cfg_text =
"{ \n"
" \"name\": \"MICROSOFT\", \n"
- " \"test\": \"" + test + "\", \n"
- " \"template-class\": true, \n"
+ " \"template-test\": \"" + test + "\", \n"
" \"option-data\": [ \n"
" { \n"
" \"name\": \"sip-server-addr\", \n"
@@ -1095,13 +1091,38 @@ TEST_F(ClientClassDefParserTest, invalidExpression) {
DhcpConfigError);
}
-// Verifies that a class with an invalid expression, fails to parse.
+// Verifies that a class with an invalid template expression, fails to parse.
TEST_F(ClientClassDefParserTest, templateInvalidExpression) {
std::string cfg_text =
"{ \n"
" \"name\": \"one\", \n"
- " \"template-class\": true, \n"
- " \"test\": 777 \n"
+ " \"template-test\": 777 \n"
+ "} \n";
+
+ ClientClassDefPtr cclass;
+ ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET6),
+ DhcpConfigError);
+}
+
+// Verifies that a class with an empty expression, fails to parse.
+TEST_F(ClientClassDefParserTest, emptyExpression) {
+ std::string cfg_text =
+ "{ \n"
+ " \"name\": \"one\", \n"
+ " \"test\": \"\" \n"
+ "} \n";
+
+ ClientClassDefPtr cclass;
+ ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET6),
+ DhcpConfigError);
+}
+
+// Verifies that a class with an empty expression, fails to parse.
+TEST_F(ClientClassDefParserTest, templateEmptyExpression) {
+ std::string cfg_text =
+ "{ \n"
+ " \"name\": \"one\", \n"
+ " \"template-test\": \"\" \n"
"} \n";
ClientClassDefPtr cclass;
@@ -1109,6 +1130,20 @@ TEST_F(ClientClassDefParserTest, templateInvalidExpression) {
DhcpConfigError);
}
+// Verifies that a class with both test and template-test expressions, fails to parse.
+TEST_F(ClientClassDefParserTest, bothTestAndTemplateTestExpressions) {
+ std::string cfg_text =
+ "{ \n"
+ " \"name\": \"one\", \n"
+ " \"test\": \"true\", \n"
+ " \"template-test\": \"\" \n"
+ "} \n";
+
+ ClientClassDefPtr cclass;
+ ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
+ DhcpConfigError);
+}
+
// Verifies that a class with invalid option-def, fails to parse.
TEST_F(ClientClassDefParserTest, invalidOptionDef) {
std::string cfg_text =
@@ -1187,15 +1222,15 @@ TEST_F(ClientClassDefListParserTest, templateSimpleValidList) {
"[ \n"
" { \n"
" \"name\": \"one\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" }, \n"
" { \n"
" \"name\": \"two\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" }, \n"
" { \n"
" \"name\": \"three\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" } \n"
"] \n";
@@ -1257,15 +1292,15 @@ TEST_F(ClientClassDefListParserTest, templateDuplicateClass) {
"[ \n"
" { \n"
" \"name\": \"one\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" }, \n"
" { \n"
" \"name\": \"two\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" }, \n"
" { \n"
" \"name\": \"two\", \n"
- " \"template-class\": true \n"
+ " \"template-test\": \"''\" \n"
" } \n"
"] \n";
diff --git a/src/lib/dhcpsrv/tests/client_class_def_unittest.cc b/src/lib/dhcpsrv/tests/client_class_def_unittest.cc
index f0f0e8451f..e7894a52c3 100644
--- a/src/lib/dhcpsrv/tests/client_class_def_unittest.cc
+++ b/src/lib/dhcpsrv/tests/client_class_def_unittest.cc
@@ -1510,7 +1510,7 @@ TEST(TemplateClientClassDef, unparseDef) {
std::string name = "class1";
ExpressionPtr expr;
ASSERT_NO_THROW(cclass.reset(new TemplateClientClassDef(name, expr)));
- std::string test = "option[12].text == 'foo'";
+ std::string test = "option[12].text";
cclass->setTest(test);
std::string comment = "bar";
std::string user_context = "{ \"comment\": \"" + comment + "\", ";
@@ -1529,11 +1529,10 @@ TEST(TemplateClientClassDef, unparseDef) {
// Unparse it
std::string expected = "{\n"
"\"name\": \"" + name + "\",\n"
- "\"test\": \"" + test + "\",\n"
+ "\"template-test\": \"" + test + "\",\n"
"\"only-if-required\": true,\n"
"\"next-server\": \"" + next_server + "\",\n"
"\"server-hostname\": \"" + sname + "\",\n"
- "\"template-class\": true,\n"
"\"boot-file-name\": \"" + filename + "\",\n"
"\"option-data\": [ ],\n"
"\"user-context\": { \"bar\": 1,\n"
@@ -1573,7 +1572,7 @@ TEST(ClientClassDictionary, templateUnparseDict) {
"\"name\": \"" + name + "\",\n"
"\"next-server\": \"0.0.0.0\",\n"
"\"server-hostname\": \"\",\n"
- "\"template-class\": true,\n"
+ "\"template-test\": \"\",\n"
"\"boot-file-name\": \"\",\n"
"\"option-data\": [ ] }");
};