From: Tomek Mrugalski Date: Tue, 16 Jul 2013 09:45:47 +0000 (+0200) Subject: [2994] lease4_select hook implemented. X-Git-Tag: bind10-1.2.0beta1-release~333^2~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5b10e071de6d724d42e2f6eba4cc78bb7fbacd23;p=thirdparty%2Fkea.git [2994] lease4_select hook implemented. --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index e94201d6e0..56894c9a68 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_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); diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index 11aee5b3ea..639e333206 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 cd69d8d611..b2860deee2 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 36f633bf24..ef9b294fc8 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);