]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3587] Bulk of the code changes
authorThomas Markwalder <tmark@isc.org>
Wed, 16 Oct 2024 18:09:50 +0000 (14:09 -0400)
committerThomas Markwalder <tmark@isc.org>
Mon, 28 Oct 2024 11:58:38 +0000 (07:58 -0400)
Everything except parsers, UTs to test
deprecation, and doc.

51 files changed:
src/bin/admin/tests/mysql_tests.sh.in
src/bin/admin/tests/pgsql_tests.sh.in
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.h
src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.h
src/hooks/dhcp/mysql/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql/mysql_cb_impl.cc
src/hooks/dhcp/mysql/mysql_cb_impl.h
src/hooks/dhcp/mysql/mysql_query_macros_dhcp.h
src/hooks/dhcp/pgsql/pgsql_cb_dhcp4.cc
src/hooks/dhcp/pgsql/pgsql_cb_dhcp6.cc
src/hooks/dhcp/pgsql/pgsql_cb_impl.cc
src/hooks/dhcp/pgsql/pgsql_cb_impl.h
src/hooks/dhcp/pgsql/pgsql_query_macros_dhcp.h
src/lib/config_backend/constants.h
src/lib/dhcp/pkt.cc
src/lib/dhcp/pkt.h
src/lib/dhcp/tests/pkt4_unittest.cc
src/lib/dhcp/tests/pkt6_unittest.cc
src/lib/dhcpsrv/client_class_def.cc
src/lib/dhcpsrv/client_class_def.h
src/lib/dhcpsrv/dhcpsrv_messages.cc
src/lib/dhcpsrv/dhcpsrv_messages.h
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/network.cc
src/lib/dhcpsrv/network.h
src/lib/dhcpsrv/parsers/base_network_parser.cc
src/lib/dhcpsrv/parsers/base_network_parser.h
src/lib/dhcpsrv/parsers/client_class_def_parser.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/parsers/shared_network_parser.cc
src/lib/dhcpsrv/parsers/simple_parser4.cc
src/lib/dhcpsrv/parsers/simple_parser6.cc
src/lib/dhcpsrv/pool.cc
src/lib/dhcpsrv/pool.h
src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc
src/lib/dhcpsrv/tests/cfg_subnets6_unittest.cc
src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
src/lib/dhcpsrv/tests/client_class_def_unittest.cc
src/lib/dhcpsrv/tests/pool_unittest.cc
src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc
src/lib/dhcpsrv/tests/shared_network_unittest.cc
src/lib/dhcpsrv/testutils/generic_cb_dhcp4_unittest.cc
src/lib/dhcpsrv/testutils/generic_cb_dhcp6_unittest.cc
src/share/database/scripts/mysql/dhcpdb_create.mysql
src/share/database/scripts/mysql/upgrade_025_to_026.sh.in
src/share/database/scripts/pgsql/dhcpdb_create.pgsql
src/share/database/scripts/pgsql/upgrade_025_to_026.sh.in

index 37121da477a38faa8c794a6bb4ced7103b1c7f7d..fddedea481d777f3d654a5d02bd8205af9d3d01e 100644 (file)
@@ -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
index 792a5c14d7a745fd37776d15bfd8a9a44cc865f0..b7ca92f0d741d9295acaf562aefbaff98a321a66 100644 (file)
@@ -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() {
index 41f22c5d040ee4c3f29cdba07a8aafaaeb0d2792..5e11dfd39d12d430168b7afd3071c2aca5042f37 100644 (file)
@@ -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);
             }
index 23ea4fbddddbea56b15ccf0deb8b8c8e649fae82..92a19df4e4a0e1e8941376642c698771bf52d209 100644 (file)
@@ -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.
     ///
index 4824c56dbbd76294773ec8d2d076f6122b53f2b4..5d37185642d3fdf2fa054f084af15faad4708cf9 100644 (file)
@@ -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();
index 7c6d972312556376179806b88cd6d731234d7d92..84e8d61f03d0ba91a42eea788c31d53f7083f6e8 100644 (file)
@@ -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);
             }
