|
@@ -356,6 +356,24 @@ public:
|
|
return pkt6_send_callout(callout_handle);
|
|
return pkt6_send_callout(callout_handle);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// @brief Test callback that stores reponse packet.
|
|
|
|
+ /// @param callout_handle handle passed by the hooks framework.
|
|
|
|
+ /// @return always 0
|
|
|
|
+ static int
|
|
|
|
+ buffer6_send_callout(CalloutHandle& callout_handle) {
|
|
|
|
+ callback_name_ = string("buffer6_send");
|
|
|
|
+
|
|
|
|
+ callback_argument_names_ = callout_handle.getArgumentNames();
|
|
|
|
+
|
|
|
|
+ callout_handle.getArgument("response6", callback_resp_pkt6_);
|
|
|
|
+
|
|
|
|
+ if (callback_resp_pkt6_) {
|
|
|
|
+ callback_resp_options_copy_ = callback_resp_pkt6_->isCopyRetrievedOptions();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return (0);
|
|
|
|
+ }
|
|
|
|
+
|
|
/// Test callback that stores received callout name and subnet6 values
|
|
/// Test callback that stores received callout name and subnet6 values
|
|
/// @param callout_handle handle passed by the hooks framework
|
|
/// @param callout_handle handle passed by the hooks framework
|
|
/// @return always 0
|
|
/// @return always 0
|
|
@@ -1113,6 +1131,46 @@ TEST_F(HooksDhcpv6SrvTest, skipPkt6Send) {
|
|
EXPECT_EQ(0, sent->getBuffer().getLength());
|
|
EXPECT_EQ(0, sent->getBuffer().getLength());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Checks if callouts installed on buffer6_send are indeed called and the
|
|
|
|
+// all necessary parameters are passed.
|
|
|
|
+TEST_F(HooksDhcpv6SrvTest, simpleBuffer6Send) {
|
|
|
|
+
|
|
|
|
+ // Install pkt6_receive_callout
|
|
|
|
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
|
|
|
+ "buffer6_send", buffer6_send_callout));
|
|
|
|
+
|
|
|
|
+ // Let's create a simple SOLICIT
|
|
|
|
+ Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
|
|
|
|
+
|
|
|
|
+ // Simulate that we have received that traffic
|
|
|
|
+ srv_->fakeReceive(sol);
|
|
|
|
+
|
|
|
|
+ // Server will now process to run its normal loop, but instead of calling
|
|
|
|
+ // IfaceMgr::receive6(), it will read all packets from the list set by
|
|
|
|
+ // fakeReceive()
|
|
|
|
+ // In particular, it should call registered pkt6_receive callback.
|
|
|
|
+ srv_->run();
|
|
|
|
+
|
|
|
|
+ // Check that the callback called is indeed the one we installed
|
|
|
|
+ EXPECT_EQ("buffer6_send", callback_name_);
|
|
|
|
+
|
|
|
|
+ // Check that there is one packet sent
|
|
|
|
+ ASSERT_EQ(1, srv_->fake_sent_.size());
|
|
|
|
+ Pkt6Ptr adv = srv_->fake_sent_.front();
|
|
|
|
+
|
|
|
|
+ // Check that pkt6 argument passing was successful and returned proper
|
|
|
|
+ // values
|
|
|
|
+ EXPECT_TRUE(callback_resp_pkt6_.get() == adv.get());
|
|
|
|
+
|
|
|
|
+ // Check that all expected parameters are there
|
|
|
|
+ vector<string> expected_argument_names;
|
|
|
|
+ expected_argument_names.push_back(string("response6"));
|
|
|
|
+ EXPECT_TRUE(expected_argument_names == callback_argument_names_);
|
|
|
|
+
|
|
|
|
+ // Pkt passed to a callout must be configured to copy retrieved options.
|
|
|
|
+ EXPECT_TRUE(callback_resp_options_copy_);
|
|
|
|
+}
|
|
|
|
+
|
|
// This test checks if subnet6_select callout is triggered and reports
|
|
// This test checks if subnet6_select callout is triggered and reports
|
|
// valid parameters
|
|
// valid parameters
|
|
TEST_F(HooksDhcpv6SrvTest, subnet6Select) {
|
|
TEST_F(HooksDhcpv6SrvTest, subnet6Select) {
|
|
@@ -1613,6 +1671,85 @@ TEST_F(HooksDhcpv6SrvTest, basicLease6Release) {
|
|
EXPECT_TRUE(callback_qry_options_copy_);
|
|
EXPECT_TRUE(callback_qry_options_copy_);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// This is a variant of the previous test that tests that callouts are
|
|
|
|
+// properly invoked for the prefix release case.
|
|
|
|
+TEST_F(HooksDhcpv6SrvTest, basicLease6ReleasePD) {
|
|
|
|
+ NakedDhcpv6Srv srv(0);
|
|
|
|
+
|
|
|
|
+ // Install pkt6_receive_callout
|
|
|
|
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
|
|
|
+ "lease6_release", lease6_release_callout));
|
|
|
|
+
|
|
|
|
+ const IOAddress prefix("2001:db8:1:2:1::");
|
|
|
|
+ const uint32_t iaid = 234;
|
|
|
|
+
|
|
|
|
+ // Generate client-id also duid_
|
|
|
|
+ OptionPtr clientid = generateClientId();
|
|
|
|
+
|
|
|
|
+ // Check that the prefix we are about to use is indeed in pool
|
|
|
|
+ ASSERT_TRUE(subnet_->inPool(Lease::TYPE_PD, prefix));
|
|
|
|
+
|
|
|
|
+ // 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_PD, prefix, duid_, iaid,
|
|
|
|
+ 501, 502, 503, 504, subnet_->getID(),
|
|
|
|
+ HWAddrPtr(), 80));
|
|
|
|
+ lease->cltt_ = 1234;
|
|
|
|
+ ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
|
|
|
|
+
|
|
|
|
+ // Check that the lease is really in the database
|
|
|
|
+ Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD,
|
|
|
|
+ prefix);
|
|
|
|
+ ASSERT_TRUE(l);
|
|
|
|
+
|
|
|
|
+ // Let's create a RELEASE
|
|
|
|
+ Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
|
|
|
|
+ req->setRemoteAddr(IOAddress("fe80::abcd"));
|
|
|
|
+ boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_PD, iaid, 1500, 3000);
|
|
|
|
+
|
|
|
|
+ OptionPtr released_addr_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix, 80,
|
|
|
|
+ 300, 500));
|
|
|
|
+ ia->addOption(released_addr_opt);
|
|
|
|
+ req->addOption(ia);
|
|
|
|
+ req->addOption(clientid);
|
|
|
|
+
|
|
|
|
+ // Server-id is mandatory in RELEASE
|
|
|
|
+ req->addOption(srv.getServerID());
|
|
|
|
+
|
|
|
|
+ // Pass it to the server and hope for a REPLY
|
|
|
|
+ Pkt6Ptr reply = srv.processRelease(req);
|
|
|
|
+
|
|
|
|
+ ASSERT_TRUE(reply);
|
|
|
|
+
|
|
|
|
+ // Check that the callback called is indeed the one we installed
|
|
|
|
+ EXPECT_EQ("lease6_release", callback_name_);
|
|
|
|
+
|
|
|
|
+ // Check that appropriate parameters are passed to the callouts
|
|
|
|
+ EXPECT_TRUE(callback_qry_pkt6_);
|
|
|
|
+ EXPECT_TRUE(callback_lease6_);
|
|
|
|
+
|
|
|
|
+ // 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");
|
|
|
|
+ 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 that the lease is really gone in the database
|
|
|
|
+ // get lease by address
|
|
|
|
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, prefix);
|
|
|
|
+ ASSERT_FALSE(l);
|
|
|
|
+
|
|
|
|
+ // Get lease by subnetid/duid/iaid combination
|
|
|
|
+ l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, *duid_, iaid,
|
|
|
|
+ subnet_->getID());
|
|
|
|
+ ASSERT_FALSE(l);
|
|
|
|
+
|
|
|
|
+ // Pkt passed to a callout must be configured to copy retrieved options.
|
|
|
|
+ EXPECT_TRUE(callback_qry_options_copy_);
|
|
|
|
+}
|
|
|
|
+
|
|
// This test verifies that incoming (positive) RELEASE can be handled properly,
|
|
// 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
|
|
// that a REPLY is generated, that the response has status code and that the
|
|
// lease is indeed removed from the database.
|
|
// lease is indeed removed from the database.
|