|
@@ -399,11 +399,73 @@ public:
|
|
|
return (0);
|
|
|
}
|
|
|
|
|
|
+ /// test callback that stores received callout name and pkt6 value
|
|
|
+ /// @param callout_handle handle passed by the hooks framework
|
|
|
+ /// @return always 0
|
|
|
+ static int
|
|
|
+ lease6_renew_callout(CalloutHandle& callout_handle) {
|
|
|
+ callback_name_ = string("lease6_renew");
|
|
|
+
|
|
|
+ callout_handle.getArgument("query6", callback_pkt6_);
|
|
|
+ callout_handle.getArgument("lease6", callback_lease6_);
|
|
|
+ callout_handle.getArgument("ia_na", callback_ia_na_);
|
|
|
+
|
|
|
+ callback_argument_names_ = callout_handle.getArgumentNames();
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// The following values are used by the callout to override
|
|
|
+ /// renewed lease parameters
|
|
|
+ static const uint32_t override_iaid_;
|
|
|
+ static const uint32_t override_t1_;
|
|
|
+ static const uint32_t override_t2_;
|
|
|
+ static const uint32_t override_preferred_;
|
|
|
+ static const uint32_t override_valid_;
|
|
|
+
|
|
|
+ /// test callback that overrides received lease. It updates
|
|
|
+ /// T1, T2, preferred and valid lifetimes
|
|
|
+ /// @param callout_handle handle passed by the hooks framework
|
|
|
+ /// @return always 0
|
|
|
+ static int
|
|
|
+ lease6_renew_update_callout(CalloutHandle& callout_handle) {
|
|
|
+ callback_name_ = string("lease6_renew");
|
|
|
+
|
|
|
+ callout_handle.getArgument("query6", callback_pkt6_);
|
|
|
+ callout_handle.getArgument("lease6", callback_lease6_);
|
|
|
+ callout_handle.getArgument("ia_na", callback_ia_na_);
|
|
|
+
|
|
|
+ // Let's override some values in the lease
|
|
|
+ callback_lease6_->iaid_ = override_iaid_;
|
|
|
+ callback_lease6_->t1_ = override_t1_;
|
|
|
+ callback_lease6_->t2_ = override_t2_;
|
|
|
+ callback_lease6_->preferred_lft_ = override_preferred_;
|
|
|
+ callback_lease6_->valid_lft_ = override_valid_;
|
|
|
+
|
|
|
+ // Override the values to be sent to the client as well
|
|
|
+ callback_ia_na_->setIAID(override_iaid_);
|
|
|
+ callback_ia_na_->setT1(override_t1_);
|
|
|
+ callback_ia_na_->setT2(override_t2_);
|
|
|
+
|
|
|
+ callback_argument_names_ = callout_handle.getArgumentNames();
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ static int
|
|
|
+ lease6_renew_skip_callout(CalloutHandle& callout_handle) {
|
|
|
+ callback_name_ = string("lease6_renew");
|
|
|
+
|
|
|
+ callout_handle.setSkip(true);
|
|
|
+
|
|
|
+ return (0);
|
|
|
+ }
|
|
|
+
|
|
|
/// resets buffers used to store data received by callouts
|
|
|
void resetCalloutBuffers() {
|
|
|
callback_name_ = string("");
|
|
|
callback_pkt6_.reset();
|
|
|
callback_subnet6_.reset();
|
|
|
+ callback_lease6_.reset();
|
|
|
+ callback_ia_na_.reset();
|
|
|
callback_subnet6collection_ = NULL;
|
|
|
callback_argument_names_.clear();
|
|
|
}
|
|
@@ -419,6 +481,12 @@ public:
|
|
|
/// Pkt6 structure returned in the callout
|
|
|
static Pkt6Ptr callback_pkt6_;
|
|
|
|
|
|
+ /// Pointer to lease6
|
|
|
+ static Lease6Ptr callback_lease6_;
|
|
|
+
|
|
|
+ /// Pointer to IA_NA option being renewed
|
|
|
+ static boost::shared_ptr<Option6IA> callback_ia_na_;
|
|
|
+
|
|
|
/// Pointer to a subnet received by callout
|
|
|
static Subnet6Ptr callback_subnet6_;
|
|
|
|
|
@@ -429,6 +497,14 @@ public:
|
|
|
static vector<string> callback_argument_names_;
|
|
|
};
|
|
|
|
|
|
+// The following parameters are used by callouts to override
|
|
|
+// renewed lease parameters
|
|
|
+const uint32_t HooksDhcpv6SrvTest::override_iaid_ = 1000;
|
|
|
+const uint32_t HooksDhcpv6SrvTest::override_t1_ = 1001;
|
|
|
+const uint32_t HooksDhcpv6SrvTest::override_t2_ = 1002;
|
|
|
+const uint32_t HooksDhcpv6SrvTest::override_preferred_ = 1003;
|
|
|
+const uint32_t HooksDhcpv6SrvTest::override_valid_ = 1004;
|
|
|
+
|
|
|
// The following fields are used in testing pkt6_receive_callout.
|
|
|
// See fields description in the class for details
|
|
|
string HooksDhcpv6SrvTest::callback_name_;
|
|
@@ -436,7 +512,8 @@ Pkt6Ptr HooksDhcpv6SrvTest::callback_pkt6_;
|
|
|
Subnet6Ptr HooksDhcpv6SrvTest::callback_subnet6_;
|
|
|
const Subnet6Collection* HooksDhcpv6SrvTest::callback_subnet6collection_;
|
|
|
vector<string> HooksDhcpv6SrvTest::callback_argument_names_;
|
|
|
-
|
|
|
+Lease6Ptr HooksDhcpv6SrvTest::callback_lease6_;
|
|
|
+boost::shared_ptr<Option6IA> HooksDhcpv6SrvTest::callback_ia_na_;
|
|
|
|
|
|
// Checks if callouts installed on pkt6_receive are indeed called and the
|
|
|
// all necessary parameters are passed.
|
|
@@ -944,4 +1021,185 @@ TEST_F(HooksDhcpv6SrvTest, subnet_select_change) {
|
|
|
EXPECT_TRUE((*subnets)[1]->inPool(addr_opt->getAddress()));
|
|
|
}
|
|
|
|
|
|
+// This test verifies that incoming (positive) RENEW can be handled properly,
|
|
|
+// and the lease6_renew callouts are triggered.
|
|
|
+TEST_F(HooksDhcpv6SrvTest, basic_lease6_renew) {
|
|
|
+ NakedDhcpv6Srv srv(0);
|
|
|
+
|
|
|
+ // Install pkt6_receive_callout
|
|
|
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
|
|
+ "lease6_renew", lease6_renew_callout));
|
|
|
+
|
|
|
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
|
|
|
+ const uint32_t iaid = 234;
|
|
|
+
|
|
|
+ // Generate client-id also duid_
|
|
|
+ OptionPtr clientid = generateClientId();
|
|
|
+
|
|
|
+ // Check that the address we are about to use is indeed in pool
|
|
|
+ ASSERT_TRUE(subnet_->inPool(addr));
|
|
|
+
|
|
|
+ // 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(Lease6::LEASE_IA_NA, addr, duid_, iaid,
|
|
|
+ 501, 502, 503, 504, subnet_->getID(), 0));
|
|
|
+ lease->cltt_ = 1234;
|
|
|
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
|
|
+
|
|
|
+ // Check that the lease is really in the database
|
|
|
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
|
|
|
+ ASSERT_TRUE(l);
|
|
|
+
|
|
|
+ // Check that T1, T2, preferred, valid and cltt really set and not using
|
|
|
+ // previous (500, 501, etc.) values
|
|
|
+ EXPECT_NE(l->t1_, subnet_->getT1());
|
|
|
+ EXPECT_NE(l->t2_, subnet_->getT2());
|
|
|
+ EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
|
|
|
+ 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"));
|
|
|
+ boost::shared_ptr<Option6IA> ia = generateIA(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());
|
|
|
+
|
|
|
+ // Pass it to the server and hope for a REPLY
|
|
|
+ Pkt6Ptr reply = srv.processRenew(req);
|
|
|
+ ASSERT_TRUE(reply);
|
|
|
+
|
|
|
+ // Check that the callback called is indeed the one we installed
|
|
|
+ EXPECT_EQ("lease6_renew", callback_name_);
|
|
|
+
|
|
|
+ // Check if all expected parameters were really received
|
|
|
+ vector<string> expected_argument_names;
|
|
|
+ expected_argument_names.push_back("query6");
|
|
|
+ expected_argument_names.push_back("lease6");
|
|
|
+ expected_argument_names.push_back("ia_na");
|
|
|
+
|
|
|
+ sort(callback_argument_names_.begin(), callback_argument_names_.end());
|
|
|
+ sort(expected_argument_names.begin(), expected_argument_names.end());
|
|
|
+
|
|
|
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
|
|
|
+
|
|
|
+ // 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_opt = checkIA_NA(reply, 234, subnet_->getT1(),
|
|
|
+ subnet_->getT2());
|
|
|
+
|
|
|
+ ASSERT_TRUE(addr_opt);
|
|
|
+ // Check that the lease is really in the database
|
|
|
+ l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
|
|
|
+ ASSERT_TRUE(l);
|
|
|
+
|
|
|
+ // Check that the lease has been returned
|
|
|
+ ASSERT_TRUE(callback_lease6_);
|
|
|
+
|
|
|
+ // Check that the returned lease6 in callout is the same as the one in the
|
|
|
+ // database
|
|
|
+ EXPECT_TRUE(*callback_lease6_ == *l);
|
|
|
+}
|
|
|
+
|
|
|
+// This test verifies that incoming (positive) RENEW can be handled properly,
|
|
|
+// and the lease6_renew callouts are able to change the lease being updated.
|
|
|
+TEST_F(HooksDhcpv6SrvTest, leaseUpdate_lease6_renew) {
|
|
|
+ NakedDhcpv6Srv srv(0);
|
|
|
+
|
|
|
+ // Install pkt6_receive_callout
|
|
|
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
|
|
+ "lease6_renew", lease6_renew_update_callout));
|
|
|
+
|
|
|
+ const IOAddress addr("2001:db8:1:1::cafe:babe");
|
|
|
+ const uint32_t iaid = 234;
|
|
|
+
|
|
|
+ // Generate client-id also duid_
|
|
|
+ OptionPtr clientid = generateClientId();
|
|
|
+
|
|
|
+ // Check that the address we are about to use is indeed in pool
|
|
|
+ ASSERT_TRUE(subnet_->inPool(addr));
|
|
|
+
|
|
|
+ // 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(Lease6::LEASE_IA_NA, addr, duid_, iaid,
|
|
|
+ 501, 502, 503, 504, subnet_->getID(), 0));
|
|
|
+ lease->cltt_ = 1234;
|
|
|
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
|
|
+
|
|
|
+ // Check that the lease is really in the database
|
|
|
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
|
|
|
+ ASSERT_TRUE(l);
|
|
|
+
|
|
|
+ // Check that T1, T2, preferred, valid and cltt really set and not using
|
|
|
+ // previous (500, 501, etc.) values
|
|
|
+ EXPECT_NE(l->t1_, subnet_->getT1());
|
|
|
+ EXPECT_NE(l->t2_, subnet_->getT2());
|
|
|
+ EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
|
|
|
+ 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"));
|
|
|
+ boost::shared_ptr<Option6IA> ia = generateIA(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());
|
|
|
+
|
|
|
+ // Pass it to the server and hope for a REPLY
|
|
|
+ Pkt6Ptr reply = srv.processRenew(req);
|
|
|
+ ASSERT_TRUE(reply);
|
|
|
+
|
|
|
+ // 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_opt = checkIA_NA(reply, 1000, 1001, 1002);
|
|
|
+
|
|
|
+ ASSERT_TRUE(addr_opt);
|
|
|
+ // Check that the lease is really in the database
|
|
|
+ l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
|
|
|
+ ASSERT_TRUE(l);
|
|
|
+
|
|
|
+ // Check that we chose the distinct override values
|
|
|
+ ASSERT_NE(override_t1_, subnet_->getT1());
|
|
|
+ ASSERT_NE(override_t2_, subnet_->getT2());
|
|
|
+ ASSERT_NE(override_preferred_, subnet_->getPreferred());
|
|
|
+ EXPECT_NE(override_valid_, subnet_->getValid());
|
|
|
+
|
|
|
+ // Check that T1, T2, preferred, valid were overridden the the callout
|
|
|
+ EXPECT_EQ(override_t1_, l->t1_);
|
|
|
+ EXPECT_EQ(override_t2_, l->t2_);
|
|
|
+ EXPECT_EQ(override_preferred_, l->preferred_lft_);
|
|
|
+ EXPECT_EQ(override_valid_, l->valid_lft_);
|
|
|
+
|
|
|
+ // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
|
|
|
+ int32_t cltt = static_cast<int32_t>(l->cltt_);
|
|
|
+ int32_t expected = static_cast<int32_t>(time(NULL));
|
|
|
+ // equality or difference by 1 between cltt and expected is ok.
|
|
|
+ EXPECT_GE(1, abs(cltt - expected));
|
|
|
+
|
|
|
+ EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr_opt->getAddress()));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
} // end of anonymous namespace
|