index cf61729b74b5db793383e6af169b269e65be374f..8e33ed1dfc900b2b8307ef7d41996be4485a8e68 100644 (file)
@@ -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
     ///
index 436b0839500de5923f6aa09e48e01c470daccfb7..fb41b7f41cc9e916a5bfd5f75f9cc099752a60e9 100644 (file)
@@ -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 = ?,"
index cb64fec0621ba1d26a9c4b3d209c5262b206e839..a183aeb3d52f4a55a7bce0d33a2fb3b6aff7bfc8 100644 (file)
@@ -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 = ?,"
index 590700a7066fdcc976cf8332d5b00a6f35cf506c..d2cfea8873671132405e3ef777f364a1ca44f16e 100644 (file)
@@ -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
index 4a76c6e273cf1d6a2940b80479fa5176cfe5bded..eba16a19de1b063d42ae37d6ee530d246441479d 100644 (file)
@@ -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.
index e22b035f1cb7f8c919feb3f6d2a30f5e037dc040..11dd9c0c6da700755c628d3fc23d70e454b0fbc5 100644 (file)
@@ -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 = ?," \
index 5a2d14715020271ac04e1a91d939fe667ae70442..709b47e61a3a0e3400407546c520949661bd8d0c 100644 (file)
@@ -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
index f5e71eeb52f430a46bbb0e8dbf6606f449ca8cba..16fc0533be690d0ab7933b729dbfef1525a57c26 100644 (file)
@@ -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
index bad28bad92472afc5eea5696f2e33ca15e70ac6d..1fdca0395eef683e50f7af92463e3a1e4b632841 100644 (file)
@@ -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) {
index a5b87a0ef93ab65a58f4467a8445a22ea02b57e7..9a019351edcf1d8c9df6e3f77ceaf05d29732b89 100644 (file)
@@ -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.
index 3b9bac276cbc5a4a677bdf48cf98931ad45502ce..138addee3fa7fc3e082357c1d9d742677ee5f574 100644 (file)
@@ -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," \
index 579f13709fe5f10076806f2ca371dbff7e5478a8..1378d54fc0f5354906c4ca876fdd3fb662982daf 100644 (file)
@@ -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
index 1276515df52a819cf206e1a5258a7ab6bc4e78da..ec22ea5894a5518b18b76c829b639f5972c5122a 100644 (file)
@@ -123,14 +123,21 @@ 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)) {
index f8a675942ebfff15268731f04558fa61f2938851..e655e6cf9cd79cad33c541941266c8b677b879d4 100644 (file)
@@ -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.
     ///
index ad418609d3b09912f5e6b7613a04bef41d301df2..80920291b2a3cdd2ed9731fa506709d55779e20e 100644 (file)
@@ -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
index 6febc4d2585267e63ed0da5d26f7f34add36b5e0..5f60b1b24dec6b5bc0ceb68e3aa17326d74ae435 100644 (file)
@@ -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
index 5d3ff21e031ea6225d14908c535f44a6eb9ba46e..b94a699eef42b5d8b2cad309cb2008d437324120 100644 (file)
@@ -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),
index c9158e1107eb0da708cb3319557b4147af6ea31c..21f5e987922c2118bb8a64c0b7dda0c632770fd9 100644 (file)
@@ -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(),
index af6e09c28df6e2bbd35fab8b7396ac8f84b43278..b2f7b9088da268e96016b9d1b7fa0dad90748051 100644 (file)
@@ -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",
index dcb74475342d74df023e31129c4b9aacfedd2d9e..4c7bf154fa97de47bb2cc5eb726b9e4c2e053e2e 100644 (file)
@@ -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;
index b9a6ac063315e4c684c8ba11111d696bd817ec1a..46c543e2cf464d0081efb0b88c2036196ad3edea 100644 (file)
@@ -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.
index bc447c86d2fe5f76455ff324bc226e809ac87379..9a138100121334db6443833155b8be31cd6b1e95 100644 (file)
@@ -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
index d8f97606146b44d2604217818eb3f177b8bbd123..fb934c4e2748cc340973f1c033635c9eca30c7b8 100644 (file)
@@ -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_;
index 8d73b7aed9c9ab90897ffe3627332dbdf84fed0c..01da86dcd4895565e20a926590af00fe89278d4b 100644 (file)
@@ -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
index cd7b4bcbaf8d662a9f26345be0e9c8f3f2087364..c4e2a14b4ecedc388bf7d1f487c91e948a8ae9ff 100644 (file)
@@ -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
index e1c377671e2264e48fc8794067a3a66ff2f44250..5d93bcd57c43603e43d0f1d077551031f90d8771 100644 (file)
@@ -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",
index 1cc76d186f53e8878313ade010bdeefab8e73f55..f6be7c794a7cf38f173ad90be5a3326da1323c65 100644 (file)
@@ -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)
index 3a6915f60dbbd7c29648db4d7a0e1a9af2681950..327e016c2cdf7f8d7ce3d9cfae45716df46477dc 100644 (file)
@@ -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");
index ac47dcb0b04cb1e746d847bf6629cca2fd8c27bd..0319814249dac8ca17f8ed7e8f9620b27a35c87a 100644 (file)
@@ -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 },
index 6359a1e96091ada5d635bea961fd2f13a82bc7f2..89fedf0a819dd797773013a9ac54a2cea5016e48 100644 (file)
@@ -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 },
index f7a53f6d8d6a76791de41f0e415763609dee0f26..65a71279cc59c852144b3d4ac0bf439878835458 100644 (file)
@@ -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_) {
index 0015bb1e8294a64299666e39cfed91564e6d300a..e85c32c9fdfaaebd2146d475885e8368c239523e 100644 (file)
@@ -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_;
index cb8840a33d4a9a88e6878b1b7a74cba1ea351ec5..42c1546b7fd5146d5900370eb4ecc1e1f4e1dc3e 100644 (file)
@@ -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"
index fdbfa124cea909de62ee5a97eb1611af43a1f0bc..4cc07fa0ab331ebaacbc294c4235354bd2f9fa58 100644 (file)
@@ -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"
index 8795ef385aea4666b6f30ec384dd2bf65ba75c3e..80da5f3b3b71cb515f279662a89c51614aff7716 100644 (file)
@@ -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";
 
index f67ce20cb503bcf2c3b47a324748ccc9fc3ccd10..db9c155b89c7fd6de66a3ad36e6b790288a6c97e 100644 (file)
@@ -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"
index 7c01098911c45784e6ab42ed17ac395c5f3f06be..548d36bba8da938027a9960420b9c7ebb0ceafe5 100644 (file)
@@ -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
index 61616c6db95082f36cdfb968847caa17e8806ef3..a5cfa258eb2ab4dcf0e679ad1381a6e837c6ca21 100644 (file)
@@ -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;
index 7e1fb44764f7ce9b5401a58e78aca36c352208e0..69f3e6201bf2305abe5eca316898d8fa615cecb0 100644 (file)
@@ -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"
index c512c9fbd40f4bbf645ec4ba376d6169be6b2a1e..c7452c86b374a130750a552b9deccb32f9ca2380 100644 (file)
@@ -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());
index c2edf634409e5df77c833f0fc1a31f27e25e98a9..5130e923bcc9618b1080c972c8dbc0e1869da1da 100644 (file)
@@ -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());
index 1466b6584f1dc4c8f3cda9b524ad5b98531bafd1..af1e1dbec226a302a44484708d7bfaa7439ddd4e 100644 (file)
@@ -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';
index 876079b58bfa41cc3e2d1e1779e3c860ae41d1e8..0439aba9f7bef8b747bd603f15609f7c07b48731 100644 (file)
@@ -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';
index 04413cad9d26bdf5ee15b2032414e2d0183f1168..508a9b22cc2abc0d91c52b9c4a3417851b3adecd 100644 (file)
@@ -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';
index cd40a1f1a483ee91b2e6c6f06e694e4a9be4bd66..a68f9cf5cbc0db10f6595a87886b6226625b47d2 100644 (file)
@@ -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';