mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[#3683] Checkpoint: created dedicated UT file
This commit is contained in:
parent
01177756b0
commit
78d714a6b7
@ -87,6 +87,7 @@ PROGRAM_TESTS = dhcp6_unittests
|
|||||||
# This list is ordered alphabetically. When adding new files, please maintain
|
# This list is ordered alphabetically. When adding new files, please maintain
|
||||||
# this order.
|
# this order.
|
||||||
dhcp6_unittests_SOURCES =
|
dhcp6_unittests_SOURCES =
|
||||||
|
dhcp6_unittests_SOURCES += addr_reg_unittest.cc
|
||||||
dhcp6_unittests_SOURCES += classify_unittest.cc
|
dhcp6_unittests_SOURCES += classify_unittest.cc
|
||||||
dhcp6_unittests_SOURCES += client_handler_unittest.cc
|
dhcp6_unittests_SOURCES += client_handler_unittest.cc
|
||||||
dhcp6_unittests_SOURCES += config_parser_unittest.cc
|
dhcp6_unittests_SOURCES += config_parser_unittest.cc
|
||||||
|
410
src/bin/dhcp6/tests/addr_reg_unittest.cc
Normal file
410
src/bin/dhcp6/tests/addr_reg_unittest.cc
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <asiolink/io_address.h>
|
||||||
|
#include <cc/data.h>
|
||||||
|
#include <dhcp/testutils/iface_mgr_test_config.h>
|
||||||
|
#include <dhcp6/json_config_parser.h>
|
||||||
|
#include <dhcp6/tests/dhcp6_message_test.h>
|
||||||
|
#include <dhcpsrv/utils.h>
|
||||||
|
|
||||||
|
using namespace isc;
|
||||||
|
using namespace isc::asiolink;
|
||||||
|
using namespace isc::data;
|
||||||
|
using namespace isc::dhcp;
|
||||||
|
using namespace isc::dhcp::test;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/// @brief Test fixture class for testing address registration..
|
||||||
|
class AddrRegTest : public Dhcpv6MessageTest {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Constructor.
|
||||||
|
///
|
||||||
|
/// Sets up fake interfaces.
|
||||||
|
AddrRegTest() : Dhcpv6MessageTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Generate IAADDR option with specified parameters.
|
||||||
|
///
|
||||||
|
/// @param addr The address.
|
||||||
|
/// @param preferred_lft The preferred lifetime.
|
||||||
|
/// @param valid_lft The valid lifetime.
|
||||||
|
Option6IAAddrPtr generateIAAddr(const IOAddress& addr,
|
||||||
|
uint32_t preferred_lft,
|
||||||
|
uint32_t valid_lft) {
|
||||||
|
Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR, addr,
|
||||||
|
preferred_lft, valid_lft));
|
||||||
|
return (iaaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Generate IAADDR option with specified parameters.
|
||||||
|
///
|
||||||
|
/// @param addr The address in textual form.
|
||||||
|
/// @param preferred_lft The preferred lifetime.
|
||||||
|
/// @param valid_lft The valid lifetime.
|
||||||
|
Option6IAAddrPtr generateIAAddr(const string& addr,
|
||||||
|
uint32_t preferred_lft,
|
||||||
|
uint32_t valid_lft) {
|
||||||
|
return (generateIAAddr(IOAddress(addr), preferred_lft, valid_lft));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Basic configuration.
|
||||||
|
string config_ = "{\n"
|
||||||
|
"\"interfaces-config\": { \"interfaces\": [ \"*\" ] },\n"
|
||||||
|
"\"valid-lifetime\": 4000,\n"
|
||||||
|
"\"preferred-lifetime\": 3000,\n"
|
||||||
|
"\"rebind-timer\": 2000,\n"
|
||||||
|
"\"renew-timer\": 1000,\n"
|
||||||
|
"\"subnet6\": [ {\n"
|
||||||
|
" \"id\": 1,\n"
|
||||||
|
" \"subnet\": \"2001:db8:1::/64\",\n"
|
||||||
|
" \"interface\": \"eth0\"\n"
|
||||||
|
"} ]\n"
|
||||||
|
"}\n";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test that client-id is mandatory and server-id forbidden for
|
||||||
|
// Addr-reg-inform messages
|
||||||
|
TEST_F(AddrRegTest, sanityCheck) {
|
||||||
|
// A message with no client-id should fail
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
EXPECT_FALSE(srv_.sanityCheck(addr_reg_inf));
|
||||||
|
|
||||||
|
// A message with a single client-id should succeed
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
EXPECT_TRUE(srv_.sanityCheck(addr_reg_inf));
|
||||||
|
|
||||||
|
// A message with server-id present should fail
|
||||||
|
addr_reg_inf->addOption(srv_.getServerID());
|
||||||
|
EXPECT_FALSE(srv_.sanityCheck(addr_reg_inf));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that subnet selection must return a subnet for processAddrRegInform.
|
||||||
|
TEST_F(AddrRegTest, noSubnet) {
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_FALSE(ctx.subnet_);
|
||||||
|
|
||||||
|
// No server: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
// The query is silently rejected so no log to check.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that an IA_NA option is required.
|
||||||
|
TEST_F(AddrRegTest, noIA_NA) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// No IA_NA: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::abcd: ";
|
||||||
|
expected += "Exactly 1 IA_NA option expected, but 0 received";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that exactly one IA_NA option is required.
|
||||||
|
TEST_F(AddrRegTest, twoIA_NAs) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
addr_reg_inf->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
|
||||||
|
addr_reg_inf->addOption(generateIA(D6O_IA_NA, 345, 1500, 3000));
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// 2 IA_NA options: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::abcd: ";
|
||||||
|
expected += "Exactly 1 IA_NA option expected, but 2 received";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that an IA_NA sub-option is required.
|
||||||
|
TEST_F(AddrRegTest, noIA_NAsub) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
addr_reg_inf->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// No IA_NA sub-options: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::abcd: ";
|
||||||
|
expected += "Exactly 1 IA_NA sub-option expected, but 0 received";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that an exactly one IA_NA sub-option is required.
|
||||||
|
TEST_F(AddrRegTest, twoIA_NAsub) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
auto ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||||
|
ia->addOption(generateIAAddr("2001:db8:1::1", 3000, 4000));
|
||||||
|
ia->addOption(generateIAAddr("2001:db8:1::2", 3000, 4000));
|
||||||
|
addr_reg_inf->addOption(ia);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// Two IA_NA sub-options: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::abcd: ";
|
||||||
|
expected += "Exactly 1 IA_NA sub-option expected, but 2 received";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that addresses must match.
|
||||||
|
TEST_F(AddrRegTest, noAddrMatch) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
auto ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||||
|
ia->addOption(generateIAAddr("2001:db8:1::1", 3000, 4000));
|
||||||
|
addr_reg_inf->addOption(ia);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// Address mismatch: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::abcd: ";
|
||||||
|
expected += "Address mismatch: client at fe80::abcd ";
|
||||||
|
expected += "wants to register 2001:db8:1::1";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that addresses must match with a relay.
|
||||||
|
TEST_F(AddrRegTest, noAddrMatchRelay) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
auto ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||||
|
ia->addOption(generateIAAddr("2001:db8:1::1", 3000, 4000));
|
||||||
|
addr_reg_inf->addOption(ia);
|
||||||
|
|
||||||
|
// Add a relay.
|
||||||
|
Pkt6::RelayInfo relay;
|
||||||
|
relay.linkaddr_ = IOAddress("fe80::ef01");
|
||||||
|
relay.peeraddr_ = IOAddress("fe80::1");
|
||||||
|
addr_reg_inf->relay_info_.push_back(relay);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// Address mismatch: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::ef01: ";
|
||||||
|
expected += "Address mismatch: client at fe80::ef01 ";
|
||||||
|
expected += "wants to register 2001:db8:1::1";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that addresses must match with relays.
|
||||||
|
TEST_F(AddrRegTest, noAddrMatch2Relays) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
auto ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||||
|
ia->addOption(generateIAAddr("2001:db8:1::1", 3000, 4000));
|
||||||
|
addr_reg_inf->addOption(ia);
|
||||||
|
|
||||||
|
// Add a relay: it will be the outer one.
|
||||||
|
Pkt6::RelayInfo relay;
|
||||||
|
relay.linkaddr_ = IOAddress("fe80::ef01");
|
||||||
|
relay.peeraddr_ = IOAddress("fe80::1");
|
||||||
|
addr_reg_inf->relay_info_.push_back(relay);
|
||||||
|
|
||||||
|
// Add a second relay: it will be the inner one.
|
||||||
|
Pkt6::RelayInfo relay2;
|
||||||
|
relay2.linkaddr_ = IOAddress("fe80::2345");
|
||||||
|
relay2.peeraddr_ = IOAddress("fe80::1");
|
||||||
|
addr_reg_inf->relay_info_.push_back(relay2);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// Address mismatch: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client fe80::2345: ";
|
||||||
|
expected += "Address mismatch: client at fe80::2345 ";
|
||||||
|
expected += "wants to register 2001:db8:1::1";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the registering address must be in the subnet.
|
||||||
|
TEST_F(AddrRegTest, noInSubnet) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(configure(config_));
|
||||||
|
|
||||||
|
Pkt6Ptr addr_reg_inf = Pkt6Ptr(new Pkt6(DHCPV6_ADDR_REG_INFORM, 1234));
|
||||||
|
addr_reg_inf->setRemoteAddr(IOAddress("2001:db8::1"));
|
||||||
|
addr_reg_inf->setIface("eth0");
|
||||||
|
addr_reg_inf->setIndex(ETH0_INDEX);
|
||||||
|
OptionPtr clientid = generateClientId();
|
||||||
|
addr_reg_inf->addOption(clientid);
|
||||||
|
auto ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||||
|
ia->addOption(generateIAAddr("2001:db8::1", 3000, 4000));
|
||||||
|
addr_reg_inf->addOption(ia);
|
||||||
|
|
||||||
|
// Pass it to the server.
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !srv_.earlyGHRLookup(addr_reg_inf, ctx);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ctx.subnet_ = srv_.selectSubnet(addr_reg_inf, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
srv_.initContext(ctx, drop);
|
||||||
|
ASSERT_FALSE(drop);
|
||||||
|
ASSERT_TRUE(ctx.subnet_);
|
||||||
|
|
||||||
|
// Not in subnet: no response.
|
||||||
|
EXPECT_FALSE(srv_.processAddrRegInform(ctx));
|
||||||
|
|
||||||
|
string expected = "DHCP6_ADDR_REG_INFORM_FAIL ";
|
||||||
|
expected += "error on addr-reg-inform from client 2001:db8::1: ";
|
||||||
|
expected += "Address 2001:db8::1 is not in subnet ";
|
||||||
|
expected += "2001:db8:1::/64 (id 1)";
|
||||||
|
EXPECT_EQ(1, countFile(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
@ -617,11 +617,14 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelStats) {
|
|||||||
"pkt6-infrequest-received",
|
"pkt6-infrequest-received",
|
||||||
"pkt6-dhcpv4-query-received",
|
"pkt6-dhcpv4-query-received",
|
||||||
"pkt6-dhcpv4-response-received",
|
"pkt6-dhcpv4-response-received",
|
||||||
|
"pkt6-addr-reg-inform-received",
|
||||||
|
"pkt6-addr-reg-reply-received",
|
||||||
"pkt6-unknown-received",
|
"pkt6-unknown-received",
|
||||||
"pkt6-sent",
|
"pkt6-sent",
|
||||||
"pkt6-advertise-sent",
|
"pkt6-advertise-sent",
|
||||||
"pkt6-reply-sent",
|
"pkt6-reply-sent",
|
||||||
"pkt6-dhcpv4-response-sent",
|
"pkt6-dhcpv4-response-sent",
|
||||||
|
"pkt6-addr-reg-reply-sent",
|
||||||
"pkt6-parse-failed",
|
"pkt6-parse-failed",
|
||||||
"pkt6-receive-drop",
|
"pkt6-receive-drop",
|
||||||
"v6-allocation-fail",
|
"v6-allocation-fail",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2014-2025 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -608,6 +608,20 @@ Dhcp6Client::doRelease() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Dhcp6Client::doAddrRegInform() {
|
||||||
|
context_.query_ = createMsg(DHCPV6_ADDR_REG_INFORM);
|
||||||
|
|
||||||
|
// Append requested IAs.
|
||||||
|
appendRequestedIAs(context_.query_);
|
||||||
|
|
||||||
|
// Add Client FQDN if configured.
|
||||||
|
appendFQDN();
|
||||||
|
|
||||||
|
sendMsg(context_.query_);
|
||||||
|
context_.response_ = receiveOneMsg();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query,
|
Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query,
|
||||||
const bool include_address) {
|
const bool include_address) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2014-2025 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -311,6 +311,12 @@ public:
|
|||||||
/// and receiving server's response.
|
/// and receiving server's response.
|
||||||
void doRelease();
|
void doRelease();
|
||||||
|
|
||||||
|
/// @brief This function generates Addr-reg-inform message, sends it
|
||||||
|
/// to the server and then receives the Addr-reg-reply.
|
||||||
|
/// This method does not process the response in any specific way,
|
||||||
|
/// just stores it.
|
||||||
|
void doAddrRegInform();
|
||||||
|
|
||||||
/// @brief Removes the stateful configuration obtained from the server.
|
/// @brief Removes the stateful configuration obtained from the server.
|
||||||
///
|
///
|
||||||
/// It removes all leases held by the client.
|
/// It removes all leases held by the client.
|
||||||
|
@ -3640,6 +3640,11 @@ TEST_F(Dhcpv6SrvTest, receiveDhcpv4QueryStat) {
|
|||||||
testReceiveStats(DHCPV6_DHCPV4_QUERY, "pkt6-dhcpv4-query-received");
|
testReceiveStats(DHCPV6_DHCPV4_QUERY, "pkt6-dhcpv4-query-received");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test checks if pkt6-addr-reg-inform-received is bumped up correctly.
|
||||||
|
TEST_F(Dhcpv6SrvTest, receiveAddrRegInformStat) {
|
||||||
|
testReceiveStats(DHCPV6_ADDR_REG_INFORM, "pkt6-addr-reg-inform-received");
|
||||||
|
}
|
||||||
|
|
||||||
// Test checks if reception of a malformed packet increases pkt-parse-failed
|
// Test checks if reception of a malformed packet increases pkt-parse-failed
|
||||||
// and pkt6-receive-drop
|
// and pkt6-receive-drop
|
||||||
TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
|
TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2013-2025 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2013-2025 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -345,6 +345,27 @@ public:
|
|||||||
return (processDecline(ctx));
|
return (processDecline(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Processes incoming Addr-reg-inform message.
|
||||||
|
///
|
||||||
|
/// @param addr_reg_inf a message received from client
|
||||||
|
/// @return Addr-reg-reply message or null
|
||||||
|
Pkt6Ptr processAddrRegInform(const Pkt6Ptr& decline) {
|
||||||
|
AllocEngine::ClientContext6 ctx;
|
||||||
|
bool drop = !earlyGHRLookup(decline, ctx);
|
||||||
|
if (drop) {
|
||||||
|
return (Pkt6Ptr());
|
||||||
|
}
|
||||||
|
ctx.subnet_ = selectSubnet(decline, drop);
|
||||||
|
if (drop) {
|
||||||
|
return (Pkt6Ptr());
|
||||||
|
}
|
||||||
|
initContext(ctx, drop);
|
||||||
|
if (drop) {
|
||||||
|
return (Pkt6Ptr());
|
||||||
|
}
|
||||||
|
return (processAddrRegInform(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
using Dhcpv6Srv::processSolicit;
|
using Dhcpv6Srv::processSolicit;
|
||||||
using Dhcpv6Srv::processRequest;
|
using Dhcpv6Srv::processRequest;
|
||||||
using Dhcpv6Srv::processRenew;
|
using Dhcpv6Srv::processRenew;
|
||||||
@ -353,6 +374,7 @@ public:
|
|||||||
using Dhcpv6Srv::processRelease;
|
using Dhcpv6Srv::processRelease;
|
||||||
using Dhcpv6Srv::processDecline;
|
using Dhcpv6Srv::processDecline;
|
||||||
using Dhcpv6Srv::processInfRequest;
|
using Dhcpv6Srv::processInfRequest;
|
||||||
|
using Dhcpv6Srv::processAddrRegInform;
|
||||||
using Dhcpv6Srv::processClientFqdn;
|
using Dhcpv6Srv::processClientFqdn;
|
||||||
using Dhcpv6Srv::createNameChangeRequests;
|
using Dhcpv6Srv::createNameChangeRequests;
|
||||||
using Dhcpv6Srv::selectSubnet;
|
using Dhcpv6Srv::selectSubnet;
|
||||||
|
@ -910,11 +910,14 @@ BaseCtrlChannelDhcpv6Test::testControlChannelStats() {
|
|||||||
"pkt6-infrequest-received",
|
"pkt6-infrequest-received",
|
||||||
"pkt6-dhcpv4-query-received",
|
"pkt6-dhcpv4-query-received",
|
||||||
"pkt6-dhcpv4-response-received",
|
"pkt6-dhcpv4-response-received",
|
||||||
|
"pkt6-addr-reg-inform-received",
|
||||||
|
"pkt6-addr-reg-reply-received",
|
||||||
"pkt6-unknown-received",
|
"pkt6-unknown-received",
|
||||||
"pkt6-sent",
|
"pkt6-sent",
|
||||||
"pkt6-advertise-sent",
|
"pkt6-advertise-sent",
|
||||||
"pkt6-reply-sent",
|
"pkt6-reply-sent",
|
||||||
"pkt6-dhcpv4-response-sent",
|
"pkt6-dhcpv4-response-sent",
|
||||||
|
"pkt6-addr-reg-reply-sent",
|
||||||
"pkt6-parse-failed",
|
"pkt6-parse-failed",
|
||||||
"pkt6-receive-drop",
|
"pkt6-receive-drop",
|
||||||
"v6-allocation-fail",
|
"v6-allocation-fail",
|
||||||
|
@ -102,6 +102,7 @@ co4 = shared_library(
|
|||||||
|
|
||||||
kea_dhcp6_tests = executable(
|
kea_dhcp6_tests = executable(
|
||||||
'kea-dhcp6-tests',
|
'kea-dhcp6-tests',
|
||||||
|
'addr_reg_unittest.cc',
|
||||||
'classify_unittest.cc',
|
'classify_unittest.cc',
|
||||||
'client_handler_unittest.cc',
|
'client_handler_unittest.cc',
|
||||||
'config_backend_unittest.cc',
|
'config_backend_unittest.cc',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user