Commit c387c4ca authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[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)
parent d05f8676
......@@ -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");
// 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.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.org.");
"alice.example.com");
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
// 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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment