Skip to content

Commit

Permalink
[#3583] Added UTs
Browse files Browse the repository at this point in the history
/src/bin/dhcp4/tests/classify_unittest.cc
    TEST_F(ClassifyTest, classTaggingAndAlwaysSend)
    TEST_F(ClassifyTest, classTaggingAndNeverSend)

/src/bin/dhcp6/tests/classify_unittest.cc
    TEST_F(ClassifyTest, classTaggingAndAlwaysSend)
    TEST_F(ClassifyTest, classTaggingAndNeverSend)
  • Loading branch information
tmarkwalder committed Oct 15, 2024
1 parent d959d41 commit 099172d
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 0 deletions.
134 changes: 134 additions & 0 deletions src/bin/dhcp4/tests/classify_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2139,4 +2139,138 @@ TEST_F(ClassifyTest, basicOptionClassTagTest) {
checkServerIdentifier(response1, "0.0.0.0");
}

// Verifies that class-tagging does not subvert always-send.
TEST_F(ClassifyTest, classTaggingAndAlwaysSend) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();

NakedDhcpv4Srv srv(0);

// Global host-name option disables always-send. Subnet level
// host-name enables always-send but has a non-matching class
// tag. The Response should contain the global value for host-name.
string config = R"^(
{
"interfaces-config": {
"interfaces": [ "*" ]
},
"rebind-timer": 2000,
"renew-timer": 1000,
"valid-lifetime": 4000,
"option-data": [{
"name": "host-name",
"data": "global.com",
"always-send" : false,
"never-send" : false
}],
"subnet4": [{
"id": 1,
"subnet": "192.0.2.0/24",
"option-data": [{
"name": "host-name",
"data": "subnet.com",
"client-classes": [ "no-match" ],
"always-send" : true
}],
"pools": [{
"pool": "192.0.2.1 - 192.0.2.100"
}]
}]
}
)^";

// Configure DHCP server.
configure(config, srv);

// Create a DISCOVER that matches class "melon".
auto id = ClientId::fromText("31:31:31");
OptionPtr clientid = (OptionPtr(new Option(Option::V4,
DHO_DHCP_CLIENT_IDENTIFIER,
id->getClientId())));

Pkt4Ptr query1(new Pkt4(DHCPDISCOVER, 1234));
query1->setRemoteAddr(IOAddress("192.0.2.1"));
query1->addOption(clientid);
query1->setIface("eth1");
query1->setIndex(ETH1_INDEX);

// Configure DHCP server.
configure(config, srv);

// Process query
Pkt4Ptr response = srv.processDiscover(query1);

// Verify that global host-name is present.
OptionStringPtr hostname;
hostname = boost::dynamic_pointer_cast<OptionString>(response->getOption(DHO_HOST_NAME));
ASSERT_TRUE(hostname);
EXPECT_EQ("global.com", hostname->getValue());
}

// Verifies that class-tagging does not subvert never-send.
TEST_F(ClassifyTest, classTaggingAndNeverSend) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();

NakedDhcpv4Srv srv(0);

// Global host-name option enables always-send. Subnet level
// host-name enables never-send but has a non-matching class
// tag. The Response should not contain a value for host-name.
string config = R"^(
{
"interfaces-config": {
"interfaces": [ "*" ]
},
"rebind-timer": 2000,
"renew-timer": 1000,
"valid-lifetime": 4000,
"option-data": [{
"name": "host-name",
"data": "global.com",
"always-send" : true,
"never-send" : false
}],
"subnet4": [{
"id": 1,
"subnet": "192.0.2.0/24",
"option-data": [{
"name": "host-name",
"data": "subnet.com",
"client-classes": [ "no-match" ],
"always-send" : false,
"never-send" : true
}],
"pools": [{
"pool": "192.0.2.1 - 192.0.2.100"
}]
}]
}
)^";

// Configure DHCP server.
configure(config, srv);

// Create a DISCOVER that matches class "melon".
auto id = ClientId::fromText("31:31:31");
OptionPtr clientid = (OptionPtr(new Option(Option::V4,
DHO_DHCP_CLIENT_IDENTIFIER,
id->getClientId())));

Pkt4Ptr query1(new Pkt4(DHCPDISCOVER, 1234));
query1->setRemoteAddr(IOAddress("192.0.2.1"));
query1->addOption(clientid);
query1->setIface("eth1");
query1->setIndex(ETH1_INDEX);

