Server completed all the processing (e.g. may have assigned, updated
or released leases), but the response will not be send to the client.
+% DHCP4_HOOK_DECLINE_SKIP Decline4 hook callouts set status to DROP, ignoring packet.
+This message indicates that the server received DHCPDECLINE message, it was verified
+to be correct and matching server's lease information. The server called hooks
+for decline4 hook point and one of the callouts set next step status to DROP.
+The server will now abort processing of the packet as if it was never
+received. The lease will continue to be assigned to this client.
+
% DHCP4_HOOK_LEASE4_RELEASE_SKIP %1: lease was not released because a callout set the skip flag.
This debug message is printed when a callout installed on lease4_release
hook point set the skip flag. For this particular hook point, the
int hook_index_lease4_release_; ///< index for "lease4_release" hook point
int hook_index_pkt4_send_; ///< index for "pkt4_send" hook point
int hook_index_buffer4_send_; ///< index for "buffer4_send" hook point
+ int hook_index_lease4_decline_; ///< index for "lease4_decline" hook point
/// Constructor that registers hook points for DHCPv4 engine
Dhcp4Hooks() {
hook_index_pkt4_send_ = HooksManager::registerHook("pkt4_send");
hook_index_lease4_release_ = HooksManager::registerHook("lease4_release");
hook_index_buffer4_send_ = HooksManager::registerHook("buffer4_send");
+ hook_index_lease4_decline_ = HooksManager::registerHook("lease4_decline");
}
};
// Ok, all is good. The client is reporting its own address. Let's
// process it.
- declineLease(lease, decline->getLabel());
+ declineLease(lease, decline);
}
void
-Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const std::string& descr) {
+Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline) {
+
+ // Let's check if there are hooks installed for decline4 hook point.
+ // If they are, let's pass the lease and client's packet. If the hook
+ // sets status to drop, we reject this Decline.
+ if (HooksManager::calloutsPresent(Hooks.hook_index_lease4_decline_)) {
+ CalloutHandlePtr callout_handle = getCalloutHandle(decline);
+
+ // Delete previously set arguments
+ callout_handle->deleteAllArguments();
+
+ // Pass incoming Decline and the lease to be declined.
+ callout_handle->setArgument("lease4", lease);
+ callout_handle->setArgument("query4", decline);
+
+ // Call callouts
+ HooksManager::callCallouts(Hooks.hook_index_lease4_decline_,
+ *callout_handle);
+
+ // Check if callouts decided to drop the packet. If any of them did,
+ // we will drop the packet.
+ if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
+ LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_DECLINE_SKIP)
+ .arg(decline->getLabel()).arg(lease->addr_.toText());
+ return;
+ }
+ }
// Clean up DDNS, if needed.
if (CfgMgr::instance().ddnsEnabled()) {
LeaseMgrFactory::instance().updateLease4(lease);
LOG_INFO(dhcp4_logger, DHCP4_DECLINE_LEASE).arg(lease->addr_.toText())
- .arg(descr).arg(lease->valid_lft_);
+ .arg(decline->getLabel()).arg(lease->valid_lft_);
}
Pkt4Ptr
/// - disassociate the client information
/// - update lease in the database (switch to DECLINED state)
/// - increase necessary statistics
- /// - call appropriate hook (@todo)
+ /// - call lease4_decline hook
///
/// @param lease lease to be declined
- /// @param descr textual description of the client (will be used for logging)
+ /// @param decline client's message
void
- declineLease(const Lease4Ptr& lease, const std::string& descr);
+ declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline);
protected:
using namespace isc::stats;
namespace {
-
/// @brief Set of JSON configurations used throughout the Decline tests.
///
/// - Configuration 0:
"}"
};
-/// @brief Test fixture class for testing DHCPDECLINE message handling.
-///
-/// @todo This class is very similar to ReleaseTest. Maybe we could
-/// merge those two classes one day and use derived classes?
-class DeclineTest : public Dhcpv4SrvTest {
-public:
-
- enum ExpectedResult {
- SHOULD_PASS, // pass = accept decline, move lease to declined state.
- SHOULD_FAIL // fail = reject the decline
- };
-
- /// @brief Constructor.
- ///
- /// Sets up fake interfaces.
- DeclineTest()
- : Dhcpv4SrvTest(),
- iface_mgr_test_config_(true) {
- IfaceMgr::instance().openSockets4();
- }
-
- /// @brief Performs 4-way exchange to obtain new lease.
- ///
- /// This is used as a preparatory step for Decline operation.
- ///
- /// @param client Client to be used to obtain a lease.
- void acquireLease(Dhcp4Client& client);
-
- /// @brief Tests if the acquired lease is or is not declined.
- ///
- /// @param hw_address_1 HW Address to be used to acquire the lease.
- /// @param client_id_1 Client id to be used to acquire the lease.
- /// @param hw_address_2 HW Address to be used to decline the lease.
- /// @param client_id_2 Client id to be used to decline the lease.
- /// @param expected_result SHOULD_PASS if the lease is expected to
- /// be successfully declined, or SHOULD_FAIL if the lease is expected
- /// to not be declined.
- void acquireAndDecline(const std::string& hw_address_1,
- const std::string& client_id_1,
- const std::string& hw_address_2,
- const std::string& client_id_2,
- ExpectedResult expected_result);
-
- /// @brief Interface Manager's fake configuration control.
- IfaceMgrTestConfig iface_mgr_test_config_;
-
};
+namespace isc {
+namespace dhcp {
+namespace test {
+
void
-DeclineTest::acquireLease(Dhcp4Client& client) {
+Dhcpv4SrvTest::acquireLease(Dhcp4Client& client) {
// Perform 4-way exchange with the server but to not request any
// specific address in the DHCPDISCOVER message.
ASSERT_NO_THROW(client.doDORA());
}
void
-DeclineTest::acquireAndDecline(const std::string& hw_address_1,
- const std::string& client_id_1,
- const std::string& hw_address_2,
- const std::string& client_id_2,
- ExpectedResult expected_result) {
+Dhcpv4SrvTest::acquireAndDecline(const std::string& hw_address_1,
+ const std::string& client_id_1,
+ const std::string& hw_address_2,
+ const std::string& client_id_2,
+ ExpectedResult expected_result) {
// Set this global statistic explicitly to zero.
isc::stats::StatsMgr::instance().setValue("declined-addresses",
}
}
+}; // end of isc::dhcp::test namespace
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
+
+namespace {
+
+/// @brief Test fixture class for testing DHCPDECLINE message handling.
+///
+/// @todo This class is very similar to ReleaseTest. Maybe we could
+/// merge those two classes one day and use derived classes?
+class DeclineTest : public Dhcpv4SrvTest {
+public:
+
+ /// @brief Constructor.
+ ///
+ /// Sets up fake interfaces.
+ DeclineTest()
+ : Dhcpv4SrvTest(),
+ iface_mgr_test_config_(true) {
+ IfaceMgr::instance().openSockets4();
+ }
+
+ /// @brief Interface Manager's fake configuration control.
+ IfaceMgrTestConfig iface_mgr_test_config_;
+
+};
+
// This test checks that the client can acquire and decline the lease.
TEST_F(DeclineTest, declineNoIdentifierChange) {
acquireAndDecline("01:02:03:04:05:06", "12:14",
EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
}
-} // end of anonymous namespace
+}; // end of anonymous namespace
typedef boost::shared_ptr<PktFilterTest> PktFilterTestPtr;
+/// Forward definition for Dhcp4Client defined in dhcp4_client.h
+/// dhcp4_client.h includes dhcp_test_utils.h (this file), so to avoid
+/// circular dependencies, we need a forward class declaration.
+class Dhcp4Client;
+
/// @brief "Naked" DHCPv4 server, exposes internal fields
class NakedDhcpv4Srv: public Dhcpv4Srv {
public:
class Dhcpv4SrvTest : public ::testing::Test {
public:
+ enum ExpectedResult {
+ SHOULD_PASS, // pass = accept decline, move lease to declined state.
+ SHOULD_FAIL // fail = reject the decline
+ };
+
/// @brief Constructor
///
/// Initializes common objects used in many tests.
/// @brief Create @c Dhcpv4Exchange from client's query.
Dhcpv4Exchange createExchange(const Pkt4Ptr& query);
+ /// @brief Performs 4-way exchange to obtain new lease.
+ ///
+ /// This is used as a preparatory step for Decline operation.
+ ///
+ /// @param client Client to be used to obtain a lease.
+ void acquireLease(Dhcp4Client& client);
+
+ /// @brief Tests if the acquired lease is or is not declined.
+ ///
+ /// @param hw_address_1 HW Address to be used to acquire the lease.
+ /// @param client_id_1 Client id to be used to acquire the lease.
+ /// @param hw_address_2 HW Address to be used to decline the lease.
+ /// @param client_id_2 Client id to be used to decline the lease.
+ /// @param expected_result SHOULD_PASS if the lease is expected to
+ /// be successfully declined, or SHOULD_FAIL if the lease is expected
+ /// to not be declined.
+ void acquireAndDecline(const std::string& hw_address_1,
+ const std::string& client_id_1,
+ const std::string& hw_address_2,
+ const std::string& client_id_2,
+ ExpectedResult expected_result);
+
/// @brief This function cleans up after the test.
virtual void TearDown();
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("subnet4_select");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_renew");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_release");
+ HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_decline");
delete srv_;
}
return (0);
}
+ /// Test lease4_decline callback that stores received parameters.
+ /// @param callout_handle handle passed by the hooks framework
+ /// @return always 0
+ static int
+ lease4_decline_callout(CalloutHandle& callout_handle) {
+ callback_name_ = string("lease4_decline");
+ callout_handle.getArgument("query4", callback_pkt4_);
+ callout_handle.getArgument("lease4", callback_lease4_);
+
+ return (0);
+ }
/// resets buffers used to store data received by callouts
void resetCalloutBuffers() {
//EXPECT_EQ(leases.size(), 1);
}
+// Checks that decline4 hooks are triggered properly.
+TEST_F(HooksDhcpv4SrvTest, HooksDecline) {
+ IfaceMgrTestConfig test_config(true);
+ IfaceMgr::instance().openSockets4();
-
-// Checks if hooks are registered properly.
-TEST_F(Dhcpv4SrvTest, HooksDecline) {
-
+ // Install a callout
+ EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+ "lease4_decline", lease4_decline_callout));
+
+ acquireAndDecline("01:02:03:04:05:06", "12:14",
+ "01:02:03:04:05:06", "12:14",
+ SHOULD_PASS);
+
+ EXPECT_EQ("lease4_decline", callback_name_);
+
+ // Verifying DHCPDECLINE is a bit tricky, as it is created somewhere in
+ // acquireAndDecline. We'll just verify that it's really a DECLINE
+ // and that its address is equal to what we have in LeaseMgr.
+ ASSERT_TRUE(callback_pkt4_);
+ ASSERT_TRUE(callback_lease4_);
+
+ // Check that it's the proper packet that was reported.
+ EXPECT_EQ(DHCPDECLINE, callback_pkt4_->getType());
+
+ // Extract the address being declined.
+ OptionCustomPtr opt_declined_addr = boost::dynamic_pointer_cast<
+ OptionCustom>(callback_pkt4_->getOption(DHO_DHCP_REQUESTED_ADDRESS));
+ ASSERT_TRUE(opt_declined_addr);
+ IOAddress addr(opt_declined_addr->readAddress());
+
+ // And try to get a matching lease from the lease mgr
+ Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(addr);
+ ASSERT_TRUE(from_mgr);
+ EXPECT_EQ(Lease::STATE_DECLINED, from_mgr->state_);
+
+ // Let's now check that those 3 things (packet, lease returned and lease from
+ // the lease manager) all match.
+ EXPECT_EQ(addr, from_mgr->addr_);
+ EXPECT_EQ(addr, callback_lease4_->addr_);
}
-