|
@@ -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_lease6_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,39 @@ 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
|
|
|
+ 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);
|
|
@@ -587,7 +626,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 +652,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 +693,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 +711,43 @@ 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
|
|
|
+ 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);
|