Commit 8afc4716 authored by Marcin Siodelski's avatar Marcin Siodelski

[5457] Created leases4_committed hook point.

parent d59f7e36
// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -24,7 +24,6 @@
#include <dhcp4/dhcp4_log.h>
#include <dhcp4/dhcp4_srv.h>
#include <dhcpsrv/addr_utilities.h>
#include <dhcpsrv/callout_handle_store.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/cfg_host_operations.h>
#include <dhcpsrv/cfg_iface.h>
......@@ -81,25 +80,27 @@ using namespace std;
/// Structure that holds registered hook indexes
struct Dhcp4Hooks {
int hook_index_buffer4_receive_; ///< index for "buffer4_receive" hook point
int hook_index_pkt4_receive_; ///< index for "pkt4_receive" hook point
int hook_index_subnet4_select_; ///< index for "subnet4_select" hook point
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
int hook_index_host4_identifier_;///< index for "host4_identifier" hook point
int hook_index_buffer4_receive_; ///< index for "buffer4_receive" hook point
int hook_index_pkt4_receive_; ///< index for "pkt4_receive" hook point
int hook_index_subnet4_select_; ///< index for "subnet4_select" hook point
int hook_index_leases4_committed_; ///< index for "leases4_committed" hook point
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
int hook_index_host4_identifier_; ///< index for "host4_identifier" hook point
/// Constructor that registers hook points for DHCPv4 engine
Dhcp4Hooks() {
hook_index_buffer4_receive_ = HooksManager::registerHook("buffer4_receive");
hook_index_pkt4_receive_ = HooksManager::registerHook("pkt4_receive");
hook_index_subnet4_select_ = HooksManager::registerHook("subnet4_select");
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");
hook_index_host4_identifier_ = HooksManager::registerHook("host4_identifier");
hook_index_buffer4_receive_ = HooksManager::registerHook("buffer4_receive");
hook_index_pkt4_receive_ = HooksManager::registerHook("pkt4_receive");
hook_index_subnet4_select_ = HooksManager::registerHook("subnet4_select");
hook_index_leases4_committed_ = HooksManager::registerHook("leases4_committed");
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");
hook_index_host4_identifier_ = HooksManager::registerHook("host4_identifier");
}
};
......@@ -1047,6 +1048,8 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
callout_handle->getArgument("query4", query);
}
AllocEngine::ClientContext4Ptr ctx;
try {
switch (query->getType()) {
case DHCPDISCOVER:
......@@ -1057,15 +1060,15 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
// Note that REQUEST is used for many things in DHCPv4: for
// requesting new leases, renewing existing ones and even
// for rebinding.
rsp = processRequest(query);
rsp = processRequest(query, ctx);
break;
case DHCPRELEASE:
processRelease(query);
processRelease(query, ctx);
break;
case DHCPDECLINE:
processDecline(query);
processDecline(query, ctx);
break;
case DHCPINFORM:
......@@ -1097,16 +1100,54 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
static_cast<int64_t>(1));
}
if (ctx && HooksManager::calloutsPresent(Hooks.hook_index_leases4_committed_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Delete all previous arguments
callout_handle->deleteAllArguments();
// Clear skip flag if it was set in previous callouts
callout_handle->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
// Also pass the corresponding query packet as argument
callout_handle->setArgument("query4", query);
Lease4CollectionPtr new_leases(new Lease4Collection());
if (ctx->new_lease_) {
new_leases->push_back(ctx->new_lease_);
}
callout_handle->setArgument("leases4", new_leases);
Lease4CollectionPtr deleted_leases(new Lease4Collection);
if (ctx->old_lease_) {
if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
deleted_leases->push_back(ctx->old_lease_);
}
}
callout_handle->setArgument("deleted_leases4", deleted_leases);
// Call all installed callouts
HooksManager::callCallouts(Hooks.hook_index_leases4_committed_,
*callout_handle);
}
if (!rsp) {
return;
}
leases4CommittedContinue(getCalloutHandle(query), query, rsp);
}
void
Dhcpv4Srv::leases4CommittedContinue(const CalloutHandlePtr& callout_handle,
Pkt4Ptr& query, Pkt4Ptr& rsp) {
// Specifies if server should do the packing
bool skip_pack = false;
// Execute all callouts registered for pkt4_send
if (HooksManager::calloutsPresent(Hooks.hook_index_pkt4_send_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Delete all previous arguments
callout_handle->deleteAllArguments();
......@@ -2394,7 +2435,7 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
}
Pkt4Ptr
Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
Dhcpv4Srv::processRequest(Pkt4Ptr& request, AllocEngine::ClientContext4Ptr& context) {
/// @todo Uncomment this (see ticket #3116)
/// sanityCheck(request, MANDATORY);
......@@ -2446,11 +2487,15 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
appendServerID(ex);
// Return the pointer to the context, which will be required by the
// leases4_comitted callouts.
context = ex.getContext();
return (ex.getResponse());
}
void
Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
Dhcpv4Srv::processRelease(Pkt4Ptr& release, AllocEngine::ClientContext4Ptr& context) {
/// @todo Uncomment this (see ticket #3116)
/// sanityCheck(release, MANDATORY);
......@@ -2529,6 +2574,10 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
bool success = LeaseMgrFactory::instance().deleteLease(lease->addr_);
if (success) {
context.reset(new AllocEngine::ClientContext4());
context->old_lease_ = lease;
// Release successful
LOG_INFO(lease4_logger, DHCP4_RELEASE)
.arg(release->getLabel())
......@@ -2558,7 +2607,7 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
}
void
Dhcpv4Srv::processDecline(Pkt4Ptr& decline) {
Dhcpv4Srv::processDecline(Pkt4Ptr& decline, AllocEngine::ClientContext4Ptr& context) {
// Server-id is mandatory in DHCPDECLINE (see table 5, RFC2131)
/// @todo Uncomment this (see ticket #3116)
......@@ -2628,11 +2677,12 @@ Dhcpv4Srv::processDecline(Pkt4Ptr& decline) {
// Ok, all is good. The client is reporting its own address. Let's
// process it.
declineLease(lease, decline);
declineLease(lease, decline, context);
}
void
Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline) {
Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline,
AllocEngine::ClientContext4Ptr& context) {
// 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
......@@ -2696,6 +2746,9 @@ Dhcpv4Srv::declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline) {
LeaseMgrFactory::instance().updateLease4(lease);
context.reset(new AllocEngine::ClientContext4());
context->new_lease_ = lease;
LOG_INFO(lease4_logger, DHCP4_DECLINE_LEASE).arg(lease->addr_.toText())
.arg(decline->getLabel()).arg(lease->valid_lft_);
}
......
// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -17,6 +17,7 @@
#include <dhcp_ddns/ncr_msg.h>
#include <dhcpsrv/alloc_engine.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/callout_handle_store.h>
#include <dhcpsrv/d2_client_mgr.h>
#include <dhcpsrv/network_state.h>
#include <dhcpsrv/subnet.h>
......@@ -261,6 +262,16 @@ public:
/// @param rsp A pointer to the response
void processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp);
/// @brief Continues DHCPv4 packet processing after leases4_committed hook
/// point.
///
/// @param callout_handle Callout handle to be used.
/// @param query A pointer to the packet to be processed.
/// @param rsp A pointer to the response
void leases4CommittedContinue(const hooks::CalloutHandlePtr& callout_handle,
Pkt4Ptr& query, Pkt4Ptr& rsp);
/// @brief Instructs the server to shut down.
void shutdown();
......@@ -446,9 +457,11 @@ protected:
/// Returns ACK message, NAK message, or NULL
///
/// @param request a message received from client
/// @param [out] context pointer to the client context where allocated
/// and deleted leases are stored.
///
/// @return ACK or NAK message
Pkt4Ptr processRequest(Pkt4Ptr& request);
Pkt4Ptr processRequest(Pkt4Ptr& request, AllocEngine::ClientContext4Ptr& context);
/// @brief Processes incoming DHCPRELEASE messages.
///
......@@ -456,7 +469,9 @@ protected:
/// this function does not return anything.
///
/// @param release message received from client
void processRelease(Pkt4Ptr& release);
/// @param [out] context pointer to the client context where released
/// lease is stored.
void processRelease(Pkt4Ptr& release, AllocEngine::ClientContext4Ptr& context);
/// @brief Process incoming DHCPDECLINE messages.
///
......@@ -465,7 +480,9 @@ protected:
/// the client and if it does, calls @ref declineLease.
///
/// @param decline message received from client
void processDecline(Pkt4Ptr& decline);
/// @param [out] context pointer to the client context where declined
/// lease is stored.
void processDecline(Pkt4Ptr& decline, AllocEngine::ClientContext4Ptr& context);
/// @brief Processes incoming DHCPINFORM messages.
///
......@@ -650,7 +667,8 @@ private:
///
/// @param lease lease to be declined
/// @param decline client's message
void declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline);
void declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline,
AllocEngine::ClientContext4Ptr& context);
protected:
......
// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -17,6 +17,7 @@
#include <dhcp/pkt4.h>
#include <dhcp/pkt_filter.h>
#include <dhcp/pkt_filter_inet.h>
#include <dhcpsrv/alloc_engine.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/lease_mgr_factory.h>
......@@ -170,6 +171,31 @@ public:
virtual ~NakedDhcpv4Srv() {
}
/// @brief Runs processing DHCPREQUEST.
///
/// @param request a message received from client
/// @return DHCPACK or DHCPNAK message
Pkt4Ptr processRequest(Pkt4Ptr& request) {
AllocEngine::ClientContext4Ptr context(new AllocEngine::ClientContext4());
return (processRequest(request, context));
}
/// @brief Runs processing DHCPRELEASE.
///
/// @param release message received from client
void processRelease(Pkt4Ptr& release) {
AllocEngine::ClientContext4Ptr context(new AllocEngine::ClientContext4());
processRelease(release, context);
}
/// @brief Runs processing DHCPDECLINE
///
/// @param decline message received from client
void processDecline(Pkt4Ptr& decline) {
AllocEngine::ClientContext4Ptr context(new AllocEngine::ClientContext4());
processDecline(decline, context);
}
/// @brief Dummy server identifier option used by various tests.
OptionPtr server_id_;
......
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -18,6 +18,7 @@
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp/option.h>
#include <asiolink/io_address.h>
#include <dhcp4/tests/dhcp4_client.h>
#include <dhcp4/tests/marker_file.h>
#include <dhcp4/tests/test_libraries.h>
......@@ -36,13 +37,14 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
NakedDhcpv4Srv srv(0);
// check if appropriate hooks are registered
int hook_index_buffer4_receive = -1;
int hook_index_pkt4_receive = -1;
int hook_index_select_subnet = -1;
int hook_index_lease4_release = -1;
int hook_index_pkt4_send = -1;
int hook_index_buffer4_send = -1;
int hook_index_host4_identifier = -1;
int hook_index_buffer4_receive = -1;
int hook_index_pkt4_receive = -1;
int hook_index_select_subnet = -1;
int hook_index_leases4_committed = -1;
int hook_index_lease4_release = -1;
int hook_index_pkt4_send = -1;
int hook_index_buffer4_send = -1;
int hook_index_host4_identifier = -1;
// check if appropriate indexes are set
EXPECT_NO_THROW(hook_index_buffer4_receive = ServerHooks::getServerHooks()
......@@ -51,6 +53,8 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
.getIndex("pkt4_receive"));
EXPECT_NO_THROW(hook_index_select_subnet = ServerHooks::getServerHooks()
.getIndex("subnet4_select"));
EXPECT_NO_THROW(hook_index_leases4_committed = ServerHooks::getServerHooks()
.getIndex("leases4_committed"));
EXPECT_NO_THROW(hook_index_lease4_release = ServerHooks::getServerHooks()
.getIndex("lease4_release"));
EXPECT_NO_THROW(hook_index_pkt4_send = ServerHooks::getServerHooks()
......@@ -63,6 +67,7 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
EXPECT_TRUE(hook_index_buffer4_receive > 0);
EXPECT_TRUE(hook_index_pkt4_receive > 0);
EXPECT_TRUE(hook_index_select_subnet > 0);
EXPECT_TRUE(hook_index_leases4_committed > 0);
EXPECT_TRUE(hook_index_lease4_release > 0);
EXPECT_TRUE(hook_index_pkt4_send > 0);
EXPECT_TRUE(hook_index_buffer4_send > 0);
......@@ -621,6 +626,35 @@ public:
return (lease4_decline_callout(callout_handle));
}
/// Test callback that stores values passed to leases4_committed.
static int
leases4_committed_callout(CalloutHandle& callout_handle) {
callback_name_ = string("leases4_committed");
callout_handle.getArgument("query4", callback_qry_pkt4_);
Lease4CollectionPtr leases4;
callout_handle.getArgument("leases4", leases4);
if (leases4->size() > 0) {
callback_lease4_ = leases4->at(0);
}
Lease4CollectionPtr deleted_leases4;
callout_handle.getArgument("deleted_leases4", deleted_leases4);
if (deleted_leases4->size() > 0) {
callback_deleted_lease4_ = deleted_leases4->at(0);
}
callback_argument_names_ = callout_handle.getArgumentNames();
sort(callback_argument_names_.begin(), callback_argument_names_.end());
if (callback_qry_pkt4_) {
callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
}
return (0);
}
/// @brief Test host4_identifier callout by setting identifier to "foo"
///
/// @param callout_handle handle passed by the hooks framework
......@@ -683,6 +717,7 @@ public:
callback_qry_pkt4_.reset();
callback_qry_pkt4_.reset();
callback_lease4_.reset();
callback_deleted_lease4_.reset();
callback_hwaddr_.reset();
callback_clientid_.reset();
callback_subnet4_.reset();
......@@ -706,9 +741,12 @@ public:
/// Server/response Pkt4 structure returned in the callout
static Pkt4Ptr callback_resp_pkt4_;
/// Lease4 structure returned in the callout
/// Lease4 structure returned in the leases4_committed callout
static Lease4Ptr callback_lease4_;
/// Lease4 structure returned in the leases4_committed callout
static Lease4Ptr callback_deleted_lease4_;
/// Hardware address returned in the callout
static HWAddrPtr callback_hwaddr_;
......@@ -743,6 +781,7 @@ Subnet4Ptr HooksDhcpv4SrvTest::callback_subnet4_;
HWAddrPtr HooksDhcpv4SrvTest::callback_hwaddr_;
ClientIdPtr HooksDhcpv4SrvTest::callback_clientid_;
Lease4Ptr HooksDhcpv4SrvTest::callback_lease4_;
Lease4Ptr HooksDhcpv4SrvTest::callback_deleted_lease4_;
const Subnet4Collection* HooksDhcpv4SrvTest::callback_subnet4collection_;
vector<string> HooksDhcpv4SrvTest::callback_argument_names_;
bool HooksDhcpv4SrvTest::callback_qry_options_copy_;
......@@ -1526,29 +1565,46 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectChange) {
EXPECT_TRUE((*subnets)[1]->inPool(Lease::TYPE_V4, addr));
}
// Checks that subnet4_select is able to drop the packet.
TEST_F(HooksDhcpv4SrvTest, subnet4SelectDrop) {
// This test verifies that the leases4_committed hook point is not triggered
// for the DHCPDISCOVER.
TEST_F(HooksDhcpv4SrvTest, leases4CommittedDiscover) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
// Install subnet4_select_drop callout
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"subnet4_select", subnet4_select_drop_callout));
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
// Let's create a simple DISCOVER
Pkt4Ptr discover = generateSimpleDiscover();
// Simulate that we have received that traffic
srv_->fakeReceive(discover);
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
ASSERT_NO_THROW(client.doDiscover());
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
// In particular, it should call registered subnet4_select callback.
srv_->run();
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
// Make sure that the callout wasn't called.
EXPECT_TRUE(callback_name_.empty());
}
// This test verifies that the leases4_committed hook point is not triggered
// for the DHCPINFORM.
TEST_F(HooksDhcpv4SrvTest, leases4CommittedInform) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
Dhcp4Client client(Dhcp4Client::SELECTING);
client.useRelay();
ASSERT_NO_THROW(client.doInform());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
// Check that there is no packet sent
EXPECT_EQ(0, srv_->fake_sent_.size());
// Make sure that the callout wasn't called.
EXPECT_TRUE(callback_name_.empty());
}
// This test verifies that incoming (positive) REQUEST/Renewing can be handled
......@@ -1719,6 +1775,111 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSkip) {
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
}
// This test verifies that the callout installed on the leases4_committed hook
// point is executed as a result of DHCPREQUEST message sent to allocate new
// lease or renew an existing lease.
TEST_F(HooksDhcpv4SrvTest, leases4CommittedRequest) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
"leases4_committed", leases4_committed_callout));
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setIfaceName("eth1");
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases4_committed", callback_name_);
// Check if all expected parameters were really received
vector<string> expected_argument_names;
expected_argument_names.push_back("query4");
expected_argument_names.push_back("deleted_leases4");
expected_argument_names.push_back("leases4");
sort(expected_argument_names.begin(), expected_argument_names.end());
EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
// Newly allocated lease should be returned.
ASSERT_TRUE(callback_lease4_);
EXPECT_EQ("192.0.2.100", callback_lease4_->addr_.toText());
// Deleted lease must not be present, because it is a new allocation.
EXPECT_FALSE(callback_deleted_lease4_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
resetCalloutBuffers();
// Renew the lease and make sure that the callout has been executed.
client.setState(Dhcp4Client::RENEWING);
ASSERT_NO_THROW(client.doRequest());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases4_committed", callback_name_);
// Renewed lease should be returned.
ASSERT_TRUE(callback_lease4_);
EXPECT_EQ("192.0.2.100", callback_lease4_->addr_.toText());
// Deleted lease must not be present, because it is a new allocation.
EXPECT_FALSE(callback_deleted_lease4_);
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
resetCalloutBuffers();
// Let's try to renew again but force the client to request a different
// address.
client.ciaddr_ = IOAddress("192.0.2.101");
ASSERT_NO_THROW(client.doRequest());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases4_committed", callback_name_);
// New lease should be returned.
ASSERT_TRUE(callback_lease4_);
EXPECT_EQ("192.0.2.101", callback_lease4_->addr_.toText());
// The old lease should have been deleted.
ASSERT_TRUE(callback_deleted_lease4_);
EXPECT_EQ("192.0.2.100", callback_deleted_lease4_->addr_.toText());
// Pkt passed to a callout must be configured to copy retrieved options.
EXPECT_TRUE(callback_qry_options_copy_);
resetCalloutBuffers();
// Now request an address that can't be allocated. The client should receive
// the DHCPNAK.
client.ciaddr_ = IOAddress("10.0.0.1");
ASSERT_NO_THROW(client.doRequest());
// Make sure that we received a response
ASSERT_TRUE(client.getContext().response_);
// Check that the callback called is indeed the one we installed
EXPECT_EQ("leases4_committed", callback_name_);
EXPECT_FALSE(callback_lease4_);
EXPECT_FALSE(callback_deleted_lease4_);
}
// This test verifies that valid RELEASE triggers lease4_release callouts
TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSimple) {
IfaceMgrTestConfig test_config(true);
......@@ -1873,6 +2034,50 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
EXPECT_EQ(leases.size(), 1);
}
// This test verifies that the leases4_committed callout is executed
// with deleted leases as argument when DHCPRELEASE is processed.
TEST_F(HooksDhcpv4SrvTest, leases4CommittedRelease) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();