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