Commit 361505f1 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3153] pdRenewReject test implemented.

parent 7f464b31
......@@ -685,8 +685,6 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
// - IA that includes IAPREFIX
TEST_F(Dhcpv6SrvTest, pdSolicitBasic) {
configurePdPool();
NakedDhcpv6Srv srv(0);
Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
......@@ -976,8 +974,6 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
// - IA that includes IAPREFIX
TEST_F(Dhcpv6SrvTest, pdRequestBasic) {
configurePdPool();
NakedDhcpv6Srv srv(0);
// Let's create a REQUEST
......@@ -1136,7 +1132,8 @@ TEST_F(Dhcpv6SrvTest, pdRenewBasic) {
"2001:db8:1:1::cafe:babe");
}
// This test verifies that incoming (invalid) RENEW can be handled properly.
// This test verifies that incoming (invalid) RENEW with an address
// can be handled properly.
//
// This test checks 3 scenarios:
// 1. there is no such lease at all
......@@ -1146,105 +1143,30 @@ TEST_F(Dhcpv6SrvTest, pdRenewBasic) {
// expected:
// - returned REPLY message has copy of client-id
// - returned REPLY message has server-id
// - returned REPLY message has IA that includes STATUS-CODE
// - returned REPLY message has IA_NA that includes STATUS-CODE
// - No lease in LeaseMgr
TEST_F(Dhcpv6SrvTest, RenewReject) {
NakedDhcpv6Srv srv(0);
const IOAddress addr("2001:db8:1:1::dead");
const uint32_t transid = 1234;
const uint32_t valid_iaid = 234;
const uint32_t bogus_iaid = 456;
// Quick sanity check that the address we're about to use is ok
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
// Check that the lease is NOT in the database
Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
addr);
ASSERT_FALSE(l);
// Let's create a RENEW
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, transid));
req->setRemoteAddr(IOAddress("fe80::abcd"));
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, bogus_iaid, 1500, 3000);
OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
ia->addOption(renewed_addr_opt);
req->addOption(ia);
req->addOption(clientid);
// Server-id is mandatory in RENEW
req->addOption(srv.getServerID());
// Case 1: No lease known to server
// Pass it to the server and hope for a REPLY
Pkt6Ptr reply = srv.processRenew(req);
// Check if we get response at all
checkResponse(reply, DHCPV6_REPLY, transid);
OptionPtr tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, STATUS_NoBinding);
// Check that there is no lease added
l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
ASSERT_FALSE(l);
// CASE 2: Lease is known and belongs to this client, but to a different IAID
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, valid_iaid,
501, 502, 503, 504, subnet_->getID(), 0));
lease->cltt_ = 123; // Let's use it as an indicator that the lease
// was NOT updated.
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
// Pass it to the server and hope for a REPLY
reply = srv.processRenew(req);
checkResponse(reply, DHCPV6_REPLY, transid);
tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, STATUS_NoBinding);
// There is a iaid mis-match, so server should respond that there is
// no such address to renew.
// CASE 3: Lease belongs to a client with different client-id
req->delOption(D6O_CLIENTID);
ia = boost::dynamic_pointer_cast<Option6IA>(req->getOption(D6O_IA_NA));
ia->setIAID(valid_iaid); // Now iaid in renew matches that in leasemgr
req->addOption(generateClientId(13)); // generate different DUID
// (with length 13)
reply = srv.processRenew(req);
checkResponse(reply, DHCPV6_REPLY, transid);
tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, STATUS_NoBinding);
lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
ASSERT_TRUE(lease);
// Verify that the lease was not updated.
EXPECT_EQ(123, lease->cltt_);
testRenewReject(Lease::TYPE_NA, IOAddress("2001:db8:1:1::dead"));
}
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
// This test verifies that incoming (invalid) RENEW with a prefix
// can be handled properly.
//
// This test checks 3 scenarios:
// 1. there is no such lease at all
// 2. there is such a lease, but it is assigned to a different IAID
// 3. there is such a lease, but it belongs to a different client
//
// expected:
// - returned REPLY message has copy of client-id
// - returned REPLY message has server-id
// - returned REPLY message has IA_PD that includes STATUS-CODE
// - No lease in LeaseMgr
TEST_F(Dhcpv6SrvTest, pdRenewReject) {
testRenewReject(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"));
}
// This test verifies that incoming (positive) RELEASE can be handled properly,
// that a REPLY is generated, that the response has status code and that the
// lease is indeed removed from the database.
......
......@@ -115,6 +115,37 @@ Dhcpv6SrvTest::checkPdLease(const DuidPtr& duid, const OptionPtr& ia_pd,
}
Pkt6Ptr
Dhcpv6SrvTest::createMessage(uint8_t message_type, Lease::Type lease_type,
const IOAddress& addr, const uint8_t prefix_len,
uint32_t iaid) {
// Let's create a RENEW
Pkt6Ptr msg = Pkt6Ptr(new Pkt6(message_type, 1234));
msg->setRemoteAddr(IOAddress("fe80::abcd"));
uint16_t code;
OptionPtr subopt;
switch (lease_type) {
case Lease::TYPE_NA:
code = D6O_IA_NA;
subopt.reset(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
break;
case Lease::TYPE_PD:
code = D6O_IA_PD;
subopt.reset(new Option6IAPrefix(D6O_IAPREFIX, addr, prefix_len,
300, 500));
default:
isc_throw(BadValue, "Invalid lease type specified");
}
boost::shared_ptr<Option6IA> ia = generateIA(code, iaid, 1500, 3000);
ia->addOption(subopt);
msg->addOption(ia);
return (msg);
}
void
Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr,
const std::string& renew_addr) {
......@@ -149,31 +180,9 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr
EXPECT_NE(l->valid_lft_, subnet_->getValid());
EXPECT_NE(l->cltt_, time(NULL));
// Let's create a RENEW
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
uint16_t code = D6O_IA_NA;
OptionPtr subopt;
switch (type) {
case Lease::TYPE_NA:
code = D6O_IA_NA;
subopt.reset(new Option6IAAddr(D6O_IAADDR, renew, 300, 500));
break;
case Lease::TYPE_PD:
code = D6O_IA_PD;
subopt.reset(new Option6IAPrefix(D6O_IAPREFIX, renew, 32u, 300, 500));
default:
isc_throw(BadValue, "Invalid lease type specified");
}
boost::shared_ptr<Option6IA> ia = generateIA(code, iaid, 1500, 3000);
ia->addOption(subopt);
req->addOption(ia);
Pkt6Ptr req = createMessage(DHCPV6_RENEW, type, IOAddress(renew_addr),
128, iaid);
req->addOption(clientid);
// Server-id is mandatory in RENEW
req->addOption(srv.getServerID());
// Pass it to the server and hope for a REPLY
......@@ -182,9 +191,6 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr
// Check if we get response at all
checkResponse(reply, DHCPV6_REPLY, 1234);
OptionPtr tmp = reply->getOption(code);
ASSERT_TRUE(tmp);
// Check DUIDs
checkServerId(reply, srv.getServerID());
checkClientId(reply, clientid);
......@@ -201,7 +207,7 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr
checkIAAddr(addr_opt, renew, Lease::TYPE_NA);
// Check that the lease is really in the database
l = checkLease(duid_, reply->getOption(code), addr_opt);
l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
ASSERT_TRUE(l);
break;
}
......@@ -218,7 +224,7 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr
EXPECT_EQ(pd_pool_->getLength(), prefix_opt->getLength());
// Check that the lease is really in the database
l = checkLease(duid_, reply->getOption(code), prefix_opt);
l = checkLease(duid_, reply->getOption(D6O_IA_PD), prefix_opt);
ASSERT_TRUE(l);
break;
}
......@@ -241,6 +247,111 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(renew_addr));
}
void
Dhcpv6SrvTest::testRenewReject(Lease::Type type, const IOAddress& addr) {
NakedDhcpv6Srv srv(0);
const uint32_t transid = 1234;
const uint32_t valid_iaid = 234;
const uint32_t bogus_iaid = 456;
uint32_t code;
uint8_t prefix_len;
if (type == Lease::TYPE_NA) {
code = D6O_IA_NA;
prefix_len = 128;
} else if (type == Lease::TYPE_PD) {
code = D6O_IA_PD;
prefix_len = pd_pool_->getLength();
} else {
isc_throw(BadValue, "Invalid lease type");
}
// Quick sanity check that the address we're about to use is ok
ASSERT_TRUE(subnet_->inPool(type, addr));
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
// Check that the lease is NOT in the database
Lease6Ptr l = LeaseMgrFactory::instance().getLease6(type, addr);
ASSERT_FALSE(l);
// Let's create a RENEW
Pkt6Ptr req = createMessage(DHCPV6_RENEW, type, IOAddress(addr), prefix_len,
bogus_iaid);
req->addOption(clientid);
req->addOption(srv.getServerID());
// Case 1: No lease known to server
// Pass it to the server and hope for a REPLY
Pkt6Ptr reply = srv.processRenew(req);
// Check if we get response at all
checkResponse(reply, DHCPV6_REPLY, transid);
OptionPtr tmp = reply->getOption(code);
ASSERT_TRUE(tmp);
// Check that IA_?? was returned and that there's an address included
boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, STATUS_NoBinding);
// Check that there is no lease added
l = LeaseMgrFactory::instance().getLease6(type, addr);
ASSERT_FALSE(l);
// CASE 2: Lease is known and belongs to this client, but to a different IAID
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
Lease6Ptr lease(new Lease6(type, addr, duid_, valid_iaid,
501, 502, 503, 504, subnet_->getID(),
prefix_len));
lease->cltt_ = 123; // Let's use it as an indicator that the lease
// was NOT updated.
ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
// Pass it to the server and hope for a REPLY
reply = srv.processRenew(req);
checkResponse(reply, DHCPV6_REPLY, transid);
tmp = reply->getOption(code);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, STATUS_NoBinding);
// There is a iaid mis-match, so server should respond that there is
// no such address to renew.
// CASE 3: Lease belongs to a client with different client-id
req->delOption(D6O_CLIENTID);
ia = boost::dynamic_pointer_cast<Option6IA>(req->getOption(code));
ia->setIAID(valid_iaid); // Now iaid in renew matches that in leasemgr
req->addOption(generateClientId(13)); // generate different DUID
// (with length 13)
reply = srv.processRenew(req);
checkResponse(reply, DHCPV6_REPLY, transid);
tmp = reply->getOption(code);
ASSERT_TRUE(tmp);
// Check that IA_NA was returned and that there's an address included
ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, STATUS_NoBinding);
lease = LeaseMgrFactory::instance().getLease6(type, addr);
ASSERT_TRUE(lease);
// Verify that the lease was not updated.
EXPECT_EQ(123, lease->cltt_);
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
}
// Generate IA_NA option with specified parameters
boost::shared_ptr<Option6IA>
NakedDhcpv6SrvTest::generateIA(uint16_t type, uint32_t iaid, uint32_t t1,
......
......@@ -325,9 +325,8 @@ public:
CfgMgr::instance().deleteSubnets6();
CfgMgr::instance().addSubnet6(subnet_);
}
void configurePdPool() {
// configure PD pool
pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:2::"), 64, 80));
subnet_->addPool(pd_pool_);
}
......@@ -387,9 +386,26 @@ public:
Lease6Ptr checkPdLease(const DuidPtr& duid, const OptionPtr& ia_pd,
boost::shared_ptr<Option6IAPrefix> prefix);
/// @brief Performs basic RENEW tests
/// @brief Creates a message with specified IA
///
/// An utility function that creates a message of specified type with
/// specified container (IA_NA or IA_PD) and an address or prefix
/// inside it.
///
/// @param message_type type of the message (e.g. DHCPV6_SOLICIT)
/// @param lease_type type of a lease (TYPE_NA or TYPE_PD)
/// @param addr address or prefix to use in IADDRESS or IAPREFIX options
/// @param prefix_len length of the prefix (used for prefixes only)
/// @param iaid IA identifier (used in IA_XX option)
/// @return created message
Pkt6Ptr
createMessage(uint8_t message_type, Lease::Type lease_type,
const IOAddress& addr, const uint8_t prefix_len,
uint32_t iaid);
/// @brief Performs basic (positive) RENEW test
///
/// See renewBasic and pdRenewBasic for detailed explanation.
/// See renewBasic and pdRenewBasic tests for detailed explanation.
/// In essence the test attempts to perform a successful RENEW scenario.
///
/// This method does not throw, but uses gtest macros to signify failures.
......@@ -401,6 +417,18 @@ public:
testRenewBasic(Lease::Type type, const std::string& existing_addr,
const std::string& renew_addr);
/// @brief Performs negative RENEW test
///
/// See renewReject and pdRenewReject tests for detailed explanation.
/// In essence the test attempts to perform a successful RENEW scenario.
///
/// This method does not throw, but uses gtest macros to signify failures.
///
/// @param type type (TYPE_NA or TYPE_PD)
/// @param addr address being sent in RENEW
void
testRenewReject(Lease::Type type, const IOAddress& addr);
~Dhcpv6SrvTest() {
CfgMgr::instance().deleteSubnets6();
};
......
Markdown is supported
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