BIND 10 trac2994, updated. 01bb436c45f4d92a3575ff4ad2f5c1cb348ce399 [2994] Minor dhcpv6 corrections:
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Jul 16 11:25:49 UTC 2013
The branch, trac2994 has been updated
via 01bb436c45f4d92a3575ff4ad2f5c1cb348ce399 (commit)
via a8a8909b511278b2abe1679a3c801bd1fd1ece74 (commit)
via 5b10e071de6d724d42e2f6eba4cc78bb7fbacd23 (commit)
from 1626b91e6d458b0dfe8fb71434b52273edaeb795 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 01bb436c45f4d92a3575ff4ad2f5c1cb348ce399
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Jul 16 13:25:31 2013 +0200
[2994] Minor dhcpv6 corrections:
- not used function removed
- DHCP6_HOOK_PACKET_RCVD_SKIP message typo fixed
commit a8a8909b511278b2abe1679a3c801bd1fd1ece74
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Jul 16 13:24:44 2013 +0200
[2994] Outstanding tests for lease4_select implemented.
commit 5b10e071de6d724d42e2f6eba4cc78bb7fbacd23
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Jul 16 11:45:47 2013 +0200
[2994] lease4_select hook implemented.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp6/dhcp6_messages.mes | 2 +-
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 21 --
src/lib/dhcpsrv/alloc_engine.cc | 110 +++++++++--
src/lib/dhcpsrv/alloc_engine.h | 16 +-
src/lib/dhcpsrv/dhcpsrv_messages.mes | 10 +-
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc | 245 ++++++++++++++++++++++--
6 files changed, 353 insertions(+), 51 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes
index 95fb386..2f30c4c 100644
--- a/src/bin/dhcp6/dhcp6_messages.mes
+++ b/src/bin/dhcp6/dhcp6_messages.mes
@@ -66,7 +66,7 @@ is started. It indicates what database backend type is being to store
lease and other information.
% DHCP6_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped, because a callout set skip flag.
-This debug message is printed when a callout installed on pkt6_received
+This debug message is printed when a callout installed on pkt6_receive
hook point sets skip flag. For this particular hook point, the setting
of the flag by a callout instructs the server to drop the packet.
diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
index 7957ed4..d2cf177 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -34,7 +34,6 @@
#include <dhcpsrv/utils.h>
#include <util/buffer.h>
#include <util/range_utilities.h>
-
#include <hooks/server_hooks.h>
#include <hooks/hooks_manager.h>
@@ -1855,26 +1854,6 @@ TEST_F(Dhcpv6SrvTest, Hooks) {
EXPECT_TRUE(hook_index_pkt6_send > 0);
}
-// This function returns buffer for empty packet (just DHCPv6 header)
-Pkt6* captureEmpty() {
- Pkt6* pkt;
- uint8_t data[4];
- data[0] = 1; // type 1 = SOLICIT
- data[1] = 0xca; // trans-id = 0xcafe01
- data[2] = 0xfe;
- data[3] = 0x01;
-
- pkt = new Pkt6(data, sizeof(data));
- pkt->setRemotePort(546);
- pkt->setRemoteAddr(IOAddress("fe80::1"));
- pkt->setLocalPort(0);
- pkt->setLocalAddr(IOAddress("ff02::1:2"));
- pkt->setIndex(2);
- pkt->setIface("eth0");
-
- return (pkt);
-}
-
// This function returns buffer for very simple Solicit
Pkt6* captureSimpleSolicit() {
Pkt6* pkt;
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index e94201d..ced228a 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -29,11 +29,13 @@ using namespace isc::hooks;
namespace {
/// Structure that holds registered hook indexes
-struct Dhcp6Hooks {
+struct AllocEngineHooks {
+ int hook_index_lease4_select_; ///< index for "lease4_receive" hook point
int hook_index_lease6_select_; ///< index for "lease6_receive" hook point
/// Constructor that registers hook points for AllocationEngine
- Dhcp6Hooks() {
+ AllocEngineHooks() {
+ hook_index_lease4_select_ = HooksManager::registerHook("lease4_select");
hook_index_lease6_select_ = HooksManager::registerHook("lease6_select");
}
};
@@ -42,7 +44,7 @@ struct Dhcp6Hooks {
// will be instantiated (and the constructor run) when the module is loaded.
// As a result, the hook indexes will be defined before any method in this
// module is called.
-Dhcp6Hooks Hooks;
+AllocEngineHooks Hooks;
}; // anonymous namespace
@@ -187,6 +189,7 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
}
// Register hook points
+ hook_index_lease4_select_ = Hooks.hook_index_lease4_select_;
hook_index_lease6_select_ = Hooks.hook_index_lease6_select_;
}
@@ -312,7 +315,8 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const IOAddress& hint,
- bool fake_allocation /* = false */ ) {
+ bool fake_allocation,
+ const isc::hooks::CalloutHandlePtr& callout_handle) {
try {
// Allocator is always created in AllocEngine constructor and there is
@@ -365,7 +369,8 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
/// implemented
// The hint is valid and not currently used, let's create a lease for it
- Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint, fake_allocation);
+ Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint,
+ callout_handle, fake_allocation);
// It can happen that the lease allocation failed (we could have lost
// the race condition. That means that the hint is lo longer usable and
@@ -376,7 +381,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
} else {
if (existing->expired()) {
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
- fake_allocation));
+ callout_handle, fake_allocation));
}
}
@@ -410,7 +415,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
// there's no existing lease for selected candidate, so it is
// free. Let's allocate it.
Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, candidate,
- fake_allocation);
+ callout_handle, fake_allocation);
if (lease) {
return (lease);
}
@@ -421,7 +426,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
} else {
if (existing->expired()) {
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
- fake_allocation));
+ callout_handle, fake_allocation));
}
}
@@ -515,7 +520,7 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
// assigned, so the client will get NoAddrAvail as a result. The lease
// won't be inserted into the
if (callout_handle->getSkip()) {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP);
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_SELECT_SKIP);
return (Lease6Ptr());
}
@@ -541,6 +546,7 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation /*= false */ ) {
if (!expired->expired()) {
@@ -563,6 +569,44 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
/// @todo: log here that the lease was reused (there's ticket #2524 for
/// logging in libdhcpsrv)
+ // Let's execute all callouts registered for lease4_select
+ if (callout_handle &&
+ HooksManager::getHooksManager().calloutsPresent(hook_index_lease4_select_)) {
+
+ // Delete all previous arguments
+ callout_handle->deleteAllArguments();
+
+ // Pass necessary arguments
+
+ // Subnet from which we do the allocation (That's as far as we can go
+ // with using SubnetPtr to point to Subnet4 object. Users should not
+ // be confused with dynamic_pointer_casts. They should get a concrete
+ // pointer (Subnet4Ptr) pointing to a Subnet4 object.
+ Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(subnet);
+ callout_handle->setArgument("subnet4", subnet4);
+
+ // Is this solicit (fake = true) or request (fake = false)
+ callout_handle->setArgument("fake_allocation", fake_allocation);
+
+ // The lease that will be assigned to a client
+ callout_handle->setArgument("lease4", expired);
+
+ // Call the callouts
+ HooksManager::callCallouts(hook_index_lease6_select_, *callout_handle);
+
+ // Callouts decided to skip the action. This means that the lease is not
+ // assigned, so the client will get NoAddrAvail as a result. The lease
+ // won't be inserted into the
+ if (callout_handle->getSkip()) {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE4_SELECT_SKIP);
+ return (Lease4Ptr());
+ }
+
+ // Let's use whatever callout returned. Hopefully it is the same lease
+ // we handled to it.
+ callout_handle->getArgument("lease4", expired);
+ }
+
if (!fake_allocation) {
// for REQUEST we do update the lease
LeaseMgrFactory::instance().updateLease4(expired);
@@ -587,7 +631,7 @@ Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
subnet->getPreferred(), subnet->getValid(),
subnet->getT1(), subnet->getT2(), subnet->getID()));
- // Let's execute all callouts registered for lease6_ia_added
+ // Let's execute all callouts registered for lease6_select
if (callout_handle &&
HooksManager::getHooksManager().calloutsPresent(hook_index_lease6_select_)) {
@@ -613,7 +657,7 @@ Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
// assigned, so the client will get NoAddrAvail as a result. The lease
// won't be inserted into the
if (callout_handle->getSkip()) {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP);
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE6_SELECT_SKIP);
return (Lease6Ptr());
}
@@ -654,6 +698,7 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
const DuidPtr& clientid,
const HWAddrPtr& hwaddr,
const IOAddress& addr,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation /*= false */ ) {
if (!hwaddr) {
isc_throw(BadValue, "Can't create a lease with NULL HW address");
@@ -671,6 +716,49 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
subnet->getT1(), subnet->getT2(), now,
subnet->getID()));
+ // Let's execute all callouts registered for lease4_select
+ if (callout_handle &&
+ HooksManager::getHooksManager().calloutsPresent(hook_index_lease4_select_)) {
+
+ // Delete all previous arguments
+ callout_handle->deleteAllArguments();
+
+ // Clear skip flag if it was set in previous callouts
+ callout_handle->setSkip(false);
+
+ // Pass necessary arguments
+
+ // Subnet from which we do the allocation (That's as far as we can go
+ // with using SubnetPtr to point to Subnet4 object. Users should not
+ // be confused with dynamic_pointer_casts. They should get a concrete
+ // pointer (Subnet4Ptr) pointing to a Subnet4 object.
+ Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(subnet);
+ callout_handle->setArgument("subnet4", subnet4);
+
+ // Is this solicit (fake = true) or request (fake = false)
+ callout_handle->setArgument("fake_allocation", fake_allocation);
+
+ // Pass the intended lease as well
+ callout_handle->setArgument("lease4", lease);
+
+ // This is the first callout, so no need to clear any arguments
+ HooksManager::callCallouts(hook_index_lease4_select_, *callout_handle);
+
+ // Callouts decided to skip the action. This means that the lease is not
+ // assigned, so the client will get NoAddrAvail as a result. The lease
+ // won't be inserted into the
+ if (callout_handle->getSkip()) {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_HOOKS, DHCPSRV_HOOK_LEASE4_SELECT_SKIP);
+ return (Lease4Ptr());
+ }
+
+ // Let's use whatever callout returned. Hopefully it is the same lease
+ // we handled to it.
+ callout_handle->getArgument("lease4", lease);
+ }
+
+
+
if (!fake_allocation) {
// That is a real (REQUEST) allocation
bool status = LeaseMgrFactory::instance().addLease(lease);
diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h
index 11aee5b..639e333 100644
--- a/src/lib/dhcpsrv/alloc_engine.h
+++ b/src/lib/dhcpsrv/alloc_engine.h
@@ -194,13 +194,16 @@ protected:
/// @param hint a hint that the client provided
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
+ /// @param callout_handle a callout handle (used in hooks). A lease callouts
+ /// will be executed if this parameter is passed.
/// @return Allocated IPv4 lease (or NULL if allocation failed)
Lease4Ptr
allocateAddress4(const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const isc::asiolink::IOAddress& hint,
- bool fake_allocation);
+ bool fake_allocation,
+ const isc::hooks::CalloutHandlePtr& callout_handle);
/// @brief Renews a IPv4 lease
///
@@ -262,6 +265,8 @@ private:
/// @param clientid client identifier
/// @param hwaddr client's hardware address
/// @param addr an address that was selected and is confirmed to be available
+ /// @param callout_handle a callout handle (used in hooks). A lease callouts
+ /// will be executed if this parameter is passed.
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
/// @return allocated lease (or NULL in the unlikely case of the lease just
@@ -269,6 +274,7 @@ private:
Lease4Ptr createLease4(const SubnetPtr& subnet, const DuidPtr& clientid,
const HWAddrPtr& hwaddr,
const isc::asiolink::IOAddress& addr,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation = false);
/// @brief creates a lease and inserts it in LeaseMgr if necessary
@@ -302,6 +308,8 @@ private:
/// @param subnet subnet the lease is allocated from
/// @param clientid client identifier
/// @param hwaddr client's hardware address
+ /// @param callout_handle a callout handle (used in hooks). A lease callouts
+ /// will be executed if this parameter is passed.
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
/// @return refreshed lease
@@ -309,6 +317,7 @@ private:
Lease4Ptr reuseExpiredLease(Lease4Ptr& expired, const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation = false);
/// @brief Reuses expired IPv6 lease
@@ -338,8 +347,9 @@ private:
/// @brief number of attempts before we give up lease allocation (0=unlimited)
unsigned int attempts_;
- /// @brief hook name index (used in hooks callouts)
- int hook_index_lease6_select_;
+ // hook name indexes (used in hooks callouts)
+ int hook_index_lease4_select_; ///< index for lease4_select hook
+ int hook_index_lease6_select_; ///< index for lease6_select hook
};
}; // namespace isc::dhcp
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes
index cd69d8d..b2860de 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.mes
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes
@@ -121,8 +121,14 @@ the database access parameters are changed: in the latter case, the
server closes the currently open database, and opens a database using
the new parameters.
-% DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP Lease6 (non-temporary) creation was skipped, because of callout skip flag.
-This debug message is printed when a callout installed on lease6_assign
+% DHCPSRV_HOOK_LEASE4_SELECT_SKIP Lease4 creation was skipped, because of callout skip flag.
+This debug message is printed when a callout installed on lease4_select
+hook point sets a skip flag. It means that the server was told that no lease4
+should be assigned. The server will not put that lease in its database and the client
+will get a NAK packet.
+
+% DHCPSRV_HOOK_LEASE6_SELECT_SKIP Lease6 (non-temporary) creation was skipped, because of callout skip flag.
+This debug message is printed when a callout installed on lease6_select
hook point sets a skip flag. It means that the server was told that no lease6
should be assigned. The server will not put that lease in its database and the client
will get a NoAddrsAvail for that IA_NA option.
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
index 36f633b..5a9ce29 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
@@ -592,7 +592,8 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
- IOAddress("0.0.0.0"), false);
+ IOAddress("0.0.0.0"), false,
+ CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
@@ -615,7 +616,8 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
ASSERT_TRUE(engine);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
- IOAddress("0.0.0.0"), true);
+ IOAddress("0.0.0.0"), true,
+ CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
@@ -638,7 +640,7 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.105"),
- false);
+ false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
@@ -678,7 +680,7 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
// twice.
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.106"),
- false);
+ false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
@@ -712,7 +714,7 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
// with the normal allocation
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("10.1.1.1"),
- false);
+ false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
@@ -739,18 +741,19 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
// Allocations without subnet are not allowed
Lease4Ptr lease = engine->allocateAddress4(SubnetPtr(), clientid_, hwaddr_,
- IOAddress("0.0.0.0"), false);
+ IOAddress("0.0.0.0"), false,
+ CalloutHandlePtr());
EXPECT_FALSE(lease);
// Allocations without HW address are not allowed
lease = engine->allocateAddress4(subnet_, clientid_, HWAddrPtr(),
- IOAddress("0.0.0.0"), false);
+ IOAddress("0.0.0.0"), false, CalloutHandlePtr());
EXPECT_FALSE(lease);
// Allocations without client-id are allowed
clientid_ = ClientIdPtr();
lease = engine->allocateAddress4(subnet_, ClientIdPtr(), hwaddr_,
- IOAddress("0.0.0.0"), false);
+ IOAddress("0.0.0.0"), false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
@@ -854,7 +857,7 @@ TEST_F(AllocEngine4Test, smallPool4) {
cfg_mgr.addSubnet4(subnet_);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
- false);
+ false, CalloutHandlePtr());
// Check that we got that single lease
ASSERT_TRUE(lease);
@@ -902,7 +905,8 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
// else, so the allocation should fail
Lease4Ptr lease2 = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
- IOAddress("0.0.0.0"), false);
+ IOAddress("0.0.0.0"), false,
+ CalloutHandlePtr());
EXPECT_FALSE(lease2);
}
@@ -935,7 +939,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
// CASE 1: Asking for any address
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
- true);
+ true, CalloutHandlePtr());
// Check that we got that single lease
ASSERT_TRUE(lease);
EXPECT_EQ(addr.toText(), lease->addr_.toText());
@@ -945,7 +949,7 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
// CASE 2: Asking specifically for this address
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress(addr.toText()),
- true);
+ true, CalloutHandlePtr());
// Check that we got that single lease
ASSERT_TRUE(lease);
EXPECT_EQ(addr.toText(), lease->addr_.toText());
@@ -972,7 +976,8 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
// A client comes along, asking specifically for this address
lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
- IOAddress(addr.toText()), false);
+ IOAddress(addr.toText()), false,
+ CalloutHandlePtr());
// Check that he got that single lease
ASSERT_TRUE(lease);
@@ -986,6 +991,8 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
detailCompareLease(lease, from_mgr);
}
+/// @todo write renewLease6
+
// This test checks if a lease is really renewed when renewLease4 method is
// called
TEST_F(AllocEngine4Test, renewLease4) {
@@ -1240,4 +1247,216 @@ TEST_F(HookAllocEngine6Test, change_lease6_select) {
EXPECT_EQ(valid_override_, from_mgr->valid_lft_);
}
+
+/// @brief helper class used in Hooks testing in AllocEngine4
+///
+/// It features a couple of callout functions and buffers to store
+/// the data that is accessible via callouts.
+class HookAllocEngine4Test : public AllocEngine4Test {
+public:
+ HookAllocEngine4Test() {
+ resetCalloutBuffers();
+ }
+
+ virtual ~HookAllocEngine4Test() {
+ HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
+ "lease4_select");
+ }
+
+ /// @brief clears out buffers, so callouts can store received arguments
+ void resetCalloutBuffers() {
+ callback_name_ = string("");
+ callback_subnet4_.reset();
+ callback_fake_allocation_ = false;
+ callback_lease4_.reset();
+ callback_argument_names_.clear();
+ callback_addr_original_ = IOAddress("::");
+ callback_addr_updated_ = IOAddress("::");
+ }
+
+ /// callback that stores received callout name and received values
+ static int
+ lease4_select_callout(CalloutHandle& callout_handle) {
+
+ callback_name_ = string("lease4_select");
+
+ callout_handle.getArgument("subnet4", callback_subnet4_);
+ callout_handle.getArgument("fake_allocation", callback_fake_allocation_);
+ callout_handle.getArgument("lease4", callback_lease4_);
+
+ callback_addr_original_ = callback_lease4_->addr_;
+
+ callback_argument_names_ = callout_handle.getArgumentNames();
+ return (0);
+ }
+
+ /// callback that overrides the lease with different values
+ static int
+ lease4_select_different_callout(CalloutHandle& callout_handle) {
+
+ // Let's call the basic callout, so it can record all parameters
+ lease4_select_callout(callout_handle);
+
+ // Now we need to tweak the least a bit
+ Lease4Ptr lease;
+ callout_handle.getArgument("lease4", lease);
+ callback_addr_updated_ = addr_override_;
+ lease->addr_ = callback_addr_updated_;
+ lease->t1_ = t1_override_;
+ lease->t2_ = t2_override_;
+ lease->valid_lft_ = valid_override_;
+
+ return (0);
+ }
+
+ // Values to be used in callout to override lease4 content
+ static const IOAddress addr_override_;
+ static const uint32_t t1_override_;
+ static const uint32_t t2_override_;
+ static const uint32_t valid_override_;
+
+ // Callback will store original and overridden values here
+ static IOAddress callback_addr_original_;
+ static IOAddress callback_addr_updated_;
+
+ // Buffers (callback will store received values here)
+ static string callback_name_;
+ static Subnet4Ptr callback_subnet4_;
+ static Lease4Ptr callback_lease4_;
+ static bool callback_fake_allocation_;
+ static vector<string> callback_argument_names_;
+};
+
+// For some reason intialization within a class makes the linker confused.
+// linker complains about undefined references if they are defined within
+// the class declaration.
+const IOAddress HookAllocEngine4Test::addr_override_("192.0.3.1");
+const uint32_t HookAllocEngine4Test::t1_override_ = 4000;
+const uint32_t HookAllocEngine4Test::t2_override_ = 7000;
+const uint32_t HookAllocEngine4Test::valid_override_ = 9000;
+
+IOAddress HookAllocEngine4Test::callback_addr_original_("::");
+IOAddress HookAllocEngine4Test::callback_addr_updated_("::");
+
+string HookAllocEngine4Test::callback_name_;
+Subnet4Ptr HookAllocEngine4Test::callback_subnet4_;
+Lease4Ptr HookAllocEngine4Test::callback_lease4_;
+bool HookAllocEngine4Test::callback_fake_allocation_;
+vector<string> HookAllocEngine4Test::callback_argument_names_;
+
+// This test checks if the lease4_select callout is executed and expected
+// parameters as passed.
+TEST_F(HookAllocEngine4Test, lease4_select) {
+
+ // Note: The following order is working as expected:
+ // 1. create AllocEngine (that register hook points)
+ // 2. call loadLibraries()
+ //
+ // This order, however, causes segfault in HooksManager
+ // 1. call loadLibraries()
+ // 2. create AllocEngine (that register hook points)
+
+ // Create allocation engine (hook names are registered in its ctor)
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+ ASSERT_TRUE(engine);
+
+ // Initialize Hooks Manager
+ vector<string> libraries; // no libraries at this time
+ HooksManager::getHooksManager().loadLibraries(libraries);
+
+ // Install pkt4_receive_callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease4_select", lease4_select_callout));
+
+ CalloutHandlePtr callout_handle = HooksManager::getHooksManager().createCalloutHandle();
+
+ Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ IOAddress("0.0.0.0"),
+ false, callout_handle);
+ // Check that we got a lease
+ ASSERT_TRUE(lease);
+
+ // Do all checks on the lease
+ checkLease4(lease);
+
+ // Check that the lease is indeed in LeaseMgr
+ Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
+ ASSERT_TRUE(from_mgr);
+
+ // Check that callouts were indeed called
+ EXPECT_EQ("lease4_select", callback_name_);
+
+ // Now check that the lease in LeaseMgr has the same parameters
+ ASSERT_TRUE(callback_lease4_);
+ detailCompareLease(callback_lease4_, from_mgr);
+
+ ASSERT_TRUE(callback_subnet4_);
+ EXPECT_EQ(subnet_->toText(), callback_subnet4_->toText());
+
+ EXPECT_EQ(callback_fake_allocation_, false);
+
+ // Check if all expected parameters are reported. It's a bit tricky, because
+ // order may be different. If the test starts failing, because someone tweaked
+ // hooks engine, we'll have to implement proper vector matching (ignoring order)
+ vector<string> expected_argument_names;
+ expected_argument_names.push_back("fake_allocation");
+ expected_argument_names.push_back("lease4");
+ expected_argument_names.push_back("subnet4");
+ EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+}
+
+// This test checks if lease4_select callout is able to override the values
+// in a lease4.
+TEST_F(HookAllocEngine4Test, change_lease4_select) {
+
+ // Make sure that the overridden values are different than the ones from
+ // subnet originally used to create the lease
+ ASSERT_NE(t1_override_, subnet_->getT1());
+ ASSERT_NE(t2_override_, subnet_->getT2());
+ ASSERT_NE(valid_override_, subnet_->getValid());
+ ASSERT_FALSE(subnet_->inRange(addr_override_));
+
+ // Create allocation engine (hook names are registered in its ctor)
+ boost::scoped_ptr<AllocEngine> engine;
+ ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+ ASSERT_TRUE(engine);
+
+ // Initialize Hooks Manager
+ vector<string> libraries; // no libraries at this time
+ HooksManager::getHooksManager().loadLibraries(libraries);
+
+ // Install a callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease4_select", lease4_select_different_callout));
+
+ // Normally, dhcpv4_srv would passed the handle when calling allocateAddress4,
+ // but in tests we need to create it on our own.
+ CalloutHandlePtr callout_handle = HooksManager::getHooksManager().createCalloutHandle();
+
+ // Call allocateAddress4. Callouts should be triggered here.
+ Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
+ false, callout_handle);
+ // Check that we got a lease
+ ASSERT_TRUE(lease);
+
+ // See if the values overridden by callout are there
+ EXPECT_TRUE(lease->addr_.equals(addr_override_));
+ EXPECT_EQ(t1_override_, lease->t1_);
+ EXPECT_EQ(t2_override_, lease->t2_);
+ EXPECT_EQ(valid_override_, lease->valid_lft_);
+
+ // Now check if the lease is in the database
+ Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
+ ASSERT_TRUE(from_mgr);
+
+ // Check if values in the database are overridden
+ EXPECT_TRUE(from_mgr->addr_.equals(addr_override_));
+ EXPECT_EQ(t1_override_, from_mgr->t1_);
+ EXPECT_EQ(t2_override_, from_mgr->t2_);
+ EXPECT_EQ(valid_override_, from_mgr->valid_lft_);
+}
+
+
+
}; // End of anonymous namespace
More information about the bind10-changes
mailing list