summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2024-10-16 20:09:50 +0200
committerThomas Markwalder <tmark@isc.org>2024-10-28 12:58:38 +0100
commit37ff02e12b866e6bea719d4ec72c101f7b975e22 (patch)
treed0e5cb51428c2e914b3ff428a38eff947a9b568e
parent[#3404] RFC3594, RFC3634 tests (diff)
downloadkea-37ff02e12b866e6bea719d4ec72c101f7b975e22.tar.xz
kea-37ff02e12b866e6bea719d4ec72c101f7b975e22.zip
[#3587] Bulk of the code changes
Everything except parsers, UTs to test deprecation, and doc.
-rw-r--r--src/bin/admin/tests/mysql_tests.sh.in63
-rw-r--r--src/bin/admin/tests/pgsql_tests.sh.in50
-rw-r--r--src/bin/dhcp4/dhcp4_srv.cc25
-rw-r--r--src/bin/dhcp4/dhcp4_srv.h18
-rw-r--r--src/bin/dhcp4/tests/dhcp4_test_utils.cc6
-rw-r--r--src/bin/dhcp6/dhcp6_srv.cc38
-rw-r--r--src/bin/dhcp6/dhcp6_srv.h21
-rw-r--r--src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc130
-rw-r--r--src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc178
-rw-r--r--src/hooks/dhcp/mysql/mysql_cb_impl.cc23
-rw-r--r--src/hooks/dhcp/mysql/mysql_cb_impl.h33
-rw-r--r--src/hooks/dhcp/mysql/mysql_query_macros_dhcp.h32
-rw-r--r--src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc68
-rw-r--r--src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc88
-rw-r--r--src/hooks/dhcp/pgsql/pgsql_cb_impl.cc31
-rw-r--r--src/hooks/dhcp/pgsql/pgsql_cb_impl.h39
-rw-r--r--src/hooks/dhcp/pgsql/pgsql_query_macros_dhcp.h32
-rw-r--r--src/lib/config_backend/constants.h4
-rw-r--r--src/lib/dhcp/pkt.cc15
-rw-r--r--src/lib/dhcp/pkt.h48
-rw-r--r--src/lib/dhcp/tests/pkt4_unittest.cc29
-rw-r--r--src/lib/dhcp/tests/pkt6_unittest.cc29
-rw-r--r--src/lib/dhcpsrv/client_class_def.cc24
-rw-r--r--src/lib/dhcpsrv/client_class_def.h22
-rw-r--r--src/lib/dhcpsrv/dhcpsrv_messages.cc4
-rw-r--r--src/lib/dhcpsrv/dhcpsrv_messages.h2
-rw-r--r--src/lib/dhcpsrv/dhcpsrv_messages.mes12
-rw-r--r--src/lib/dhcpsrv/network.cc14
-rw-r--r--src/lib/dhcpsrv/network.h24
-rw-r--r--src/lib/dhcpsrv/parsers/base_network_parser.cc30
-rw-r--r--src/lib/dhcpsrv/parsers/base_network_parser.h12
-rw-r--r--src/lib/dhcpsrv/parsers/client_class_def_parser.cc41
-rw-r--r--src/lib/dhcpsrv/parsers/dhcp_parsers.cc69
-rw-r--r--src/lib/dhcpsrv/parsers/shared_network_parser.cc33
-rw-r--r--src/lib/dhcpsrv/parsers/simple_parser4.cc19
-rw-r--r--src/lib/dhcpsrv/parsers/simple_parser6.cc44
-rw-r--r--src/lib/dhcpsrv/pool.cc4
-rw-r--r--src/lib/dhcpsrv/pool.h27
-rw-r--r--src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc18
-rw-r--r--src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc22
-rw-r--r--src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc26
-rw-r--r--src/lib/dhcpsrv/tests/client_class_def_unittest.cc48
-rw-r--r--src/lib/dhcpsrv/tests/pool_unittest.cc64
-rw-r--r--src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc38
-rw-r--r--src/lib/dhcpsrv/tests/shared_network_unittest.cc10
-rw-r--r--src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc16
-rw-r--r--src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc20
-rw-r--r--src/share/database/scripts/mysql/dhcpdb_create.mysql28
-rw-r--r--src/share/database/scripts/mysql/upgrade_025_to_026.sh.in28
-rw-r--r--src/share/database/scripts/pgsql/dhcpdb_create.pgsql28
-rw-r--r--src/share/database/scripts/pgsql/upgrade_025_to_026.sh.in28
51 files changed, 928 insertions, 827 deletions
diff --git a/src/bin/admin/tests/mysql_tests.sh.in b/src/bin/admin/tests/mysql_tests.sh.in
index 37121da477..fddedea481 100644
--- a/src/bin/admin/tests/mysql_tests.sh.in
+++ b/src/bin/admin/tests/mysql_tests.sh.in
@@ -72,6 +72,19 @@ mysql_wipe() {
assert_eq 0 "${EXIT_CODE}" "mysql-wipe: drop table sql failed, expected %d, returned %d"
}
+# Checks that a column in a table exists.
+# param table name of table containgin the column
+# param column name of the column to check
+check_table_column() {
+ column=$1;shift
+ table=$1;shift
+
+ qry="select $column from $table limit 1"
+ run_command \
+ mysql_execute "${qry}"
+ assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)"
+}
+
mysql_db_init_test() {
test_start "mysql.db-init"
@@ -946,13 +959,37 @@ mysql_upgrade_24_to_25_test() {
}
mysql_upgrade_25_to_26_test() {
- # client_classes been added to dhcp4_options
+
+ # client_classes been added to dhcp4_options
+ check_table_column client_classes dhcp4_options;
+
+ # client_classes been added to 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
+ check_table_column evaluate_additional_classes dhcp4_shared_network
+ check_table_column evaluate_additional_classes dhcp4_shared_network
+ check_table_column evaluate_additional_classes dhcp4_subnet
+ check_table_column evaluate_additional_classes dhcp6_shared_network
+ check_table_column evaluate_additional_classes dhcp6_subnet
+ check_table_column evaluate_additional_classes dhcp4_pool
+ check_table_column evaluate_additional_classes dhcp6_pd_pool
+ check_table_column evaluate_additional_classes dhcp6_pool
+
+ # check rename of only_if_required to only_in_additional_list.
+ check_table_column only_in_additional_list dhcp4_client_class
+ check_table_column only_in_additional_list dhcp6_client_class
+}
+
+mysql_upgrade_25_to_26_test() {
+ # client_classes been added to dhcp4_options
qry="select client_classes from dhcp4_options limit 1"
run_command \
mysql_execute "${qry}"
assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)"
- # client_classes been added to dhcp6_options
+ # client_classes been added to dhcp6_options
qry="select client_classes from dhcp6_options limit 1"
run_command \
mysql_execute "${qry}"
@@ -1232,7 +1269,7 @@ mysql_upgrade_test() {
run_statement "dhcp4_option_def_server" "$qry"
# table: dhcp4_shared_network
- qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network"
+ qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, evaluate_additional_classes, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network"
run_statement "dhcp4_shared_network" "$qry"
# table: dhcp4_shared_network_server
@@ -1240,7 +1277,7 @@ mysql_upgrade_test() {
run_statement "dhcp4_shared_network_server" "$qry"
# table: dhcp4_subnet
- qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, require_client_classes, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet"
+ qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, evaluate_additional_classes, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet"
run_statement "dhcp4_subnet" "$qry"
# table: dhcp4_pool
@@ -1288,7 +1325,7 @@ mysql_upgrade_test() {
run_statement "dhcp6_option_def_server" "$qry"
# table: dhcp6_shared_network
- qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_shared_network"
+ qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, evaluate_additional_classes, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_shared_network"
run_statement "dhcp6_shared_network" "$qry"
# table: dhcp6_shared_network_server
@@ -1296,7 +1333,7 @@ mysql_upgrade_test() {
run_statement "dhcp6_shared_network" "$qry"
# table: dhcp6_subnet
- qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, shared_network_name, subnet_id, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_subnet"
+ qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, evaluate_additional_classes, shared_network_name, subnet_id, user_context, valid_lifetime, calculate_tee_times, t1_percent, t2_percent, interface_id from dhcp6_subnet"
run_statement "dhcp6_subnet" "$qry"
# table: dhcp6_subnet_server
@@ -1419,31 +1456,31 @@ mysql_upgrade_test() {
# New lifetime bounds.
# table: dhcp4_shared_network
- qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network"
+ qry="select id, name, client_class, interface, match_client_id, modification_ts, rebind_timer, relay, renew_timer, evaluate_additional_classes, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent, boot_file_name, next_server, server_hostname from dhcp4_shared_network"
run_statement "dhcp4_shared_network" "$qry"
# table: dhcp4_subnet
- qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, require_client_classes, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet"
+ qry="select subnet_prefix, 4o6_interface, 4o6_interface_id, 4o6_subnet, boot_file_name, client_class, interface, match_client_id, modification_ts, next_server, rebind_timer, relay, renew_timer, evaluate_additional_classes, server_hostname, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, authoritative, calculate_tee_times, t1_percent, t2_percent from dhcp4_subnet"
run_statement "dhcp4_subnet" "$qry"
# table: dhcp6_shared_network
- qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime,rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_shared_network"
+ qry="select id, name, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime,rapid_commit, rebind_timer, relay, renew_timer, evaluate_additional_classes, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_shared_network"
run_statement "dhcp6_shared_network" "$qry"
# table: dhcp6_subnet
- qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, require_client_classes, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_subnet"
+ qry="select subnet_prefix, client_class, interface, modification_ts, preferred_lifetime, min_preferred_lifetime, max_preferred_lifetime, rapid_commit, rebind_timer, relay, renew_timer, evaluate_additional_classes, shared_network_name, subnet_id, user_context, valid_lifetime, min_valid_lifetime, max_valid_lifetime, calculate_tee_times, t1_percent, t2_percent from dhcp6_subnet"
run_statement "dhcp6_subnet" "$qry"
# table: dhcp4_pool (should include three new columns)
- qry="select client_class, require_client_classes, user_context from dhcp4_pool"
+ qry="select client_class, evaluate_additional_classes, user_context from dhcp4_pool"
run_statement "dhcp4_pool" "$qry"
# table: dhcp6_pd_pool (should include five new columns)
- qry="select excluded_prefix, excluded_prefix_length, client_class, require_client_classes, user_context from dhcp6_pd_pool"
+ qry="select excluded_prefix, excluded_prefix_length, client_class, evaluate_additional_classes, user_context from dhcp6_pd_pool"
run_statement "dhcp6_pd_pool" "$qry"
# table: dhcp6_pool (should include three new columns)
- qry="select client_class, require_client_classes, user_context from dhcp6_pool"
+ qry="select client_class, evaluate_additional_classes, user_context from dhcp6_pool"
run_statement "dhcp6_pool" "$qry"
# Verify that dhcp4_option_def column name is is_array
diff --git a/src/bin/admin/tests/pgsql_tests.sh.in b/src/bin/admin/tests/pgsql_tests.sh.in
index 792a5c14d7..b7ca92f0d7 100644
--- a/src/bin/admin/tests/pgsql_tests.sh.in
+++ b/src/bin/admin/tests/pgsql_tests.sh.in
@@ -60,6 +60,19 @@ run_statement() {
fi
}
+# Checks that a column in a table exists.
+# param table name of table containgin the column
+# param column name of the column to check
+check_table_column() {
+ column=$1;shift
+ table=$1;shift
+
+ qry="select $column from $table limit 1"
+ run_command \
+ pgsql_execute "${qry}"
+ assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)"
+}
+
# Wipe all tables from the DB:
pgsql_wipe() {
printf "Wiping whole database %s...\n" "${db_name}"
@@ -1039,23 +1052,26 @@ pgsql_upgrade_24_to_25_test() {
}
pgsql_upgrade_25_to_26_test() {
- # client_classes been added to dhcp4_options
- qry="select client_classes from dhcp4_options limit 1"
- run_command \
- pgsql_execute "${qry}"
- assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)"
-
- # client_classes been added to dhcp6_options
- qry="select client_classes from dhcp6_options limit 1"
- run_command \
- pgsql_execute "${qry}"
- assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)"
-
- qry="select name from option_def_data_type where id = 3"
- run_command \
- pgsql_execute "${qry}"
- assert_eq 0 "${EXIT_CODE}" "${qry}. (expected status code %d, returned %d)"
- assert_str_eq 'int8' "${OUTPUT}" "${query}: expected output %s, returned %s"
+ # client_classes been added to dhcp4_options
+ check_table_column client_classes dhcp4_options;
+
+ # client_classes been added to 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
+ check_table_column evaluate_additional_classes dhcp4_shared_network
+ check_table_column evaluate_additional_classes dhcp4_shared_network
+ check_table_column evaluate_additional_classes dhcp4_subnet
+ check_table_column evaluate_additional_classes dhcp6_shared_network
+ check_table_column evaluate_additional_classes dhcp6_subnet
+ check_table_column evaluate_additional_classes dhcp4_pool
+ check_table_column evaluate_additional_classes dhcp6_pd_pool
+ check_table_column evaluate_additional_classes dhcp6_pool
+
+ # check rename of only_if_required to only_in_additional_list.
+ check_table_column only_in_additional_list dhcp4_client_class
+ check_table_column only_in_additional_list dhcp6_client_class
}
pgsql_upgrade_test() {
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 41f22c5d04..5e11dfd39d 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -645,8 +645,8 @@ void Dhcpv4Exchange::evaluateClasses(const Pkt4Ptr& pkt, bool depend_on_known) {
if (!expr_ptr) {
continue;
}
- // Not the right time if only when required
- if (it->getRequired()) {
+ // Not the right time if only when additional
+ if (it->getAdditional()) {
continue;
}
// Not the right pass.
@@ -3838,8 +3838,8 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover, AllocEngine::ClientContext4Ptr& co
// network we have already fetched it and evaluated the classes.
ex.conditionallySetReservedClientClasses();
- // Required classification
- requiredClassify(ex);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(ex);
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASSES_ASSIGNED)
.arg(discover->getLabel())
@@ -3924,8 +3924,8 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request, AllocEngine::ClientContext4Ptr& cont
// network we have already fetched it and evaluated the classes.
ex.conditionallySetReservedClientClasses();
- // Required classification
- requiredClassify(ex);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(ex);
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASSES_ASSIGNED)
.arg(request->getLabel())
@@ -4437,7 +4437,8 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform, AllocEngine::ClientContext4Ptr& contex
// network we have already fetched it and evaluated the classes.
ex.conditionallySetReservedClientClasses();
- requiredClassify(ex);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(ex);
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASSES_ASSIGNED)
.arg(inform->getLabel())
@@ -4888,10 +4889,10 @@ void Dhcpv4Srv::classifyPacket(const Pkt4Ptr& pkt) {
Dhcpv4Exchange::classifyPacket(pkt);
}
-void Dhcpv4Srv::requiredClassify(Dhcpv4Exchange& ex) {
+void Dhcpv4Srv::evaluateAdditionalClasses(Dhcpv4Exchange& ex) {
// First collect required classes
Pkt4Ptr query = ex.getQuery();
- ClientClasses classes = query->getClasses(true);
+ ClientClasses classes = query->getAdditionalClasses();
Subnet4Ptr subnet = ex.getContext()->subnet_;
if (subnet) {
@@ -4906,7 +4907,7 @@ void Dhcpv4Srv::requiredClassify(Dhcpv4Exchange& ex) {
if (!addr.isV4Zero()) {
PoolPtr pool = subnet->getPool(Lease::TYPE_V4, addr, false);
if (pool) {
- const ClientClasses& pool_to_add = pool->getRequiredClasses();
+ const ClientClasses& pool_to_add = pool->getAdditionalClasses();
for (auto const& cclass : pool_to_add) {
classes.insert(cclass);
}
@@ -4914,7 +4915,7 @@ void Dhcpv4Srv::requiredClassify(Dhcpv4Exchange& ex) {
}
// Followed by the subnet
- const ClientClasses& to_add = subnet->getRequiredClasses();
+ const ClientClasses& to_add = subnet->getAdditionalClasses();
for (auto const& cclass : to_add) {
classes.insert(cclass);
}
@@ -4923,7 +4924,7 @@ void Dhcpv4Srv::requiredClassify(Dhcpv4Exchange& ex) {
SharedNetwork4Ptr network;
subnet->getSharedNetwork(network);
if (network) {
- const ClientClasses& net_to_add = network->getRequiredClasses();
+ const ClientClasses& net_to_add = network->getAdditionalClasses();
for (auto const& cclass : net_to_add) {
classes.insert(cclass);
}
diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h
index 23ea4fbddd..92a19df4e4 100644
--- a/src/bin/dhcp4/dhcp4_srv.h
+++ b/src/bin/dhcp4/dhcp4_srv.h
@@ -1187,17 +1187,23 @@ protected:
protected:
- /// @brief Assigns incoming packet to zero or more classes (required pass).
+ /// @brief Evaluates classes in the additional classes lists
///
- /// @note This required classification evaluates all classes which
- /// were marked for required evaluation. Classes are collected so
- /// evaluated in the reversed order than output option processing.
+ /// The evaluation takes place after all other classification and
+ /// lease assignment. It evaluates all classes in the packet's
+ /// additional_classes_ list plus any contributed via evaluate-additional-
+ /// class lists.
///
- /// @note The only-if-required flag is related because it avoids
+ /// @note Evaluates all classes which were marked for the additional
+ /// evaluation stage. Classes are collected and evaluated in the following
+ /// order: pool, subnet, shared-network to produce option precedence
+ /// pool over subnet over shared-network.
+ ///
+ /// @note The only-in-additional-list flag is related because it avoids
/// double evaluation (which is not forbidden).
///
/// @param ex The exchange holding needed information.
- void requiredClassify(Dhcpv4Exchange& ex);
+ void evaluateAdditionalClasses(Dhcpv4Exchange& ex);
/// @brief Perform deferred option unpacking.
///
diff --git a/src/bin/dhcp4/tests/dhcp4_test_utils.cc b/src/bin/dhcp4/tests/dhcp4_test_utils.cc
index 4824c56dbb..5d37185642 100644
--- a/src/bin/dhcp4/tests/dhcp4_test_utils.cc
+++ b/src/bin/dhcp4/tests/dhcp4_test_utils.cc
@@ -218,7 +218,7 @@ Dhcpv4SrvTest::configureServerIdentifier() {
desc.option_ = makeServerIdOption(IOAddress("192.0.5.254"));
options->add(desc, DHCP4_OPTION_SPACE);
CfgMgr::instance().getStagingCfg()->getClientClassDictionary()->addClass("foo", ExpressionPtr(), "", true, false, options);
- subnet5->requireClientClass("foo");
+ subnet5->addAdditionalClass("foo");
// Build and add subnet6.
Subnet4Ptr subnet6(new Subnet4(IOAddress("192.0.6.0"), 24, unspec, unspec, 3600, 6));
@@ -233,7 +233,7 @@ Dhcpv4SrvTest::configureServerIdentifier() {
desc_other.option_ = makeFqdnListOption();
options->add(desc_other, DHCP4_OPTION_SPACE);
CfgMgr::instance().getStagingCfg()->getClientClassDictionary()->addClass("bar", ExpressionPtr(), "", true, false, options);
- subnet6->requireClientClass("bar");
+ subnet6->addAdditionalClass("bar");
// Build and add subnet7.
Subnet4Ptr subnet7(new Subnet4(IOAddress("192.0.7.0"), 24, unspec, unspec, 3600, 7));
@@ -245,7 +245,7 @@ Dhcpv4SrvTest::configureServerIdentifier() {
options.reset();
CfgMgr::instance().getStagingCfg()->getClientClassDictionary()->addClass("xyz", ExpressionPtr(), "", true, false, options);
- subnet7->requireClientClass("xyz");
+ subnet7->addAdditionalClass("xyz");
// Build and add a shared-network.
CfgSharedNetworks4Ptr networks = cfg_mgr.getStagingCfg()->getCfgSharedNetworks4();
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 7c6d972312..84e8d61f03 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -3777,7 +3777,8 @@ Dhcpv6Srv::processSolicit(AllocEngine::ClientContext6& ctx) {
}
conditionallySetReservedClientClasses(solicit, ctx);
- requiredClassify(solicit, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(solicit, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(solicit->getLabel())
@@ -3820,7 +3821,8 @@ Dhcpv6Srv::processRequest(AllocEngine::ClientContext6& ctx) {
}
conditionallySetReservedClientClasses(request, ctx);
- requiredClassify(request, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(request, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(request->getLabel())
@@ -3859,7 +3861,8 @@ Dhcpv6Srv::processRenew(AllocEngine::ClientContext6& ctx) {
}
conditionallySetReservedClientClasses(renew, ctx);
- requiredClassify(renew, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(renew, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(renew->getLabel())
@@ -3898,7 +3901,8 @@ Dhcpv6Srv::processRebind(AllocEngine::ClientContext6& ctx) {
}
conditionallySetReservedClientClasses(rebind, ctx);
- requiredClassify(rebind, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(rebind, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(rebind->getLabel())
@@ -3924,7 +3928,8 @@ Dhcpv6Srv::processConfirm(AllocEngine::ClientContext6& ctx) {
Pkt6Ptr confirm = ctx.query_;
conditionallySetReservedClientClasses(confirm, ctx);
- requiredClassify(confirm, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(confirm, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(confirm->getLabel())
@@ -4017,7 +4022,8 @@ Dhcpv6Srv::processRelease(AllocEngine::ClientContext6& ctx) {
Pkt6Ptr release = ctx.query_;
conditionallySetReservedClientClasses(release, ctx);
- requiredClassify(release, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(release, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(release->getLabel())
@@ -4048,7 +4054,8 @@ Dhcpv6Srv::processDecline(AllocEngine::ClientContext6& ctx) {
Pkt6Ptr decline = ctx.query_;
conditionallySetReservedClientClasses(decline, ctx);
- requiredClassify(decline, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(decline, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(decline->getLabel())
@@ -4368,7 +4375,8 @@ Dhcpv6Srv::processInfRequest(AllocEngine::ClientContext6& ctx) {
Pkt6Ptr inf_request = ctx.query_;
conditionallySetReservedClientClasses(inf_request, ctx);
- requiredClassify(inf_request, ctx);
+ // Evaluate addditional classes.
+ evaluateAdditionalClasses(inf_request, ctx);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASSES_ASSIGNED)
.arg(inf_request->getLabel())
@@ -4466,7 +4474,7 @@ void Dhcpv6Srv::evaluateClasses(const Pkt6Ptr& pkt, bool depend_on_known) {
continue;
}
// Not the right time if only when required
- if (it->getRequired()) {
+ if (it->getAdditional()) {
continue;
}
// Not the right pass.
@@ -4519,9 +4527,9 @@ Dhcpv6Srv::conditionallySetReservedClientClasses(const Pkt6Ptr& pkt,
}
void
-Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx) {
- // First collect required classes
- ClientClasses classes = pkt->getClasses(true);
+Dhcpv6Srv::evaluateAdditionalClasses(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx) {
+ // Get additional classes to evaluate added elsewhere, posssibly by hooks.
+ ClientClasses classes = pkt->getAdditionalClasses();
Subnet6Ptr subnet = ctx.subnet_;
if (subnet) {
@@ -4535,7 +4543,7 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx
resource.getAddress(),
false);
if (pool) {
- const ClientClasses& pool_to_add = pool->getRequiredClasses();
+ const ClientClasses& pool_to_add = pool->getAdditionalClasses();
for (auto const& cclass : pool_to_add) {
classes.insert(cclass);
}
@@ -4543,7 +4551,7 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx
}
// Followed by the subnet
- const ClientClasses& to_add = subnet->getRequiredClasses();
+ const ClientClasses& to_add = subnet->getAdditionalClasses();
for (auto const& cclass : to_add) {
classes.insert(cclass);
}
@@ -4552,7 +4560,7 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx
SharedNetwork6Ptr network;
subnet->getSharedNetwork(network);
if (network) {
- const ClientClasses& net_to_add = network->getRequiredClasses();
+ const ClientClasses& net_to_add = network->getAdditionalClasses();
for (auto const& cclass : net_to_add) {
classes.insert(cclass);
}
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index cf61729b74..8e33ed1dfc 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -902,18 +902,23 @@ protected:
void conditionallySetReservedClientClasses(const Pkt6Ptr& pkt,
const AllocEngine::ClientContext6& ctx);
- /// @brief Assigns incoming packet to zero or more classes (required pass).
+ /// @brief Evaluates classes in the additional classes lists
///
- /// @note This required classification evaluates all classes which
- /// were marked for required evaluation. Classes are collected so
- /// evaluated in the reversed order than output option processing.
+ /// The evaluation takes place after all other classification and
+ /// lease assignment. It evaluates all classes in the packet's
+ /// additional_classes_ list plus any contributed via evaluate-additional-
+ /// class lists.
///
- /// @note The only-if-required flag is related because it avoids
+ /// @note Evaluates all classes which were marked for the additional
+ /// evaluation stage. Classes are collected and evaluated in the following
+ /// order: pool, subnet, shared-network to produce option precedence
+ /// pool over subnet over shared-network.
+ ///
+ /// @note The only-in-additional-list flag is related because it avoids
/// double evaluation (which is not forbidden).
///
- /// @param pkt packet to be classified
- /// @param ctx allocation context where to get information
- void requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx);
+ /// @param ex The exchange holding needed information.
+ void evaluateAdditionalClasses(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx);
/// @brief Attempts to get a MAC/hardware address using configured sources
///
diff --git a/src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc
index 436b083950..fb41b7f41c 100644
--- a/src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc
+++ b/src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc
@@ -300,7 +300,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // rebind_timer
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // evaluate_additional_classes
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(SERVER_HOSTNAME_BUF_LENGTH), // server_hostname
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // shared_network_name
@@ -324,7 +324,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pool option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // pool option: pool_id
MySqlBinding::createTimestamp(), //pool option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // pool option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pool option: client_classes
MySqlBinding::createInteger<uint64_t>(), // option: option_id
MySqlBinding::createInteger<uint8_t>(), // option: code
MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // option: value
@@ -338,7 +338,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // option: pool_id
MySqlBinding::createTimestamp(), //option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // option: client_classes
MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
MySqlBinding::createInteger<float>(), // t1_percent
MySqlBinding::createInteger<float>(), // t2_percent
@@ -346,7 +346,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // min_valid_lifetime
MySqlBinding::createInteger<uint32_t>(), // max_valid_lifetime
MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pool: evaluate_additional_classes
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context
MySqlBinding::createInteger<uint8_t>(), // ddns_send_updates
MySqlBinding::createInteger<uint8_t>(), // ddns_override_no_update
@@ -498,22 +498,9 @@ public:
// renew_timer at 13.
- // require_client_classes at 14.
- ElementPtr require_element = out_bindings[14]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid require_client_classes value "
- << out_bindings[14]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of require_client_classes list must"
- "be valid strings");
- }
- last_subnet->requireClientClass(require_item->stringValue());
- }
- }
+ // evaluate_additional_classes at 14.
+ clientClassesFromBinding(out_bindings[14], "evaluate-additional-classes",
+ last_subnet->getMutableAdditionalClasses());
// reservations_global at 15.
if (!out_bindings[15]->amNull()) {
@@ -563,7 +550,7 @@ public:
// min_valid_lifetime at 57.
// max_valid_lifetime at 58.
- // pool client_class, require_client_classes and user_context
+ // pool client_class, evaluate_additional_classes and user_context
// from 59 to 61.
// ddns_send_updates at 62.
@@ -671,22 +658,9 @@ public:
last_pool->allowClientClass(out_bindings[59]->getString());
}
- // pool require_client_classes at 60.
- ElementPtr require_element = out_bindings[60]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid pool require_client_classes value "
- << out_bindings[60]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of pool require_client_classes list must"
- "be valid strings");
- }
- last_pool->requireClientClass(require_item->stringValue());
- }
- }
+ // pool evaluate_additional_classes at 60.
+ clientClassesFromBinding(out_bindings[60], "evaluate-additional-classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context at 61.
ElementPtr user_context = out_bindings[61]->getJSON();
@@ -868,7 +842,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // pool: end_address
MySqlBinding::createInteger<uint32_t>(), // pool: subnet_id
MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pool: evaluate_additional_classes
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context
MySqlBinding::createTimestamp(), // pool: modification_ts
MySqlBinding::createInteger<uint64_t>(), // pool option: option_id
@@ -884,7 +858,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pool option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // pool option: pool_id
MySqlBinding::createTimestamp(), //pool option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH) // pool option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH) // pool option: client_classes
};
uint64_t last_pool_id = 0;
@@ -912,22 +886,9 @@ public:
last_pool->allowClientClass(out_bindings[4]->getString());
}
- // pool require_client_classes (5)
- ElementPtr require_element = out_bindings[5]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid pool require_client_classes value "
- << out_bindings[5]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of pool require_client_classes list must"
- "be valid strings");
- }
- last_pool->requireClientClass(require_item->stringValue());
- }
- }
+ // pool evaluate_additional_classes (5)
+ clientClassesFromBinding(out_bindings[5], "evaluate-additional-classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context (6)
ElementPtr user_context = out_bindings[6]->getJSON();
@@ -1035,11 +996,11 @@ public:
dhcp4o6_subnet = s.str();
}
- // Create JSON list of required classes.
- ElementPtr required_classes_element = Element::createList();
- auto const& required_classes = subnet->getRequiredClasses();
- for (auto const& required_class : required_classes) {
- required_classes_element->add(Element::create(required_class));
+ // Create JSON list of additional classes.
+ ElementPtr additional_classes_element = Element::createList();
+ auto const& additional_classes = subnet->getAdditionalClasses();
+ for (auto const& additional_class : additional_classes) {
+ additional_classes_element->add(Element::create(additional_class));
}
// Create binding for DDNS replace client name mode.
@@ -1095,7 +1056,7 @@ public:
createBinding(subnet->getT2(Network::Inheritance::NONE)),
createInputRelayBinding(subnet),
createBinding(subnet->getT1(Network::Inheritance::NONE)),
- createInputRequiredClassesBinding(subnet),
+ createInputClientClassesBinding(subnet->getAdditionalClasses()),
MySqlBinding::condCreateBool(subnet->getReservationsGlobal(Network::Inheritance::NONE)),
MySqlBinding::condCreateString(subnet->getSname(Network::Inheritance::NONE)),
shared_network_binding,
@@ -1193,7 +1154,7 @@ public:
MySqlBinding::createInteger<uint32_t>(pool->getLastAddress().toUint32()),
MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet->getID())),
MySqlBinding::condCreateString(pool->getClientClass()),
- createInputRequiredClassesBinding(pool),
+ createInputClientClassesBinding(pool->getAdditionalClasses()),
createInputContextBinding(pool),
MySqlBinding::createTimestamp(subnet->getModificationTime())
};
@@ -1331,7 +1292,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // rebind_timer
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // evaluate_additional_classes
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
@@ -1348,7 +1309,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // option: pool_id
MySqlBinding::createTimestamp(), // option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // option: client_classes
MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
MySqlBinding::createInteger<float>(), // t1_percent
MySqlBinding::createInteger<float>(), // t2_percent
@@ -1446,22 +1407,9 @@ public:
last_network->setT1(createTriplet(out_bindings[8]));
}
- // require_client_classes at 9.
- ElementPtr require_element = out_bindings[9]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid require_client_classes value "
- << out_bindings[9]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of require_client_classes list must"
- "be valid strings");
- }
- last_network->requireClientClass(require_item->stringValue());
- }
- }
+ // evaluate_additional_classes at 9.
+ clientClassesFromBinding(out_bindings[9], "evaluate-additional-classes",
+ last_network->getMutableAdditionalClasses());
// reservations_global at 10.
if (!out_bindings[10]->amNull()) {
@@ -1732,7 +1680,7 @@ public:
createBinding(shared_network->getT2(Network::Inheritance::NONE)),
createInputRelayBinding(shared_network),
createBinding(shared_network->getT1(Network::Inheritance::NONE)),
- createInputRequiredClassesBinding(shared_network),
+ createInputClientClassesBinding(shared_network->getAdditionalClasses()),
MySqlBinding::condCreateBool(shared_network->getReservationsGlobal(Network::Inheritance::NONE)),
createInputContextBinding(shared_network),
createBinding(shared_network->getValid(Network::Inheritance::NONE)),
@@ -2417,7 +2365,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // next server
MySqlBinding::createString(CLIENT_CLASS_SNAME_BUF_LENGTH), // sname
MySqlBinding::createString(CLIENT_CLASS_FILENAME_BUF_LENGTH), // filename
- MySqlBinding::createInteger<uint8_t>(), // required
+ MySqlBinding::createInteger<uint8_t>(), // additional
MySqlBinding::createInteger<uint32_t>(), // valid lifetime
MySqlBinding::createInteger<uint32_t>(), // min valid lifetime
MySqlBinding::createInteger<uint32_t>(), // max valid lifetime
@@ -2449,7 +2397,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // option: pool_id
MySqlBinding::createTimestamp(), // option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // option: client_classes
MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server tag
};
@@ -2505,9 +2453,9 @@ public:
last_client_class->setFilename(out_bindings[5]->getString());
}
- // required
+ // additional
if (!out_bindings[6]->amNull()) {
- last_client_class->setRequired(out_bindings[6]->getBool());
+ last_client_class->setAdditional(out_bindings[6]->getBool());
}
// valid lifetime: default, min, max
@@ -2675,7 +2623,7 @@ public:
MySqlBinding::createInteger<uint32_t>(client_class->getNextServer().toUint32()),
MySqlBinding::createString(client_class->getSname()),
MySqlBinding::createString(client_class->getFilename()),
- MySqlBinding::createBool(client_class->getRequired()),
+ MySqlBinding::createBool(client_class->getAdditional()),
createBinding(client_class->getValid()),
createMinBinding(client_class->getValid()),
createMaxBinding(client_class->getValid()),
@@ -3248,7 +3196,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" server_hostname,"
" shared_network_name,"
@@ -3296,7 +3244,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
@@ -3362,7 +3310,7 @@ TaggedStatementArray tagged_statements = { {
" next_server,"
" server_hostname,"
" boot_file_name,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
@@ -3411,7 +3359,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" server_hostname = ?,"
" shared_network_name = ?,"
@@ -3448,7 +3396,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
diff --git a/src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc b/src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc
index cb64fec062..a183aeb3d5 100644
--- a/src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc
+++ b/src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc
@@ -305,7 +305,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // rebind_timer
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // evaluate_additional_classes
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // shared_network_name
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
@@ -334,7 +334,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pool option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // pool option: pool_id
MySqlBinding::createTimestamp(), // pool option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // pool option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pool option: client_classes
MySqlBinding::createInteger<uint64_t>(), // pool option: pd_pool_id
MySqlBinding::createInteger<uint64_t>(), // pd pool option: option_id
MySqlBinding::createInteger<uint16_t>(), // pd pool option: code
@@ -349,7 +349,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pd pool option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // pd pool option: pool_id
MySqlBinding::createTimestamp(), // pd pool option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // pd_pool option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pd_pool option: client_classes
MySqlBinding::createInteger<uint64_t>(), // pd pool option: pd_pool_id
MySqlBinding::createInteger<uint64_t>(), // option: option_id
MySqlBinding::createInteger<uint16_t>(), // option: code
@@ -364,7 +364,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // option: pool_id
MySqlBinding::createTimestamp(), // option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // option: client_classes
MySqlBinding::createInteger<uint64_t>(), // option: pd_pool_id
MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
MySqlBinding::createInteger<float>(), // t1_percent
@@ -375,12 +375,12 @@ public:
MySqlBinding::createInteger<uint32_t>(), // min_valid_lifetime
MySqlBinding::createInteger<uint32_t>(), // max_valid_lifetime
MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pool: evaluate_additional_classes
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context
MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: excluded_prefix
MySqlBinding::createInteger<uint8_t>(), // pd pool: excluded_prefix_length
MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pd pool: client_class
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pd pool: require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pd pool: evaluate_additional_classes
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool: user_context
MySqlBinding::createInteger<uint8_t>(), // ddns_send_updates
MySqlBinding::createInteger<uint8_t>(), // ddns_override_no_update
@@ -511,22 +511,9 @@ public:
// 9 is renew_timer
- // require_client_classes (10)
- ElementPtr require_element = out_bindings[10]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid require_client_classes value "
- << out_bindings[10]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of require_client_classes list must"
- "be valid strings");
- }
- last_subnet->requireClientClass(require_item->stringValue());
- }
- }
+ // evaluate_additional_classes (10)
+ clientClassesFromBinding(out_bindings[10], "evaluate-additional-classes",
+ last_subnet->getMutableAdditionalClasses());
// reservations_global (11)
if (!out_bindings[11]->amNull()) {
@@ -582,12 +569,12 @@ public:
// 77 and 78 are {min,max}_valid_lifetime
// 79 is pool client_class
- // 80 is pool require_client_classes
+ // 80 is pool evaluate_additional_classes
// 81 is pool user_context
// 82 is pd pool excluded_prefix
// 83 is pd pool excluded_prefix_length
// 84 is pd pool client_class
- // 85 is pd pool require_client_classes
+ // 85 is pd pool evaluate_additional_classes
// 86 is pd pool user_context
// ddns_send_updates (87)
@@ -699,22 +686,9 @@ public:
last_pool->allowClientClass(out_bindings[79]->getString());
}
- // pool require_client_classes (80)
- ElementPtr require_element = out_bindings[80]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid pool require_client_classes value "
- << out_bindings[80]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of pool require_client_classes list must"
- "be valid strings");
- }
- last_pool->requireClientClass(require_item->stringValue());
- }
- }
+ // pool evaluate_additional_classes (80)
+ clientClassesFromBinding(out_bindings[80], "evaluate-additional-classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context (81)
ElementPtr user_context = out_bindings[81]->getJSON();
@@ -761,22 +735,9 @@ public:
last_pd_pool->allowClientClass(out_bindings[84]->getString());
}
- // pd pool require_client_classes (85)
- ElementPtr require_element = out_bindings[85]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid pd pool require_client_classes value "
- << out_bindings[85]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of pd pool require_client_classes list must"
- "be valid strings");
- }
- last_pd_pool->requireClientClass(require_item->stringValue());
- }
- }
+ // pd pool evaluate_additional_classes (85)
+ clientClassesFromBinding(out_bindings[85], "evaluate-additional-classes",
+ last_pd_pool->getMutableAdditionalClasses());
// pd pool user_context (86)
ElementPtr user_context = out_bindings[86]->getJSON();
@@ -969,7 +930,7 @@ public:
MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: end_address
MySqlBinding::createInteger<uint32_t>(), // pool: subnet_id
MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pool: evaluate_additional_classes
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context
MySqlBinding::createTimestamp(), // pool: modification_ts
MySqlBinding::createInteger<uint64_t>(), // pool option: option_id
@@ -1013,22 +974,9 @@ public:
last_pool->allowClientClass(out_bindings[4]->getString());
}
- // pool require_client_classes (5)
- ElementPtr require_element = out_bindings[5]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid pool require_client_classes value "
- << out_bindings[5]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of pool require_client_classes list must"
- "be valid strings");
- }
- last_pool->requireClientClass(require_item->stringValue());
- }
- }
+ // pool evaluate_additional_classes (5)
+ clientClassesFromBinding(out_bindings[5], "evaluate-additional-classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context (6)
ElementPtr user_context = out_bindings[6]->getJSON();
@@ -1081,7 +1029,7 @@ public:
MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: excluded_prefix
MySqlBinding::createInteger<uint8_t>(), // pd pool: excluded_prefix_length
MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pd pool: client_class
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pd pool: require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pd pool: evaluate_additional_classes
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool: user_context
MySqlBinding::createTimestamp(), // pd pool: modification_ts
MySqlBinding::createInteger<uint64_t>(), // pd pool option: option_id
@@ -1097,7 +1045,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pd pool option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // pd pool option: pool_id
MySqlBinding::createTimestamp(), // pd pool option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // pd pool option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // pd pool option: client_classes
MySqlBinding::createInteger<uint64_t>() // pd pool option: pd_pool_id
};
@@ -1136,22 +1084,9 @@ public:
last_pd_pool->allowClientClass(out_bindings[7]->getString());
}
- // pd pool require_client_classes (8)
- ElementPtr require_element = out_bindings[8]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid pd pool require_client_classes value "
- << out_bindings[8]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of pd pool require_client_classes list must"
- "be valid strings");
- }
- last_pd_pool->requireClientClass(require_item->stringValue());
- }
- }
+ // pd pool evaluate_additional_classes (8)
+ clientClassesFromBinding(out_bindings[8], "evaluate-additional-classes",
+ last_pd_pool->getMutableAdditionalClasses());
// pd pool user_context (9)
ElementPtr user_context = out_bindings[9]->getJSON();
@@ -1279,11 +1214,11 @@ public:
" (unassigned) is unsupported at the moment");
}
- // Create JSON list of required classes.
- ElementPtr required_classes_element = Element::createList();
- auto const& required_classes = subnet->getRequiredClasses();
- for (auto const& required_class : required_classes) {
- required_classes_element->add(Element::create(required_class));
+ // Create JSON list of additional classes.
+ ElementPtr additional_classes_element = Element::createList();
+ auto const& additional_classes = subnet->getAdditionalClasses();
+ for (auto const& additional_class : additional_classes) {
+ additional_classes_element->add(Element::create(additional_class));
}
// Create binding for DDNS replace client name mode.
@@ -1348,7 +1283,7 @@ public:
createBinding(subnet->getT2(Network::Inheritance::NONE)),
createInputRelayBinding(subnet),
createBinding(subnet->getT1(Network::Inheritance::NONE)),
- createInputRequiredClassesBinding(subnet),
+ createInputClientClassesBinding(subnet->getAdditionalClasses()),
MySqlBinding::condCreateBool(subnet->getReservationsGlobal(Network::Inheritance::NONE)),
shared_network_binding,
createInputContextBinding(subnet),
@@ -1453,7 +1388,7 @@ public:
MySqlBinding::createString(pool->getLastAddress().toText()),
MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet->getID())),
MySqlBinding::condCreateString(pool->getClientClass()),
- createInputRequiredClassesBinding(pool),
+ createInputClientClassesBinding(pool->getAdditionalClasses()),
createInputContextBinding(pool),
MySqlBinding::createTimestamp(subnet->getModificationTime())
};
@@ -1504,7 +1439,7 @@ public:
MySqlBinding::condCreateString(xprefix_txt),
MySqlBinding::createInteger<uint8_t>(xlen),
MySqlBinding::condCreateString(pd_pool->getClientClass()),
- createInputRequiredClassesBinding(pd_pool),
+ createInputClientClassesBinding(pd_pool->getAdditionalClasses()),
createInputContextBinding(pd_pool),
MySqlBinding::createTimestamp(subnet->getModificationTime())
};
@@ -1661,7 +1596,7 @@ public:
MySqlBinding::createInteger<uint32_t>(), // rebind_timer
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
- MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // evaluate_additional_classes
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
@@ -1678,7 +1613,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // option: pool_id
MySqlBinding::createTimestamp(), // option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // option: client_classes
MySqlBinding::createInteger<uint64_t>(), // option: pd_pool_id
MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
MySqlBinding::createInteger<float>(), // t1_percent
@@ -1785,22 +1720,9 @@ public:
last_network->setT1(createTriplet(out_bindings[9]));
}
- // require_client_classes at 10.
- ElementPtr require_element = out_bindings[10]->getJSON();
- if (require_element) {
- if (require_element->getType() != Element::list) {
- isc_throw(BadValue, "invalid require_client_classes value "
- << out_bindings[10]->getString());
- }
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of require_client_classes list must"
- "be valid strings");
- }
- last_network->requireClientClass(require_item->stringValue());
- }
- }
+ // evaluate_additional_classes at 10.
+ clientClassesFromBinding(out_bindings[10], "evaluate-additional-classes",
+ last_network->getMutableAdditionalClasses());
// reservations_global at 11.
if (!out_bindings[11]->amNull()) {
@@ -2076,7 +1998,7 @@ public:
createBinding(shared_network->getT2(Network::Inheritance::NONE)),
createInputRelayBinding(shared_network),
createBinding(shared_network->getT1(Network::Inheritance::NONE)),
- createInputRequiredClassesBinding(shared_network),
+ createInputClientClassesBinding(shared_network->getAdditionalClasses()),
MySqlBinding::condCreateBool(shared_network->getReservationsGlobal(Network::Inheritance::NONE)),
createInputContextBinding(shared_network),
createBinding(shared_network->getValid(Network::Inheritance::NONE)),
@@ -2851,7 +2773,7 @@ public:
MySqlBinding::createInteger<uint64_t>(), // id
MySqlBinding::createString(CLIENT_CLASS_NAME_BUF_LENGTH), // name
MySqlBinding::createString(CLIENT_CLASS_TEST_BUF_LENGTH), // test
- MySqlBinding::createInteger<uint8_t>(), // required
+ MySqlBinding::createInteger<uint8_t>(), // additional
MySqlBinding::createInteger<uint32_t>(), // valid lifetime
MySqlBinding::createInteger<uint32_t>(), // min valid lifetime
MySqlBinding::createInteger<uint32_t>(), // max valid lifetime
@@ -2882,7 +2804,7 @@ public:
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
MySqlBinding::createInteger<uint64_t>(), // option: pool_id
MySqlBinding::createTimestamp(), // option: modification_ts
- MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH), // option: client_classes
+ MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH), // option: client_classes
MySqlBinding::createString(SERVER_TAG_BUF_LENGTH),// server tag
MySqlBinding::createInteger<uint32_t>(), // preferred lifetime
MySqlBinding::createInteger<uint32_t>(), // min preferred lifetime
@@ -2926,9 +2848,9 @@ public:
last_client_class->setTest(out_bindings[2]->getString());
}
- // required
+ // additional
if (!out_bindings[3]->amNull()) {
- last_client_class->setRequired(out_bindings[3]->getBool());
+ last_client_class->setAdditional(out_bindings[3]->getBool());
}
// valid lifetime: default, min, max
@@ -3093,7 +3015,7 @@ public:
MySqlBindingCollection in_bindings = {
MySqlBinding::createString(client_class->getName()),
MySqlBinding::createString(client_class->getTest()),
- MySqlBinding::createBool(client_class->getRequired()),
+ MySqlBinding::createBool(client_class->getAdditional()),
createBinding(client_class->getValid()),
createMinBinding(client_class->getValid()),
createMaxBinding(client_class->getValid()),
@@ -3682,7 +3604,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" shared_network_name,"
" user_context,"
@@ -3737,7 +3659,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
@@ -3797,7 +3719,7 @@ TaggedStatementArray tagged_statements = { {
"INSERT INTO dhcp6_client_class("
" name,"
" test,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
@@ -3846,7 +3768,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" shared_network_name = ?,"
" user_context = ?,"
@@ -3885,7 +3807,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
diff --git a/src/hooks/dhcp/mysql/mysql_cb_impl.cc b/src/hooks/dhcp/mysql/mysql_cb_impl.cc
index 590700a706..d2cfea8873 100644
--- a/src/hooks/dhcp/mysql/mysql_cb_impl.cc
+++ b/src/hooks/dhcp/mysql/mysql_cb_impl.cc
@@ -758,7 +758,7 @@ MySqlConfigBackendImpl::getOptions(const int index,
// modification_ts
out_bindings.push_back(MySqlBinding::createTimestamp());
// client_classes
- out_bindings.push_back(MySqlBinding::createString(OPTION_CLIENT_CLASSES_BUF_LENGTH));
+ out_bindings.push_back(MySqlBinding::createString(CLIENT_CLASS_LIST_BUF_LENGTH));
// server_tag
out_bindings.push_back(MySqlBinding::createString(SERVER_TAG_BUF_LENGTH));
// pd_pool_id
@@ -883,14 +883,7 @@ MySqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
}
// Get client classes list
- ElementPtr client_classes = (*(first_binding + 13))->getJSON();
- try {
- desc->client_classes_.fromElement(client_classes);
- } catch (const std::exception& ex) {
- isc_throw(BadValue, "invalid 'client_classes' : "
- << (*(first_binding + 13))->getString()
- << ex.what());
- }
+ clientClassesFromBinding(*(first_binding + 13), "client_classe", desc->client_classes_);
return (desc);
}
@@ -1135,5 +1128,17 @@ MySqlConfigBackendImpl::createInputClientClassesBinding(const ClientClasses& cli
return (db::MySqlBinding::createString(client_classes_element->str()));
}
+void
+MySqlConfigBackendImpl::clientClassesFromBinding(const MySqlBindingPtr& binding,
+ const std::string& column,
+ ClientClasses& client_classes) {
+ try {
+ ElementPtr cclist_element = binding->getJSON();
+ client_classes.fromElement(cclist_element);
+ } catch (const std::exception& ex) {
+ isc_throw(BadValue, "invalid '" << column << "' value " << ex.what());
+ }
+}
+
} // end of namespace isc::dhcp
} // end of namespace isc
diff --git a/src/hooks/dhcp/mysql/mysql_cb_impl.h b/src/hooks/dhcp/mysql/mysql_cb_impl.h
index 4a76c6e273..eba16a19de 100644
--- a/src/hooks/dhcp/mysql/mysql_cb_impl.h
+++ b/src/hooks/dhcp/mysql/mysql_cb_impl.h
@@ -622,27 +622,6 @@ public:
/// relay addresses specified).
db::MySqlBindingPtr createInputRelayBinding(const NetworkPtr& network);
- /// @brief Creates input binding for 'require_client_classes' parameter.
- ///
- /// @tparam T of pointer to objects with getRequiredClasses
- /// method, e.g. shared network, subnet, pool or prefix delegation pool.
- /// @param object Pointer to an object with getRequiredClasses method
- /// @return Pointer to the binding (possibly null binding if there are no
- /// required classes specified).
- template<typename T>
- db::MySqlBindingPtr createInputRequiredClassesBinding(const T& object) {
- // Create JSON list of required classes.
- data::ElementPtr required_classes_element = data::Element::createList();
- auto const& required_classes = object->getRequiredClasses();
- for (auto const& required_class : required_classes) {
- required_classes_element->add(data::Element::create(required_class));
- }
-
- return (required_classes_element ?
- db::MySqlBinding::createString(required_classes_element->str()) :
- db::MySqlBinding::createNull());
- }
-
/// @brief Creates input binding from a list of client classes
///
/// @param client_classes ClientClasses collection containing the class names
@@ -650,6 +629,18 @@ public:
/// classes specified).
db::MySqlBindingPtr createInputClientClassesBinding(const ClientClasses& client_classes);
+ /// @brief Populates a ClientClasses container from a binding
+ ///
+ /// The input column is expected to be a JSON list of class names.
+ ///
+ /// @param binding binding of the column containing the class list.
+ /// @param column name of the column, used for error messages.
+ /// @param client_classes reference to the container to populate.
+ /// @throw BadValue if the input is invalid.k
+ void clientClassesFromBinding(const db::MySqlBindingPtr& binding,
+ const std::string& column,
+ ClientClasses& client_classes);
+
/// @brief Creates input binding for user context parameter.
///
/// @tparam T Type of the configuration element to which context belongs.
diff --git a/src/hooks/dhcp/mysql/mysql_query_macros_dhcp.h b/src/hooks/dhcp/mysql/mysql_query_macros_dhcp.h
index e22b035f1c..11dd9c0c6d 100644
--- a/src/hooks/dhcp/mysql/mysql_query_macros_dhcp.h
+++ b/src/hooks/dhcp/mysql/mysql_query_macros_dhcp.h
@@ -64,7 +64,7 @@ namespace {
" s.rebind_timer," \
" s.relay," \
" s.renew_timer," \
- " s.require_client_classes," \
+ " s.evaluate_additional_classes," \
" s.reservations_global," \
" s.server_hostname," \
" s.shared_network_name," \
@@ -110,7 +110,7 @@ namespace {
" s.min_valid_lifetime," \
" s.max_valid_lifetime," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" s.ddns_send_updates," \
" s.ddns_override_no_update," \
@@ -171,7 +171,7 @@ namespace {
" s.rebind_timer," \
" s.relay," \
" s.renew_timer," \
- " s.require_client_classes," \
+ " s.evaluate_additional_classes," \
" s.reservations_global," \
" s.shared_network_name," \
" s.user_context," \
@@ -241,12 +241,12 @@ namespace {
" s.min_valid_lifetime," \
" s.max_valid_lifetime," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" d.excluded_prefix," \
" d.excluded_prefix_length," \
" d.client_class," \
- " d.require_client_classes," \
+ " d.evaluate_additional_classes," \
" d.user_context," \
" s.ddns_send_updates," \
" s.ddns_override_no_update," \
@@ -304,7 +304,7 @@ namespace {
" p.end_address," \
" p.subnet_id," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" p.modification_ts," \
" x.option_id," \
@@ -346,7 +346,7 @@ namespace {
" p.end_address," \
" p.subnet_id," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" p.modification_ts," \
" x.option_id," \
@@ -391,7 +391,7 @@ namespace {
" p.excluded_prefix," \
" p.excluded_prefix_length," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" p.modification_ts," \
" x.option_id," \
@@ -438,7 +438,7 @@ namespace {
" n.rebind_timer," \
" n.relay," \
" n.renew_timer," \
- " n.require_client_classes," \
+ " n.evaluate_additional_classes," \
" n.reservations_global," \
" n.user_context," \
" n.valid_lifetime," \
@@ -522,7 +522,7 @@ namespace {
" n.rebind_timer," \
" n.relay," \
" n.renew_timer," \
- " n.require_client_classes," \
+ " n.evaluate_additional_classes," \
" n.reservations_global," \
" n.user_context," \
" n.valid_lifetime," \
@@ -697,7 +697,7 @@ namespace {
" c.next_server," \
" c.server_hostname," \
" c.boot_file_name," \
- " c.only_if_required," \
+ " c.only_in_additional_list," \
" c.valid_lifetime," \
" c.min_valid_lifetime," \
" c.max_valid_lifetime," \
@@ -763,7 +763,7 @@ namespace {
" c.id," \
" c.name," \
" c.test," \
- " c.only_if_required," \
+ " c.only_in_additional_list," \
" c.valid_lifetime," \
" c.min_valid_lifetime," \
" c.max_valid_lifetime," \
@@ -860,7 +860,7 @@ namespace {
" end_address," \
" subnet_id," \
" client_class," \
- " require_client_classes," \
+ " evaluate_additional_classes," \
" user_context," \
" modification_ts" \
") VALUES (?, ?, ?, ?, ?, ?, ?)"
@@ -876,7 +876,7 @@ namespace {
" excluded_prefix," \
" excluded_prefix_length," \
" client_class," \
- " require_client_classes," \
+ " evaluate_additional_classes," \
" user_context," \
" modification_ts" \
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
@@ -1107,7 +1107,7 @@ namespace {
" next_server = ?," \
" server_hostname = ?," \
" boot_file_name = ?," \
- " only_if_required = ?," \
+ " only_in_additional_list = ?," \
" valid_lifetime = ?," \
" min_valid_lifetime = ?," \
" max_valid_lifetime = ?," \
@@ -1124,7 +1124,7 @@ namespace {
"UPDATE dhcp6_client_class SET" \
" name = ?," \
" test = ?," \
- " only_if_required = ?," \
+ " only_in_additional_list = ?," \
" valid_lifetime = ?," \
" min_valid_lifetime = ?," \
" max_valid_lifetime = ?," \
diff --git a/src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc b/src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc
index 5a2d147150..709b47e61a 100644
--- a/src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc
+++ b/src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc
@@ -393,10 +393,9 @@ public:
// renew_timer at 13 (fetched before subnet create).
- // require_client_classes at 14.
- setRequiredClasses(worker, 14, [&last_subnet](const std::string& class_name) {
- last_subnet->requireClientClass(class_name);
- });
+ // evaluate_additional_classes at 14.
+ clientClassesFromColumn(worker, 14, "evaluate_additional_classes",
+ last_subnet->getMutableAdditionalClasses());
// reservations_global at 15.
if (!worker.isColumnNull(15)) {
@@ -448,7 +447,7 @@ public:
// min_valid_lifetime at 57 (fetched as part of triplet).
// max_valid_lifetime at 58 (fetched as part of triplet).
- // pool client_class, require_client_classes and user_context
+ // pool client_class, evaluate_additional_classes and user_context
// from 59 to 61.
// ddns_send_updates at 62.
@@ -558,10 +557,9 @@ public:
last_pool->allowClientClass(worker.getString(59));
}
- // pool require_client_classes at 60.
- setRequiredClasses(worker, 60, [&last_pool](const std::string& class_name) {
- last_pool->requireClientClass(class_name);
- });
+ // pool evaluate_additional_classes at 60.
+ clientClassesFromColumn(worker, 60, "evaluate_additional_classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context at 61.
if (!worker.isColumnNull(61)) {
@@ -767,10 +765,9 @@ public:
last_pool->allowClientClass(worker.getString(4));
}
- // pool require_client_classes (5)
- setRequiredClasses(worker, 5, [&last_pool](const std::string& class_name) {
- last_pool->requireClientClass(class_name);
- });
+ // pool evaluate_additional_classes (5)
+ clientClassesFromColumn(worker, 5, "evaluate_additional_classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context (6)
if (!worker.isColumnNull(6)) {
@@ -895,7 +892,7 @@ public:
in_bindings.add(subnet->getT2(Network::Inheritance::NONE));
addRelayBinding(in_bindings, subnet);
in_bindings.add(subnet->getT1(Network::Inheritance::NONE));
- addRequiredClassesBinding(in_bindings, subnet);
+ addAdditionalClassesBinding(in_bindings, subnet);
in_bindings.addOptional(subnet->getReservationsGlobal(Network::Inheritance::NONE));
in_bindings.addOptional(subnet->getSname(Network::Inheritance::NONE));
@@ -1036,7 +1033,7 @@ public:
in_bindings.addInet4(pool->getLastAddress());
in_bindings.add(subnet->getID());
in_bindings.addOptional(pool->getClientClass());
- addRequiredClassesBinding(in_bindings, pool);
+ addAdditionalClassesBinding(in_bindings, pool);
in_bindings.add(pool->getContext());
in_bindings.addTimestamp(subnet->getModificationTime());
@@ -1226,10 +1223,9 @@ public:
last_network->setT1(worker.getTriplet(8));
}
- // require_client_classes at 9.
- setRequiredClasses(worker, 9, [&last_network](const std::string& class_name) {
- last_network->requireClientClass(class_name);
- });
+ // evaluate_additional_classes at 9.
+ clientClassesFromColumn(worker, 9, "evaluate_additional_classes",
+ last_network->getMutableAdditionalClasses());
// reservations_global at 10.
if (!worker.isColumnNull(10)) {
@@ -1495,7 +1491,7 @@ public:
in_bindings.add(shared_network->getT2(Network::Inheritance::NONE));
addRelayBinding(in_bindings, shared_network);
in_bindings.add(shared_network->getT1(Network::Inheritance::NONE));
- addRequiredClassesBinding(in_bindings, shared_network);
+ addAdditionalClassesBinding(in_bindings, shared_network);
in_bindings.addOptional(shared_network->getReservationsGlobal(Network::Inheritance::NONE));
in_bindings.add(shared_network->getContext());
in_bindings.add(shared_network->getValid(Network::Inheritance::NONE));
@@ -2279,9 +2275,9 @@ public:
last_client_class->setFilename(worker.getString(5));
}
- // required
+ // additional
if (!worker.isColumnNull(6)) {
- last_client_class->setRequired(worker.getBool(6));
+ last_client_class->setAdditional(worker.getBool(6));
}
// valid lifetime: default, min, max
@@ -2451,7 +2447,7 @@ public:
in_bindings.addInet4(client_class->getNextServer());
in_bindings.addTempString(client_class->getSname());
in_bindings.addTempString(client_class->getFilename());
- in_bindings.add(client_class->getRequired());
+ in_bindings.add(client_class->getAdditional());
in_bindings.add(client_class->getValid());
in_bindings.add(client_class->getValid().getMin());
in_bindings.add(client_class->getValid().getMax());
@@ -3339,7 +3335,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 12 rebind_timer
OID_TEXT, // 13 relay
OID_INT8, // 14 renew_timer
- OID_TEXT, // 15 require_client_classes
+ OID_TEXT, // 15 evaluate_additional_classes
OID_BOOL, // 16 reservations_global
OID_VARCHAR, // 17 server_hostname
OID_VARCHAR, // 18 shared_network_name
@@ -3380,7 +3376,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" server_hostname,"
" shared_network_name,"
@@ -3434,7 +3430,7 @@ TaggedStatementArray tagged_statements = { {
OID_TEXT, // 2 end_address - cast as inet
OID_INT8, // 3 subnet_id
OID_VARCHAR, // 4 client_class
- OID_TEXT, // 5 require_client_classes
+ OID_TEXT, // 5 evaluate_additional_classes
OID_TEXT, // 6 user_context - cast as json
OID_TIMESTAMP // 7 modification_ts
},
@@ -3455,7 +3451,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 6 rebind_timer,
OID_TEXT, // 7 relay,
OID_INT8, // 8 renew_timer,
- OID_TEXT, // 9 require_client_classes,
+ OID_TEXT, // 9 evaluate_additional_classes,
OID_BOOL, // 10 reservations_global,
OID_TEXT, // 11 user_context,
OID_INT8, // 12 valid_lifetime,
@@ -3491,7 +3487,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
@@ -3637,7 +3633,7 @@ TaggedStatementArray tagged_statements = { {
OID_TEXT, // 3 next_server - cast as inet
OID_VARCHAR, // 4 server_hostname
OID_VARCHAR, // 5 boot_file_name
- OID_BOOL, // 6 only_if_required
+ OID_BOOL, // 6 only_in_additional_list
OID_INT8, // 7 valid_lifetime
OID_INT8, // 8 min_valid_lifetime
OID_INT8, // 9 max_valid_lifetime
@@ -3654,7 +3650,7 @@ TaggedStatementArray tagged_statements = { {
" next_server,"
" server_hostname,"
" boot_file_name,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
@@ -3741,7 +3737,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 12 rebind_timer
OID_TEXT, // 13 relay
OID_INT8, // 14 renew_timer
- OID_TEXT, // 15 require_client_classes
+ OID_TEXT, // 15 evaluate_additional_classes
OID_BOOL, // 16 reservations_global
OID_VARCHAR, // 17 server_hostname
OID_VARCHAR, // 18 shared_network_name
@@ -3784,7 +3780,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = $12,"
" relay = $13,"
" renew_timer = $14,"
- " require_client_classes = $15,"
+ " evaluate_additional_classes = $15,"
" reservations_global = $16,"
" server_hostname = $17,"
" shared_network_name = $18,"
@@ -3824,7 +3820,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 6 rebind_timer,
OID_TEXT, // 7 relay,
OID_INT8, // 8 renew_timer,
- OID_TEXT, // 9 require_client_classes,
+ OID_TEXT, // 9 evaluate_additional_classes,
OID_BOOL, // 10 reservations_global,
OID_TEXT, // 11 user_context,
OID_INT8, // 12 valid_lifetime,
@@ -3861,7 +3857,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = $6,"
" relay = $7,"
" renew_timer = $8,"
- " require_client_classes = $9,"
+ " evaluate_additional_classes = $9,"
" reservations_global = $10,"
" user_context = cast($11 as json),"
" valid_lifetime = $12,"
@@ -4080,7 +4076,7 @@ TaggedStatementArray tagged_statements = { {
OID_TEXT, // 3 next_server - cast as inet
OID_VARCHAR, // 4 server_hostname
OID_VARCHAR, // 5 boot_file_name
- OID_BOOL, // 6 only_if_required
+ OID_BOOL, // 6 only_in_additional_list
OID_INT8, // 7 valid_lifetime
OID_INT8, // 8 min_valid_lifetime
OID_INT8, // 9 max_valid_lifetime
@@ -4105,7 +4101,7 @@ TaggedStatementArray tagged_statements = { {
OID_TEXT, // 3 next_server - cast as inet
OID_VARCHAR, // 4 server_hostname
OID_VARCHAR, // 5 boot_file_name
- OID_BOOL, // 6 only_if_required
+ OID_BOOL, // 6 only_in_additional_list
OID_INT8, // 7 valid_lifetime
OID_INT8, // 8 min_valid_lifetime
OID_INT8, // 9 max_valid_lifetime
diff --git a/src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc b/src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc
index f5e71eeb52..16fc0533be 100644
--- a/src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc
+++ b/src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc
@@ -385,10 +385,9 @@ public:
// renew_timer is 9.
- // require_client_classes at 10.
- setRequiredClasses(worker, 10, [&last_subnet](const std::string& class_name) {
- last_subnet->requireClientClass(class_name);
- });
+ // evaluate_additional_classes at 10.
+ clientClassesFromColumn(worker, 10, "evaluate_additional_classes",
+ last_subnet->getMutableAdditionalClasses());
// reservations_global at 11.
if (!worker.isColumnNull(11)) {
@@ -439,12 +438,12 @@ public:
// 77 and 78 are {min,max}_valid_lifetime
// 79 is pool client_class
- // 80 is pool require_client_classes
+ // 80 is pool evaluate_additional_classes
// 81 is pool user_context
// 82 is pd pool excluded_prefix
// 83 is pd pool excluded_prefix_length
// 84 is pd pool client_class
- // 85 is pd pool require_client_classes
+ // 85 is pd pool evaluate_additional_classes
// 86 is pd pool user_context
// ddns_send_updates at 87.
@@ -559,10 +558,9 @@ public:
last_pool->allowClientClass(worker.getString(79));
}
- // pool require_client_classes at 80.
- setRequiredClasses(worker, 80, [&last_pool](const std::string& class_name) {
- last_pool->requireClientClass(class_name);
- });
+ // pool evaluate_additional_classes at 80.
+ clientClassesFromColumn(worker, 80, "evaluate_additional_classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context at 81.
if (!worker.isColumnNull(81)) {
@@ -612,10 +610,9 @@ public:
last_pd_pool->allowClientClass(worker.getString(84));
}
- // pd pool require_client_classes at 85.
- setRequiredClasses(worker, 85, [&last_pd_pool](const std::string& class_name) {
- last_pd_pool->requireClientClass(class_name);
- });
+ // pd pool evaluate_additional_classes at 85.
+ clientClassesFromColumn(worker, 85, "evaluate_additional_classes",
+ last_pd_pool->getMutableAdditionalClasses());
// pd pool user_context at 86.
if (!worker.isColumnNull(86)) {
@@ -832,10 +829,9 @@ public:
last_pool->allowClientClass(worker.getString(4));
}
- // pool require_client_classes (5)
- setRequiredClasses(worker, 5, [&last_pool](const std::string& class_name) {
- last_pool->requireClientClass(class_name);
- });
+ // pool evaluate_additional_classes (5)
+ clientClassesFromColumn(worker, 5, "evaluate_additional_classes",
+ last_pool->getMutableAdditionalClasses());
// pool user_context (6)
if (!worker.isColumnNull(6)) {
@@ -920,10 +916,9 @@ public:
last_pd_pool->allowClientClass(worker.getString(7));
}
- // pool require_client_classes (8)
- setRequiredClasses(worker, 8, [&last_pd_pool](const std::string& class_name) {
- last_pd_pool->requireClientClass(class_name);
- });
+ // pool evaluate_additional_classes (8)
+ clientClassesFromColumn(worker, 8, "evaluate_additional_classes",
+ last_pd_pool->getMutableAdditionalClasses());
// pd pool user_context (9)
if (!worker.isColumnNull(9)) {
@@ -1064,7 +1059,7 @@ public:
in_bindings.add(subnet->getT2(Network::Inheritance::NONE));
addRelayBinding(in_bindings, subnet);
in_bindings.add(subnet->getT1(Network::Inheritance::NONE));
- addRequiredClassesBinding(in_bindings, subnet);
+ addAdditionalClassesBinding(in_bindings, subnet);
in_bindings.addOptional(subnet->getReservationsGlobal(Network::Inheritance::NONE));
// Add shared network.
@@ -1211,7 +1206,7 @@ public:
in_bindings.addInet6(pool->getLastAddress());
in_bindings.add(subnet->getID());
in_bindings.addOptional(pool->getClientClass());
- addRequiredClassesBinding(in_bindings, pool);
+ addAdditionalClassesBinding(in_bindings, pool);
in_bindings.add(pool->getContext());
in_bindings.addTimestamp(subnet->getModificationTime());
@@ -1265,7 +1260,7 @@ public:
in_bindings.addOptional(xprefix_txt);
in_bindings.add(xlen);
in_bindings.addOptional(pd_pool->getClientClass());
- addRequiredClassesBinding(in_bindings, pd_pool);
+ addAdditionalClassesBinding(in_bindings, pd_pool);
in_bindings.add(pd_pool->getContext());
in_bindings.addTimestamp(subnet->getModificationTime());
@@ -1478,10 +1473,9 @@ public:
last_network->setT1(worker.getTriplet(9));
}
- // require_client_classes at 10.
- setRequiredClasses(worker, 10, [&last_network](const std::string& class_name) {
- last_network->requireClientClass(class_name);
- });
+ // evaluate_additional_classes at 10.
+ clientClassesFromColumn(worker, 10, "evaluate_additional_classes",
+ last_network->getMutableAdditionalClasses());
// reservations_global at 11.
if (!worker.isColumnNull(11)) {
@@ -1735,7 +1729,7 @@ public:
in_bindings.add(shared_network->getT2(Network::Inheritance::NONE));
addRelayBinding(in_bindings, shared_network);
in_bindings.add(shared_network->getT1(Network::Inheritance::NONE));
- addRequiredClassesBinding(in_bindings, shared_network);
+ addAdditionalClassesBinding(in_bindings, shared_network);
in_bindings.addOptional(shared_network->getReservationsGlobal(Network::Inheritance::NONE));
in_bindings.add(shared_network->getContext());
in_bindings.add(shared_network->getValid(Network::Inheritance::NONE));
@@ -2600,9 +2594,9 @@ public:
last_client_class->setTest(worker.getString(2));
}
- // required
+ // additional
if (!worker.isColumnNull(3)) {
- last_client_class->setRequired(worker.getBool(3));
+ last_client_class->setAdditional(worker.getBool(3));
}
// valid lifetime: default, min, max
@@ -2771,7 +2765,7 @@ public:
std::string class_name = client_class->getName();
in_bindings.add(class_name);
in_bindings.addTempString(client_class->getTest());
- in_bindings.add(client_class->getRequired());
+ in_bindings.add(client_class->getAdditional());
in_bindings.add(client_class->getValid());
in_bindings.add(client_class->getValid().getMin());
in_bindings.add(client_class->getValid().getMax());
@@ -3738,7 +3732,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 10 rebind_timer
OID_TEXT, // 11 relay
OID_INT8, // 12 renew_timer
- OID_TEXT, // 13 require_client_classes
+ OID_TEXT, // 13 evaluate_additional_classes
OID_BOOL, // 14 reservations_global
OID_VARCHAR, // 15 shared_network_name
OID_TEXT, // 16 user_context - cast as json
@@ -3776,7 +3770,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" shared_network_name,"
" user_context,"
@@ -3829,7 +3823,7 @@ TaggedStatementArray tagged_statements = { {
OID_TEXT, // 2 end_address - cast as inet
OID_INT8, // 3 subnet_id
OID_VARCHAR, // 4 client_class
- OID_TEXT, // 5 require_client_classes
+ OID_TEXT, // 5 evaluate_additional_classes
OID_TEXT, // 6 user_context - cast as json
OID_TIMESTAMP // 7 modification_ts
},
@@ -3849,7 +3843,7 @@ TaggedStatementArray tagged_statements = { {
OID_VARCHAR, // 5 excluded_prefix
OID_INT2, // 6 excluded_prefix_length
OID_VARCHAR, // 7 client_class
- OID_TEXT, // 8 require_client_classes
+ OID_TEXT, // 8 evaluate_additional_classes
OID_TEXT, // 9 user_context - cast as json
OID_TIMESTAMP, // 10 modification_ts
},
@@ -3873,7 +3867,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 9 rebind_timer
OID_TEXT, // 10 relay
OID_INT8, // 11 renew_timer
- OID_TEXT, // 12 require_client_classes
+ OID_TEXT, // 12 evaluate_additional_classes
OID_BOOL, // 13 reservations_global
OID_TEXT, // 14 user_context - cast as json
OID_INT8, // 15 valid_lifetime
@@ -3909,7 +3903,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
@@ -4050,7 +4044,7 @@ TaggedStatementArray tagged_statements = { {
{
OID_VARCHAR, // 1 name
OID_TEXT, // 2 test
- OID_BOOL, // 3 only_if_required
+ OID_BOOL, // 3 only_in_additional_list
OID_INT8, // 4 valid_lifetime
OID_INT8, // 5 min_valid_lifetime
OID_INT8, // 6 max_valid_lifetime
@@ -4066,7 +4060,7 @@ TaggedStatementArray tagged_statements = { {
"INSERT INTO dhcp6_client_class("
" name,"
" test,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
@@ -4153,7 +4147,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 10 rebind_timer
OID_TEXT, // 11 relay
OID_INT8, // 12 renew_timer
- OID_TEXT, // 13 require_client_classes
+ OID_TEXT, // 13 evaluate_additional_classes
OID_BOOL, // 14 reservations_global
OID_VARCHAR, // 15 shared_network_name
OID_TEXT, // 16 user_context - cast as json
@@ -4191,7 +4185,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = $10,"
" relay = $11,"
" renew_timer = $12,"
- " require_client_classes = $13,"
+ " evaluate_additional_classes = $13,"
" reservations_global = $14,"
" shared_network_name = $15,"
" user_context = cast($16 as json),"
@@ -4233,7 +4227,7 @@ TaggedStatementArray tagged_statements = { {
OID_INT8, // 9 rebind_timer
OID_TEXT, // 10 relay
OID_INT8, // 11 renew_timer
- OID_TEXT, // 12 require_client_classes
+ OID_TEXT, // 12 evaluate_additional_classes
OID_BOOL, // 13 reservations_global
OID_TEXT, // 14 user_context - cast as json
OID_INT8, // 15 valid_lifetime
@@ -4269,7 +4263,7 @@ TaggedStatementArray tagged_statements = { {
" rebind_timer = $9,"
" relay = $10,"
" renew_timer = $11,"
- " require_client_classes = $12,"
+ " evaluate_additional_classes = $12,"
" reservations_global = $13,"
" user_context = cast($14 as json),"
" valid_lifetime = $15,"
@@ -4515,7 +4509,7 @@ TaggedStatementArray tagged_statements = { {
{
OID_VARCHAR, // 1 name
OID_TEXT, // 2 test
- OID_BOOL, // 3 only_if_required
+ OID_BOOL, // 3 only_in_additional_list
OID_INT8, // 4 valid_lifetime
OID_INT8, // 5 min_valid_lifetime
OID_INT8, // 6 max_valid_lifetime
@@ -4539,7 +4533,7 @@ TaggedStatementArray tagged_statements = { {
{
OID_VARCHAR, // 1 name
OID_TEXT, // 2 test
- OID_BOOL, // 3 only_if_required
+ OID_BOOL, // 3 only_in_additional_list
OID_INT8, // 4 valid_lifetime
OID_INT8, // 5 min_valid_lifetime
OID_INT8, // 6 max_valid_lifetime
diff --git a/src/hooks/dhcp/pgsql/pgsql_cb_impl.cc b/src/hooks/dhcp/pgsql/pgsql_cb_impl.cc
index bad28bad92..1fdca0395e 100644
--- a/src/hooks/dhcp/pgsql/pgsql_cb_impl.cc
+++ b/src/hooks/dhcp/pgsql/pgsql_cb_impl.cc
@@ -837,7 +837,7 @@ PgSqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
}
// Populate client classes.
- setClientClasses(worker, first_col + 13, desc->client_classes_);
+ setClientClasses(worker, first_col + 13, "client_classes", desc->client_classes_);
// Set database id for the option.
// @todo Can this actually ever be null and if it is, isn't that an error?
@@ -850,6 +850,7 @@ PgSqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
void
PgSqlConfigBackendImpl::setClientClasses(PgSqlResultRowWorker& worker, size_t col,
+ const std::string& column,
ClientClasses& client_classes) {
if (worker.isColumnNull(col)) {
return;
@@ -862,7 +863,7 @@ PgSqlConfigBackendImpl::setClientClasses(PgSqlResultRowWorker& worker, size_t co
} catch (const std::exception& ex) {
std::ostringstream ss;
cclasses_element->toJSON(ss);
- isc_throw(BadValue, "invalid 'client_classes' : " << ss.str() << ex.what());
+ isc_throw(BadValue, "invalid '" << column << "' : " << ss.str() << ex.what());
}
}
@@ -1137,30 +1138,22 @@ PgSqlConfigBackendImpl::setRelays(PgSqlResultRowWorker& worker, size_t col, Netw
}
void
-PgSqlConfigBackendImpl::setRequiredClasses(PgSqlResultRowWorker& worker, size_t col,
- std::function<void(const std::string&)> setter) {
+PgSqlConfigBackendImpl::clientClassesFromColumn(PgSqlResultRowWorker& worker, size_t col,
+ const std::string& column,
+ ClientClasses& client_classes) {
if (worker.isColumnNull(col)) {
return;
}
- ElementPtr require_element = worker.getJSON(col);
- if (require_element->getType() != Element::list) {
- std::ostringstream ss;
- require_element->toJSON(ss);
- isc_throw(BadValue, "invalid require_client_classes value " << ss.str());
- }
-
- for (auto i = 0; i < require_element->size(); ++i) {
- auto require_item = require_element->get(i);
- if (require_item->getType() != Element::string) {
- isc_throw(BadValue, "elements of require_client_classes list must"
- "be valid strings");
- }
-
- setter(require_item->stringValue());
+ try {
+ ElementPtr cclist_element = worker.getJSON(col);
+ client_classes.fromElement(cclist_element);
+ } catch (const std::exception& ex) {
+ isc_throw(BadValue, "invalid '" << column << "' value " << ex.what());
}
}
+
void
PgSqlConfigBackendImpl::addOptionValueBinding(PsqlBindArray& bindings,
const OptionDescriptorPtr& option) {
diff --git a/src/hooks/dhcp/pgsql/pgsql_cb_impl.h b/src/hooks/dhcp/pgsql/pgsql_cb_impl.h
index a5b87a0ef9..9a019351ed 100644
--- a/src/hooks/dhcp/pgsql/pgsql_cb_impl.h
+++ b/src/hooks/dhcp/pgsql/pgsql_cb_impl.h
@@ -585,44 +585,45 @@ public:
/// list's elements are not valid IP addresses in string form.
void setRelays(db::PgSqlResultRowWorker& r, size_t col, Network& network);
- /// @brief Adds 'require_client_classes' parameter to a bind array.
+ /// @brief Adds 'evaluate_additional_classes' parameter to a bind array.
///
- /// Creates an Element tree of required class names and adds that to the end
+ /// Creates an Element tree of additional class names and adds that to the end
/// of the given bind array.
///
- /// @tparam T of pointer to objects with getRequiredClasses
+ /// @tparam T of pointer to objects with getAdditionalClasses
/// method, e.g. shared network, subnet, pool or prefix delegation pool.
/// @param bindings PsqlBindArray to which the classes should be added.
- /// @param object Pointer to an object with getRequiredClasses method
+ /// @param object Pointer to an object with getAdditionalClasses method
/// @return Pointer to the binding (possibly null binding if there are no
- /// required classes specified).
+ /// additional classes specified).
template<typename T>
- void addRequiredClassesBinding(db::PsqlBindArray& bindings, const T& object) {
- // Create JSON list of required classes.
- data::ElementPtr required_classes_element = data::Element::createList();
- auto const& required_classes = object->getRequiredClasses();
- for (auto const& required_class : required_classes) {
- required_classes_element->add(data::Element::create(required_class));
+ void addAdditionalClassesBinding(db::PsqlBindArray& bindings, const T& object) {
+ // Create JSON list of additional classes.
+ data::ElementPtr additional_classes_element = data::Element::createList();
+ auto const& additional_classes = object->getAdditionalClasses();
+ for (auto const& additional_class : additional_classes) {
+ additional_classes_element->add(data::Element::create(additional_class));
}
- bindings.add(required_classes_element);
+ bindings.add(additional_classes_element);
}
- /// @brief Iterates over the class names in a JSON list element at a
- /// given column, invoking a setter function for each one.
+ /// @brief Populates a ClientClasses container from a given column
///
/// Has no effect if the column is null or is an empty list.
///
/// @param worker result set row worker containing the row data
/// @param col column index of JSON element column
- /// @param setter function to invoke for each class name in the list
+ /// @param column name of the column used for error logging
+ /// @param client_classes reference to the container to populate.
///
/// @throw BadValue if the Element is not a list or if any of the
/// list's elements are not strings.
- void setRequiredClasses(db::PgSqlResultRowWorker& worker, size_t col,
- std::function<void(const std::string&)> setter);
+ void clientClassesFromColumn(db::PgSqlResultRowWorker& worker, size_t col,
+ const std::string& column,
+ ClientClasses& client_classes);
- /// @brief Addds 'client-classes' parameter to a bind array.
+ /// @brief Adds 'client-classes' parameter to a bind array.
///
/// Creates an Element tree of client class names and adds that to the end
/// of the given bind array.
@@ -637,12 +638,14 @@ public:
/// Has no effect if the column is null or is an empty list.
///
/// @param worker result set row worker containing the row data
+ /// @param column column name used for error messages
/// @param col column index of JSON element column
/// @param client_classes ClientCaLsses instance to populate
///
/// @throw BadValue if the Element is not a list or if any of the
/// list's elements are not strings.
void setClientClasses(db::PgSqlResultRowWorker& worker, size_t col,
+ const std::string& column,
ClientClasses& client_classes);
/// @brief Adds an option value to a bind array.
diff --git a/src/hooks/dhcp/pgsql/pgsql_query_macros_dhcp.h b/src/hooks/dhcp/pgsql/pgsql_query_macros_dhcp.h
index 3b9bac276c..138addee3f 100644
--- a/src/hooks/dhcp/pgsql/pgsql_query_macros_dhcp.h
+++ b/src/hooks/dhcp/pgsql/pgsql_query_macros_dhcp.h
@@ -60,7 +60,7 @@ namespace {
" s.rebind_timer," \
" s.relay," \
" s.renew_timer," \
- " s.require_client_classes," \
+ " s.evaluate_additional_classes," \
" s.reservations_global," \
" s.server_hostname," \
" s.shared_network_name," \
@@ -106,7 +106,7 @@ namespace {
" s.min_valid_lifetime," \
" s.max_valid_lifetime," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" s.ddns_send_updates," \
" s.ddns_override_no_update," \
@@ -167,7 +167,7 @@ namespace {
" s.rebind_timer," \
" s.relay," \
" s.renew_timer," \
- " s.require_client_classes," \
+ " s.evaluate_additional_classes," \
" s.reservations_global," \
" s.shared_network_name," \
" s.user_context," \
@@ -237,12 +237,12 @@ namespace {
" s.min_valid_lifetime," \
" s.max_valid_lifetime," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" d.excluded_prefix," \
" d.excluded_prefix_length," \
" d.client_class," \
- " d.require_client_classes," \
+ " d.evaluate_additional_classes," \
" d.user_context," \
" s.ddns_send_updates," \
" s.ddns_override_no_update," \
@@ -300,7 +300,7 @@ namespace {
" p.end_address," \
" p.subnet_id," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" gmt_epoch(p.modification_ts) as modification_ts, " \
" x.option_id," \
@@ -342,7 +342,7 @@ namespace {
" p.end_address," \
" p.subnet_id," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" gmt_epoch(p.modification_ts) as modification_ts, " \
" x.option_id," \
@@ -388,7 +388,7 @@ namespace {
" p.excluded_prefix," \
" p.excluded_prefix_length," \
" p.client_class," \
- " p.require_client_classes," \
+ " p.evaluate_additional_classes," \
" p.user_context," \
" gmt_epoch(p.modification_ts) as modification_ts, " \
" x.option_id," \
@@ -435,7 +435,7 @@ namespace {
" n.rebind_timer," \
" n.relay," \
" n.renew_timer," \
- " n.require_client_classes," \
+ " n.evaluate_additional_classes," \
" n.reservations_global," \
" n.user_context," \
" n.valid_lifetime," \
@@ -519,7 +519,7 @@ namespace {
" n.rebind_timer," \
" n.relay," \
" n.renew_timer," \
- " n.require_client_classes," \
+ " n.evaluate_additional_classes," \
" n.reservations_global," \
" n.user_context," \
" n.valid_lifetime," \
@@ -694,7 +694,7 @@ namespace {
" c.next_server," \
" c.server_hostname," \
" c.boot_file_name," \
- " c.only_if_required," \
+ " c.only_in_additional_list," \
" c.valid_lifetime," \
" c.min_valid_lifetime," \
" c.max_valid_lifetime," \
@@ -760,7 +760,7 @@ namespace {
" c.id," \
" c.name," \
" c.test," \
- " c.only_if_required," \
+ " c.only_in_additional_list," \
" c.valid_lifetime," \
" c.min_valid_lifetime," \
" c.max_valid_lifetime," \
@@ -857,7 +857,7 @@ namespace {
" end_address," \
" subnet_id," \
" client_class," \
- " require_client_classes," \
+ " evaluate_additional_classes," \
" user_context," \
" modification_ts" \
") VALUES (cast($1 as inet), cast($2 as inet), $3, $4, $5, cast($6 as json), $7)"
@@ -873,7 +873,7 @@ namespace {
" excluded_prefix," \
" excluded_prefix_length," \
" client_class," \
- " require_client_classes," \
+ " evaluate_additional_classes," \
" user_context," \
" modification_ts" \
") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, cast($9 as json), $10)"
@@ -1123,7 +1123,7 @@ namespace {
" next_server = cast($3 as inet)," \
" server_hostname = $4," \
" boot_file_name = $5," \
- " only_if_required = $6," \
+ " only_in_additional_list = $6," \
" valid_lifetime = $7," \
" min_valid_lifetime = $8," \
" max_valid_lifetime = $9," \
@@ -1140,7 +1140,7 @@ namespace {
"UPDATE dhcp6_client_class SET" \
" name = $1," \
" test = $2," \
- " only_if_required = $3," \
+ " only_in_additional_list = $3," \
" valid_lifetime = $4," \
" min_valid_lifetime = $5," \
" max_valid_lifetime = $6," \
diff --git a/src/lib/config_backend/constants.h b/src/lib/config_backend/constants.h
index 579f13709f..1378d54fc0 100644
--- a/src/lib/config_backend/constants.h
+++ b/src/lib/config_backend/constants.h
@@ -38,7 +38,7 @@ constexpr unsigned long INTERFACE_ID_BUF_LENGTH = 128;
constexpr unsigned long RELAY_BUF_LENGTH = 65536;
-constexpr unsigned long REQUIRE_CLIENT_CLASSES_BUF_LENGTH = 65536;
+constexpr unsigned long CLIENT_CLASS_LIST_BUF_LENGTH = 65536;
constexpr unsigned long SERVER_HOSTNAME_BUF_LENGTH = 512;
@@ -82,8 +82,6 @@ constexpr unsigned long DNS_NAME_BUF_LENGTH = 255;
constexpr unsigned long ALLOCATOR_TYPE_BUF_LENGTH = 64;
-constexpr unsigned long OPTION_CLIENT_CLASSES_BUF_LENGTH = 65536;
-
//*}
} // end of namespace isc::cb
diff --git a/src/lib/dhcp/pkt.cc b/src/lib/dhcp/pkt.cc
index 1276515df5..ec22ea5894 100644
--- a/src/lib/dhcp/pkt.cc
+++ b/src/lib/dhcp/pkt.cc
@@ -123,15 +123,22 @@ Pkt::inClass(const ClientClass& client_class) {
}
void
-Pkt::addClass(const ClientClass& client_class, bool required) {
- ClientClasses& classes = !required ? classes_ : required_classes_;
- if (!classes.contains(client_class)) {
- classes.insert(client_class);
+Pkt::addClass(const ClientClass& client_class) {
+ if (!classes_.contains(client_class)) {
+ classes_.insert(client_class);
static_cast<void>(subclasses_.push_back(SubClassRelation(client_class, client_class)));
}
}
void
+Pkt::addAdditionalClass(const ClientClass& client_class) {
+ if (!additional_classes_.contains(client_class)) {
+ additional_classes_.insert(client_class);
+ // Since this list is pre-evaluation, we do not add subclass relationship.
+ }
+}
+
+void
Pkt::addSubClass(const ClientClass& class_def, const ClientClass& subclass) {
if (!classes_.contains(subclass)) {
classes_.insert(subclass);
diff --git a/src/lib/dhcp/pkt.h b/src/lib/dhcp/pkt.h
index f8a675942e..e655e6cf9c 100644
--- a/src/lib/dhcp/pkt.h
+++ b/src/lib/dhcp/pkt.h
@@ -355,9 +355,16 @@ public:
/// ignored silently.
///
/// @param client_class name of the class to be added
- /// @param required the class is marked for required evaluation
- void addClass(const isc::dhcp::ClientClass& client_class,
- bool required = false);
+ void addClass(const isc::dhcp::ClientClass& client_class);
+
+ /// @brief Adds a specified class to the packet's additional class list.
+ ///
+ /// A class can be added to the same packet repeatedly. Any additional
+ /// attempts to add to a packet the class already added, will be
+ /// ignored silently.
+ ///
+ /// @param client_class name of the class to be added
+ void addAdditionalClass(const isc::dhcp::ClientClass& client_class);
/// @brief Adds a specified subclass to the packet.
///
@@ -373,12 +380,17 @@ public:
/// @brief Returns the class set
///
/// @note This should be used only to iterate over the class set.
- /// @param required return classes or required to be evaluated classes.
- /// @return if required is false (the default) the classes the
- /// packet belongs to else the classes which are required to be
- /// evaluated.
- const ClientClasses& getClasses(bool required = false) const {
- return (!required ? classes_ : required_classes_);
+ /// @return Classes to which the packet belongs
+ const ClientClasses& getClasses() const {
+ return (classes_);
+ }
+
+ /// @brief Returns the additional class list.
+ ///
+ /// @note This should be used only to iterate over the additional class set.
+ /// @return The classes to be evaluated.
+ const ClientClasses& getAdditionalClasses() const {
+ return (additional_classes_);
}
/// @brief Returns the class set including template classes associated with
@@ -386,9 +398,7 @@ public:
///
/// @note This should be used only to iterate over the class set.
/// @note SubClasses are always last.
- /// @return if required is false (the default) the classes the
- /// packet belongs to else the classes which are required to be
- /// evaluated.
+ /// @return sub class relationships to which the packet belongs.
const SubClassRelationContainer& getSubClassesRelations() const {
return (subclasses_);
}
@@ -769,13 +779,19 @@ public:
/// @ref addClass to operate on this field.
ClientClasses classes_;
- /// @brief Classes which are required to be evaluated.
+ /// @brief Classes to be evaluated during additional class evaluation
+ ///
+ /// This list allows hook libraries a way to add classes to the list of classes
+ /// which will be evaluated during evaluate-addtional-classes evaluation.
///
- /// The comment on @ref classes_ applies here.
+ /// This field is public, so the code outside of Pkt4 or Pkt6 class can
+ /// iterate over additional classes. Having it public also solves the problem
+ /// of returned reference lifetime. It is preferred to use @ref addAdditionalClass
+ /// operate on this field.
///
/// Before output option processing these classes will be evaluated
- /// and if evaluation status is true added to the previous collection.
- ClientClasses required_classes_;
+ /// and if evaluation status is true added to the classes_ collection.
+ ClientClasses additional_classes_;
/// @brief SubClasses this packet belongs to.
///
diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc
index ad418609d3..80920291b2 100644
--- a/src/lib/dhcp/tests/pkt4_unittest.cc
+++ b/src/lib/dhcp/tests/pkt4_unittest.cc
@@ -1037,32 +1037,31 @@ TEST_F(Pkt4Test, clientClasses) {
EXPECT_TRUE(pkt.inClass("foo"));
}
-// Tests whether a packet can be marked to evaluate later a class and
-// after check if a given class is in the collection
-TEST_F(Pkt4Test, deferredClientClasses) {
+// Tests operations on additional classes list.
+TEST_F(Pkt4Test, additionalClientClasses) {
Pkt4 pkt(DHCPOFFER, 1234);
// Default values (do not belong to any class)
- EXPECT_TRUE(pkt.getClasses(true).empty());
+ EXPECT_TRUE(pkt.getAdditionalClasses().empty());
// Add to the first class
- pkt.addClass(DOCSIS3_CLASS_EROUTER, true);
- EXPECT_EQ(1, pkt.getClasses(true).size());
+ pkt.addAdditionalClass(DOCSIS3_CLASS_EROUTER);
+ EXPECT_EQ(1, pkt.getAdditionalClasses().size());
// Add to a second class
- pkt.addClass(DOCSIS3_CLASS_MODEM, true);
- EXPECT_EQ(2, pkt.getClasses(true).size());
- 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"));
+ pkt.addAdditionalClass(DOCSIS3_CLASS_MODEM);
+ EXPECT_EQ(2, pkt.getAdditionalClasses().size());
+ EXPECT_TRUE(pkt.getAdditionalClasses().contains(DOCSIS3_CLASS_EROUTER));
+ EXPECT_TRUE(pkt.getAdditionalClasses().contains(DOCSIS3_CLASS_MODEM));
+ EXPECT_FALSE(pkt.getAdditionalClasses().contains("foo"));
// Check that it's ok to add to the same class repeatedly
- EXPECT_NO_THROW(pkt.addClass("foo", true));
- EXPECT_NO_THROW(pkt.addClass("foo", true));
- EXPECT_NO_THROW(pkt.addClass("foo", true));
+ EXPECT_NO_THROW(pkt.addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pkt.addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pkt.addAdditionalClass("foo"));
// Check that the packet belongs to 'foo'
- EXPECT_TRUE(pkt.getClasses(true).contains("foo"));
+ EXPECT_TRUE(pkt.getAdditionalClasses().contains("foo"));
}
// Tests whether a packet can be assigned to a subclass and later
diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc
index 6febc4d258..5f60b1b24d 100644
--- a/src/lib/dhcp/tests/pkt6_unittest.cc
+++ b/src/lib/dhcp/tests/pkt6_unittest.cc
@@ -1337,32 +1337,31 @@ TEST_F(Pkt6Test, clientClasses) {
EXPECT_TRUE(pkt.inClass("foo"));
}
-// Tests whether a packet can be marked to evaluate later a class and
-// after check if a given class is in the collection
-TEST_F(Pkt6Test, deferredClientClasses) {
+// Tests operations on additional classes list.
+TEST_F(Pkt6Test, additionalClientClasses) {
Pkt6 pkt(DHCPV6_ADVERTISE, 1234);
// Default values (do not belong to any class)
- EXPECT_TRUE(pkt.getClasses(true).empty());
+ EXPECT_TRUE(pkt.getAdditionalClasses().empty());
// Add to the first class
- pkt.addClass(DOCSIS3_CLASS_EROUTER, true);
- EXPECT_EQ(1, pkt.getClasses(true).size());
+ pkt.addAdditionalClass(DOCSIS3_CLASS_EROUTER);
+ EXPECT_EQ(1, pkt.getAdditionalClasses().size());
// Add to a second class
- pkt.addClass(DOCSIS3_CLASS_MODEM, true);
- EXPECT_EQ(2, pkt.getClasses(true).size());
- 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"));
+ pkt.addAdditionalClass(DOCSIS3_CLASS_MODEM);
+ EXPECT_EQ(2, pkt.getAdditionalClasses().size());
+ EXPECT_TRUE(pkt.getAdditionalClasses().contains(DOCSIS3_CLASS_EROUTER));
+ EXPECT_TRUE(pkt.getAdditionalClasses().contains(DOCSIS3_CLASS_MODEM));
+ EXPECT_FALSE(pkt.getAdditionalClasses().contains("foo"));
// Check that it's ok to add to the same class repeatedly
- EXPECT_NO_THROW(pkt.addClass("foo", true));
- EXPECT_NO_THROW(pkt.addClass("foo", true));
- EXPECT_NO_THROW(pkt.addClass("foo", true));
+ EXPECT_NO_THROW(pkt.addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pkt.addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pkt.addAdditionalClass("foo"));
// Check that the packet belongs to 'foo'
- EXPECT_TRUE(pkt.getClasses(true).contains("foo"));
+ EXPECT_TRUE(pkt.getAdditionalClasses().contains("foo"));
}
// Tests whether a packet can be assigned to a subclass and later
diff --git a/src/lib/dhcpsrv/client_class_def.cc b/src/lib/dhcpsrv/client_class_def.cc
index 5d3ff21e03..b94a699eef 100644
--- a/src/lib/dhcpsrv/client_class_def.cc
+++ b/src/lib/dhcpsrv/client_class_def.cc
@@ -27,7 +27,7 @@ ClientClassDef::ClientClassDef(const std::string& name,
const ExpressionPtr& match_expr,
const CfgOptionPtr& cfg_option)
: UserContext(), CfgToElement(), StampedElement(), name_(name),
- match_expr_(match_expr), required_(false), depend_on_known_(false),
+ match_expr_(match_expr), additional_(false), depend_on_known_(false),
cfg_option_(cfg_option), next_server_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
valid_(), preferred_() {
@@ -46,7 +46,7 @@ ClientClassDef::ClientClassDef(const std::string& name,
ClientClassDef::ClientClassDef(const ClientClassDef& rhs)
: UserContext(rhs), CfgToElement(rhs), StampedElement(rhs), name_(rhs.name_),
- match_expr_(ExpressionPtr()), test_(rhs.test_), required_(rhs.required_),
+ match_expr_(ExpressionPtr()), test_(rhs.test_), additional_(rhs.additional_),
depend_on_known_(rhs.depend_on_known_), cfg_option_(new CfgOption()),
next_server_(rhs.next_server_), sname_(rhs.sname_),
filename_(rhs.filename_), valid_(rhs.valid_), preferred_(rhs.preferred_),
@@ -101,13 +101,13 @@ ClientClassDef::setTest(const std::string& test) {
}
bool
-ClientClassDef::getRequired() const {
- return (required_);
+ClientClassDef::getAdditional() const {
+ return (additional_);
}
void
-ClientClassDef::setRequired(bool required) {
- required_ = required;
+ClientClassDef::setAdditional(bool additional) {
+ additional_ = additional;
}
bool
@@ -213,7 +213,7 @@ ClientClassDef::equals(const ClientClassDef& other) const {
((!cfg_option_def_ && !other.cfg_option_def_) ||
(cfg_option_def_ && other.cfg_option_def_ &&
(*cfg_option_def_ == *other.cfg_option_def_))) &&
- (required_ == other.required_) &&
+ (additional_ == other.additional_) &&
(depend_on_known_ == other.depend_on_known_) &&
(next_server_ == other.next_server_) &&
(sname_ == other.sname_) &&
@@ -232,9 +232,9 @@ ClientClassDef::toElement() const {
if (!test_.empty()) {
result->set("test", Element::create(test_));
}
- // Set only-if-required
- if (required_) {
- result->set("only-if-required", Element::create(required_));
+ // Set only-in-additional-list
+ if (additional_) {
+ result->set("only-in-additional-list", Element::create(additional_));
}
// Set option-def (used only by DHCPv4)
if (cfg_option_def_ && (family == AF_INET)) {
@@ -336,7 +336,7 @@ void
ClientClassDictionary::addClass(const std::string& name,
const ExpressionPtr& match_expr,
const std::string& test,
- bool required,
+ bool additional,
bool depend_on_known,
const CfgOptionPtr& cfg_option,
CfgOptionDefPtr cfg_option_def,
@@ -355,7 +355,7 @@ ClientClassDictionary::addClass(const std::string& name,
cclass.reset(new ClientClassDef(name, match_expr, cfg_option));
}
cclass->setTest(test);
- cclass->setRequired(required);
+ cclass->setAdditional(additional);
cclass->setDependOnKnown(depend_on_known);
cclass->setCfgOptionDef(cfg_option_def);
cclass->setContext(user_context),
diff --git a/src/lib/dhcpsrv/client_class_def.h b/src/lib/dhcpsrv/client_class_def.h
index c9158e1107..21f5e98792 100644
--- a/src/lib/dhcpsrv/client_class_def.h
+++ b/src/lib/dhcpsrv/client_class_def.h
@@ -88,13 +88,13 @@ public:
/// @param test the original expression to assign the class
void setTest(const std::string& test);
- /// @brief Fetches the only if required flag
- bool getRequired() const;
+ /// @brief Fetches the only if additional flag
+ bool getAdditional() const;
- /// @brief Sets the only if required flag
+ /// @brief Sets the only if additional flag
///
- /// @param required the value of the only if required flag
- void setRequired(bool required);
+ /// @param additional the value of the only if additional flag
+ void setAdditional(bool additional);
/// @brief Fetches the depend on known flag aka use host flag
bool getDependOnKnown() const;
@@ -261,14 +261,14 @@ private:
/// this class.
std::string test_;
- /// @brief The only-if-required flag: when false (the default) membership
+ /// @brief The only-in-additional-list flag: when false (the default) membership
/// is determined during classification so is available for instance for
- /// subnet selection. When true, membership is evaluated only when required
+ /// subnet selection. When true, membership is evaluated only when additional
/// and is usable only for option configuration.
- bool required_;
+ bool additional_;
/// @brief The depend on known aka use host flag: when false (the default),
- /// the required flag is false and the class has a match expression
+ /// the additional flag is false and the class has a match expression
/// the expression is evaluated in the first pass. When true and the
/// two other conditions stand the expression is evaluated later when
/// the host reservation membership was determined.
@@ -375,7 +375,7 @@ public:
/// @param name Name to assign to this class
/// @param match_expr Expression the class will use to determine membership
/// @param test Original version of match_expr
- /// @param required Original value of the only if required flag
+ /// @param additional Original value of the only if additional flag
/// @param depend_on_known Using host so will be evaluated later
/// @param options Collection of options members should be given
/// @param defs Option definitions (optional)
@@ -392,7 +392,7 @@ public:
/// dictionary. See @ref dhcp::ClientClassDef::ClientClassDef() for
/// others.
void addClass(const std::string& name, const ExpressionPtr& match_expr,
- const std::string& test, bool required, bool depend_on_known,
+ const std::string& test, bool additional, bool depend_on_known,
const CfgOptionPtr& options,
CfgOptionDefPtr defs = CfgOptionDefPtr(),
isc::data::ConstElementPtr user_context = isc::data::ConstElementPtr(),
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.cc b/src/lib/dhcpsrv/dhcpsrv_messages.cc
index af6e09c28d..b2f7b9088d 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.cc
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.cc
@@ -143,10 +143,12 @@ extern const isc::log::MessageID DHCPSRV_MT_DISABLED_QUEUE_CONTROL = "DHCPSRV_MT
extern const isc::log::MessageID DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE = "DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE";
extern const isc::log::MessageID DHCPSRV_NOTYPE_DB = "DHCPSRV_NOTYPE_DB";
extern const isc::log::MessageID DHCPSRV_NO_SOCKETS_OPEN = "DHCPSRV_NO_SOCKETS_OPEN";
+extern const isc::log::MessageID DHCPSRV_ONLY_IF_REQUIRED_DEPRECATED = "DHCPSRV_ONLY_IF_REQUIRED_DEPRECATED";
extern const isc::log::MessageID DHCPSRV_OPEN_SOCKET_FAIL = "DHCPSRV_OPEN_SOCKET_FAIL";
extern const isc::log::MessageID DHCPSRV_QUEUE_NCR = "DHCPSRV_QUEUE_NCR";
extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_FAILED = "DHCPSRV_QUEUE_NCR_FAILED";
extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_SKIP = "DHCPSRV_QUEUE_NCR_SKIP";
+extern const isc::log::MessageID DHCPSRV_REQUIRE_CLIENT_CLASSES_DEPRECATED = "DHCPSRV_REQUIRE_CLIENT_CLASSES_DEPRECATED";
extern const isc::log::MessageID DHCPSRV_SUBNET4O6_SELECT_FAILED = "DHCPSRV_SUBNET4O6_SELECT_FAILED";
extern const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_ADDRESS_NO_MATCH = "DHCPSRV_SUBNET4_SELECT_BY_ADDRESS_NO_MATCH";
extern const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_INTERFACE_NO_MATCH = "DHCPSRV_SUBNET4_SELECT_BY_INTERFACE_NO_MATCH";
@@ -310,10 +312,12 @@ const char* values[] = {
"DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE", "current configuration will result in opening multiple broadcast capable sockets on some interfaces and some DHCP messages may be duplicated",
"DHCPSRV_NOTYPE_DB", "no 'type' keyword to determine database backend: %1",
"DHCPSRV_NO_SOCKETS_OPEN", "no interface configured to listen to DHCP traffic",
+ "DHCPSRV_ONLY_IF_REQUIRED_DEPRECATED", "The parameter 'only-if-required' is deprecated. Use 'only-in-additional-list' instead",
"DHCPSRV_OPEN_SOCKET_FAIL", "failed to open socket: %1",
"DHCPSRV_QUEUE_NCR", "%1: Name change request to %2 DNS entry queued: %3",
"DHCPSRV_QUEUE_NCR_FAILED", "%1: queuing %2 name change request failed for lease %3: %4",
"DHCPSRV_QUEUE_NCR_SKIP", "%1: skip queuing name change request for lease: %2",
+ "DHCPSRV_REQUIRE_CLIENT_CLASSES_DEPRECATED", "The parameter 'require-client-classes' is deprecated. Use 'evaluate-additional-classes' instead",
"DHCPSRV_SUBNET4O6_SELECT_FAILED", "Failed to select any subnet for the DHCPv4o6 packet",
"DHCPSRV_SUBNET4_SELECT_BY_ADDRESS_NO_MATCH", "No subnet matches address: %1",
"DHCPSRV_SUBNET4_SELECT_BY_INTERFACE_NO_MATCH", "No subnet matches interface: %1",
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.h b/src/lib/dhcpsrv/dhcpsrv_messages.h
index dcb7447534..4c7bf154fa 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.h
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.h
@@ -144,10 +144,12 @@ extern const isc::log::MessageID DHCPSRV_MT_DISABLED_QUEUE_CONTROL;
extern const isc::log::MessageID DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE;
extern const isc::log::MessageID DHCPSRV_NOTYPE_DB;
extern const isc::log::MessageID DHCPSRV_NO_SOCKETS_OPEN;
+extern const isc::log::MessageID DHCPSRV_ONLY_IF_REQUIRED_DEPRECATED;
extern const isc::log::MessageID DHCPSRV_OPEN_SOCKET_FAIL;
extern const isc::log::MessageID DHCPSRV_QUEUE_NCR;
extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_FAILED;
extern const isc::log::MessageID DHCPSRV_QUEUE_NCR_SKIP;
+extern const isc::log::MessageID DHCPSRV_REQUIRE_CLIENT_CLASSES_DEPRECATED;
extern const isc::log::MessageID DHCPSRV_SUBNET4O6_SELECT_FAILED;
extern const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_ADDRESS_NO_MATCH;
extern const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_INTERFACE_NO_MATCH;
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes
index b9a6ac0633..46c543e2cf 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.mes
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes
@@ -945,3 +945,15 @@ included in the message.
% DHCPSRV_UNKNOWN_DB unknown database type: %1
The database access string specified a database type (given in the
message) that is unknown to the software. This is a configuration error.
+
+% DHCPSRV_REQUIRE_CLIENT_CLASSES_DEPRECATED The parameter 'require-client-classes' is deprecated. Use 'evaluate-additional-classes' instead
+This warning message is emitted when configuration parsing detects
+the use of the deprecated 'require-client-classes' parameter. It has
+been replaced by 'evaluate-additional-classes'. Users should migrate
+to the new parameter.
+
+% DHCPSRV_ONLY_IF_REQUIRED_DEPRECATED The parameter 'only-if-required' is deprecated. Use 'only-in-additional-list' instead
+This warning message is emitted when configuration parsing detects
+the use of the deprecated 'only-if-required' parameter. It has
+been replaced by 'only-in-additional-list'. Users should migrate
+to the new parameter.
diff --git a/src/lib/dhcpsrv/network.cc b/src/lib/dhcpsrv/network.cc
index bc447c86d2..9a13810012 100644
--- a/src/lib/dhcpsrv/network.cc
+++ b/src/lib/dhcpsrv/network.cc
@@ -82,15 +82,15 @@ Network::allowClientClass(const isc::dhcp::ClientClass& class_name) {
}
void
-Network::requireClientClass(const isc::dhcp::ClientClass& class_name) {
- if (!required_classes_.contains(class_name)) {
- required_classes_.insert(class_name);
+Network::addAdditionalClass(const isc::dhcp::ClientClass& class_name) {
+ if (!additional_classes_.contains(class_name)) {
+ additional_classes_.insert(class_name);
}
}
const ClientClasses&
-Network::getRequiredClasses() const {
- return (required_classes_);
+Network::getAdditionalClasses() const {
+ return (additional_classes_);
}
Optional<IOAddress>
@@ -141,13 +141,13 @@ Network::toElement() const {
}
// Set require-client-classes
- const ClientClasses& classes = getRequiredClasses();
+ const ClientClasses& classes = getAdditionalClasses();
if (!classes.empty()) {
ElementPtr class_list = Element::createList();
for (auto const& it : classes) {
class_list->add(Element::create(it));
}
- map->set("require-client-classes", class_list);
+ map->set("evaluate-additional-classes", class_list);
}
// T1, T2, and Valid are optional for SharedNetworks, and
diff --git a/src/lib/dhcpsrv/network.h b/src/lib/dhcpsrv/network.h
index d8f9760614..fb934c4e27 100644
--- a/src/lib/dhcpsrv/network.h
+++ b/src/lib/dhcpsrv/network.h
@@ -349,13 +349,18 @@ public:
/// @param class_name client class to be supported by this network
void allowClientClass(const isc::dhcp::ClientClass& class_name);
- /// @brief Adds class class_name to classes required to be evaluated.
+ /// @brief Adds class class_name to the additional classes list.
///
- /// @param class_name client class required to be evaluated
- void requireClientClass(const isc::dhcp::ClientClass& class_name);
+ /// @param class_name client class to add
+ void addAdditionalClass(const isc::dhcp::ClientClass& class_name);
- /// @brief Returns classes which are required to be evaluated
- const ClientClasses& getRequiredClasses() const;
+ /// @brief Returns the additional classes list.
+ const ClientClasses& getAdditionalClasses() const;
+
+ /// @brief Returns the mutable additional classes list.
+ ClientClasses& getMutableAdditionalClasses() {
+ return (additional_classes_);
+ }
/// @brief returns the client class
///
@@ -1147,11 +1152,12 @@ protected:
/// which means that any client is allowed, regardless of its class.
util::Optional<ClientClass> client_class_;
- /// @brief Required classes
+ /// @brief Additional classes
///
- /// If the network is selected these classes will be added to the
- /// incoming packet and their evaluation will be required.
- ClientClasses required_classes_;
+ /// If the network is selected these classes will be evaluated against
+ /// incoming packet after all other classification and the lease has
+ /// been assigned.
+ ClientClasses additional_classes_;
/// @brief a isc::util::Triplet (min/default/max) holding allowed renew timer values
isc::util::Triplet<uint32_t> t1_;
diff --git a/src/lib/dhcpsrv/parsers/base_network_parser.cc b/src/lib/dhcpsrv/parsers/base_network_parser.cc
index 8d73b7aed9..01da86dcd4 100644
--- a/src/lib/dhcpsrv/parsers/base_network_parser.cc
+++ b/src/lib/dhcpsrv/parsers/base_network_parser.cc
@@ -17,6 +17,7 @@ using namespace isc::util;
namespace isc {
namespace dhcp {
+
void
BaseNetworkParser::parseCommon(const ConstElementPtr& network_data,
NetworkPtr& network) {
@@ -250,6 +251,35 @@ BaseNetworkParser::parseOfferLft(const data::ConstElementPtr& network_data,
}
}
+void
+BaseNetworkParser::getAdditionalClassesElem(ConstElementPtr params,
+ ClassAdderFunc adder_func) {
+ // Try setting up additional lient classes.
+ ConstElementPtr req_class_list = params->get("require-client-classes");
+ ConstElementPtr class_list = params->get("evaluate-additional-classes");
+ if (req_class_list) {
+ if (!class_list) {
+ LOG_WARN(dhcpsrv_logger, DHCPSRV_REQUIRE_CLIENT_CLASSES_DEPRECATED);
+ class_list = req_class_list;
+ } else {
+ isc_throw(isc::dhcp::DhcpConfigError,
+ "cannot specify both 'require-client-classes' and "
+ "'evaluate-additional-classes'. Use only the latter.");
+ }
+ }
+
+ if (class_list) {
+ const std::vector<data::ElementPtr>& classes = class_list->listValue();
+ for (auto const& cclass : classes) {
+ if ((cclass->getType() != Element::string) ||
+ cclass->stringValue().empty()) {
+ isc_throw(DhcpConfigError, "invalid class name (" << cclass->getPosition() << ")");
+ }
+
+ (adder_func)(cclass->stringValue());
+ }
+ }
+}
} // end of namespace isc::dhcp
} // end of namespace isc
diff --git a/src/lib/dhcpsrv/parsers/base_network_parser.h b/src/lib/dhcpsrv/parsers/base_network_parser.h
index cd7b4bcbaf..c4e2a14b4e 100644
--- a/src/lib/dhcpsrv/parsers/base_network_parser.h
+++ b/src/lib/dhcpsrv/parsers/base_network_parser.h
@@ -126,6 +126,18 @@ protected:
/// @throw DhcpConfigError if the value is less than 0.
void parseOfferLft(const data::ConstElementPtr& network_data,
Network4Ptr& network);
+public:
+ typedef std::function<void(const isc::dhcp::ClientClass&)> ClassAdderFunc;
+
+ /// @brief Fetches the element for either 'evaluate-additional-classes' or deprecated
+ /// 'require-client-classes'
+ ///
+ /// @param params configuration element tree to search.
+ /// @param adder_func function to add class names to an object's additional class list.
+ /// @return Element referred to or an empty pointer.
+ /// @throw DhcpConfigError if both entries are present.
+ static void getAdditionalClassesElem(data::ConstElementPtr params,
+ ClassAdderFunc adder_func);
};
} // end of namespace isc::dhcp
diff --git a/src/lib/dhcpsrv/parsers/client_class_def_parser.cc b/src/lib/dhcpsrv/parsers/client_class_def_parser.cc
index e1c377671e..5d93bcd57c 100644
--- a/src/lib/dhcpsrv/parsers/client_class_def_parser.cc
+++ b/src/lib/dhcpsrv/parsers/client_class_def_parser.cc
@@ -8,6 +8,7 @@
#include <dhcp/libdhcp++.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/client_class_def.h>
+#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
#include <dhcpsrv/parsers/simple_parser4.h>
@@ -170,10 +171,29 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
}
}
- // Let's try to parse the only-if-required flag
- bool required = false;
- if (class_def_cfg->contains("only-if-required")) {
- required = getBoolean(class_def_cfg, "only-if-required");
+ // Let's try to parse the only-in-additional-list/only-if-required flag
+ auto required_elem = class_def_cfg->get("only-if-required");
+ auto additional_elem = class_def_cfg->get("only-in-additional-list");
+ if (required_elem) {
+ if (!additional_elem) {
+ LOG_WARN(dhcpsrv_logger, DHCPSRV_ONLY_IF_REQUIRED_DEPRECATED);
+ additional_elem = required_elem;
+ } else {
+ isc_throw(isc::dhcp::DhcpConfigError,
+ "cannot specify both 'only-if-required' and "
+ "'only-in-additional-list'. Use only the latter.");
+ }
+ }
+
+ bool additional = false;
+ if (additional_elem) {
+ if (additional_elem->getType() == Element::boolean) {
+ additional = additional_elem->boolValue();
+ } else {
+ isc_throw(isc::dhcp::DhcpConfigError,
+ "'only-in-additional-list' must be boolean"
+ << additional_elem->getPosition());
+ }
}
// Let's try to parse the next-server field
@@ -252,9 +272,9 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
// Sanity checks on built-in classes
for (auto const& bn : builtinNames) {
if (name == bn) {
- if (required) {
+ if (additional) {
isc_throw(DhcpConfigError, "built-in class '" << name
- << "' only-if-required flag must be false");
+ << "' only-in-additional-list flag must be false");
}
if (!test.empty()) {
isc_throw(DhcpConfigError, "built-in class '" << name
@@ -265,16 +285,16 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
// Sanity checks on DROP
if (name == "DROP") {
- if (required) {
+ if (additional) {
isc_throw(DhcpConfigError, "special class '" << name
- << "' only-if-required flag must be false");
+ << "' only-in-additional-list flag must be false");
}
// depend_on_known is now allowed
}
// Add the client class definition
try {
- class_dictionary->addClass(name, match_expr, test, required,
+ class_dictionary->addClass(name, match_expr, test, additional,
depend_on_known, options, defs,
user_context, next_server, sname, filename,
valid_lft, preferred_lft, is_template, offer_lft);
@@ -302,7 +322,8 @@ ClientClassDefParser::checkParametersSupported(const ConstElementPtr& class_def_
"test",
"option-data",
"user-context",
- "only-if-required",
+ "only-if-required", // deprecated
+ "only-in-additional-list",
"valid-lifetime",
"min-valid-lifetime",
"max-valid-lifetime",
diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc
index 1cc76d186f..f6be7c794a 100644
--- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc
+++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc
@@ -37,6 +37,7 @@ using namespace std;
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::util;
+namespace ph = std::placeholders;
namespace isc {
namespace dhcp {
@@ -522,19 +523,10 @@ PoolParser::parse(PoolStoragePtr pools,
}
}
- // Try setting up required client classes.
- ConstElementPtr class_list = pool_structure->get("require-client-classes");
- if (class_list) {
- const std::vector<data::ElementPtr>& classes = class_list->listValue();
- for (auto const& cclass : classes) {
- if ((cclass->getType() != Element::string) ||
- cclass->stringValue().empty()) {
- isc_throw(DhcpConfigError, "invalid class name ("
- << cclass->getPosition() << ")");
- }
- pool->requireClientClass(cclass->stringValue());
- }
- }
+ // Setup additional class list.
+ BaseNetworkParser::getAdditionalClassesElem(pool_structure,
+ std::bind(&Pool::addAdditionalClass,
+ pool, ph::_1));
}
boost::shared_ptr<OptionDataListParser>
@@ -898,19 +890,9 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
}
}
- // Try setting up required client classes.
- ConstElementPtr class_list = params->get("require-client-classes");
- if (class_list) {
- const std::vector<data::ElementPtr>& classes = class_list->listValue();
- for (auto const& cclass : classes) {
- if ((cclass->getType() != Element::string) ||
- cclass->stringValue().empty()) {
- isc_throw(DhcpConfigError, "invalid class name ("
- << cclass->getPosition() << ")");
- }
- subnet4->requireClientClass(cclass->stringValue());
- }
- }
+ // Setup additional class list.
+ getAdditionalClassesElem(params, std::bind(&Network::addAdditionalClass,
+ subnet4, ph::_1));
// 4o6 specific parameter: 4o6-interface.
if (params->contains("4o6-interface")) {
@@ -1131,8 +1113,6 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool,
client_class_ = client_class;
}
- ConstElementPtr class_list = pd_pool->get("require-client-classes");
-
// Check the pool parameters. It will throw an exception if any
// of the required parameters are invalid.
try {
@@ -1187,17 +1167,10 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool,
}
}
- if (class_list) {
- const std::vector<data::ElementPtr>& classes = class_list->listValue();
- for (auto const& cclass : classes) {
- if ((cclass->getType() != Element::string) ||
- cclass->stringValue().empty()) {
- isc_throw(DhcpConfigError, "invalid class name ("
- << cclass->getPosition() << ")");
- }
- pool_->requireClientClass(cclass->stringValue());
- }
- }
+ // Setup additional class list.
+ BaseNetworkParser::getAdditionalClassesElem(pd_pool,
+ std::bind(&Pool::addAdditionalClass,
+ pool_, ph::_1));
// Add the local pool to the external storage ptr.
pools->push_back(pool_);
@@ -1426,21 +1399,9 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
}
}
- if (params->contains("require-client-classes")) {
- // Try setting up required client classes.
- ConstElementPtr class_list = params->get("require-client-classes");
- if (class_list) {
- const std::vector<data::ElementPtr>& classes = class_list->listValue();
- for (auto const& cclass : classes) {
- if ((cclass->getType() != Element::string) ||
- cclass->stringValue().empty()) {
- isc_throw(DhcpConfigError, "invalid class name ("
- << cclass->getPosition() << ")");
- }
- subnet6->requireClientClass(cclass->stringValue());
- }
- }
- }
+ // Setup additional class list.
+ getAdditionalClassesElem(params, std::bind(&Network::addAdditionalClass,
+ subnet6, ph::_1));
/// client-class processing is now generic and handled in the common
/// code (see isc::data::SubnetConfigParser::createSubnet)
diff --git a/src/lib/dhcpsrv/parsers/shared_network_parser.cc b/src/lib/dhcpsrv/parsers/shared_network_parser.cc
index 3a6915f60d..327e016c2c 100644
--- a/src/lib/dhcpsrv/parsers/shared_network_parser.cc
+++ b/src/lib/dhcpsrv/parsers/shared_network_parser.cc
@@ -22,6 +22,7 @@
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::util;
+namespace ph = std::placeholders;
namespace isc {
namespace dhcp {
@@ -164,18 +165,10 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data,
shared_network->setContext(user_context);
}
- if (shared_network_data->contains("require-client-classes")) {
- const std::vector<data::ElementPtr>& class_list =
- shared_network_data->get("require-client-classes")->listValue();
- for (auto const& cclass : class_list) {
- if ((cclass->getType() != Element::string) ||
- cclass->stringValue().empty()) {
- isc_throw(DhcpConfigError, "invalid class name ("
- << cclass->getPosition() << ")");
- }
- shared_network->requireClientClass(cclass->stringValue());
- }
- }
+ // Setup additional class list.
+ getAdditionalClassesElem(shared_network_data,
+ std::bind(&Network::addAdditionalClass,
+ shared_network, ph::_1));
if (shared_network_data->contains("relay")) {
auto relay_parms = shared_network_data->get("relay");
@@ -335,18 +328,10 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data,
shared_network->setContext(user_context);
}
- if (shared_network_data->contains("require-client-classes")) {
- const std::vector<data::ElementPtr>& class_list =
- shared_network_data->get("require-client-classes")->listValue();
- for (auto const& cclass : class_list) {
- if ((cclass->getType() != Element::string) ||
- cclass->stringValue().empty()) {
- isc_throw(DhcpConfigError, "invalid class name ("
- << cclass->getPosition() << ")");
- }
- shared_network->requireClientClass(cclass->stringValue());
- }
- }
+ // Setup additional class list.
+ getAdditionalClassesElem(shared_network_data,
+ std::bind(&Network::addAdditionalClass,
+ shared_network, ph::_1));
if (shared_network_data->contains("subnet6")) {
auto json = shared_network_data->get("subnet6");
diff --git a/src/lib/dhcpsrv/parsers/simple_parser4.cc b/src/lib/dhcpsrv/parsers/simple_parser4.cc
index ac47dcb0b0..0319814249 100644
--- a/src/lib/dhcpsrv/parsers/simple_parser4.cc
+++ b/src/lib/dhcpsrv/parsers/simple_parser4.cc
@@ -224,6 +224,7 @@ const SimpleKeywords SimpleParser4::SUBNET4_PARAMETERS = {
{ "id", Element::integer },
{ "client-class", Element::string },
{ "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
{ "reservations", Element::list },
{ "reservations-global", Element::boolean },
{ "reservations-in-subnet", Element::boolean },
@@ -326,14 +327,15 @@ const ParamsList SimpleParser4::INHERIT_TO_SUBNET4 = {
/// list and map types for entries.
/// Order follows pool_param rules in bison grammar.
const SimpleKeywords SimpleParser4::POOL4_PARAMETERS = {
- { "pool", Element::string },
- { "pool-id", Element::integer },
- { "option-data", Element::list },
- { "client-class", Element::string },
- { "require-client-classes", Element::list },
- { "user-context", Element::map },
- { "comment", Element::string },
- { "metadata", Element::map }
+ { "pool", Element::string },
+ { "pool-id", Element::integer },
+ { "option-data", Element::list },
+ { "client-class", Element::string },
+ { "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
+ { "user-context", Element::map },
+ { "comment", Element::string },
+ { "metadata", Element::map }
};
/// @brief This table defines all shared network parameters for DHCPv4.
@@ -359,6 +361,7 @@ const SimpleKeywords SimpleParser4::SHARED_NETWORK4_PARAMETERS = {
{ "reservations-out-of-pool", Element::boolean },
{ "client-class", Element::string },
{ "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
{ "valid-lifetime", Element::integer },
{ "min-valid-lifetime", Element::integer },
{ "max-valid-lifetime", Element::integer },
diff --git a/src/lib/dhcpsrv/parsers/simple_parser6.cc b/src/lib/dhcpsrv/parsers/simple_parser6.cc
index 6359a1e960..89fedf0a81 100644
--- a/src/lib/dhcpsrv/parsers/simple_parser6.cc
+++ b/src/lib/dhcpsrv/parsers/simple_parser6.cc
@@ -224,6 +224,7 @@ const SimpleKeywords SimpleParser6::SUBNET6_PARAMETERS = {
{ "rapid-commit", Element::boolean },
{ "client-class", Element::string },
{ "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
{ "reservations", Element::list },
{ "reservations-global", Element::boolean },
{ "reservations-in-subnet", Element::boolean },
@@ -317,14 +318,15 @@ const ParamsList SimpleParser6::INHERIT_TO_SUBNET6 = {
/// list and map types for entries.
/// Order follows pool_param rules in bison grammar.
const SimpleKeywords SimpleParser6::POOL6_PARAMETERS = {
- { "pool", Element::string },
- { "pool-id", Element::integer },
- { "option-data", Element::list },
- { "client-class", Element::string },
- { "require-client-classes", Element::list },
- { "user-context", Element::map },
- { "comment", Element::string },
- { "metadata", Element::map }
+ { "pool", Element::string },
+ { "pool-id", Element::integer },
+ { "option-data", Element::list },
+ { "client-class", Element::string },
+ { "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
+ { "user-context", Element::map },
+ { "comment", Element::string },
+ { "metadata", Element::map }
};
/// @brief This table defines all prefix delegation pool parameters.
@@ -333,18 +335,19 @@ const SimpleKeywords SimpleParser6::POOL6_PARAMETERS = {
/// list and map types for entries.
/// Order follows pd_pool_param rules in bison grammar.
const SimpleKeywords SimpleParser6::PD_POOL6_PARAMETERS = {
- { "prefix", Element::string },
- { "prefix-len", Element::integer },
- { "delegated-len", Element::integer },
- { "pool-id", Element::integer },
- { "option-data", Element::list },
- { "client-class", Element::string },
- { "require-client-classes", Element::list },
- { "excluded-prefix", Element::string },
- { "excluded-prefix-len", Element::integer },
- { "user-context", Element::map },
- { "comment", Element::string },
- { "metadata", Element::map }
+ { "prefix", Element::string },
+ { "prefix-len", Element::integer },
+ { "delegated-len", Element::integer },
+ { "pool-id", Element::integer },
+ { "option-data", Element::list },
+ { "client-class", Element::string },
+ { "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
+ { "excluded-prefix", Element::string },
+ { "excluded-prefix-len", Element::integer },
+ { "user-context", Element::map },
+ { "comment", Element::string },
+ { "metadata", Element::map }
};
/// @brief This table defines all shared network parameters for DHCPv6.
@@ -366,6 +369,7 @@ const SimpleKeywords SimpleParser6::SHARED_NETWORK6_PARAMETERS = {
{ "reservations-out-of-pool", Element::boolean },
{ "client-class", Element::string },
{ "require-client-classes", Element::list },
+ { "evaluate-additional-classes", Element::list },
{ "preferred-lifetime", Element::integer },
{ "min-preferred-lifetime", Element::integer },
{ "max-preferred-lifetime", Element::integer },
diff --git a/src/lib/dhcpsrv/pool.cc b/src/lib/dhcpsrv/pool.cc
index f7a53f6d8d..65a71279cc 100644
--- a/src/lib/dhcpsrv/pool.cc
+++ b/src/lib/dhcpsrv/pool.cc
@@ -122,13 +122,13 @@ Pool::toElement() const {
}
// Set require-client-classes
- const ClientClasses& classes = getRequiredClasses();
+ const ClientClasses& classes = getAdditionalClasses();
if (!classes.empty()) {
ElementPtr class_list = Element::createList();
for (auto const& it : classes) {
class_list->add(Element::create(it));
}
- map->set("require-client-classes", class_list);
+ map->set("evaluate-additional-classes", class_list);
}
if (id_) {
diff --git a/src/lib/dhcpsrv/pool.h b/src/lib/dhcpsrv/pool.h
index 0015bb1e82..e85c32c9fd 100644
--- a/src/lib/dhcpsrv/pool.h
+++ b/src/lib/dhcpsrv/pool.h
@@ -135,18 +135,23 @@ public:
return (client_class_);
}
- /// @brief Adds class class_name to classes required to be evaluated
+ /// @brief Adds class class_name to the additional classes list.
///
- /// @param class_name client class required to be evaluated
- void requireClientClass(const ClientClass& class_name) {
- if (!required_classes_.contains(class_name)) {
- required_classes_.insert(class_name);
+ /// @param class_name client class to add
+ void addAdditionalClass(const ClientClass& class_name) {
+ if (!additional_classes_.contains(class_name)) {
+ additional_classes_.insert(class_name);
}
}
- /// @brief Returns classes which are required to be evaluated
- const ClientClasses& getRequiredClasses() const {
- return (required_classes_);
+ /// @brief Returns the additional classes list.
+ const ClientClasses& getAdditionalClasses() const {
+ return (additional_classes_);
+ }
+
+ /// @brief Returns the mutable additional classes list.
+ ClientClasses& getMutableAdditionalClasses() {
+ return (additional_classes_);
}
/// @brief Returns pool-specific allocation state.
@@ -216,10 +221,10 @@ protected:
/// @ref Network::client_class_
ClientClass client_class_;
- /// @brief Required classes
+ /// @brief Additional classes
///
- /// @ref isc::dhcp::Network::required_classes_
- ClientClasses required_classes_;
+ /// @ref isc::dhcp::Network::additional_classes_
+ ClientClasses additional_classes_;
/// @brief Pointer to the user context (may be NULL)
data::ConstElementPtr user_context_;
diff --git a/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc b/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc
index cb8840a33d..42c1546b7f 100644
--- a/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc
+++ b/src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc
@@ -1095,8 +1095,8 @@ TEST(CfgSubnets4Test, unparseSubnet) {
subnet2->setOfferLft(99);
subnet3->setIface("eth1");
- subnet3->requireClientClass("foo");
- subnet3->requireClientClass("bar");
+ subnet3->addAdditionalClass("foo");
+ subnet3->addAdditionalClass("bar");
subnet3->setCalculateTeeTimes(true);
subnet3->setT1Percent(0.50);
subnet3->setT2Percent(0.65);
@@ -1190,7 +1190,7 @@ TEST(CfgSubnets4Test, unparseSubnet) {
" \"reservations-out-of-pool\": false,\n"
" \"option-data\": [ ],\n"
" \"pools\": [ ]\n,"
- " \"require-client-classes\": [ \"foo\", \"bar\" ],\n"
+ " \"evaluate-additional-classes\": [ \"foo\", \"bar\" ],\n"
" \"calculate-tee-times\": true,\n"
" \"t1-percent\": 0.50,\n"
" \"t2-percent\": 0.65,\n"
@@ -1222,7 +1222,7 @@ TEST(CfgSubnets4Test, unparsePool) {
pool1->setContext(ctx1);
data::ElementPtr ctx2 = data::Element::fromJSON("{ \"foo\": \"bar\" }");
pool2->setContext(ctx2);
- pool2->requireClientClass("foo");
+ pool2->addAdditionalClass("foo");
subnet->addPool(pool1);
subnet->addPool(pool2);
@@ -1254,7 +1254,7 @@ TEST(CfgSubnets4Test, unparsePool) {
" \"pool\": \"192.0.2.64/26\",\n"
" \"user-context\": { \"foo\": \"bar\" },\n"
" \"client-class\": \"bar\",\n"
- " \"require-client-classes\": [ \"foo\" ]\n"
+ " \"evaluate-additional-classes\": [ \"foo\" ]\n"
" }\n"
" ]\n"
"} ]\n";
@@ -1427,7 +1427,7 @@ TEST(CfgSubnets4Test, teeTimePercentValidation) {
" \"server-hostname\": \"\", \n"
" \"boot-file-name\": \"\", \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false, \n"
@@ -1496,7 +1496,7 @@ TEST(CfgSubnets4Test, validLifetimeValidation) {
" \"server-hostname\": \"\", \n"
" \"boot-file-name\": \"\", \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false, \n"
@@ -1758,7 +1758,7 @@ TEST(CfgSubnets4Test, hostnameSanitizierValidation) {
" \"server-hostname\": \"\", \n"
" \"boot-file-name\": \"\", \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false, \n"
@@ -1838,7 +1838,7 @@ TEST(CfgSubnets4Test, cacheParamValidation) {
" \"server-hostname\": \"\", \n"
" \"boot-file-name\": \"\", \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false, \n"
diff --git a/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc b/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc
index fdbfa124ce..4cc07fa0ab 100644
--- a/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc
+++ b/src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc
@@ -690,8 +690,8 @@ TEST(CfgSubnets6Test, unparseSubnet) {
subnet2->setCacheMaxAge(80);
subnet3->setIface("eth1");
- subnet3->requireClientClass("foo");
- subnet3->requireClientClass("bar");
+ subnet3->addAdditionalClass("foo");
+ subnet3->addAdditionalClass("bar");
subnet3->setReservationsGlobal(false);
subnet3->setReservationsInSubnet(true);
subnet3->setReservationsOutOfPool(false);
@@ -781,7 +781,7 @@ TEST(CfgSubnets6Test, unparseSubnet) {
" \"pools\": [ ],\n"
" \"pd-pools\": [ ],\n"
" \"option-data\": [ ],\n"
- " \"require-client-classes\": [ \"foo\", \"bar\" ],\n"
+ " \"evaluate-additional-classes\": [ \"foo\", \"bar\" ],\n"
" \"calculate-tee-times\": true,\n"
" \"t1-percent\": 0.50,\n"
" \"t2-percent\": 0.65,\n"
@@ -816,7 +816,7 @@ TEST(CfgSubnets6Test, unparsePool) {
pool1->setContext(ctx1);
data::ElementPtr ctx2 = data::Element::fromJSON("{ \"foo\": \"bar\" }");
pool2->setContext(ctx2);
- pool2->requireClientClass("foo");
+ pool2->addAdditionalClass("foo");
subnet->addPool(pool1);
subnet->addPool(pool2);
@@ -847,7 +847,7 @@ TEST(CfgSubnets6Test, unparsePool) {
" \"user-context\": { \"foo\": \"bar\" },\n"
" \"option-data\": [ ],\n"
" \"client-class\": \"bar\",\n"
- " \"require-client-classes\": [ \"foo\" ]\n"
+ " \"evaluate-additional-classes\": [ \"foo\" ]\n"
" }\n"
" ],\n"
" \"pd-pools\": [ ],\n"
@@ -872,7 +872,7 @@ TEST(CfgSubnets6Test, unparsePdPool) {
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"foo\": [ \"bar\" ] }");
pdpool1->setContext(ctx1);
- pdpool1->requireClientClass("bar");
+ pdpool1->addAdditionalClass("bar");
pdpool2->allowClientClass("bar");
subnet->addPool(pdpool1);
@@ -901,7 +901,7 @@ TEST(CfgSubnets6Test, unparsePdPool) {
" \"delegated-len\": 64,\n"
" \"user-context\": { \"foo\": [ \"bar\" ] },\n"
" \"option-data\": [ ],\n"
- " \"require-client-classes\": [ \"bar\" ]\n"
+ " \"evaluate-additional-classes\": [ \"bar\" ]\n"
" },{\n"
" \"prefix\": \"2001:db8:3::\",\n"
" \"prefix-len\": 48,\n"
@@ -1228,7 +1228,7 @@ TEST(CfgSubnets6Test, teeTimePercentValidation) {
" \"rebind-timer\": 200, \n"
" \"valid-lifetime\": 300, \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false \n"
@@ -1293,7 +1293,7 @@ TEST(CfgSubnets6Test, preferredLifetimeValidation) {
" \"rebind-timer\": 200, \n"
" \"valid-lifetime\": 300, \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false \n"
@@ -1548,7 +1548,7 @@ TEST(CfgSubnets6Test, hostnameSanitizierValidation) {
" \"rebind-timer\": 200, \n"
" \"valid-lifetime\": 300, \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false \n"
@@ -1620,7 +1620,7 @@ TEST(CfgSubnets6Test, cacheParamValidation) {
" \"rebind-timer\": 200, \n"
" \"valid-lifetime\": 300, \n"
" \"client-class\": \"\", \n"
- " \"require-client-classes\": [] \n,"
+ " \"evaluate-additional-classes\": [] \n,"
" \"reservations-global\": false, \n"
" \"reservations-in-subnet\": true, \n"
" \"reservations-out-of-pool\": false \n"
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 8795ef385a..80da5f3b3b 100644
--- a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
+++ b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
@@ -373,7 +373,7 @@ TEST_F(ClientClassDefParserTest, checkAllSupported4) {
" \"option-def\": [ ],\n"
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false,\n"
+ " \"only-in-additional-list\": false,\n"
" \"valid-lifetime\": 1000,\n"
" \"min-valid-lifetime\": 1000,\n"
" \"max-valid-lifetime\": 1000,\n"
@@ -399,7 +399,7 @@ TEST_F(ClientClassDefParserTest, checkAllSupported6) {
" \"test\": \"member('ALL')\","
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false,\n"
+ " \"only-in-additional-list\": false,\n"
" \"template-test\": \"\",\n"
" \"preferred-lifetime\": 800,\n"
" \"min-preferred-lifetime\": 800,\n"
@@ -427,7 +427,7 @@ TEST_F(ClientClassDefParserTest, checkParams4Unsupported6) {
" \"option-def\": [ ],\n"
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false\n"
+ " \"only-in-additional-list\": false\n"
"}\n";
testClassParamsUnsupported(cfg_text, AF_INET6);
@@ -441,7 +441,7 @@ TEST_F(ClientClassDefParserTest, checkParams4Unsupported6) {
" \"test\": \"member('ALL')\","
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false,\n"
+ " \"only-in-additional-list\": false,\n"
" \"next-server\": \"192.0.2.3\"\n"
"}\n";
@@ -456,7 +456,7 @@ TEST_F(ClientClassDefParserTest, checkParams4Unsupported6) {
" \"test\": \"member('ALL')\","
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false,\n"
+ " \"only-in-additional-list\": false,\n"
" \"server-hostname\": \"myhost\"\n"
"}\n";
@@ -471,7 +471,7 @@ TEST_F(ClientClassDefParserTest, checkParams4Unsupported6) {
" \"test\": \"member('ALL')\","
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false,\n"
+ " \"only-in-additional-list\": false,\n"
" \"boot-file-name\": \"efi\""
"}\n";
@@ -494,7 +494,7 @@ TEST_F(ClientClassDefParserTest, checkParams6Unsupported4) {
" \"preferred-lifetime\": 800,\n"
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false\n"
+ " \"only-in-additional-list\": false\n"
"}\n";
testClassParamsUnsupported(cfg_text, AF_INET);
@@ -509,7 +509,7 @@ TEST_F(ClientClassDefParserTest, checkParams6Unsupported4) {
" \"min-preferred-lifetime\": 800,\n"
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false\n"
+ " \"only-in-additional-list\": false\n"
"}\n";
testClassParamsUnsupported(cfg_text, AF_INET);
@@ -524,7 +524,7 @@ TEST_F(ClientClassDefParserTest, checkParams6Unsupported4) {
" \"max-preferred-lifetime\": 800,\n"
" \"option-data\": [ ],\n"
" \"user-context\": { },\n"
- " \"only-if-required\": false\n"
+ " \"only-in-additional-list\": false\n"
"}\n";
testClassParamsUnsupported(cfg_text, AF_INET);
@@ -1887,7 +1887,7 @@ TEST_F(ClientClassDefListParserTest, builtinCheckError) {
"[ \n"
" { \n"
" \"name\": \"ALL\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
@@ -1907,7 +1907,7 @@ TEST_F(ClientClassDefListParserTest, builtinCheckError) {
"[ \n"
" { \n"
" \"name\": \"KNOWN\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
@@ -1927,7 +1927,7 @@ TEST_F(ClientClassDefListParserTest, builtinCheckError) {
"[ \n"
" { \n"
" \"name\": \"UNKNOWN\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
@@ -1960,7 +1960,7 @@ TEST_F(ClientClassDefListParserTest, dropCheckError) {
"[ \n"
" { \n"
" \"name\": \"DROP\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \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 f67ce20cb5..db9c155b89 100644
--- a/src/lib/dhcpsrv/tests/client_class_def_unittest.cc
+++ b/src/lib/dhcpsrv/tests/client_class_def_unittest.cc
@@ -77,7 +77,7 @@ TEST(ClientClassDef, copyConstruction) {
cclass->setContext(data::Element::create("my-context"));
cclass->setCfgOptionDef(cfg_option_def);
cclass->setTest("member('KNOWN')");
- cclass->setRequired(true);
+ cclass->setAdditional(true);
cclass->setDependOnKnown(true);
cclass->setNextServer(IOAddress("1.2.3.4"));
cclass->setSname("ufo");
@@ -98,7 +98,7 @@ TEST(ClientClassDef, copyConstruction) {
ASSERT_TRUE(cclass->getMatchExpr());
EXPECT_NE(cclass_copy->getMatchExpr(), cclass->getMatchExpr());
EXPECT_EQ(cclass->getTest(), cclass_copy->getTest());
- EXPECT_EQ(cclass->getRequired(), cclass_copy->getRequired());
+ EXPECT_EQ(cclass->getAdditional(), cclass_copy->getAdditional());
EXPECT_EQ(cclass->getDependOnKnown(), cclass_copy->getDependOnKnown());
EXPECT_EQ(cclass->getNextServer().toText(), cclass_copy->getNextServer().toText());
EXPECT_EQ(cclass->getSname(), cclass_copy->getSname());
@@ -213,13 +213,13 @@ TEST(ClientClassDef, copyAndEquality) {
EXPECT_TRUE(*cclass == *cclass2);
EXPECT_FALSE(*cclass != *cclass2);
- // Verify the required flag is enough to make classes not equal.
- EXPECT_FALSE(cclass->getRequired());
- cclass2->setRequired(true);
- EXPECT_TRUE(cclass2->getRequired());
+ // Verify the additional flag is enough to make classes not equal.
+ EXPECT_FALSE(cclass->getAdditional());
+ cclass2->setAdditional(true);
+ EXPECT_TRUE(cclass2->getAdditional());
EXPECT_FALSE(*cclass == *cclass2);
EXPECT_TRUE(*cclass != *cclass2);
- cclass2->setRequired(false);
+ cclass2->setAdditional(false);
EXPECT_TRUE(*cclass == *cclass2);
// Verify the depend on known flag is enough to make classes not equal.
@@ -623,7 +623,7 @@ TEST(ClientClassDef, fixedFieldsDefaults) {
ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr)));
// Let's checks that it doesn't return any nonsense
- EXPECT_FALSE(cclass->getRequired());
+ EXPECT_FALSE(cclass->getAdditional());
EXPECT_FALSE(cclass->getDependOnKnown());
EXPECT_FALSE(cclass->getCfgOptionDef());
string empty;
@@ -648,7 +648,7 @@ TEST(ClientClassDef, fixedFieldsBasics) {
// Verify we can create a class with a name, expression, and no cfg_option
ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr)));
- cclass->setRequired(true);
+ cclass->setAdditional(true);
cclass->setDependOnKnown(true);
string sname = "This is a very long string that can be a server name";
@@ -659,7 +659,7 @@ TEST(ClientClassDef, fixedFieldsBasics) {
cclass->setFilename(filename);
// Let's checks that it doesn't return any nonsense
- EXPECT_TRUE(cclass->getRequired());
+ EXPECT_TRUE(cclass->getAdditional());
EXPECT_TRUE(cclass->getDependOnKnown());
EXPECT_EQ(IOAddress("1.2.3.4"), cclass->getNextServer());
EXPECT_EQ(sname, cclass->getSname());
@@ -681,7 +681,7 @@ TEST(ClientClassDef, unparseDef) {
std::string user_context = "{ \"comment\": \"" + comment + "\", ";
user_context += "\"bar\": 1 }";
cclass->setContext(isc::data::Element::fromJSON(user_context));
- cclass->setRequired(true);
+ cclass->setAdditional(true);
// The depend on known flag in not visible
cclass->setDependOnKnown(true);
std::string next_server = "1.2.3.4";
@@ -695,7 +695,7 @@ TEST(ClientClassDef, unparseDef) {
std::string expected = "{\n"
"\"name\": \"" + name + "\",\n"
"\"test\": \"" + test + "\",\n"
- "\"only-if-required\": true,\n"
+ "\"only-in-additional-list\": true,\n"
"\"next-server\": \"" + next_server + "\",\n"
"\"server-hostname\": \"" + sname + "\",\n"
"\"boot-file-name\": \"" + filename + "\",\n"
@@ -860,7 +860,7 @@ TEST(TemplateClientClassDef, copyConstruction) {
cclass->setContext(data::Element::create("my-context"));
cclass->setCfgOptionDef(cfg_option_def);
cclass->setTest("member('KNOWN')");
- cclass->setRequired(true);
+ cclass->setAdditional(true);
cclass->setDependOnKnown(true);
cclass->setNextServer(IOAddress("1.2.3.4"));
cclass->setSname("ufo");
@@ -881,7 +881,7 @@ TEST(TemplateClientClassDef, copyConstruction) {
ASSERT_TRUE(cclass->getMatchExpr());
EXPECT_NE(cclass_copy->getMatchExpr(), cclass->getMatchExpr());
EXPECT_EQ(cclass->getTest(), cclass_copy->getTest());
- EXPECT_EQ(cclass->getRequired(), cclass_copy->getRequired());
+ EXPECT_EQ(cclass->getAdditional(), cclass_copy->getAdditional());
EXPECT_EQ(cclass->getDependOnKnown(), cclass_copy->getDependOnKnown());
EXPECT_EQ(cclass->getNextServer().toText(), cclass_copy->getNextServer().toText());
EXPECT_EQ(cclass->getSname(), cclass_copy->getSname());
@@ -996,13 +996,13 @@ TEST(TemplateClientClassDef, copyAndEquality) {
EXPECT_TRUE(*cclass == *cclass2);
EXPECT_FALSE(*cclass != *cclass2);
- // Verify the required flag is enough to make classes not equal.
- EXPECT_FALSE(cclass->getRequired());
- cclass2->setRequired(true);
- EXPECT_TRUE(cclass2->getRequired());
+ // Verify the additional flag is enough to make classes not equal.
+ EXPECT_FALSE(cclass->getAdditional());
+ cclass2->setAdditional(true);
+ EXPECT_TRUE(cclass2->getAdditional());
EXPECT_FALSE(*cclass == *cclass2);
EXPECT_TRUE(*cclass != *cclass2);
- cclass2->setRequired(false);
+ cclass2->setAdditional(false);
EXPECT_TRUE(*cclass == *cclass2);
// Verify the depend on known flag is enough to make classes not equal.
@@ -1469,7 +1469,7 @@ TEST(TemplateClientClassDef, fixedFieldsDefaults) {
ASSERT_NO_THROW(cclass.reset(new TemplateClientClassDef(name, expr)));
// Let's checks that it doesn't return any nonsense
- EXPECT_FALSE(cclass->getRequired());
+ EXPECT_FALSE(cclass->getAdditional());
EXPECT_FALSE(cclass->getDependOnKnown());
EXPECT_FALSE(cclass->getCfgOptionDef());
string empty;
@@ -1493,7 +1493,7 @@ TEST(TemplateClientClassDef, fixedFieldsBasics) {
// Verify we can create a class with a name, expression, and no cfg_option
ASSERT_NO_THROW(cclass.reset(new TemplateClientClassDef(name, expr)));
- cclass->setRequired(true);
+ cclass->setAdditional(true);
cclass->setDependOnKnown(true);
string sname = "This is a very long string that can be a server name";
@@ -1504,7 +1504,7 @@ TEST(TemplateClientClassDef, fixedFieldsBasics) {
cclass->setFilename(filename);
// Let's checks that it doesn't return any nonsense
- EXPECT_TRUE(cclass->getRequired());
+ EXPECT_TRUE(cclass->getAdditional());
EXPECT_TRUE(cclass->getDependOnKnown());
EXPECT_EQ(IOAddress("1.2.3.4"), cclass->getNextServer());
EXPECT_EQ(sname, cclass->getSname());
@@ -1526,7 +1526,7 @@ TEST(TemplateClientClassDef, unparseDef) {
std::string user_context = "{ \"comment\": \"" + comment + "\", ";
user_context += "\"bar\": 1 }";
cclass->setContext(isc::data::Element::fromJSON(user_context));
- cclass->setRequired(true);
+ cclass->setAdditional(true);
// The depend on known flag in not visible
cclass->setDependOnKnown(true);
std::string next_server = "1.2.3.4";
@@ -1540,7 +1540,7 @@ TEST(TemplateClientClassDef, unparseDef) {
std::string expected = "{\n"
"\"name\": \"" + name + "\",\n"
"\"template-test\": \"" + test + "\",\n"
- "\"only-if-required\": true,\n"
+ "\"only-in-additional-list\": true,\n"
"\"next-server\": \"" + next_server + "\",\n"
"\"server-hostname\": \"" + sname + "\",\n"
"\"boot-file-name\": \"" + filename + "\",\n"
diff --git a/src/lib/dhcpsrv/tests/pool_unittest.cc b/src/lib/dhcpsrv/tests/pool_unittest.cc
index 7c01098911..548d36bba8 100644
--- a/src/lib/dhcpsrv/tests/pool_unittest.cc
+++ b/src/lib/dhcpsrv/tests/pool_unittest.cc
@@ -236,33 +236,33 @@ TEST(Pool4Test, clientClass) {
EXPECT_TRUE(pool->clientSupported(three_classes));
}
-// This test checks that handling for require-client-classes is valid.
-TEST(Pool4Test, requiredClasses) {
+// This test checks that handling for evaluate-additional-classes is valid.
+TEST(Pool4Test, additionalClasses) {
// Create a pool.
Pool4Ptr pool(new Pool4(IOAddress("192.0.2.0"),
IOAddress("192.0.2.255")));
- // This client starts with no required classes.
- EXPECT_TRUE(pool->getRequiredClasses().empty());
+ // This client starts with no additional classes.
+ EXPECT_TRUE(pool->getAdditionalClasses().empty());
// Add the first class
- pool->requireClientClass("router");
- EXPECT_EQ(1, pool->getRequiredClasses().size());
+ pool->addAdditionalClass("router");
+ EXPECT_EQ(1, pool->getAdditionalClasses().size());
// Add a second class
- pool->requireClientClass("modem");
- EXPECT_EQ(2, pool->getRequiredClasses().size());
- EXPECT_TRUE(pool->getRequiredClasses().contains("router"));
- EXPECT_TRUE(pool->getRequiredClasses().contains("modem"));
- EXPECT_FALSE(pool->getRequiredClasses().contains("foo"));
+ pool->addAdditionalClass("modem");
+ EXPECT_EQ(2, pool->getAdditionalClasses().size());
+ EXPECT_TRUE(pool->getAdditionalClasses().contains("router"));
+ EXPECT_TRUE(pool->getAdditionalClasses().contains("modem"));
+ EXPECT_FALSE(pool->getAdditionalClasses().contains("foo"));
// Check that it's ok to add the same class repeatedly
- EXPECT_NO_THROW(pool->requireClientClass("foo"));
- EXPECT_NO_THROW(pool->requireClientClass("foo"));
- EXPECT_NO_THROW(pool->requireClientClass("foo"));
+ EXPECT_NO_THROW(pool->addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pool->addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pool->addAdditionalClass("foo"));
- // Check that 'foo' is marked for required evaluation
- EXPECT_TRUE(pool->getRequiredClasses().contains("foo"));
+ // Check that 'foo' is marked for additional evaluation
+ EXPECT_TRUE(pool->getAdditionalClasses().contains("foo"));
}
TEST(Pool6Test, constructorFirstLast) {
@@ -640,33 +640,33 @@ TEST(Pool6Test, clientClass) {
EXPECT_TRUE(pool.clientSupported(three_classes));
}
-// This test checks that handling for require-client-classes is valid.
-TEST(Pool6Test, requiredClasses) {
+// This test checks that handling for evaluate-additional-classes is valid.
+TEST(Pool6Test, additionalClasses) {
// Create a pool.
Pool6 pool(Lease::TYPE_NA, IOAddress("2001:db8::1"),
IOAddress("2001:db8::2"));
- // This client starts with no required classes.
- EXPECT_TRUE(pool.getRequiredClasses().empty());
+ // This client starts with no additional classes.
+ EXPECT_TRUE(pool.getAdditionalClasses().empty());
// Add the first class
- pool.requireClientClass("router");
- EXPECT_EQ(1, pool.getRequiredClasses().size());
+ pool.addAdditionalClass("router");
+ EXPECT_EQ(1, pool.getAdditionalClasses().size());
// Add a second class
- pool.requireClientClass("modem");
- EXPECT_EQ(2, pool.getRequiredClasses().size());
- EXPECT_TRUE(pool.getRequiredClasses().contains("router"));
- EXPECT_TRUE(pool.getRequiredClasses().contains("modem"));
- EXPECT_FALSE(pool.getRequiredClasses().contains("foo"));
+ pool.addAdditionalClass("modem");
+ EXPECT_EQ(2, pool.getAdditionalClasses().size());
+ EXPECT_TRUE(pool.getAdditionalClasses().contains("router"));
+ EXPECT_TRUE(pool.getAdditionalClasses().contains("modem"));
+ EXPECT_FALSE(pool.getAdditionalClasses().contains("foo"));
// Check that it's ok to add the same class repeatedly
- EXPECT_NO_THROW(pool.requireClientClass("foo"));
- EXPECT_NO_THROW(pool.requireClientClass("foo"));
- EXPECT_NO_THROW(pool.requireClientClass("foo"));
+ EXPECT_NO_THROW(pool.addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pool.addAdditionalClass("foo"));
+ EXPECT_NO_THROW(pool.addAdditionalClass("foo"));
- // Check that 'foo' is marked for required evaluation
- EXPECT_TRUE(pool.getRequiredClasses().contains("foo"));
+ // Check that 'foo' is marked for additional evaluation
+ EXPECT_TRUE(pool.getAdditionalClasses().contains("foo"));
}
} // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc
index 61616c6db9..a5cfa258eb 100644
--- a/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc
+++ b/src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc
@@ -133,7 +133,7 @@ public:
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": true,"
" \"server-hostname\": \"example.org\","
- " \"require-client-classes\": [ \"runner\" ],"
+ " \"evaluate-additional-classes\": [ \"runner\" ],"
" \"user-context\": { \"comment\": \"example\" },"
" \"valid-lifetime\": 399,"
" \"min-valid-lifetime\": 299,"
@@ -176,7 +176,7 @@ public:
" \"server-hostname\": \"\","
" \"boot-file-name\": \"\","
" \"client-class\": \"\","
- " \"require-client-classes\": []\n,"
+ " \"evaluate-additional-classes\": []\n,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false,"
@@ -204,7 +204,7 @@ public:
" \"server-hostname\": \"\","
" \"boot-file-name\": \"\","
" \"client-class\": \"\","
- " \"require-client-classes\": []\n,"
+ " \"evaluate-additional-classes\": []\n,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false,"
@@ -291,10 +291,10 @@ TEST_F(SharedNetwork4ParserTest, parse) {
EXPECT_EQ(1, relay_info.getAddresses().size());
EXPECT_TRUE(relay_info.containsAddress(IOAddress("10.1.1.1")));
- // Required client classes.
- auto required = network->getRequiredClasses();
- ASSERT_EQ(1, required.size());
- EXPECT_EQ("runner", *required.cbegin());
+ // Additional client classes.
+ auto additional = network->getAdditionalClasses();
+ ASSERT_EQ(1, additional.size());
+ EXPECT_EQ("runner", *additional.cbegin());
// Check user context.
ConstElementPtr context = network->getContext();
@@ -558,7 +558,7 @@ public:
" \"rebind-timer\": 199,"
" \"relay\": { \"ip-addresses\": [ \"2001:db8:1::1\" ] },"
" \"renew-timer\": 99,"
- " \"require-client-classes\": [ \"runner\" ],"
+ " \"evaluate-additional-classes\": [ \"runner\" ],"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": true,"
@@ -604,7 +604,7 @@ public:
" \"min-valid-lifetime\": 300,"
" \"max-valid-lifetime\": 500,"
" \"client-class\": \"\","
- " \"require-client-classes\": []\n,"
+ " \"evaluate-additional-classes\": []\n,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false,"
@@ -623,7 +623,7 @@ public:
" \"preferred-lifetime\": 30,"
" \"valid-lifetime\": 40,"
" \"client-class\": \"\","
- " \"require-client-classes\": []\n,"
+ " \"evaluate-additional-classes\": []\n,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false,"
@@ -704,10 +704,10 @@ TEST_F(SharedNetwork6ParserTest, parse) {
EXPECT_EQ(1, relay_info.getAddresses().size());
EXPECT_TRUE(relay_info.containsAddress(IOAddress("2001:db8:1::1")));
- // Required client classes.
- auto required = network->getRequiredClasses();
- ASSERT_EQ(1, required.size());
- EXPECT_EQ("runner", *required.cbegin());
+ // Additional client classes.
+ auto additional = network->getAdditionalClasses();
+ ASSERT_EQ(1, additional.size());
+ EXPECT_EQ("runner", *additional.cbegin());
// Check user context.
ConstElementPtr context = network->getContext();
@@ -870,7 +870,7 @@ TEST_F(SharedNetwork6ParserTest, clientClass) {
EXPECT_EQ("alpha", network->getClientClass().get());
}
-// This test verifies that it's possible to specify require-client-classes
+// This test verifies that it's possible to specify evaluate-additional-classes
// on shared-network level.
TEST_F(SharedNetwork6ParserTest, evalClientClasses) {
IfaceMgrTestConfig ifmgr(true);
@@ -881,7 +881,7 @@ TEST_F(SharedNetwork6ParserTest, evalClientClasses) {
ElementPtr class_list = Element::createList();
class_list->add(Element::create("alpha"));
class_list->add(Element::create("beta"));
- config_element->set("require-client-classes", class_list);
+ config_element->set("evaluate-additional-classes", class_list);
// Parse configuration specified above.
SharedNetwork6Parser parser;
@@ -889,12 +889,12 @@ TEST_F(SharedNetwork6ParserTest, evalClientClasses) {
network = parser.parse(config_element);
ASSERT_TRUE(network);
- const ClientClasses& classes = network->getRequiredClasses();
+ const ClientClasses& classes = network->getAdditionalClasses();
EXPECT_EQ(2, classes.size());
EXPECT_EQ("alpha, beta", classes.toText());
}
-// This test verifies that bad require-client-classes configs raise
+// This test verifies that bad evaluate-additional-classes configs raise
// expected errors.
TEST_F(SharedNetwork6ParserTest, badEvalClientClasses) {
IfaceMgrTestConfig ifmgr(true);
@@ -906,7 +906,7 @@ TEST_F(SharedNetwork6ParserTest, badEvalClientClasses) {
ElementPtr class_list = Element::createList();
class_list->add(Element::create("alpha"));
class_list->add(Element::create(1234));
- config_element->set("require-client-classes", class_list);
+ config_element->set("evaluate-additional-classes", class_list);
// Parse configuration specified above.
SharedNetwork6Parser parser;
diff --git a/src/lib/dhcpsrv/tests/shared_network_unittest.cc b/src/lib/dhcpsrv/tests/shared_network_unittest.cc
index 7e1fb44764..69f3e6201b 100644
--- a/src/lib/dhcpsrv/tests/shared_network_unittest.cc
+++ b/src/lib/dhcpsrv/tests/shared_network_unittest.cc
@@ -688,7 +688,7 @@ TEST(SharedNetwork4Test, unparse) {
std::string uc = "{ \"comment\": \"bar\", \"foo\": 1}";
data::ElementPtr ctx = data::Element::fromJSON(uc);
network->setContext(ctx);
- network->requireClientClass("foo");
+ network->addAdditionalClass("foo");
network->addRelayAddress(IOAddress("192.168.2.1"));
network->setAuthoritative(false);
network->setMatchClientId(false);
@@ -718,7 +718,7 @@ TEST(SharedNetwork4Test, unparse) {
" \"ip-addresses\": [ \"192.168.2.1\" ]\n"
" },\n"
" \"renew-timer\": 100,\n"
- " \"require-client-classes\": [ \"foo\" ],\n"
+ " \"evaluate-additional-classes\": [ \"foo\" ],\n"
" \"reservations-global\": false,\n"
" \"reservations-in-subnet\": true,\n"
" \"reservations-out-of-pool\": false,\n"
@@ -1402,11 +1402,11 @@ TEST(SharedNetwork6Test, unparse) {
network->setPreferred(200);
network->setValid(300);
network->setRapidCommit(true);
- network->requireClientClass("foo");
+ network->addAdditionalClass("foo");
data::ElementPtr ctx = data::Element::fromJSON("{ \"foo\": \"bar\" }");
network->setContext(ctx);
- network->requireClientClass("foo");
+ network->addAdditionalClass("foo");
network->addRelayAddress(IOAddress("2001:db8:1::7"));
network->addRelayAddress(IOAddress("2001:db8:1::8"));
@@ -1457,7 +1457,7 @@ TEST(SharedNetwork6Test, unparse) {
" \"ip-addresses\": [ \"2001:db8:1::7\", \"2001:db8:1::8\" ]\n"
" },\n"
" \"renew-timer\": 100,\n"
- " \"require-client-classes\": [ \"foo\" ],\n"
+ " \"evaluate-additional-classes\": [ \"foo\" ],\n"
" \"reservations-global\": false,\n"
" \"reservations-in-subnet\": true,\n"
" \"reservations-out-of-pool\": false,\n"
diff --git a/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc b/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc
index c512c9fbd4..c7452c86b3 100644
--- a/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc
+++ b/src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc
@@ -114,8 +114,8 @@ GenericConfigBackendDHCPv4Test::initTestSubnets() {
subnet->addRelayAddress(IOAddress("10.2.3.4"));
subnet->addRelayAddress(IOAddress("10.5.6.7"));
subnet->setT1(1234);
- subnet->requireClientClass("required-class1");
- subnet->requireClientClass("required-class2");
+ subnet->addAdditionalClass("required-class1");
+ subnet->addAdditionalClass("required-class2");
subnet->setReservationsGlobal(false);
subnet->setReservationsInSubnet(false);
subnet->setSname("server-hostname");
@@ -163,8 +163,8 @@ GenericConfigBackendDHCPv4Test::initTestSubnets() {
IOAddress("10.0.0.60")));
pool2->allowClientClass("work");
- pool2->requireClientClass("required-class3");
- pool2->requireClientClass("required-class4");
+ pool2->addAdditionalClass("required-class3");
+ pool2->addAdditionalClass("required-class4");
user_context = Element::createMap();
user_context->set("bar", Element::create("foo"));
pool2->setContext(user_context);
@@ -209,8 +209,8 @@ GenericConfigBackendDHCPv4Test::initTestSharedNetworks() {
shared_network->addRelayAddress(IOAddress("10.2.3.4"));
shared_network->addRelayAddress(IOAddress("10.5.6.7"));
shared_network->setT1(1234);
- shared_network->requireClientClass("required-class1");
- shared_network->requireClientClass("required-class2");
+ shared_network->addAdditionalClass("required-class1");
+ shared_network->addAdditionalClass("required-class2");
shared_network->setReservationsGlobal(false);
shared_network->setReservationsInSubnet(false);
shared_network->setContext(user_context);
@@ -369,7 +369,7 @@ GenericConfigBackendDHCPv4Test::initTestClientClasses() {
CfgOptionPtr cfg_option = boost::make_shared<CfgOption>();
auto class1 = boost::make_shared<ClientClassDef>("foo", match_expr, cfg_option);
class1->setCfgOptionDef(boost::make_shared<CfgOptionDef>());
- class1->setRequired(true);
+ class1->setAdditional(true);
class1->setNextServer(IOAddress("1.2.3.4"));
class1->setSname("cool");
class1->setFilename("epc.cfg");
@@ -4191,7 +4191,7 @@ GenericConfigBackendDHCPv4Test::getClientClass4Test() {
ASSERT_NO_THROW_LOG(client_class = cbptr_->getClientClass4(ServerSelector::ALL(), class1->getName()));
ASSERT_TRUE(client_class);
EXPECT_EQ("foo", client_class->getName());
- EXPECT_TRUE(client_class->getRequired());
+ EXPECT_TRUE(client_class->getAdditional());
EXPECT_EQ("1.2.3.4", client_class->getNextServer().toText());
EXPECT_EQ("cool", client_class->getSname());
EXPECT_EQ("epc.cfg", client_class->getFilename());
diff --git a/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc b/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc
index c2edf63440..5130e923bc 100644
--- a/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc
+++ b/src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc
@@ -112,8 +112,8 @@ GenericConfigBackendDHCPv6Test::initTestSubnets() {
subnet->addRelayAddress(IOAddress("2001:db8:1::2"));
subnet->addRelayAddress(IOAddress("2001:db8:3::4"));
subnet->setT1(1234);
- subnet->requireClientClass("required-class1");
- subnet->requireClientClass("required-class2");
+ subnet->addAdditionalClass("required-class1");
+ subnet->addAdditionalClass("required-class2");
subnet->setReservationsGlobal(false);
subnet->setReservationsInSubnet(false);
subnet->setContext(user_context);
@@ -171,8 +171,8 @@ GenericConfigBackendDHCPv6Test::initTestSubnets() {
subnet->addPool(pool2);
pool2->allowClientClass("work");
- pool2->requireClientClass("required-class3");
- pool2->requireClientClass("required-class4");
+ pool2->addAdditionalClass("required-class3");
+ pool2->addAdditionalClass("required-class4");
user_context = Element::createMap();
user_context->set("bar", Element::create("foo"));
pool2->setContext(user_context);
@@ -190,8 +190,8 @@ GenericConfigBackendDHCPv6Test::initTestSubnets() {
subnet->addPool(pdpool2);
pdpool2->allowClientClass("work");
- pdpool2->requireClientClass("required-class3");
- pdpool2->requireClientClass("required-class4");
+ pdpool2->addAdditionalClass("required-class3");
+ pdpool2->addAdditionalClass("required-class4");
user_context = Element::createMap();
user_context->set("bar", Element::create("foo"));
pdpool2->setContext(user_context);
@@ -241,8 +241,8 @@ GenericConfigBackendDHCPv6Test::initTestSharedNetworks() {
shared_network->addRelayAddress(IOAddress("2001:db8:1::2"));
shared_network->addRelayAddress(IOAddress("2001:db8:3::4"));
shared_network->setT1(1234);
- shared_network->requireClientClass("required-class1");
- shared_network->requireClientClass("required-class2");
+ shared_network->addAdditionalClass("required-class1");
+ shared_network->addAdditionalClass("required-class2");
shared_network->setReservationsGlobal(false);
shared_network->setReservationsInSubnet(false);
shared_network->setContext(user_context);
@@ -398,7 +398,7 @@ GenericConfigBackendDHCPv6Test::initTestClientClasses() {
CfgOptionPtr cfg_option = boost::make_shared<CfgOption>();
auto class1 = boost::make_shared<ClientClassDef>("foo", match_expr, cfg_option);
class1->setCfgOptionDef(boost::make_shared<CfgOptionDef>());
- class1->setRequired(true);
+ class1->setAdditional(true);
class1->setValid(Triplet<uint32_t>(30, 60, 90));
class1->setPreferred(Triplet<uint32_t>(25, 55, 85));
test_client_classes_.push_back(class1);
@@ -4339,7 +4339,7 @@ GenericConfigBackendDHCPv6Test::getClientClass6Test() {
ASSERT_NO_THROW_LOG(client_class = cbptr_->getClientClass6(ServerSelector::ALL(), class1->getName()));
ASSERT_TRUE(client_class);
EXPECT_EQ("foo", client_class->getName());
- EXPECT_TRUE(client_class->getRequired());
+ EXPECT_TRUE(client_class->getAdditional());
EXPECT_EQ(30, client_class->getValid().getMin());
EXPECT_EQ(60, client_class->getValid().get());
EXPECT_EQ(90, client_class->getValid().getMax());
diff --git a/src/share/database/scripts/mysql/dhcpdb_create.mysql b/src/share/database/scripts/mysql/dhcpdb_create.mysql
index 1466b6584f..af1e1dbec2 100644
--- a/src/share/database/scripts/mysql/dhcpdb_create.mysql
+++ b/src/share/database/scripts/mysql/dhcpdb_create.mysql
@@ -6032,6 +6032,34 @@ ALTER TABLE dhcp4_options
ALTER TABLE dhcp6_options
ADD COLUMN client_classes LONGTEXT DEFAULT NULL;
+-- Rename require_client_classes and only_if_required.
+ALTER TABLE dhcp4_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pd_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
+ALTER TABLE dhcp6_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
-- Update the schema version number.
UPDATE schema_version
SET version = '26', minor = '0';
diff --git a/src/share/database/scripts/mysql/upgrade_025_to_026.sh.in b/src/share/database/scripts/mysql/upgrade_025_to_026.sh.in
index 876079b58b..0439aba9f7 100644
--- a/src/share/database/scripts/mysql/upgrade_025_to_026.sh.in
+++ b/src/share/database/scripts/mysql/upgrade_025_to_026.sh.in
@@ -65,6 +65,34 @@ ALTER TABLE dhcp6_options
UPDATE option_def_data_type SET name='int8' where id = 3;
+-- Rename require_client_classes and only_if_required.
+ALTER TABLE dhcp4_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pd_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
+ALTER TABLE dhcp6_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
-- Update the schema version number.
UPDATE schema_version
SET version = '26', minor = '0';
diff --git a/src/share/database/scripts/pgsql/dhcpdb_create.pgsql b/src/share/database/scripts/pgsql/dhcpdb_create.pgsql
index 04413cad9d..508a9b22cc 100644
--- a/src/share/database/scripts/pgsql/dhcpdb_create.pgsql
+++ b/src/share/database/scripts/pgsql/dhcpdb_create.pgsql
@@ -6493,6 +6493,34 @@ ALTER TABLE dhcp4_options
ALTER TABLE dhcp6_options
ADD COLUMN client_classes TEXT DEFAULT NULL;
+-- Rename require_client_classes and only_if_required.
+ALTER TABLE dhcp4_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pd_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
+ALTER TABLE dhcp6_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
-- Update the schema version number.
UPDATE schema_version
SET version = '26', minor = '0';
diff --git a/src/share/database/scripts/pgsql/upgrade_025_to_026.sh.in b/src/share/database/scripts/pgsql/upgrade_025_to_026.sh.in
index cd40a1f1a4..a68f9cf5cb 100644
--- a/src/share/database/scripts/pgsql/upgrade_025_to_026.sh.in
+++ b/src/share/database/scripts/pgsql/upgrade_025_to_026.sh.in
@@ -48,6 +48,34 @@ ALTER TABLE dhcp6_options
UPDATE option_def_data_type SET name='int8' where id = 3;
+-- Rename require_client_classes and only_if_required.
+ALTER TABLE dhcp4_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_shared_network
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_subnet
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pd_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp6_pool
+ RENAME COLUMN require_client_classes TO evaluate_additional_classes;
+
+ALTER TABLE dhcp4_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
+ALTER TABLE dhcp6_client_class
+ RENAME COLUMN only_if_required TO only_in_additional_list;
+
-- Update the schema version number.
UPDATE schema_version
SET version = '26', minor = '0';