mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[2995] 4 hook points implemented:
- pkt6_receive, subnet6_select, lease6_select, pkt6_send - framework updated - some unittests implemented
This commit is contained in:
@@ -63,6 +63,7 @@ b10_dhcp4_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
|
||||
b10_dhcp4_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||
b10_dhcp4_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
|
||||
b10_dhcp4_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
|
||||
b10_dhcp4_LDADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
|
||||
|
||||
b10_dhcp4dir = $(pkgdatadir)
|
||||
b10_dhcp4_DATA = dhcp4.spec
|
||||
|
@@ -71,6 +71,7 @@ dhcp4_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
|
||||
dhcp4_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||
dhcp4_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||
dhcp4_unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
||||
dhcp4_unittests_LDADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
@@ -65,6 +65,7 @@ b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
|
||||
b10_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||
b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||
b10_dhcp6_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
||||
b10_dhcp6_LDADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
|
||||
|
||||
b10_dhcp6dir = $(pkgdatadir)
|
||||
b10_dhcp6_DATA = dhcp6.spec
|
||||
|
@@ -38,6 +38,9 @@ const int DBG_DHCP6_COMMAND = DBGLVL_COMMAND;
|
||||
// Trace basic operations within the code.
|
||||
const int DBG_DHCP6_BASIC = DBGLVL_TRACE_BASIC;
|
||||
|
||||
// Trace hook related operations
|
||||
const int DBG_DHCP6_HOOKS = DBGLVL_TRACE_BASIC;
|
||||
|
||||
// Trace detailed operations, including errors raised when processing invalid
|
||||
// packets. (These are not logged at severities of WARN or higher for fear
|
||||
// that a set of deliberately invalid packets set to the server could overwhelm
|
||||
|
@@ -65,6 +65,24 @@ This informational message is printed every time the IPv6 DHCP server
|
||||
is started. It indicates what database backend type is being to store
|
||||
lease and other information.
|
||||
|
||||
% DHCP6_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped, because a callout set skip flag.
|
||||
This debug message is printed when a callout installed on pkt6_received
|
||||
hook point sets skip flag. This flag instructs the server to skip the next processing
|
||||
stage, which would be to handle the packet. This effectively means drop the packet.
|
||||
|
||||
% DHCP6_HOOK_PACKET_SEND_SKIP Prepared DHCPv6 response was not sent, because a callout set skip flag.
|
||||
This debug message is printed when a callout installed on pkt6_send
|
||||
hook point sets skip flag. This flag instructs the server to skip the next processing
|
||||
stage, which would be to send a response. This effectively means that the client will
|
||||
not get any response, even though the server processed client's request and acted on
|
||||
it (e.g. could possible allocate a lease).
|
||||
|
||||
% DHCP6_HOOK_SUBNET6_SELECT_SKIP No subnet was selected, because a callout set skip flag.
|
||||
This debug message is printed when a callout installed on subnet6_select
|
||||
hook point sets a skip flag. It means that the server was told that no subnet
|
||||
should be selected. This severely limits further processing - server will be only
|
||||
able to offer global options. No addresses or prefixes could be assigned.
|
||||
|
||||
% DHCP6_LEASE_ADVERT lease %1 advertised (client duid=%2, iaid=%3)
|
||||
This debug message indicates that the server successfully advertised
|
||||
a lease. It is up to the client to choose one server out of the
|
||||
|
@@ -37,6 +37,9 @@
|
||||
#include <util/io_utilities.h>
|
||||
#include <util/range_utilities.h>
|
||||
#include <util/encode/hex.h>
|
||||
#include <hooks/server_hooks.h>
|
||||
#include <hooks/hooks_manager.h>
|
||||
#include <hooks/callout_handle.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
@@ -50,6 +53,7 @@
|
||||
using namespace isc;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::hooks;
|
||||
using namespace isc::util;
|
||||
using namespace std;
|
||||
|
||||
@@ -67,7 +71,9 @@ namespace dhcp {
|
||||
static const char* SERVER_DUID_FILE = "b10-dhcp6-serverid";
|
||||
|
||||
Dhcpv6Srv::Dhcpv6Srv(uint16_t port)
|
||||
: alloc_engine_(), serverid_(), shutdown_(true) {
|
||||
:alloc_engine_(), serverid_(), shutdown_(true), hook_index_pkt6_receive_(100),
|
||||
hook_index_subnet6_select_(101), hook_index_pkt6_send_(102)
|
||||
{
|
||||
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_OPEN_SOCKET).arg(port);
|
||||
|
||||
@@ -106,6 +112,15 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port)
|
||||
// Instantiate allocation engine
|
||||
alloc_engine_.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100));
|
||||
|
||||
// Register hook points
|
||||
hook_index_pkt6_receive_ = ServerHooks::getServerHooks().registerHook("pkt6_receive");
|
||||
hook_index_subnet6_select_ = ServerHooks::getServerHooks().registerHook("subnet6_select");
|
||||
hook_index_pkt6_send_ = ServerHooks::getServerHooks().registerHook("pkt6_send");
|
||||
|
||||
/// @todo call loadLibraries() when handling configuration changes
|
||||
vector<string> libraries; // no libraries at this time
|
||||
HooksManager::getHooksManager().loadLibraries(libraries);
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR(dhcp6_logger, DHCP6_SRV_CONSTRUCT_ERROR).arg(e.what());
|
||||
return;
|
||||
@@ -126,6 +141,10 @@ void Dhcpv6Srv::shutdown() {
|
||||
shutdown_ = true;
|
||||
}
|
||||
|
||||
Pkt6Ptr Dhcpv6Srv::receivePacket(int timeout) {
|
||||
return (IfaceMgr::instance().receive6(timeout));
|
||||
}
|
||||
|
||||
bool Dhcpv6Srv::run() {
|
||||
while (!shutdown_) {
|
||||
/// @todo: calculate actual timeout to the next event (e.g. lease
|
||||
@@ -134,14 +153,15 @@ bool Dhcpv6Srv::run() {
|
||||
/// For now, we are just calling select for 1000 seconds. There
|
||||
/// were some issues reported on some systems when calling select()
|
||||
/// with too large values. Unfortunately, I don't recall the details.
|
||||
int timeout = 1000;
|
||||
//cppcheck-suppress variableScope This is temporary anyway
|
||||
const int timeout = 1000;
|
||||
|
||||
// client's message and server's response
|
||||
Pkt6Ptr query;
|
||||
Pkt6Ptr rsp;
|
||||
|
||||
try {
|
||||
query = IfaceMgr::instance().receive6(timeout);
|
||||
query = receivePacket(timeout);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR(dhcp6_logger, DHCP6_PACKET_RECEIVE_FAIL).arg(e.what());
|
||||
}
|
||||
@@ -159,6 +179,24 @@ bool Dhcpv6Srv::run() {
|
||||
.arg(query->getBuffer().getLength())
|
||||
.arg(query->toText());
|
||||
|
||||
// Let's execute all callouts registered for packet_received
|
||||
if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_receive_)) {
|
||||
CalloutHandlePtr callout_handle = getCalloutHandle(query);
|
||||
|
||||
// This is the first callout, so no need to clear any arguments
|
||||
callout_handle->setArgument("pkt6", query);
|
||||
HooksManager::getHooksManager().callCallouts(hook_index_pkt6_receive_,
|
||||
*callout_handle);
|
||||
|
||||
// Callouts decided to skip the next processing step. The next
|
||||
// processing step would to process the packet, so skip at this
|
||||
// stage means drop.
|
||||
if (callout_handle->getSkip()) {
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_RCVD_SKIP);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
switch (query->getType()) {
|
||||
case DHCPV6_SOLICIT:
|
||||
@@ -203,7 +241,7 @@ bool Dhcpv6Srv::run() {
|
||||
} catch (const RFCViolation& e) {
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_REQUIRED_OPTIONS_CHECK_FAIL)
|
||||
.arg(query->getName())
|
||||
.arg(query->getRemoteAddr())
|
||||
.arg(query->getRemoteAddr().toText())
|
||||
.arg(e.what());
|
||||
|
||||
} catch (const isc::Exception& e) {
|
||||
@@ -217,7 +255,7 @@ bool Dhcpv6Srv::run() {
|
||||
// packets.)
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_PACKET_PROCESS_FAIL)
|
||||
.arg(query->getName())
|
||||
.arg(query->getRemoteAddr())
|
||||
.arg(query->getRemoteAddr().toText())
|
||||
.arg(e.what());
|
||||
}
|
||||
|
||||
@@ -229,6 +267,32 @@ bool Dhcpv6Srv::run() {
|
||||
rsp->setIndex(query->getIndex());
|
||||
rsp->setIface(query->getIface());
|
||||
|
||||
// Execute all callouts registered for packet6_send
|
||||
if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_send_)) {
|
||||
boost::shared_ptr<CalloutHandle> callout_handle = getCalloutHandle(query);
|
||||
|
||||
// Delete all previous arguments
|
||||
callout_handle->deleteAllArguments();
|
||||
|
||||
// Clear skip flag if it was set in previous callouts
|
||||
callout_handle->setSkip(false);
|
||||
|
||||
// Set our response
|
||||
callout_handle->setArgument("pkt6", rsp);
|
||||
|
||||
// Call all installed callouts
|
||||
HooksManager::getHooksManager().callCallouts(hook_index_pkt6_send_,
|
||||
*callout_handle);
|
||||
|
||||
// Callouts decided to skip the next processing step. The next
|
||||
// processing step would to send the packet, so skip at this
|
||||
// stage means "drop response".
|
||||
if (callout_handle->getSkip()) {
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_SEND_SKIP);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA,
|
||||
DHCP6_RESPONSE_DATA)
|
||||
.arg(static_cast<int>(rsp->getType())).arg(rsp->toText());
|
||||
@@ -559,6 +623,29 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
|
||||
}
|
||||
}
|
||||
|
||||
// Let's execute all callouts registered for packet_received
|
||||
if (HooksManager::getHooksManager().calloutsPresent(hook_index_subnet6_select_)) {
|
||||
boost::shared_ptr<CalloutHandle> callout_handle = getCalloutHandle(question);
|
||||
|
||||
// This is the first callout, so no need to clear any arguments
|
||||
callout_handle->setArgument("pkt6", question);
|
||||
callout_handle->setArgument("subnet6", subnet);
|
||||
callout_handle->setArgument("subnet6collection", CfgMgr::instance().getSubnets6());
|
||||
HooksManager::getHooksManager().callCallouts(hook_index_subnet6_select_,
|
||||
*callout_handle);
|
||||
|
||||
// Callouts decided to skip this step. This means that no subnet will be
|
||||
// selected. Packet processing will continue, but it will be severly limited
|
||||
// (i.e. only global options will be assigned)
|
||||
if (callout_handle->getSkip()) {
|
||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_SUBNET6_SELECT_SKIP);
|
||||
return (Subnet6Ptr());
|
||||
}
|
||||
|
||||
// Use whatever subnet was specified by the callout
|
||||
callout_handle->getArgument("subnet6", subnet);
|
||||
}
|
||||
|
||||
return (subnet);
|
||||
}
|
||||
|
||||
@@ -618,7 +705,8 @@ Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
|
||||
switch (opt->second->getType()) {
|
||||
case D6O_IA_NA: {
|
||||
OptionPtr answer_opt = assignIA_NA(subnet, duid, question,
|
||||
boost::dynamic_pointer_cast<Option6IA>(opt->second));
|
||||
boost::dynamic_pointer_cast<Option6IA>(opt->second),
|
||||
question);
|
||||
if (answer_opt) {
|
||||
answer->addOption(answer_opt);
|
||||
}
|
||||
@@ -632,7 +720,7 @@ Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
|
||||
|
||||
OptionPtr
|
||||
Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
|
||||
Pkt6Ptr question, boost::shared_ptr<Option6IA> ia) {
|
||||
Pkt6Ptr question, boost::shared_ptr<Option6IA> ia, const Pkt6Ptr& query) {
|
||||
// If there is no subnet selected for handling this IA_NA, the only thing to do left is
|
||||
// to say that we are sorry, but the user won't get an address. As a convenience, we
|
||||
// use a different status text to indicate that (compare to the same status code,
|
||||
@@ -676,12 +764,15 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
|
||||
fake_allocation = true;
|
||||
}
|
||||
|
||||
CalloutHandlePtr callout_handle = getCalloutHandle(query);
|
||||
|
||||
// Use allocation engine to pick a lease for this client. Allocation engine
|
||||
// will try to honour the hint, but it is just a hint - some other address
|
||||
// may be used instead. If fake_allocation is set to false, the lease will
|
||||
// be inserted into the LeaseMgr as well.
|
||||
Lease6Ptr lease = alloc_engine_->allocateAddress6(subnet, duid, ia->getIAID(),
|
||||
hint, fake_allocation);
|
||||
hint, fake_allocation,
|
||||
callout_handle);
|
||||
|
||||
// Create IA_NA that we will put in the response.
|
||||
// Do not use OptionDefinition to create option's instance so
|
||||
@@ -1102,5 +1193,24 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
|
||||
return reply;
|
||||
}
|
||||
|
||||
isc::hooks::CalloutHandlePtr Dhcpv6Srv::getCalloutHandle(const Pkt6Ptr& pkt) {
|
||||
CalloutHandlePtr callout_handle;
|
||||
|
||||
static Pkt6Ptr old_pointer;
|
||||
|
||||
if (!callout_handle ||
|
||||
old_pointer != pkt) {
|
||||
// This is the first packet or a different packet than previously
|
||||
// passed to getCalloutHandle()
|
||||
|
||||
// Remember the pointer to this packet
|
||||
old_pointer = pkt;
|
||||
|
||||
callout_handle = HooksManager::getHooksManager().createCalloutHandle();
|
||||
}
|
||||
|
||||
return (callout_handle);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <dhcp/pkt6.h>
|
||||
#include <dhcpsrv/alloc_engine.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <hooks/hooks_manager.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
@@ -87,6 +88,20 @@ public:
|
||||
/// @brief Instructs the server to shut down.
|
||||
void shutdown();
|
||||
|
||||
/// @brief returns ServerHooks object
|
||||
/// @todo: remove this as soon as ServerHooks object is converted
|
||||
/// to a signleton.
|
||||
//static boost::shared_ptr<isc::util::ServerHooks> getServerHooks();
|
||||
|
||||
/// @brief returns Callout Manager object
|
||||
///
|
||||
/// This manager is used to manage callouts registered on various hook
|
||||
/// points. @todo exact access method for HooksManager manager will change
|
||||
/// when it will be converted to a singleton.
|
||||
///
|
||||
/// @return CalloutManager instance
|
||||
//static boost::shared_ptr<isc::util::HooksManager> getHooksManager();
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief verifies if specified packet meets RFC requirements
|
||||
@@ -189,7 +204,8 @@ protected:
|
||||
OptionPtr assignIA_NA(const isc::dhcp::Subnet6Ptr& subnet,
|
||||
const isc::dhcp::DuidPtr& duid,
|
||||
isc::dhcp::Pkt6Ptr question,
|
||||
boost::shared_ptr<Option6IA> ia);
|
||||
boost::shared_ptr<Option6IA> ia,
|
||||
const Pkt6Ptr& query);
|
||||
|
||||
/// @brief Renews specific IA_NA option
|
||||
///
|
||||
@@ -321,6 +337,13 @@ protected:
|
||||
/// @return string representation
|
||||
static std::string duidToString(const OptionPtr& opt);
|
||||
|
||||
|
||||
/// @brief dummy wrapper around IfaceMgr::receive6
|
||||
///
|
||||
/// This method is useful for testing purposes, where its replacement
|
||||
/// simulates reception of a packet. For that purpose it is protected.
|
||||
virtual Pkt6Ptr receivePacket(int timeout);
|
||||
|
||||
private:
|
||||
/// @brief Allocation Engine.
|
||||
/// Pointer to the allocation engine that we are currently using
|
||||
@@ -334,6 +357,17 @@ private:
|
||||
/// Indicates if shutdown is in progress. Setting it to true will
|
||||
/// initiate server shutdown procedure.
|
||||
volatile bool shutdown_;
|
||||
|
||||
isc::hooks::CalloutHandlePtr getCalloutHandle(const Pkt6Ptr& pkt);
|
||||
|
||||
void packetProcessStart(const Pkt6Ptr& pkt);
|
||||
|
||||
void packetProcessEnd(const Pkt6Ptr& pkt);
|
||||
|
||||
/// Indexes for registered hook points
|
||||
int hook_index_pkt6_receive_;
|
||||
int hook_index_subnet6_select_;
|
||||
int hook_index_pkt6_send_;
|
||||
};
|
||||
|
||||
}; // namespace isc::dhcp
|
||||
|
@@ -68,6 +68,7 @@ dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
|
||||
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
@@ -33,12 +33,16 @@
|
||||
#include <util/buffer.h>
|
||||
#include <util/range_utilities.h>
|
||||
|
||||
#include <hooks/server_hooks.h>
|
||||
#include <hooks/callout_manager.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
|
||||
using namespace isc;
|
||||
using namespace isc::asiolink;
|
||||
@@ -46,6 +50,7 @@ using namespace isc::config;
|
||||
using namespace isc::data;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::util;
|
||||
using namespace isc::hooks;
|
||||
using namespace std;
|
||||
|
||||
// namespace has to be named, because friends are defined in Dhcpv6Srv class
|
||||
@@ -61,6 +66,26 @@ public:
|
||||
LeaseMgrFactory::create(memfile);
|
||||
}
|
||||
|
||||
virtual Pkt6Ptr receivePacket(int /*timeout*/) {
|
||||
|
||||
// If there is anything prepared as fake incoming
|
||||
// traffic, use it
|
||||
if (!to_be_received_.empty()) {
|
||||
Pkt6Ptr pkt = to_be_received_.front();
|
||||
to_be_received_.pop_front();
|
||||
return (pkt);
|
||||
}
|
||||
|
||||
// If not, just trigger shutdown and
|
||||
// return immediately
|
||||
shutdown();
|
||||
return (Pkt6Ptr());
|
||||
}
|
||||
|
||||
void fakeReceive(const Pkt6Ptr& pkt) {
|
||||
to_be_received_.push_back(pkt);
|
||||
}
|
||||
|
||||
virtual ~NakedDhcpv6Srv() {
|
||||
// Close the lease database
|
||||
LeaseMgrFactory::destroy();
|
||||
@@ -75,6 +100,8 @@ public:
|
||||
using Dhcpv6Srv::sanityCheck;
|
||||
using Dhcpv6Srv::loadServerID;
|
||||
using Dhcpv6Srv::writeServerID;
|
||||
|
||||
list<Pkt6Ptr> to_be_received_;
|
||||
};
|
||||
|
||||
static const char* DUID_FILE = "server-id-test.txt";
|
||||
@@ -226,6 +253,9 @@ public:
|
||||
}
|
||||
|
||||
virtual ~NakedDhcpv6SrvTest() {
|
||||
// Remove all registered hook points
|
||||
ServerHooks::getServerHooks().reset();
|
||||
|
||||
// Let's clean up if there is such a file.
|
||||
unlink(DUID_FILE);
|
||||
};
|
||||
@@ -1756,6 +1786,85 @@ TEST_F(Dhcpv6SrvTest, ServerID) {
|
||||
EXPECT_EQ(duid1_text, text);
|
||||
}
|
||||
|
||||
// Checks if hooks are implemented properly.
|
||||
TEST_F(Dhcpv6SrvTest, Hooks) {
|
||||
NakedDhcpv6Srv srv(0);
|
||||
|
||||
// check if appropriate hooks are registered
|
||||
|
||||
// check if appropriate indexes are set
|
||||
int hook_index_pkt6_received = ServerHooks::getServerHooks().getIndex("pkt6_receive");
|
||||
int hook_index_select_subnet = ServerHooks::getServerHooks().getIndex("subnet6_select");
|
||||
int hook_index_pkt6_send = ServerHooks::getServerHooks().getIndex("pkt6_send");
|
||||
|
||||
EXPECT_TRUE(hook_index_pkt6_received > 0);
|
||||
EXPECT_TRUE(hook_index_select_subnet > 0);
|
||||
EXPECT_TRUE(hook_index_pkt6_send > 0);
|
||||
}
|
||||
|
||||
// This function returns buffer for empty packet (just DHCPv6 header)
|
||||
Pkt6* captureEmpty() {
|
||||
Pkt6* pkt;
|
||||
uint8_t data[4];
|
||||
data[0] = 1; // type 1 = SOLICIT
|
||||
data[1] = 0xca; // trans-id = 0xcafe01
|
||||
data[2] = 0xfe;
|
||||
data[3] = 0x01;
|
||||
|
||||
pkt = new Pkt6(data, sizeof(data));
|
||||
pkt->setRemotePort(546);
|
||||
pkt->setRemoteAddr(IOAddress("fe80::1"));
|
||||
pkt->setLocalPort(0);
|
||||
pkt->setLocalAddr(IOAddress("ff02::1:2"));
|
||||
pkt->setIndex(2);
|
||||
pkt->setIface("eth0");
|
||||
|
||||
return (pkt);
|
||||
}
|
||||
|
||||
string callback_name("");
|
||||
|
||||
Pkt6Ptr callback_packet;
|
||||
|
||||
int
|
||||
pkt6_receive_callout(CalloutHandle& callout_handle) {
|
||||
printf("pkt6_receive_callout called!");
|
||||
callback_name = string("pkt6_receive");
|
||||
|
||||
callout_handle.getArgument("pkt6", callback_packet);
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Checks if callouts installed on pkt6_received are indeed called
|
||||
// Note that the test name does not follow test naming convention,
|
||||
// but the proper hook name is "pkt6_receive".
|
||||
TEST_F(Dhcpv6SrvTest, Hook_pkt6_receive) {
|
||||
|
||||
// This calls Dhcpv6Srv::ctor, which registers hook names
|
||||
NakedDhcpv6Srv srv(0);
|
||||
|
||||
// Let's pretend there will be 3 libraries
|
||||
CalloutManager callout_mgr(3);
|
||||
|
||||
// Let's pretent we're the library 0
|
||||
EXPECT_NO_THROW(callout_mgr.setLibraryIndex(0));
|
||||
|
||||
EXPECT_NO_THROW( callout_mgr.registerCallout("pkt6_receive", pkt6_receive_callout) );
|
||||
|
||||
// Let's create a REQUEST
|
||||
Pkt6Ptr req = Pkt6Ptr(captureEmpty());
|
||||
|
||||
// Simulate that we have received that traffic
|
||||
srv.fakeReceive(req);
|
||||
|
||||
// Server will now process to run its normal loop, but instead of calling
|
||||
// IfaceMgr::receive6(), it will read all packets from the list set by
|
||||
// fakeReceive()
|
||||
// In particular, it should call registered pkt6_receive callback.
|
||||
srv.run();
|
||||
}
|
||||
|
||||
|
||||
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
|
||||
/// to call processX() methods.
|
||||
|
||||
|
@@ -16,11 +16,15 @@
|
||||
#include <dhcpsrv/dhcpsrv_log.h>
|
||||
#include <dhcpsrv/lease_mgr_factory.h>
|
||||
|
||||
#include <hooks/server_hooks.h>
|
||||
#include <hooks/hooks_manager.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::hooks;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
@@ -161,6 +165,9 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
|
||||
default:
|
||||
isc_throw(BadValue, "Invalid/unsupported allocation algorithm");
|
||||
}
|
||||
|
||||
// Register hook points
|
||||
hook_index_lease6_select_ = ServerHooks::getServerHooks().registerHook("lease6_select");
|
||||
}
|
||||
|
||||
Lease6Ptr
|
||||
@@ -168,7 +175,8 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
||||
const DuidPtr& duid,
|
||||
uint32_t iaid,
|
||||
const IOAddress& hint,
|
||||
bool fake_allocation /* = false */ ) {
|
||||
bool fake_allocation,
|
||||
const isc::hooks::CalloutHandlePtr& callout_handle) {
|
||||
|
||||
try {
|
||||
// That check is not necessary. We create allocator in AllocEngine
|
||||
@@ -201,7 +209,8 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
||||
/// implemented
|
||||
|
||||
// the hint is valid and not currently used, let's create a lease for it
|
||||
Lease6Ptr lease = createLease6(subnet, duid, iaid, hint, fake_allocation);
|
||||
Lease6Ptr lease = createLease6(subnet, duid, iaid, 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
|
||||
@@ -212,7 +221,7 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
||||
} else {
|
||||
if (existing->expired()) {
|
||||
return (reuseExpiredLease(existing, subnet, duid, iaid,
|
||||
fake_allocation));
|
||||
callout_handle, fake_allocation));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,7 +255,7 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
||||
// there's no existing lease for selected candidate, so it is
|
||||
// free. Let's allocate it.
|
||||
Lease6Ptr lease = createLease6(subnet, duid, iaid, candidate,
|
||||
fake_allocation);
|
||||
callout_handle, fake_allocation);
|
||||
if (lease) {
|
||||
return (lease);
|
||||
}
|
||||
@@ -257,7 +266,7 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
||||
} else {
|
||||
if (existing->expired()) {
|
||||
return (reuseExpiredLease(existing, subnet, duid, iaid,
|
||||
fake_allocation));
|
||||
callout_handle, fake_allocation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +447,7 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
|
||||
const Subnet6Ptr& subnet,
|
||||
const DuidPtr& duid,
|
||||
uint32_t iaid,
|
||||
const isc::hooks::CalloutHandlePtr& callout_handle,
|
||||
bool fake_allocation /*= false */ ) {
|
||||
|
||||
if (!expired->expired()) {
|
||||
@@ -461,6 +471,42 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
|
||||
/// @todo: log here that the lease was reused (there's ticket #2524 for
|
||||
/// logging in libdhcpsrv)
|
||||
|
||||
// Let's execute all callouts registered for lease6_ia_added
|
||||
if (callout_handle &&
|
||||
HooksManager::getHooksManager().calloutsPresent(hook_index_lease6_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("subnet6", subnet);
|
||||
|
||||
// Is this solicit (fake = true) or request (fake = false)
|
||||
callout_handle->setArgument("fake_allocation", fake_allocation);
|
||||
callout_handle->setArgument("lease6", expired);
|
||||
|
||||
// This is the first callout, so no need to clear any arguments
|
||||
HooksManager::getHooksManager().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_HOOKS, DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP);
|
||||
return (Lease6Ptr());
|
||||
}
|
||||
|
||||
// Let's use whatever callout returned. Hopefully it is the same lease
|
||||
// we handled to it.
|
||||
callout_handle->getArgument("lease6", expired);
|
||||
}
|
||||
|
||||
if (!fake_allocation) {
|
||||
// for REQUEST we do update the lease
|
||||
LeaseMgrFactory::instance().updateLease6(expired);
|
||||
@@ -517,12 +563,49 @@ Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
|
||||
const DuidPtr& duid,
|
||||
uint32_t iaid,
|
||||
const IOAddress& addr,
|
||||
const isc::hooks::CalloutHandlePtr& callout_handle,
|
||||
bool fake_allocation /*= false */ ) {
|
||||
|
||||
Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid, iaid,
|
||||
subnet->getPreferred(), subnet->getValid(),
|
||||
subnet->getT1(), subnet->getT2(), subnet->getID()));
|
||||
|
||||
// Let's execute all callouts registered for lease6_ia_added
|
||||
if (callout_handle &&
|
||||
HooksManager::getHooksManager().calloutsPresent(hook_index_lease6_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("subnet6", subnet);
|
||||
|
||||
// Is this solicit (fake = true) or request (fake = false)
|
||||
callout_handle->setArgument("fake_allocation", fake_allocation);
|
||||
callout_handle->setArgument("lease6", lease);
|
||||
|
||||
// This is the first callout, so no need to clear any arguments
|
||||
HooksManager::getHooksManager().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_HOOKS, DHCPSRV_HOOK_LEASE6_IA_ADD_SKIP);
|
||||
return (Lease6Ptr());
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <dhcp/hwaddr.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <dhcpsrv/lease_mgr.h>
|
||||
#include <hooks/callout_handle.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
@@ -235,13 +236,17 @@ 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 SOLICIT 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 IPv6 lease (or NULL if allocation failed)
|
||||
Lease6Ptr
|
||||
allocateAddress6(const Subnet6Ptr& subnet,
|
||||
const DuidPtr& duid,
|
||||
uint32_t iaid,
|
||||
const isc::asiolink::IOAddress& hint,
|
||||
bool fake_allocation);
|
||||
bool fake_allocation,
|
||||
const isc::hooks::CalloutHandlePtr& callout_handle);
|
||||
|
||||
/// @brief Destructor. Used during DHCPv6 service shutdown.
|
||||
virtual ~AllocEngine();
|
||||
@@ -276,12 +281,15 @@ private:
|
||||
/// @param duid client's DUID
|
||||
/// @param iaid IAID from the IA_NA container the client sent to us
|
||||
/// @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 SOLICIT that is not really allocated (true)
|
||||
/// @return allocated lease (or NULL in the unlikely case of the lease just
|
||||
/// becomed unavailable)
|
||||
Lease6Ptr createLease6(const Subnet6Ptr& subnet, const DuidPtr& duid,
|
||||
uint32_t iaid, const isc::asiolink::IOAddress& addr,
|
||||
const isc::hooks::CalloutHandlePtr& callout_handle,
|
||||
bool fake_allocation = false);
|
||||
|
||||
/// @brief Reuses expired IPv4 lease
|
||||
@@ -313,12 +321,15 @@ private:
|
||||
/// @param subnet subnet the lease is allocated from
|
||||
/// @param duid client's DUID
|
||||
/// @param iaid IAID from the IA_NA container the client sent to us
|
||||
/// @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 SOLICIT that is not really allocated (true)
|
||||
/// @return refreshed lease
|
||||
/// @throw BadValue if trying to recycle lease that is still valid
|
||||
Lease6Ptr reuseExpiredLease(Lease6Ptr& expired, const Subnet6Ptr& subnet,
|
||||
const DuidPtr& duid, uint32_t iaid,
|
||||
const isc::hooks::CalloutHandlePtr& callout_handle,
|
||||
bool fake_allocation = false);
|
||||
|
||||
/// @brief a pointer to currently used allocator
|
||||
@@ -326,6 +337,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_;
|
||||
};
|
||||
|
||||
}; // namespace isc::dhcp
|
||||
|
@@ -262,6 +262,11 @@ void CfgMgr::deleteSubnets6() {
|
||||
subnets6_.clear();
|
||||
}
|
||||
|
||||
const Subnet6Collection& CfgMgr::getSubnets6() {
|
||||
return (subnets6_);
|
||||
}
|
||||
|
||||
|
||||
std::string CfgMgr::getDataDir() {
|
||||
return (datadir_);
|
||||
}
|
||||
|
@@ -201,6 +201,15 @@ public:
|
||||
/// completely new?
|
||||
void deleteSubnets6();
|
||||
|
||||
|
||||
/// @brief returns const reference to all subnets6
|
||||
///
|
||||
/// This is used in a hook (subnet6_select), where the hook is able
|
||||
/// to choose a different subnet. Server code has to offer a list
|
||||
/// of possible choices (i.e. all subnets).
|
||||
/// @return const reference to Subnet6 collection
|
||||
const Subnet6Collection& getSubnets6();
|
||||
|
||||
/// @brief get IPv4 subnet by address
|
||||
///
|
||||
/// Finds a matching subnet, based on an address. This can be used
|
||||
|
@@ -50,6 +50,9 @@ const int DHCPSRV_DBG_TRACE_DETAIL = DBGLVL_TRACE_DETAIL;
|
||||
/// Record detailed (and verbose) data on the server.
|
||||
const int DHCPSRV_DBG_TRACE_DETAIL_DATA = DBGLVL_TRACE_DETAIL_DATA;
|
||||
|
||||
// Trace hook related operations
|
||||
const int DHCPSRV_HOOKS = DBGLVL_TRACE_BASIC;
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
|
@@ -121,6 +121,12 @@ 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_ia_assign
|
||||
hook point sets a skip flag. It means that the server was told that no lease6
|
||||
should be assigned. Server will not put that lease in its database and the client
|
||||
will get a NoAddrsAvail for that IA_NA option.
|
||||
|
||||
% DHCPSRV_INVALID_ACCESS invalid database access string: %1
|
||||
This is logged when an attempt has been made to parse a database access string
|
||||
and the attempt ended in error. The access string in question - which
|
||||
|
@@ -69,6 +69,7 @@ libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
|
||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
|
||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
|
||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
|
||||
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
|
||||
libdhcpsrv_unittests_LDADD += $(GTEST_LDADD)
|
||||
endif
|
||||
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#include <dhcpsrv/tests/test_utils.h>
|
||||
|
||||
#include <hooks/callout_handle.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -37,6 +39,7 @@
|
||||
using namespace std;
|
||||
using namespace isc;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::hooks;
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc::dhcp::test;
|
||||
|
||||
@@ -203,7 +206,7 @@ TEST_F(AllocEngine6Test, simpleAlloc6) {
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
|
||||
false);
|
||||
false, CalloutHandlePtr());
|
||||
|
||||
// Check that we got a lease
|
||||
ASSERT_TRUE(lease);
|
||||
@@ -226,7 +229,7 @@ TEST_F(AllocEngine6Test, fakeAlloc6) {
|
||||
ASSERT_TRUE(engine);
|
||||
|
||||
Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
|
||||
true);
|
||||
true, CalloutHandlePtr());
|
||||
|
||||
// Check that we got a lease
|
||||
ASSERT_TRUE(lease);
|
||||
@@ -248,7 +251,7 @@ TEST_F(AllocEngine6Test, allocWithValidHint6) {
|
||||
|
||||
Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
|
||||
IOAddress("2001:db8:1::15"),
|
||||
false);
|
||||
false, CalloutHandlePtr());
|
||||
|
||||
// Check that we got a lease
|
||||
ASSERT_TRUE(lease);
|
||||
@@ -286,7 +289,7 @@ TEST_F(AllocEngine6Test, allocWithUsedHint6) {
|
||||
// twice.
|
||||
Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
|
||||
IOAddress("2001:db8:1::1f"),
|
||||
false);
|
||||
false, CalloutHandlePtr());
|
||||
// Check that we got a lease
|
||||
ASSERT_TRUE(lease);
|
||||
|
||||
@@ -319,7 +322,7 @@ TEST_F(AllocEngine6Test, allocBogusHint6) {
|
||||
// with the normal allocation
|
||||
Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
|
||||
IOAddress("3000::abc"),
|
||||
false);
|
||||
false, CalloutHandlePtr());
|
||||
// Check that we got a lease
|
||||
ASSERT_TRUE(lease);
|
||||
|
||||
@@ -345,12 +348,12 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
|
||||
|
||||
// Allocations without subnet are not allowed
|
||||
Lease6Ptr lease = engine->allocateAddress6(Subnet6Ptr(), duid_, iaid_,
|
||||
IOAddress("::"), false);
|
||||
IOAddress("::"), false, CalloutHandlePtr());
|
||||
ASSERT_FALSE(lease);
|
||||
|
||||
// Allocations without DUID are not allowed either
|
||||
lease = engine->allocateAddress6(subnet_, DuidPtr(), iaid_,
|
||||
IOAddress("::"), false);
|
||||
IOAddress("::"), false, CalloutHandlePtr());
|
||||
ASSERT_FALSE(lease);
|
||||
}
|
||||
|
||||
@@ -439,7 +442,7 @@ TEST_F(AllocEngine6Test, smallPool6) {
|
||||
cfg_mgr.addSubnet6(subnet_);
|
||||
|
||||
Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
|
||||
false);
|
||||
false, CalloutHandlePtr());
|
||||
|
||||
// Check that we got that single lease
|
||||
ASSERT_TRUE(lease);
|
||||
@@ -485,7 +488,7 @@ TEST_F(AllocEngine6Test, outOfAddresses6) {
|
||||
// There is just a single address in the pool and allocated it to someone
|
||||
// else, so the allocation should fail
|
||||
Lease6Ptr lease2 = engine->allocateAddress6(subnet_, duid_, iaid_,
|
||||
IOAddress("::"), false);
|
||||
IOAddress("::"), false, CalloutHandlePtr());
|
||||
EXPECT_FALSE(lease2);
|
||||
}
|
||||
|
||||
@@ -519,7 +522,7 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
|
||||
|
||||
// CASE 1: Asking for any address
|
||||
lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
|
||||
true);
|
||||
true, CalloutHandlePtr());
|
||||
// Check that we got that single lease
|
||||
ASSERT_TRUE(lease);
|
||||
EXPECT_EQ(addr.toText(), lease->addr_.toText());
|
||||
@@ -529,7 +532,7 @@ TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
|
||||
|
||||
// CASE 2: Asking specifically for this address
|
||||
lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress(addr.toText()),
|
||||
true);
|
||||
true, CalloutHandlePtr());
|
||||
// Check that we got that single lease
|
||||
ASSERT_TRUE(lease);
|
||||
EXPECT_EQ(addr.toText(), lease->addr_.toText());
|
||||
@@ -563,7 +566,8 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
|
||||
|
||||
// A client comes along, asking specifically for this address
|
||||
lease = engine->allocateAddress6(subnet_, duid_, iaid_,
|
||||
IOAddress(addr.toText()), false);
|
||||
IOAddress(addr.toText()), false,
|
||||
CalloutHandlePtr());
|
||||
|
||||
// Check that he got that single lease
|
||||
ASSERT_TRUE(lease);
|
||||
|
@@ -34,6 +34,7 @@ libb10_hooks_la_SOURCES += hooks_log.cc hooks_log.h
|
||||
libb10_hooks_la_SOURCES += library_handle.cc library_handle.h
|
||||
libb10_hooks_la_SOURCES += library_manager.cc library_manager.h
|
||||
libb10_hooks_la_SOURCES += server_hooks.cc server_hooks.h
|
||||
libb10_hooks_la_SOURCES += hooks_manager.cc hooks_manager.h
|
||||
|
||||
nodist_libb10_hooks_la_SOURCES = hooks_messages.cc hooks_messages.h
|
||||
|
||||
|
@@ -353,6 +353,9 @@ private:
|
||||
bool skip_;
|
||||
};
|
||||
|
||||
/// a shared pointer to CalloutHandle object
|
||||
typedef boost::shared_ptr<CalloutHandle> CalloutHandlePtr;
|
||||
|
||||
} // namespace util
|
||||
} // namespace isc
|
||||
|
||||
|
Reference in New Issue
Block a user