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"
}
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}"
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
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
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
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
# 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
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}"
}
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() {
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.
// 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())
// 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())
// 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())
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) {
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);
}
}
// 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);
}
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);
}
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.
///
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));
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));
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();
}
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())
}
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())
}
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())
}
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())
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())
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())
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())
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())
continue;
}
// Not the right time if only when required
- if (it->getRequired()) {
+ if (it->getAdditional()) {
continue;
}
// Not the right pass.
}
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) {
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);
}
}
// 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);
}
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);
}
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
///
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
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
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
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
// 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()) {
// 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.
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();
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
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;
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();
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.
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,
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())
};
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
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
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()) {
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)),
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
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
};
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
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()),
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" server_hostname,"
" shared_network_name,"
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
" next_server,"
" server_hostname,"
" boot_file_name,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" server_hostname = ?,"
" shared_network_name = ?,"
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
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
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
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
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
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
// 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()) {
// 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)
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();
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();
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
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();
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
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
};
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();
" (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.
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),
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())
};
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())
};
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
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
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()) {
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)),
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
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
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
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()),
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" shared_network_name,"
" user_context,"
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
"INSERT INTO dhcp6_client_class("
" name,"
" test,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" shared_network_name = ?,"
" user_context = ?,"
" rebind_timer = ?,"
" relay = ?,"
" renew_timer = ?,"
- " require_client_classes = ?,"
+ " evaluate_additional_classes = ?,"
" reservations_global = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
// 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
}
// 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);
}
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
/// 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
/// 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.
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" end_address," \
" subnet_id," \
" client_class," \
- " require_client_classes," \
+ " evaluate_additional_classes," \
" user_context," \
" modification_ts" \
") VALUES (?, ?, ?, ?, ?, ?, ?)"
" excluded_prefix," \
" excluded_prefix_length," \
" client_class," \
- " require_client_classes," \
+ " evaluate_additional_classes," \
" user_context," \
" modification_ts" \
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
" next_server = ?," \
" server_hostname = ?," \
" boot_file_name = ?," \
- " only_if_required = ?," \
+ " only_in_additional_list = ?," \
" valid_lifetime = ?," \
" min_valid_lifetime = ?," \
" max_valid_lifetime = ?," \
"UPDATE dhcp6_client_class SET" \
" name = ?," \
" test = ?," \
- " only_if_required = ?," \
+ " only_in_additional_list = ?," \
" valid_lifetime = ?," \
" min_valid_lifetime = ?," \
" max_valid_lifetime = ?," \
// 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)) {
// 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.
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)) {
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)) {
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));
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());
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)) {
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));
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
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());
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
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" server_hostname,"
" shared_network_name,"
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
},
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,
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
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
" next_server,"
" server_hostname,"
" boot_file_name,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
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
" 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,"
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,
" 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,"
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
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
// 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)) {
// 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.
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)) {
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)) {
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)) {
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)) {
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.
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());
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());
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)) {
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));
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
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());
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
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" shared_network_name,"
" user_context,"
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
},
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
},
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
" rebind_timer,"
" relay,"
" renew_timer,"
- " require_client_classes,"
+ " evaluate_additional_classes,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
{
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
"INSERT INTO dhcp6_client_class("
" name,"
" test,"
- " only_if_required,"
+ " only_in_additional_list,"
" valid_lifetime,"
" min_valid_lifetime,"
" max_valid_lifetime,"
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
" 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),"
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
" 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,"
{
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
{
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
}
// 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?
void
PgSqlConfigBackendImpl::setClientClasses(PgSqlResultRowWorker& worker, size_t col,
+ const std::string& column,
ClientClasses& client_classes) {
if (worker.isColumnNull(col)) {
return;
} 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());
}
}
}
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) {
/// 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.
/// 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.
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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," \
" 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)"
" 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)"
" 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," \
"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," \
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;
constexpr unsigned long ALLOCATOR_TYPE_BUF_LENGTH = 64;
-constexpr unsigned long OPTION_CLIENT_CLASSES_BUF_LENGTH = 65536;
-
//*}
} // end of namespace isc::cb
}
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)) {
/// 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.
///
/// @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
///
/// @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_);
}
/// @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.
///
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
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
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_() {
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_),
}
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
((!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_) &&
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)) {
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,
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),
/// @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;
/// 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.
/// @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)
/// 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(),
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";
"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",
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;
% 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.
}
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>
}
// 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
/// @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
///
/// 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_;
namespace isc {
namespace dhcp {
+
void
BaseNetworkParser::parseCommon(const ConstElementPtr& network_data,
NetworkPtr& network) {
}
}
+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
/// @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
#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>
}
}
- // 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
// 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
// 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);
"test",
"option-data",
"user-context",
- "only-if-required",
+ "only-if-required", // deprecated
+ "only-in-additional-list",
"valid-lifetime",
"min-valid-lifetime",
"max-valid-lifetime",
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::util;
+namespace ph = std::placeholders;
namespace isc {
namespace dhcp {
}
}
- // 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>
}
}
- // 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")) {
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 {
}
}
- 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_);
}
}
- 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)
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::util;
+namespace ph = std::placeholders;
namespace isc {
namespace dhcp {
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");
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");
{ "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 },
/// 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.
{ "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 },
{ "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 },
/// 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.
/// 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.
{ "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 },
}
// 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_) {
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.
/// @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_;
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);
" \"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"
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);
" \"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";
" \"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"
" \"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"
" \"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"
" \"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"
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);
" \"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"
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);
" \"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"
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"foo\": [ \"bar\" ] }");
pdpool1->setContext(ctx1);
- pdpool1->requireClientClass("bar");
+ pdpool1->addAdditionalClass("bar");
pdpool2->allowClientClass("bar");
subnet->addPool(pdpool1);
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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"
" \"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);
" \"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";
" \"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";
" \"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";
" \"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);
" \"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);
" \"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);
"[ \n"
" { \n"
" \"name\": \"ALL\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
"[ \n"
" { \n"
" \"name\": \"KNOWN\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
"[ \n"
" { \n"
" \"name\": \"UNKNOWN\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
"[ \n"
" { \n"
" \"name\": \"DROP\", \n"
- " \"only-if-required\": true \n"
+ " \"only-in-additional-list\": true \n"
" } \n"
"] \n";
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");
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());
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.
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;
// 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";
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());
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";
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"
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");
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());
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.
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;
// 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";
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());
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";
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"
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) {
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
" \"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,"
" \"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,"
" \"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,"
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();
" \"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,"
" \"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,"
" \"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,"
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();
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);
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;
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);
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;
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);
" \"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"
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"));
" \"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"
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");
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);
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);
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");
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());
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);
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);
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);
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);
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);
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());
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';
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';
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';
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';