Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
0f8f7995
Commit
0f8f7995
authored
Jul 15, 2013
by
Tomek Mrugalski
🛰
Browse files
[master] Merge branch 'trac2995' (4 initial hooks for DHCPv6)
parents
bb7465ef
d6de376f
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
doc/devel/mainpage.dox
View file @
0f8f7995
...
...
@@ -52,6 +52,7 @@
* - @subpage dhcpv6Session
* - @subpage dhcpv6ConfigParser
* - @subpage dhcpv6ConfigInherit
* - @subpage dhcpv6Hooks
* - @subpage libdhcp
* - @subpage libdhcpIntro
* - @subpage libdhcpRelay
...
...
src/bin/dhcp4/Makefile.am
View file @
0f8f7995
...
...
@@ -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
src/bin/dhcp4/tests/Makefile.am
View file @
0f8f7995
...
...
@@ -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)
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
0f8f7995
...
...
@@ -26,6 +26,7 @@
#include
<dhcp/pkt_filter_inet.h>
#include
<dhcp4/dhcp4_srv.h>
#include
<dhcp4/dhcp4_log.h>
#include
<hooks/server_hooks.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcpsrv/lease_mgr.h>
#include
<dhcpsrv/lease_mgr_factory.h>
...
...
@@ -155,6 +156,9 @@ public:
unlink
(
SRVID_FILE
);
}
virtual
~
Dhcpv4SrvTest
()
{
}
/// @brief Add 'Parameter Request List' option to the packet.
///
/// This function PRL option comprising the following option codes:
...
...
src/bin/dhcp6/Makefile.am
View file @
0f8f7995
...
...
@@ -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
src/bin/dhcp6/dhcp6_hooks.dox
0 → 100644
View file @
0f8f7995
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
/**
@page dhcpv6Hooks The Hooks API for the DHCPv6 Server
@section dhcpv6HooksIntroduction Introduction
BIND10 features an API (the "Hooks" API) that allows user-written code to
be integrated into BIND 10 and called at specific points in its processing.
An overview of the API and a tutorial for writing such code can be found in
the @ref hooksDevelopersGuide. Information for BIND 10 maintainers can be
found in the @ref hooksComponentDeveloperGuide.
This manual is more specialised and is aimed at developers of hook
code for the DHCPv6 server. It describes each hook point, what the callouts
attached to the hook are able to do, and the arguments passed to the
callouts. Each entry in this manual has the following information:
- Name of the hook point.
- Arguments for the callout. As well as the argument name and data type, the
information includes the direction, which can be one of:
- @b in - the server passes values to the callout but ignored any data
returned.
- @b out - the callout is expected to set this value.
- <b>in/out</b> - the server passes a value to the callout and uses whatever
value the callout sends back. Note that the callout may choose not to
do any modification, in which case the server will use whatever value
it sent to the callout.
- Description of the hook. This explains where in the processing the hook
is located, the possible actions a callout attached to this hook could take,
and a description of the data passed to the callouts.
- Skip flag action: the action taken by the server if a callout chooses to set
the "skip" flag.
@section dhcpv6HooksHookPoints Hooks in the DHCPv6 Server
The following list is ordered by appearance of specific hook points during
packet processing. Hook points that are not specific to packet processing
(e.g. lease expiration) will be added to the end of this list.
@subsection dhcpv6HooksPkt6Receive pkt6_receive
- @b Arguments:
- name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when an incoming DHCPv6
packet is received and its content is parsed. The sole argument -
query6 - contains a pointer to an isc::dhcp::Pkt6 object that contains
all information regarding incoming packet, including its source and
destination addresses, interface over which it was received, a list
of all options present within and relay information. All fields of
the Pkt6 object can be modified at this time, except data_. (data_
contains the incoming packet as raw buffer. By the time this hook is
reached, that information has already parsed and is available though
other fields in the Pkt6 object. For this reason, it doesn't make
sense to modify it.)
- <b>Skip flag action</b>: If any callout sets the skip flag, the server will
drop the packet and start processing the next one. The reason for the drop
will be logged if logging is set to the appropriate debug level.
@subsection dhcpv6HooksSubnet6Select subnet6_select
- @b Arguments:
- name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in/out</b>
- name: @b subnet6collection, type: const isc::dhcp::Subnet6Collection *, direction: <b>in</b>
- @b Description: this callout is executed when a subnet is being
selected for the incoming packet. All parameters, addresses and
prefixes will be assigned from that subnet. A callout can select a
different subnet if it wishes so, the list of all subnets currently
configured being provided as 'subnet6collection'. The list itself must
not be modified.
- <b>Skip flag action</b>: If any callout installed on 'subnet6_select'
sets the skip flag, the server will not select any subnet. Packet processing
will continue, but will be severely limited (i.e. only global options
will be assigned).
@subsection dhcpv6HooksLeaseSelect lease6_select
- @b Arguments:
- name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in</b>
- name: @b fake_allocation, type: bool, direction: <b>in</b>
- name: @b lease6, type: isc::dhcp::Lease6Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed after the server engine
has selected a lease for client's request but before the lease
has been inserted into the database. Any modifications made to the
isc::dhcp::Lease6 object will be stored in the lease's record in the
database. The callout should make sure that any modifications are
sanity checked as the server will use that data as is with no further
checking.\n\n The server processes lease requests for SOLICIT and
REQUEST in a very similar way. The only major difference is that
for SOLICIT the lease is just selected; it is not inserted into
the database. It is possible to distinguish between SOLICIT and
REQUEST by checking value of the fake_allocation flag: a value of true
means that the lease won't be inserted into the database (SOLICIT),
a value of false means that it will (REQUEST).
- <b>Skip flag action</b>: the "skip" flag is ignored by the server on this
hook.
@subsection dhcpv6HooksPkt6Send pkt6_send
- @b Arguments:
- name: @b response6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when server's response
is about to be send back to the client. The sole argument - response6 -
contains a pointer to an isc::dhcp::Pkt6 object that contains the
packet, with set source and destination addresses, interface over which
it will be send, list of all options and relay information. All fields
of the Pkt6 object can be modified at this time, except bufferOut_.
(This is scratch space used for constructing the packet after all
pkt6_send callouts are complete, so any changes to that field will
be overwritten.)
- <b>Skip flag action</b>: if any callout sets the skip flag, the server
will drop this response packet. However, the original request packet
from a client was processed, so server's state was most likely changed
(e.g. lease was allocated). Setting this flag merely stops the change
being communicated to the client.
*/
src/bin/dhcp6/dhcp6_log.h
View file @
0f8f7995
...
...
@@ -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
...
...
src/bin/dhcp6/dhcp6_messages.mes
View file @
0f8f7995
...
...
@@ -65,6 +65,25 @@ 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. For this particular hook point, the setting
of the flag by a callout instructs the server to 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. For this particular hook point, the setting
of the flag by a callout instructs the server to drop the packet. 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. possibly
allocated 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
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
0f8f7995
...
...
@@ -37,6 +37,8 @@
#include
<util/io_utilities.h>
#include
<util/range_utilities.h>
#include
<util/encode/hex.h>
#include
<hooks/hooks_manager.h>
#include
<hooks/callout_handle.h>
#include
<boost/foreach.hpp>
#include
<boost/tokenizer.hpp>
...
...
@@ -50,9 +52,34 @@
using
namespace
isc
;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
dhcp
;
using
namespace
isc
::
hooks
;
using
namespace
isc
::
util
;
using
namespace
std
;
namespace
{
/// Structure that holds registered hook indexes
struct
Dhcp6Hooks
{
int
hook_index_pkt6_receive_
;
///< index for "pkt6_receive" hook point
int
hook_index_subnet6_select_
;
///< index for "subnet6_select" hook point
int
hook_index_pkt6_send_
;
///< index for "pkt6_send" hook point
/// Constructor that registers hook points for DHCPv6 engine
Dhcp6Hooks
()
{
hook_index_pkt6_receive_
=
HooksManager
::
registerHook
(
"pkt6_receive"
);
hook_index_subnet6_select_
=
HooksManager
::
registerHook
(
"subnet6_select"
);
hook_index_pkt6_send_
=
HooksManager
::
registerHook
(
"pkt6_send"
);
}
};
// Declare a Hooks object. As this is outside any function or method, it
// 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
;
};
// anonymous namespace
namespace
isc
{
namespace
dhcp
{
...
...
@@ -67,7 +94,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_
(
-
1
),
hook_index_subnet6_select_
(
-
1
),
hook_index_pkt6_send_
(
-
1
)
{
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_START
,
DHCP6_OPEN_SOCKET
).
arg
(
port
);
...
...
@@ -106,6 +135,13 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port)
// Instantiate allocation engine
alloc_engine_
.
reset
(
new
AllocEngine
(
AllocEngine
::
ALLOC_ITERATIVE
,
100
));
// Register hook points
hook_index_pkt6_receive_
=
Hooks
.
hook_index_pkt6_receive_
;
hook_index_subnet6_select_
=
Hooks
.
hook_index_subnet6_select_
;
hook_index_pkt6_send_
=
Hooks
.
hook_index_pkt6_send_
;
/// @todo call loadLibraries() when handling configuration changes
}
catch
(
const
std
::
exception
&
e
)
{
LOG_ERROR
(
dhcp6_logger
,
DHCP6_SRV_CONSTRUCT_ERROR
).
arg
(
e
.
what
());
return
;
...
...
@@ -126,9 +162,17 @@ void Dhcpv6Srv::shutdown() {
shutdown_
=
true
;
}
Pkt6Ptr
Dhcpv6Srv
::
receivePacket
(
int
timeout
)
{
return
(
IfaceMgr
::
instance
().
receive6
(
timeout
));
}
void
Dhcpv6Srv
::
sendPacket
(
const
Pkt6Ptr
&
packet
)
{
IfaceMgr
::
instance
().
send
(
packet
);
}
bool
Dhcpv6Srv
::
run
()
{
while
(
!
shutdown_
)
{
/// @todo
: c
alculate actual timeout to the next event (e.g. lease
/// @todo
C
alculate actual timeout to the next event (e.g. lease
/// expiration) once we have lease database. The idea here is that
/// it is possible to do everything in a single process/thread.
/// For now, we are just calling select for 1000 seconds. There
...
...
@@ -142,7 +186,7 @@ bool Dhcpv6Srv::run() {
Pkt6Ptr
rsp
;
try
{
query
=
IfaceMgr
::
instance
().
receive
6
(
timeout
);
query
=
receive
Packet
(
timeout
);
}
catch
(
const
std
::
exception
&
e
)
{
LOG_ERROR
(
dhcp6_logger
,
DHCP6_PACKET_RECEIVE_FAIL
).
arg
(
e
.
what
());
}
...
...
@@ -160,6 +204,30 @@ 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
);
// Delete previously set arguments
callout_handle
->
deleteAllArguments
();
// Pass incoming packet as argument
callout_handle
->
setArgument
(
"query6"
,
query
);
// Call callouts
HooksManager
::
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
;
}
callout_handle
->
getArgument
(
"query6"
,
query
);
}
try
{
switch
(
query
->
getType
())
{
case
DHCPV6_SOLICIT
:
...
...
@@ -204,7 +272,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
)
{
...
...
@@ -218,7 +286,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
());
}
...
...
@@ -230,13 +298,35 @@ 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_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete all previous arguments
callout_handle
->
deleteAllArguments
();
// Set our response
callout_handle
->
setArgument
(
"response6"
,
rsp
);
// Call all installed callouts
HooksManager
::
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
());
if
(
rsp
->
pack
())
{
try
{
IfaceMgr
::
instance
().
send
(
rsp
);
sendPacket
(
rsp
);
}
catch
(
const
std
::
exception
&
e
)
{
LOG_ERROR
(
dhcp6_logger
,
DHCP6_PACKET_SEND_FAIL
).
arg
(
e
.
what
());
}
...
...
@@ -560,6 +650,37 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
}
}
// Let's execute all callouts registered for packet_received
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
hook_index_subnet6_select_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
question
);
// We're reusing callout_handle from previous calls
callout_handle
->
deleteAllArguments
();
// Set new arguments
callout_handle
->
setArgument
(
"query6"
,
question
);
callout_handle
->
setArgument
(
"subnet6"
,
subnet
);
// We pass pointer to const collection for performance reasons.
// Otherwise we would get a non-trivial performance penalty each
// time subnet6_select is called.
callout_handle
->
setArgument
(
"subnet6collection"
,
CfgMgr
::
instance
().
getSubnets6
());
// Call user (and server-side) callouts
HooksManager
::
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
);
}
...
...
@@ -619,7 +740,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
);
}
...
...
@@ -633,7 +755,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,
...
...
@@ -677,12 +799,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
...
...
@@ -1103,5 +1228,32 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
return
reply
;
}
isc
::
hooks
::
CalloutHandlePtr
Dhcpv6Srv
::
getCalloutHandle
(
const
Pkt6Ptr
&
pkt
)
{
// This method returns a CalloutHandle for a given packet. It is guaranteed
// to return the same callout_handle (so user library contexts are
// preserved). This method works well if the server processes one packet
// at a time. Once the server architecture is extended to cover parallel
// packets processing (e.g. delayed-ack, some form of buffering etc.), this
// method has to be extended (e.g. store callouts in a map and use pkt as
// a key). Additional code would be required to release the callout handle
// once the server finished processing.
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
);
}
};
};
src/bin/dhcp6/dhcp6_srv.h
View file @
0f8f7995
...
...
@@ -23,6 +23,7 @@
#include
<dhcp/pkt6.h>
#include
<dhcpsrv/alloc_engine.h>
#include
<dhcpsrv/subnet.h>
#include
<hooks/callout_handle.h>
#include
<boost/noncopyable.hpp>
...
...
@@ -189,7 +190,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 +323,19 @@ 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
);
/// @brief dummy wrapper around IfaceMgr::send()
///
/// This method is useful for testing purposes, where its replacement
/// simulates transmission of a packet. For that purpose it is protected.
virtual
void
sendPacket
(
const
Pkt6Ptr
&
pkt
);
private:
/// @brief Allocation Engine.
/// Pointer to the allocation engine that we are currently using
...
...
@@ -334,6 +349,18 @@ private:
/// Indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure.
volatile
bool
shutdown_
;
/// @brief returns callout handle for specified packet
///
/// @param pkt packet for which the handle should be returned
///
/// @return a callout handle to be used in hooks related to said packet
isc
::
hooks
::
CalloutHandlePtr
getCalloutHandle
(
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
...
...
src/bin/dhcp6/tests/Makefile.am
View file @
0f8f7995
...
...
@@ -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)
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
0f8f7995
This diff is collapsed.
Click to expand it.
src/lib/dhcpsrv/alloc_engine.cc
View file @
0f8f7995
...
...
@@ -16,11 +16,35 @@
#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
{
/// Structure that holds registered hook indexes
struct
Dhcp6Hooks
{
int
hook_index_lease6_select_
;
///< index for "lease6_receive" hook point
/// Constructor that registers hook points for AllocationEngine
Dhcp6Hooks
()
{
hook_index_lease6_select_
=
HooksManager
::
registerHook
(
"lease6_select"
);
}
};
// Declare a Hooks object. As this is outside any function or method, it
// 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
;
};
// anonymous namespace
namespace
isc
{
namespace
dhcp
{
...
...
@@ -161,6 +185,9 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
default:
isc_throw
(
BadValue
,
"Invalid/unsupported allocation algorithm"
);
}
// Register hook points
hook_index_lease6_select_
=
Hooks
.
hook_index_lease6_select_
;
}
Lease6Ptr
...
...
@@ -168,7 +195,8 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
const
DuidPtr
&
duid
,
uint32_t
iaid
,
const
IOAddress
&
hint
,
bool
fake_allocation
/* = false */
)
{