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_lease6_select_ = HooksManager::registerHook("lease4_select");
hook_index_lease6_select_ = HooksManager::registerHook("lease6_select");
}
};
// 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
}
// Register hook points
+ hook_index_lease4_select_ = Hooks.hook_index_lease4_select_;
hook_index_lease6_select_ = Hooks.hook_index_lease6_select_;
}
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
/// 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
} else {
if (existing->expired()) {
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
- fake_allocation));
+ callout_handle, fake_allocation));
}
}
// 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);
}
} else {
if (existing->expired()) {
return (reuseExpiredLease(existing, subnet, clientid, hwaddr,
- fake_allocation));
+ callout_handle, fake_allocation));
}
}
// 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());
}
const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
+ const isc::hooks::CalloutHandlePtr& callout_handle,
bool fake_allocation /*= false */ ) {
if (!expired->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
+ callout_handle->setArgument("subnet4", subnet);
+
+ // 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);
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_)) {
// 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());
}
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");
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
+ callout_handle->setArgument("subnet4", subnet);
+
+ // Is this solicit (fake = true) or request (fake = false)
+ callout_handle->setArgument("fake_allocation", fake_allocation);
+ 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("lease6", lease);
+ }
+
+
+
if (!fake_allocation) {
// That is a real (REQUEST) allocation
bool status = LeaseMgrFactory::instance().addLease(lease);
/// @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
///
/// @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
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
/// @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
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
/// @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
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.
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);
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);
Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
IOAddress("192.0.2.105"),
- false);
+ false, CalloutHandlePtr());
// Check that we got a lease
ASSERT_TRUE(lease);
// 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);
// 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);
// 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);
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);
// 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);
}
// 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());
// 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());
// 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);