2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-29 04:57:52 +00:00

[#3588] Modified no test required classes

This commit is contained in:
Francis Dupont 2024-10-08 16:10:13 +02:00
parent 8263915af3
commit dc8af16a6e
14 changed files with 256 additions and 38 deletions

View File

@ -0,0 +1,6 @@
[func]* fdupont
Modified the behavior of required client classes
configured without a test expression: they are now
unconditionally added as they always evaluate to
true (vs false previously).
(Gitlab #3388)

View File

@ -3423,6 +3423,10 @@ The order in which required classes are considered is: pool, subnet,
and shared network, i.e. in the same order from the way in which
``option-data`` is processed.
Since Kea version 2.7.4 required client classes configured without
a test expression are unconditionally added, i.e. they are considered
to always be evaluated to ``true``.
.. note::
Vendor-Identifying Vendor Options are a special case: for all other

View File

@ -3201,6 +3201,10 @@ levels. The order in which required classes are considered is:
(pd-)pool, subnet, and shared network, i.e. in the same order from the
way in which ``option-data`` is processed.
Since Kea version 2.7.4 required client classes configured without
a test expression are unconditionally added, i.e. they are considered
to always be evaluated to ``true``.
.. _dhcp6-ddns-config:
DDNS for DHCPv6

View File

@ -19,8 +19,6 @@ extern const isc::log::MessageID DHCP4_CLASSES_ASSIGNED = "DHCP4_CLASSES_ASSIGNE
extern const isc::log::MessageID DHCP4_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION = "DHCP4_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION";
extern const isc::log::MessageID DHCP4_CLASS_ASSIGNED = "DHCP4_CLASS_ASSIGNED";
extern const isc::log::MessageID DHCP4_CLASS_UNCONFIGURED = "DHCP4_CLASS_UNCONFIGURED";
extern const isc::log::MessageID DHCP4_CLASS_UNDEFINED = "DHCP4_CLASS_UNDEFINED";
extern const isc::log::MessageID DHCP4_CLASS_UNTESTABLE = "DHCP4_CLASS_UNTESTABLE";
extern const isc::log::MessageID DHCP4_CLIENTID_IGNORED_FOR_LEASES = "DHCP4_CLIENTID_IGNORED_FOR_LEASES";
extern const isc::log::MessageID DHCP4_CLIENT_FQDN_DATA = "DHCP4_CLIENT_FQDN_DATA";
extern const isc::log::MessageID DHCP4_CLIENT_FQDN_PROCESS = "DHCP4_CLIENT_FQDN_PROCESS";
@ -150,6 +148,8 @@ extern const isc::log::MessageID DHCP4_RELEASE_FAIL_WRONG_CLIENT = "DHCP4_RELEAS
extern const isc::log::MessageID DHCP4_REQUEST = "DHCP4_REQUEST";
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_EVAL_ERROR = "DHCP4_REQUIRED_CLASS_EVAL_ERROR";
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_EVAL_RESULT = "DHCP4_REQUIRED_CLASS_EVAL_RESULT";
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_UNDEFINED = "DHCP4_REQUIRED_CLASS_UNDEFINED";
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_UNTESTABLE = "DHCP4_REQUIRED_CLASS_UNTESTABLE";
extern const isc::log::MessageID DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED = "DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED";
extern const isc::log::MessageID DHCP4_RESERVED_HOSTNAME_ASSIGNED = "DHCP4_RESERVED_HOSTNAME_ASSIGNED";
extern const isc::log::MessageID DHCP4_RESPONSE_DATA = "DHCP4_RESPONSE_DATA";
@ -197,8 +197,6 @@ const char* values[] = {
"DHCP4_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION", "%1: client packet has been assigned to the following classes: %2",
"DHCP4_CLASS_ASSIGNED", "%1: client packet has been assigned to the following class: %2",
"DHCP4_CLASS_UNCONFIGURED", "%1: client packet belongs to an unconfigured class: %2",
"DHCP4_CLASS_UNDEFINED", "required class %1 has no definition",
"DHCP4_CLASS_UNTESTABLE", "required class %1 has no test expression",
"DHCP4_CLIENTID_IGNORED_FOR_LEASES", "%1: not using client identifier for lease allocation for subnet %2",
"DHCP4_CLIENT_FQDN_DATA", "%1: Client sent FQDN option: %2",
"DHCP4_CLIENT_FQDN_PROCESS", "%1: processing Client FQDN option",
@ -328,6 +326,8 @@ const char* values[] = {
"DHCP4_REQUEST", "%1: server is processing DHCPREQUEST with hint=%2",
"DHCP4_REQUIRED_CLASS_EVAL_ERROR", "%1: Expression '%2' evaluated to %3",
"DHCP4_REQUIRED_CLASS_EVAL_RESULT", "%1: Expression '%2' evaluated to %3",
"DHCP4_REQUIRED_CLASS_UNDEFINED", "required class %1 has no definition",
"DHCP4_REQUIRED_CLASS_UNTESTABLE", "required class %1 has no test expression",
"DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED", "Multi-threading is enabled and host reservations lookup is always performed first.",
"DHCP4_RESERVED_HOSTNAME_ASSIGNED", "%1: server assigned reserved hostname %2",
"DHCP4_RESPONSE_DATA", "%1: responding with packet %2 (type %3), packet details: %4",

View File

@ -20,8 +20,6 @@ extern const isc::log::MessageID DHCP4_CLASSES_ASSIGNED;
extern const isc::log::MessageID DHCP4_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION;
extern const isc::log::MessageID DHCP4_CLASS_ASSIGNED;
extern const isc::log::MessageID DHCP4_CLASS_UNCONFIGURED;
extern const isc::log::MessageID DHCP4_CLASS_UNDEFINED;
extern const isc::log::MessageID DHCP4_CLASS_UNTESTABLE;
extern const isc::log::MessageID DHCP4_CLIENTID_IGNORED_FOR_LEASES;
extern const isc::log::MessageID DHCP4_CLIENT_FQDN_DATA;
extern const isc::log::MessageID DHCP4_CLIENT_FQDN_PROCESS;
@ -151,6 +149,8 @@ extern const isc::log::MessageID DHCP4_RELEASE_FAIL_WRONG_CLIENT;
extern const isc::log::MessageID DHCP4_REQUEST;
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_EVAL_ERROR;
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_EVAL_RESULT;
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_UNDEFINED;
extern const isc::log::MessageID DHCP4_REQUIRED_CLASS_UNTESTABLE;
extern const isc::log::MessageID DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED;
extern const isc::log::MessageID DHCP4_RESERVED_HOSTNAME_ASSIGNED;
extern const isc::log::MessageID DHCP4_RESPONSE_DATA;

View File

@ -94,16 +94,6 @@ which cannot be found in the configuration. Either a hook written
before the classification was added to Kea is used, or class naming is
inconsistent.
% DHCP4_CLASS_UNDEFINED required class %1 has no definition
Logged at debug log level 40.
This debug message informs that a class is listed for required evaluation but
has no definition.
% DHCP4_CLASS_UNTESTABLE required class %1 has no test expression
Logged at debug log level 40.
This debug message informs that a class was listed for required evaluation but
its definition does not include a test expression to evaluate.
% DHCP4_CLIENTID_IGNORED_FOR_LEASES %1: not using client identifier for lease allocation for subnet %2
Logged at debug log level 50.
This debug message is issued when the server is processing the DHCPv4 message
@ -989,6 +979,17 @@ This debug message indicates that the expression of a required client class has
been successfully evaluated. The client class name and the result value of the
evaluation are printed.
% DHCP4_REQUIRED_CLASS_UNDEFINED required class %1 has no definition
Logged at debug log level 40.
This debug message informs that a class is listed for required evaluation but
has no definition. The class is ignored.
% DHCP4_REQUIRED_CLASS_UNTESTABLE required class %1 has no test expression
Logged at debug log level 40.
This debug message informs that a class was listed for required evaluation but
its definition does not include a test expression to evaluate. The class is
unconditionally added to the query.
% DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED Multi-threading is enabled and host reservations lookup is always performed first.
This is a message informing that host reservations lookup is performed before
lease lookup when multi-threading is enabled overwriting configured value.

View File

@ -4866,15 +4866,19 @@ void Dhcpv4Srv::requiredClassify(Dhcpv4Exchange& ex) {
for (auto const& cclass : classes) {
const ClientClassDefPtr class_def = dict->findClass(cclass);
if (!class_def) {
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_UNDEFINED)
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC,
DHCP4_REQUIRED_CLASS_UNDEFINED)
.arg(cclass);
// Ignore it as it can't have an attached action
continue;
}
const ExpressionPtr& expr_ptr = class_def->getMatchExpr();
// Nothing to do without an expression to evaluate
// Add a class without an expression to evaluate
if (!expr_ptr) {
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_UNTESTABLE)
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC,
DHCP4_REQUIRED_CLASS_UNTESTABLE)
.arg(cclass);
query->addClass(cclass);
continue;
}
// Evaluate the expression which can return false (no match),

View File

@ -1238,6 +1238,100 @@ TEST_F(ClassifyTest, precedenceNetwork) {
EXPECT_EQ("10.0.0.3", addrs[0].toText());
}
// This test checks a required class without a test entry can be
// unconditionally added.
TEST_F(ClassifyTest, requiredNoTest) {
std::string config =
"{"
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 600,"
"\"client-classes\": ["
" {"
" \"name\": \"for-network\","
" \"option-data\": [ {"
" \"name\": \"domain-name-servers\","
" \"data\": \"10.0.0.3\""
" } ]"
" }"
"],"
"\"shared-networks\": [ {"
" \"name\": \"frog\","
" \"require-client-classes\": [ \"for-network\" ],"
" \"subnet4\": [ { "
" \"subnet\": \"10.0.0.0/24\","
" \"id\": 1,"
" \"pools\": [ { "
" \"pool\": \"10.0.0.10-10.0.0.100\""
" } ]"
" } ]"
"} ]"
"}";
// Create a client requesting domain-name-servers option
Dhcp4Client client(Dhcp4Client::SELECTING);
client.requestOptions(DHO_DOMAIN_NAME_SERVERS);
// Load the config and perform a DORA
configure(config, *client.getServer());
ASSERT_NO_THROW(client.doDORA());
// Check response
Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
EXPECT_EQ("10.0.0.10", resp->getYiaddr().toText());
// Check domain-name-servers option
OptionPtr opt = resp->getOption(DHO_DOMAIN_NAME_SERVERS);
ASSERT_TRUE(opt);
Option4AddrLstPtr servers =
boost::dynamic_pointer_cast<Option4AddrLst>(opt);
ASSERT_TRUE(servers);
auto addrs = servers->getAddresses();
ASSERT_EQ(1, addrs.size());
EXPECT_EQ("10.0.0.3", addrs[0].toText());
}
// This test checks a required class which is not defined is ignored.
TEST_F(ClassifyTest, requiredNoDefined) {
std::string config =
"{"
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 600,"
"\"shared-networks\": [ {"
" \"name\": \"frog\","
" \"require-client-classes\": [ \"for-network\" ],"
" \"subnet4\": [ { "
" \"subnet\": \"10.0.0.0/24\","
" \"id\": 1,"
" \"pools\": [ { "
" \"pool\": \"10.0.0.10-10.0.0.100\""
" } ]"
" } ]"
"} ]"
"}";
// Create a client requesting domain-name-servers option
Dhcp4Client client(Dhcp4Client::SELECTING);
client.requestOptions(DHO_DOMAIN_NAME_SERVERS);
// Load the config and perform a DORA
configure(config, *client.getServer());
ASSERT_NO_THROW(client.doDORA());
// Check response
Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
EXPECT_EQ("10.0.0.10", resp->getYiaddr().toText());
// Check domain-name-servers option
OptionPtr opt = resp->getOption(DHO_DOMAIN_NAME_SERVERS);
EXPECT_FALSE(opt);
}
// This test checks the handling for the DROP special class.
TEST_F(ClassifyTest, dropClass) {
Dhcp4Client client(Dhcp4Client::SELECTING);

View File

@ -21,8 +21,6 @@ extern const isc::log::MessageID DHCP6_CLASSES_ASSIGNED = "DHCP6_CLASSES_ASSIGNE
extern const isc::log::MessageID DHCP6_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION = "DHCP6_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION";
extern const isc::log::MessageID DHCP6_CLASS_ASSIGNED = "DHCP6_CLASS_ASSIGNED";
extern const isc::log::MessageID DHCP6_CLASS_UNCONFIGURED = "DHCP6_CLASS_UNCONFIGURED";
extern const isc::log::MessageID DHCP6_CLASS_UNDEFINED = "DHCP6_CLASS_UNDEFINED";
extern const isc::log::MessageID DHCP6_CLASS_UNTESTABLE = "DHCP6_CLASS_UNTESTABLE";
extern const isc::log::MessageID DHCP6_CONFIG_COMPLETE = "DHCP6_CONFIG_COMPLETE";
extern const isc::log::MessageID DHCP6_CONFIG_LOAD_FAIL = "DHCP6_CONFIG_LOAD_FAIL";
extern const isc::log::MessageID DHCP6_CONFIG_PACKET_QUEUE = "DHCP6_CONFIG_PACKET_QUEUE";
@ -149,6 +147,8 @@ extern const isc::log::MessageID DHCP6_RELEASE_PD_FAIL_WRONG_DUID = "DHCP6_RELEA
extern const isc::log::MessageID DHCP6_RELEASE_PD_FAIL_WRONG_IAID = "DHCP6_RELEASE_PD_FAIL_WRONG_IAID";
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_EVAL_ERROR = "DHCP6_REQUIRED_CLASS_EVAL_ERROR";
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_EVAL_RESULT = "DHCP6_REQUIRED_CLASS_EVAL_RESULT";
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_UNDEFINED = "DHCP6_REQUIRED_CLASS_UNDEFINED";
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_UNTESTABLE = "DHCP6_REQUIRED_CLASS_UNTESTABLE";
extern const isc::log::MessageID DHCP6_REQUIRED_OPTIONS_CHECK_FAIL = "DHCP6_REQUIRED_OPTIONS_CHECK_FAIL";
extern const isc::log::MessageID DHCP6_RESERVATIONS_LOOKUP_FIRST_ENABLED = "DHCP6_RESERVATIONS_LOOKUP_FIRST_ENABLED";
extern const isc::log::MessageID DHCP6_RESPONSE_DATA = "DHCP6_RESPONSE_DATA";
@ -188,8 +188,6 @@ const char* values[] = {
"DHCP6_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION", "%1: client packet has been assigned to the following classes: %2",
"DHCP6_CLASS_ASSIGNED", "%1: client packet has been assigned to the following class: %2",
"DHCP6_CLASS_UNCONFIGURED", "%1: client packet belongs to an unconfigured class: %2",
"DHCP6_CLASS_UNDEFINED", "required class %1 has no definition",
"DHCP6_CLASS_UNTESTABLE", "required class %1 has no test expression",
"DHCP6_CONFIG_COMPLETE", "DHCPv6 server has completed configuration: %1",
"DHCP6_CONFIG_LOAD_FAIL", "configuration error using file: %1, reason: %2",
"DHCP6_CONFIG_PACKET_QUEUE", "DHCPv6 packet queue info after configuration: %1",
@ -316,6 +314,8 @@ const char* values[] = {
"DHCP6_RELEASE_PD_FAIL_WRONG_IAID", "%1: client tried to release prefix %2/%3, but it used wrong IAID (expected %4, but got %5)",
"DHCP6_REQUIRED_CLASS_EVAL_ERROR", "%1: Expression '%2' evaluated to %3",
"DHCP6_REQUIRED_CLASS_EVAL_RESULT", "%1: Expression '%2' evaluated to %3",
"DHCP6_REQUIRED_CLASS_UNDEFINED", "required class %1 has no definition",
"DHCP6_REQUIRED_CLASS_UNTESTABLE", "required class %1 has no test expression",
"DHCP6_REQUIRED_OPTIONS_CHECK_FAIL", "%1: %2 message received from %3 failed the following check: %4",
"DHCP6_RESERVATIONS_LOOKUP_FIRST_ENABLED", "Multi-threading is enabled and host reservations lookup is always performed first.",
"DHCP6_RESPONSE_DATA", "%1: responding with packet %2 (type %3), packet details: %4",

View File

@ -22,8 +22,6 @@ extern const isc::log::MessageID DHCP6_CLASSES_ASSIGNED;
extern const isc::log::MessageID DHCP6_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION;
extern const isc::log::MessageID DHCP6_CLASS_ASSIGNED;
extern const isc::log::MessageID DHCP6_CLASS_UNCONFIGURED;
extern const isc::log::MessageID DHCP6_CLASS_UNDEFINED;
extern const isc::log::MessageID DHCP6_CLASS_UNTESTABLE;
extern const isc::log::MessageID DHCP6_CONFIG_COMPLETE;
extern const isc::log::MessageID DHCP6_CONFIG_LOAD_FAIL;
extern const isc::log::MessageID DHCP6_CONFIG_PACKET_QUEUE;
@ -150,6 +148,8 @@ extern const isc::log::MessageID DHCP6_RELEASE_PD_FAIL_WRONG_DUID;
extern const isc::log::MessageID DHCP6_RELEASE_PD_FAIL_WRONG_IAID;
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_EVAL_ERROR;
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_EVAL_RESULT;
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_UNDEFINED;
extern const isc::log::MessageID DHCP6_REQUIRED_CLASS_UNTESTABLE;
extern const isc::log::MessageID DHCP6_REQUIRED_OPTIONS_CHECK_FAIL;
extern const isc::log::MessageID DHCP6_RESERVATIONS_LOOKUP_FIRST_ENABLED;
extern const isc::log::MessageID DHCP6_RESPONSE_DATA;

View File

@ -112,16 +112,6 @@ which cannot be found in the configuration. Either a hook written
before the classification was added to Kea is used, or class naming is
inconsistent.
% DHCP6_CLASS_UNDEFINED required class %1 has no definition
Logged at debug log level 40.
This debug message informs that a class is listed for required evaluation but
has no definition.
% DHCP6_CLASS_UNTESTABLE required class %1 has no test expression
Logged at debug log level 40.
This debug message informs that a class was listed for required evaluation but
its definition does not include a test expression to evaluate.
% DHCP6_CONFIG_COMPLETE DHCPv6 server has completed configuration: %1
This is an informational message announcing the successful processing of a
new configuration. it is output during server startup, and when an updated
@ -994,6 +984,17 @@ This debug message indicates that the expression of a required client class has
been successfully evaluated. The client class name and the result value of the
evaluation are printed.
% DHCP6_REQUIRED_CLASS_UNDEFINED required class %1 has no definition
Logged at debug log level 40.
This debug message informs that a class is listed for required evaluation but
has no definition. The class is ignored.
% DHCP6_REQUIRED_CLASS_UNTESTABLE required class %1 has no test expression
Logged at debug log level 40.
This debug message informs that a class was listed for required evaluation but
its definition does not include a test expression to evaluate. The class is
unconditionally added to the query.
% DHCP6_REQUIRED_OPTIONS_CHECK_FAIL %1: %2 message received from %3 failed the following check: %4
Logged at debug log level 40.
This message indicates that received DHCPv6 packet is invalid. This may be due

View File

@ -4495,15 +4495,19 @@ Dhcpv6Srv::requiredClassify(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx
for (auto const& cclass : classes) {
const ClientClassDefPtr class_def = dict->findClass(cclass);
if (!class_def) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_UNDEFINED)
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC,
DHCP6_REQUIRED_CLASS_UNDEFINED)
.arg(cclass);
// Ignore it as it can't have an attached action
continue;
}
const ExpressionPtr& expr_ptr = class_def->getMatchExpr();
// Nothing to do without an expression to evaluate
// Add a class without an expression to evaluate
if (!expr_ptr) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_UNTESTABLE)
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC,
DHCP6_REQUIRED_CLASS_UNTESTABLE)
.arg(cclass);
pkt->addClass(cclass);
continue;
}
// Evaluate the expression which can return false (no match),

View File

@ -2268,6 +2268,106 @@ TEST_F(ClassifyTest, precedenceNetwork) {
EXPECT_EQ("2001:db8:1::3", addrs[0].toText());
}
// This test checks a required class without a test entry can be
// unconditionally added.
TEST_F(ClassifyTest, requiredNoTest) {
std::string config =
"{"
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"client-classes\": ["
" {"
" \"name\": \"for-network\","
" \"option-data\": [ {"
" \"name\": \"dns-servers\","
" \"data\": \"2001:db8:1::3\""
" } ]"
" }"
"],"
"\"shared-networks\": [ {"
" \"name\": \"frog\","
" \"interface\": \"eth1\","
" \"require-client-classes\": [ \"for-network\" ],"
" \"subnet6\": [ { "
" \"subnet\": \"2001:db8:1::/64\","
" \"id\": 1,"
" \"pools\": [ { "
" \"pool\": \"2001:db8:1::1 - 2001:db8:1::64\""
" } ]"
" } ]"
"} ],"
"\"valid-lifetime\": 600"
"}";
// Create a client requesting dns-servers option
Dhcp6Client client;
client.setInterface("eth1");
client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
client.requestOption(D6O_NAME_SERVERS);
// Load the config and perform a SARR
configure(config, *client.getServer());
ASSERT_NO_THROW(client.doSARR());
// Check response
EXPECT_EQ(1, client.getLeaseNum());
Pkt6Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// Check dns-servers option
OptionPtr opt = resp->getOption(D6O_NAME_SERVERS);
ASSERT_TRUE(opt);
Option6AddrLstPtr servers =
boost::dynamic_pointer_cast<Option6AddrLst>(opt);
ASSERT_TRUE(servers);
auto addrs = servers->getAddresses();
ASSERT_EQ(1, addrs.size());
EXPECT_EQ("2001:db8:1::3", addrs[0].toText());
}
// This test checks a required class which is not defined is ignored.
TEST_F(ClassifyTest, requiredNoDefined) {
std::string config =
"{"
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"shared-networks\": [ {"
" \"name\": \"frog\","
" \"interface\": \"eth1\","
" \"require-client-classes\": [ \"for-network\" ],"
" \"subnet6\": [ { "
" \"subnet\": \"2001:db8:1::/64\","
" \"id\": 1,"
" \"pools\": [ { "
" \"pool\": \"2001:db8:1::1 - 2001:db8:1::64\""
" } ]"
" } ]"
"} ],"
"\"valid-lifetime\": 600"
"}";
// Create a client requesting dns-servers option
Dhcp6Client client;
client.setInterface("eth1");
client.requestAddress(0xabca, IOAddress("2001:db8:1::28"));
client.requestOption(D6O_NAME_SERVERS);
// Load the config and perform a SARR
configure(config, *client.getServer());
ASSERT_NO_THROW(client.doSARR());
// Check response
EXPECT_EQ(1, client.getLeaseNum());
Pkt6Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// Check dns-servers option
OptionPtr opt = resp->getOption(D6O_NAME_SERVERS);
EXPECT_FALSE(opt);
}
// This test checks the complex membership from HA with server1 telephone.
TEST_F(ClassifyTest, server1Telephone) {
// Create a client.