// Configure DHCP server.
configure(config, srv);

// Process query
Pkt4Ptr response = srv.processDiscover(query1);

// The response should not contain host-name.
ASSERT_FALSE(response->getOption(DHO_HOST_NAME));
}

} // end of anonymous namespace
127 changes: 127 additions & 0 deletions src/bin/dhcp6/tests/classify_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3279,4 +3279,131 @@ TEST_F(ClassifyTest, requestedVendorOptionsClassTag) {
EXPECT_TRUE(custom);
}

// Verifies that class-tagging does not subvert always-send.
TEST_F(ClassifyTest, classTaggingAndAlwaysSend) {
IfaceMgrTestConfig test_config(true);

NakedDhcpv6Srv srv(0);

// Subnet level ipv6-forwarding enables always-send but with a non-matching
// class-tag. Response should contain the global value for ip6-fowarding.
std::string config = R"^(
{
"interfaces-config": { "interfaces": [ "*" ] },
"preferred-lifetime": 3000,
"rebind-timer": 2000,
"renew-timer": 1000,
"valid-lifetime": 4000,
"option-def": [{
"name": "ipv6-forwarding",
"code": 2345,
"type": "boolean"
}],
"option-data": [{
"name": "ipv6-forwarding",
"data": "true",
"always-send": false,
"never-send": false
}],
"subnet6": [{
"pools": [ { "pool": "2001:db8:1::/64" } ],
"id": 1,
"subnet": "2001:db8:1::/48",
"interface": "eth1",
"option-data": [{
"name": "ipv6-forwarding",
"data": "false",
"client-classes": [ "no-match" ],
"always-send": true
}]
}]
}
)^";

ASSERT_NO_THROW(configure(config));

// Create a packet with enough to select the subnet and go through
// the SOLICIT processing
Pkt6Ptr query = createSolicit();

// Do not add an ORO.
OptionPtr oro = query->getOption(D6O_ORO);
EXPECT_FALSE(oro);

// Process the query
Pkt6Ptr response;
processQuery(srv, query, response);

// Processing should add the global ip-forwarding option.
OptionPtr opt = response->getOption(2345);
ASSERT_TRUE(opt);
ASSERT_GT(opt->len(), opt->getHeaderLen());
EXPECT_EQ(1, opt->getUint8());
}

// Verifies that option class-tagging does not subvert never-send.
TEST_F(ClassifyTest, classTaggingAndNeverSend) {
IfaceMgrTestConfig test_config(true);

NakedDhcpv6Srv srv(0);

// Subnet sets an ipv6-forwarding option in the response.
// The router class matches incoming packets with foo in a host-name
// option (code 1234) and sets an ipv6-forwarding option in the response.
// Subnet level option enables never-send non-matching class-tag.
// Response should not contain a value for ip6-fowarding.
std::string config = R"^(
{
"interfaces-config": { "interfaces": [ "*" ] },
"preferred-lifetime": 3000,
"rebind-timer": 2000,
"renew-timer": 1000,
"valid-lifetime": 4000,
"option-def": [{
"name": "ipv6-forwarding",
"code": 2345,
"type": "boolean"
}],
"option-data": [{
"name": "ipv6-forwarding",
"data": "true",
"always-send": true,
"never-send": false
}],
"subnet6": [{
"pools": [ { "pool": "2001:db8:1::/64" } ],
"id": 1,
"subnet": "2001:db8:1::/48",
"interface": "eth1",
"option-data": [{
"name": "ipv6-forwarding",
"data": "false",
"client-classes": [ "no-match" ],
"always-send": false,
"never-send": true
}]
}]
}
)^";

ASSERT_NO_THROW(configure(config));

// Create a packet with enough to select the subnet and go through
// the SOLICIT processing
Pkt6Ptr query = createSolicit();

// Do not add an ORO.
OptionPtr oro = query->getOption(D6O_ORO);
EXPECT_FALSE(oro);

// Process the query
Pkt6Ptr response;
processQuery(srv, query, response);

// Processing should not add an ip-forwarding option
OptionPtr opt = response->getOption(2345);
ASSERT_FALSE(opt);
}

} // end of anonymous namespace

0 comments on commit 099172d

Please sign in to comment.