mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[3689] Added host reservation tests
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc added tests: TEST_F(Dhcpv6SrvTest, hostReservationWithHostName) TEST_F(Dhcpv6SrvTest, hostReservationWithoutHostName) src/bin/dhcp6/tests/dhcp6_test_utils.h src/bin/dhcp6/tests/dhcp6_test_utils.cc Dhcpv6SrvTest::createHost6() - this method was moved here from FqdnDhcpv6SrvTest() src/bin/dhcp6/tests/fqdn_unittest.cc added tests: TEST_F(FqdnDhcpv6SrvTest, hostnameReservationSuffix) TEST_F(FqdnDhcpv6SrvTest, hostnameReservationNoSuffix) TEST_F(FqdnDhcpv6SrvTest, hostnameReservationDdnsDisabled)
This commit is contained in:
@@ -2094,7 +2094,123 @@ TEST_F(Dhcpv6SrvTest, relayOverrideAndClientClass) {
|
||||
EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol));
|
||||
}
|
||||
|
||||
// Verify that a host reservation is used and that the lease name is set to
|
||||
// the reservation hostname.
|
||||
TEST_F(Dhcpv6SrvTest, hostReservationWithHostName) {
|
||||
// set duid_ for createHost6
|
||||
generateClientId();
|
||||
|
||||
// create host reservation
|
||||
IOAddress res_address("2001:db8:1:1::babe");
|
||||
createHost6(true, IPv6Resrv::TYPE_NA, res_address, "alice");
|
||||
|
||||
// Let's create a REQUEST
|
||||
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
|
||||
req->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||
req->setIface("eth0");
|
||||
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||
|
||||
// with a valid hint
|
||||
IOAddress hint("2001:db8:1:1::dead:beef");
|
||||
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
|
||||
|
||||
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
|
||||
ia->addOption(hint_opt);
|
||||
req->addOption(ia);
|
||||
|
||||
// Set client id to match duid_
|
||||
OptionPtr clientid = generateClientId();
|
||||
req->addOption(clientid);
|
||||
|
||||
// server-id is mandatory in REQUEST
|
||||
req->addOption(srv_.getServerID());
|
||||
|
||||
// Pass it to the server and hope for a REPLY
|
||||
Pkt6Ptr reply = srv_.processRequest(req);
|
||||
|
||||
// check if we get response at all
|
||||
checkResponse(reply, DHCPV6_REPLY, 1234);
|
||||
|
||||
OptionPtr tmp = reply->getOption(D6O_IA_NA);
|
||||
ASSERT_TRUE(tmp);
|
||||
|
||||
// check that IA_NA was returned and that there's an address included
|
||||
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
|
||||
subnet_->getT1(),
|
||||
subnet_->getT2());
|
||||
ASSERT_TRUE(addr);
|
||||
|
||||
// check that we've got the address we requested
|
||||
checkIAAddr(addr, res_address, Lease::TYPE_NA);
|
||||
|
||||
// check that the lease is really in the database
|
||||
Lease6Ptr l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Verify that lease hostname matches the reservation name
|
||||
EXPECT_EQ("alice", l->hostname_);
|
||||
}
|
||||
|
||||
// Verify that a host reservation is used and that the lease name is blank
|
||||
// when the reservation hostname is blank.
|
||||
TEST_F(Dhcpv6SrvTest, hostReservationWithoutHostName) {
|
||||
// set duid_ for createHost6
|
||||
generateClientId();
|
||||
|
||||
// create host reservation
|
||||
IOAddress res_address("2001:db8:1:1::babe");
|
||||
createHost6(true, IPv6Resrv::TYPE_NA, res_address, "");
|
||||
|
||||
// Let's create a REQUEST
|
||||
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
|
||||
req->setRemoteAddr(IOAddress("fe80::abcd"));
|
||||
req->setIface("eth0");
|
||||
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
|
||||
|
||||
// with a valid hint
|
||||
IOAddress hint("2001:db8:1:1::dead:beef");
|
||||
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
|
||||
|
||||
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
|
||||
ia->addOption(hint_opt);
|
||||
req->addOption(ia);
|
||||
|
||||
// Set client id to match duid_
|
||||
OptionPtr clientid = generateClientId();
|
||||
req->addOption(clientid);
|
||||
|
||||
// server-id is mandatory in REQUEST
|
||||
req->addOption(srv_.getServerID());
|
||||
|
||||
// Pass it to the server and hope for a REPLY
|
||||
Pkt6Ptr reply = srv_.processRequest(req);
|
||||
|
||||
// check if we get response at all
|
||||
checkResponse(reply, DHCPV6_REPLY, 1234);
|
||||
|
||||
OptionPtr tmp = reply->getOption(D6O_IA_NA);
|
||||
ASSERT_TRUE(tmp);
|
||||
|
||||
// check that IA_NA was returned and that there's an address included
|
||||
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
|
||||
subnet_->getT1(),
|
||||
subnet_->getT2());
|
||||
ASSERT_TRUE(addr);
|
||||
|
||||
// check that we've got the address we requested
|
||||
checkIAAddr(addr, res_address, Lease::TYPE_NA);
|
||||
|
||||
// check that the lease is really in the database
|
||||
Lease6Ptr l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr);
|
||||
ASSERT_TRUE(l);
|
||||
|
||||
// Verify that lease hostname matches the reservation name
|
||||
EXPECT_EQ("", l->hostname_);
|
||||
}
|
||||
|
||||
|
||||
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
|
||||
/// to call processX() methods.
|
||||
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
@@ -77,6 +77,40 @@ Dhcpv6SrvTest::checkIA_NA(const Pkt6Ptr& rsp, uint32_t expected_iaid,
|
||||
return (addr);
|
||||
}
|
||||
|
||||
/// @brief Utility function that creates a host reservation (duid)
|
||||
///
|
||||
/// @param add_to_host_mgr true if the reservation should be added
|
||||
/// @param type specifies reservation type (NA or PD)
|
||||
/// @param addr specifies reserved address
|
||||
/// @param hostname specifies hostname to be used in reservation
|
||||
/// @return created Host object.
|
||||
HostPtr
|
||||
Dhcpv6SrvTest::createHost6(bool add_to_host_mgr, IPv6Resrv::Type type,
|
||||
const asiolink::IOAddress& addr, const std::string& hostname) {
|
||||
HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
|
||||
Host::IDENT_DUID, SubnetID(0), subnet_->getID(),
|
||||
asiolink::IOAddress("0.0.0.0"), hostname));
|
||||
|
||||
// Prefix length doesn't matter here, let's assume address is /128 and
|
||||
// prefix is /64
|
||||
IPv6Resrv resv(type, addr, type == IPv6Resrv::TYPE_NA? 128 : 64);
|
||||
host->addReservation(resv);
|
||||
|
||||
if (add_to_host_mgr) {
|
||||
|
||||
// Let's add the host.
|
||||
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
|
||||
|
||||
// We also need to add existing subnet
|
||||
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet_);
|
||||
|
||||
// Commit this configuration.
|
||||
CfgMgr::instance().commit();
|
||||
}
|
||||
|
||||
return (host);
|
||||
}
|
||||
|
||||
boost::shared_ptr<Option6IAPrefix>
|
||||
Dhcpv6SrvTest::checkIA_PD(const Pkt6Ptr& rsp, uint32_t expected_iaid,
|
||||
uint32_t expected_t1, uint32_t expected_t2) {
|
||||
|
@@ -345,6 +345,17 @@ public:
|
||||
/// @param srv Server to be configured.
|
||||
void configure(const std::string& config, NakedDhcpv6Srv& srv);
|
||||
|
||||
/// @brief Utility function that creates a host reservation (duid)
|
||||
///
|
||||
/// @param add_to_host_mgr true if the reservation should be added
|
||||
/// @param type specifies reservation type (NA or PD)
|
||||
/// @param addr specifies reserved address
|
||||
/// @param hostname specifies hostname to be used in reservation
|
||||
/// @return created Host object.
|
||||
isc::dhcp::HostPtr
|
||||
createHost6(bool add_to_host_mgr, isc::dhcp::IPv6Resrv::Type type,
|
||||
const asiolink::IOAddress& addr, const std::string& hostname);
|
||||
|
||||
/// @brief Checks that server response (ADVERTISE or REPLY) contains proper
|
||||
/// IA_NA option
|
||||
///
|
||||
|
@@ -507,40 +507,6 @@ public:
|
||||
ASSERT_NO_THROW(d2_mgr_.runReadyIO());
|
||||
}
|
||||
|
||||
/// @brief Utility function that creates a host reservation (duid)
|
||||
///
|
||||
/// @param add_to_host_mgr true if the reservation should be added
|
||||
/// @param type specifies reservation type (NA or PD)
|
||||
/// @param addr specifies reserved address
|
||||
/// @param hostname specifies hostname to be used in reservation
|
||||
/// @return created Host object.
|
||||
HostPtr
|
||||
createHost6(bool add_to_host_mgr, IPv6Resrv::Type type,
|
||||
const asiolink::IOAddress& addr, const std::string& hostname) {
|
||||
HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
|
||||
Host::IDENT_DUID, SubnetID(0), subnet_->getID(),
|
||||
asiolink::IOAddress("0.0.0.0"),
|
||||
hostname));
|
||||
|
||||
// Prefix length doesn't matter here, let's assume address is /128 and
|
||||
// prefix is /64
|
||||
IPv6Resrv resv(type, addr, type == IPv6Resrv::TYPE_NA? 128 : 64);
|
||||
host->addReservation(resv);
|
||||
|
||||
if (add_to_host_mgr) {
|
||||
|
||||
// Let's add the host.
|
||||
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
|
||||
|
||||
// We also need to add existing subnet
|
||||
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet_);
|
||||
|
||||
// Commit this configuration.
|
||||
CfgMgr::instance().commit();
|
||||
}
|
||||
return (host);
|
||||
}
|
||||
|
||||
// Holds a lease used by a test.
|
||||
Lease6Ptr lease_;
|
||||
|
||||
@@ -1088,15 +1054,114 @@ TEST_F(FqdnDhcpv6SrvTest, processClientDelegation) {
|
||||
0, 4000);
|
||||
}
|
||||
|
||||
TEST_F(FqdnDhcpv6SrvTest, hostnameReservation) {
|
||||
|
||||
// Verify that the host reservation is found and used. Lease host name and
|
||||
// FQDN should be the reservation hostname suffixed by the qualifying suffix.
|
||||
TEST_F(FqdnDhcpv6SrvTest, hostnameReservationSuffix) {
|
||||
// Create host reservation with a partial FQDN for hostname
|
||||
createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1:1::babe"),
|
||||
"alice.example.org.");
|
||||
"alice");
|
||||
|
||||
// Verify that the host reservation is found and lease name/FQDN are
|
||||
// formed properly from the host name and qualifying suffix.
|
||||
testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
|
||||
"alice.example.org.", 0, IOAddress("2001:db8:1:1::babe"));
|
||||
"alice.example.com.", 0, IOAddress("2001:db8:1:1::babe"));
|
||||
ASSERT_EQ(1, d2_mgr_.getQueueSize());
|
||||
}
|
||||
|
||||
// Verify that the host reservation is found and used, rather than dynamic
|
||||
// Address. Lease host name and FQDN should be the reservation hostname
|
||||
// without a qualifying suffix.
|
||||
TEST_F(FqdnDhcpv6SrvTest, hostnameReservationNoSuffix) {
|
||||
|
||||
string config_str = "{ "
|
||||
"\"interfaces-config\": {"
|
||||
" \"interfaces\": [ \"*\" ]"
|
||||
"},"
|
||||
"\"preferred-lifetime\": 3000,"
|
||||
"\"valid-lifetime\": 4000,"
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"subnet6\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
|
||||
" \"subnet\": \"2001:db8:1::/64\" } ], "
|
||||
" \"dhcp-ddns\" : {"
|
||||
" \"enable-updates\" : true, "
|
||||
" \"server-ip\" : \"::1\", "
|
||||
" \"server-port\" : 53001, "
|
||||
" \"sender-ip\" : \"::\", "
|
||||
" \"sender-port\" : 0, "
|
||||
" \"max-queue-size\" : 2048, "
|
||||
" \"ncr-protocol\" : \"UDP\", "
|
||||
" \"ncr-format\" : \"JSON\", "
|
||||
" \"always-include-fqdn\" : true, "
|
||||
" \"allow-client-update\" : true, "
|
||||
" \"override-no-update\" : true, "
|
||||
" \"override-client-update\" : true, "
|
||||
" \"replace-client-name\" : true, "
|
||||
" \"generated-prefix\" : \"test.prefix\", "
|
||||
" \"qualifying-suffix\" : \"\" },"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
configure(config_str);
|
||||
|
||||
ASSERT_NO_THROW(srv_->startD2());
|
||||
|
||||
ASSERT_TRUE(CfgMgr::instance().ddnsEnabled());
|
||||
|
||||
createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1:1::babe"),
|
||||
"alice.example.com");
|
||||
|
||||
testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
|
||||
"alice.example.com.", 0, IOAddress("2001:db8:1:1::babe"));
|
||||
ASSERT_EQ(1, d2_mgr_.getQueueSize());
|
||||
}
|
||||
|
||||
// Verify that the host reservation is found and used, rather than dynamic
|
||||
// Address. Lease host name and FQDN should be the reservation hostname
|
||||
// with the qualifying suffix even though updates are disabled.
|
||||
TEST_F(FqdnDhcpv6SrvTest, hostnameReservationDdnsDisabled) {
|
||||
|
||||
string config_str = "{ "
|
||||
"\"interfaces-config\": {"
|
||||
" \"interfaces\": [ \"*\" ]"
|
||||
"},"
|
||||
"\"preferred-lifetime\": 3000,"
|
||||
"\"valid-lifetime\": 4000,"
|
||||
"\"rebind-timer\": 2000, "
|
||||
"\"renew-timer\": 1000, "
|
||||
"\"subnet6\": [ { "
|
||||
" \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
|
||||
" \"subnet\": \"2001:db8:1::/64\" } ], "
|
||||
" \"dhcp-ddns\" : {"
|
||||
" \"enable-updates\" : false, "
|
||||
" \"server-ip\" : \"::1\", "
|
||||
" \"server-port\" : 53001, "
|
||||
" \"sender-ip\" : \"::\", "
|
||||
" \"sender-port\" : 0, "
|
||||
" \"max-queue-size\" : 2048, "
|
||||
" \"ncr-protocol\" : \"UDP\", "
|
||||
" \"ncr-format\" : \"JSON\", "
|
||||
" \"always-include-fqdn\" : true, "
|
||||
" \"allow-client-update\" : true, "
|
||||
" \"override-no-update\" : true, "
|
||||
" \"override-client-update\" : true, "
|
||||
" \"replace-client-name\" : true, "
|
||||
" \"generated-prefix\" : \"test.prefix\", "
|
||||
" \"qualifying-suffix\" : \"disabled.example.com\" },"
|
||||
"\"valid-lifetime\": 4000 }";
|
||||
|
||||
configure(config_str);
|
||||
|
||||
ASSERT_NO_THROW(srv_->startD2());
|
||||
|
||||
ASSERT_FALSE(CfgMgr::instance().ddnsEnabled());
|
||||
|
||||
createHost6(true, IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1:1::babe"),
|
||||
"alice");
|
||||
|
||||
testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
|
||||
"alice.disabled.example.com.", 0,
|
||||
IOAddress("2001:db8:1:1::babe"));
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
Reference in New Issue
Block a user