Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
8ab644fc
Commit
8ab644fc
authored
Aug 23, 2013
by
Tomek Mrugalski
🛰
Browse files
[master] Merge branch 'trac2983' (4 extra hooks for DHCPv4)
Conflicts: ChangeLog
parents
e40e2e96
fd47f18f
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
8ab644fc
667. [func] tomek
Additional hooks (buffer4_receive, lease4_renew,
lease4_release, buffer4_send) added to the DHCPv4 server.
(Trac #2983, git fd47f18f898695b98623a63a0a1c68d2e4b37568)
666. [func] vorner
The CmdCtl's command "print_settings" was removed. It served no real
purpose and was just experimental leftover from early development.
...
...
src/bin/dhcp4/dhcp4_hooks.dox
View file @
8ab644fc
...
...
@@ -49,22 +49,45 @@ 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 dhcpv4HooksBuffer4Receive buffer4_receive
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when an incoming DHCPv4
buffer is received, before its content is parsed. The sole argument
- query4 - contains a pointer to an isc::dhcp::Pkt4 object that
contains raw information regarding incoming packet, including its
source and destination addresses, interface over which it was
received, and a raw buffer stored in data_ field. None of the
packet fields (op_, hlen_, chaddr_, etc.) are set yet. Callouts
installed on this hook point can modify the incoming buffer. The
server will parse the buffer afterwards.
- <b>Skip flag action</b>: If any callout sets the skip flag, the server will
skip the buffer parsing. In such case there is an expectation that
the callout will parse the buffer and create option objects (see
isc::dhcp::Pkt4::addOption()). Otherwise the server will find out
that some mandatory options are missing (e.g. DHCP Message Type) and
will drop the packet. If you want to have the capability to drop
a message, it is better to use skip flag in pkt4_receive callout.
@subsection dhcpv4HooksPkt4Receive pkt4_receive
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when an incoming DHCPv4
packet is received and its content
is
parsed. The sole
argument -
query4 - contains a pointer to an isc::dhcp::Pkt4 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 Pkt4 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 Pkt4 object. For this reas
on
,
i
t doesn't make
sense to modify i
t.)
packet is received and its content
has been
parsed. The sole
argument -
query4 - contains a pointer to an isc::dhcp::Pkt4 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 Pkt4 object can be modified at this
time, except data_
.
(
By the time this hook is
reached, the contents
of the data_ field has been already parsed and stored in other
fields. Therefore, the modificati
on i
n the data_ field has no
effec
t.)
- <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
...
...
@@ -97,42 +120,97 @@ packet processing. Hook points that are not specific to packet processing
- name: @b lease4, type: isc::dhcp::Lease4Ptr, 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::Lease4 object will be stored in the lease's record in
the
database. The callout should
make sure that any
modifications a
re
sanity checked as
the server will use that data as is with no further
checking.\n\n
The server processes lease requests for DISCOVER and
REQUEST in a
very similar way. The only major difference is that
for DISCOVER
the lease is just selected, but not inserted into
the database. It
is possible to distinguish between DISCOVER 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 (DISCOVER),
a value of false mean
s that it will (REQUEST).
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::Lease4 object will be stored in the lease's record in
the
database. The callout should
sanity check all
modifications a
s
the server will use that data as is with no further
checking.\n\n
The server processes lease requests for DISCOVER and
REQUEST in a
very similar way. The only major difference is that
for DISCOVER
the lease is just selected, but not inserted into
the database. It
is possible to distinguish between DISCOVER and
REQUEST by checking
value of the fake_allocation flag: a value of true
indicates that the
lease won't be inserted into the database (DISCOVER),
a value of
false indicate
s that it will (REQUEST).
- <b>Skip flag action</b>: If any callout installed on 'lease4_select'
sets the skip flag, the server will not assign any lease. Packet
processing will continue, but client will not get an address.
@subsection dhcpv4HooksLeaseRenew lease4_renew
- @b Arguments:
- name: @b subnet4, type: isc::dhcp::Subnet4Ptr, direction: <b>in</b>
- name: @b clientid, type: isc::dhcp::ClientId, direction: <b>in</b>
- name: @b hwaddr, type: isc::dhcp::HWAddr, direction: <b>in</b>
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when the server engine
is about to renew a lease, as a result of receiving REQUEST/Renewing
packet. The lease4 argument points to Lease4 object that contains
the updated values. Callout can modify those values. Care should be taken
as the server will attempt to update the lease in the database without
any additional checks.
- <b>Skip flag action</b>: If any callout installed on 'lease4_renew'
sets the skip flag, the server will not update the lease and will
use old values instead.
@subsection dhcpv4HooksLeaseRelease lease4_release
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in</b>
- @b Description: this callout is executed when the server engine
is about to release a lease, as a result of receiving RELEASE packet.
The lease4 argument points to Lease4 object that contains the lease to
be released. It doesn't make sense to modify it at this time.
- <b>Skip flag action</b>: If any callout installed on 'lease4_release'
sets the skip flag, the server will not delete the lease. It will be
kept in the database and will go through the regular expiration/reuse
process.
@subsection dhcpv4HooksPkt4Send pkt4_send
- @b Arguments:
- name: @b response4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when server's response
is about to be sen
d
back to the client. The sole argument - response4 -
is about to be sen
t
back to the client. The sole argument - response4 -
contains a pointer to an isc::dhcp::Pkt4 object that contains the
packet, with
set
source and destination addresses, interface over which
it will be sen
d,
list of all options and relay information. All fields
of the Pkt4 object can be modified at this time, except buffer
O
ut_.
packet, with source and destination addresses
set
, interface over which
it will be sen
t, and a
list of all options and relay information. All fields
of the Pkt4 object can be modified at this time, except buffer
_o
ut_.
(This is scratch space used for constructing the packet after all
pkt4_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 not construct raw buffer. The expectation is that if the callout
set skip flag, it is responsible for constructing raw form on its own.
Otherwise the output packet will be sent with zero length.
@subsection dhcpv4HooksBuffer4Send buffer4_send
- @b Arguments:
- name: @b response4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when server's response
is about to be sent back to the client. The sole argument - response4 -
contains a pointer to an isc::dhcp::Pkt4 object that contains the
packet, with source and destination addresses set, interface over which
it will be sent, and a list of all options and relay information. The raw
on-wire form is already prepared in buffer_out_ (see isc::dhcp::Pkt4::getBuffer())
It doesn't make any sense to modify packet fields or options content
at this time, because they were already used to construct on-wire buffer.
- <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/dhcp4/dhcp4_messages.mes
View file @
8ab644fc
...
...
@@ -70,6 +70,24 @@ This message is printed when DHCPv4 server disables an interface from being
used to receive DHCPv4 traffic. Sockets on this interface will not be opened
by the Interface Manager until interface is enabled.
% DHCP4_HOOK_BUFFER_RCVD_SKIP received DHCPv4 buffer was dropped because a callout set the skip flag.
This debug message is printed when a callout installed on buffer4_receive
hook point set the skip flag. For this particular hook point, the
setting of the flag by a callout instructs the server to drop the packet.
% DHCP4_HOOK_BUFFER_SEND_SKIP prepared DHCPv4 response was dropped because a callout set the skip flag.
This debug message is printed when a callout installed on buffer4_send
hook point set the skip flag. For this particular hook point, the
setting of the flag by a callout instructs the server to drop the packet.
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_LEASE4_RELEASE_SKIP DHCPv4 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
setting of the flag by a callout instructs the server to not release
a lease.
% DHCP4_HOOK_PACKET_RCVD_SKIP received DHCPv4 packet was dropped, because a callout set the skip flag.
This debug message is printed when a callout installed on the pkt4_receive
hook point sets the skip flag. For this particular hook point, the
...
...
@@ -138,6 +156,10 @@ This is a general catch-all message indicating that the processing of a
received packet failed. The reason is given in the message. The server
will not send a response but will instead ignore the packet.
% DHCP4_PACKET_DROP_NO_TYPE packet received on interface %1 dropped, because of missing msg-type option
This is a debug message informing that incoming DHCPv4 packet did not
have mandatory DHCP message type option and thus was dropped.
% DHCP4_PACKET_RECEIVED %1 (type %2) packet received on interface %3
A debug message noting that the server has received the specified type of
packet on the specified interface. Note that a packet marked as UNKNOWN
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
8ab644fc
This diff is collapsed.
Click to expand it.
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
8ab644fc
This diff is collapsed.
Click to expand it.
src/bin/dhcp6/dhcp6_messages.mes
View file @
8ab644fc
...
...
@@ -118,7 +118,7 @@ hook point set the skip flag. For this particular hook point, the
setting of the flag by a callout instructs the server to drop the packet.
% DHCP6_HOOK_BUFFER_SEND_SKIP prepared DHCPv6 response was dropped because a callout set the skip flag.
This debug message is printed when a callout installed on buffer6_
receive
This debug message is printed when a callout installed on buffer6_
send
hook point set the skip flag. For this particular hook point, the
setting of the flag by a callout instructs the server to drop the packet.
Server completed all the processing (e.g. may have assigned, updated
...
...
src/bin/dhcp6/tests/hooks_unittest.cc
View file @
8ab644fc
...
...
@@ -285,10 +285,6 @@ public:
/// @return always 0
static
int
buffer6_receive_skip
(
CalloutHandle
&
callout_handle
)
{
Pkt6Ptr
pkt
;
callout_handle
.
getArgument
(
"query6"
,
pkt
);
callout_handle
.
setSkip
(
true
);
// Carry on as usual
...
...
@@ -561,7 +557,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_buffer6_receive) {
// 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
pkt
6_receive callback.
// In particular, it should call registered
buffer
6_receive callback.
srv_
->
run
();
// Check that the callback called is indeed the one we installed
...
...
@@ -577,7 +573,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_buffer6_receive) {
EXPECT_TRUE
(
expected_argument_names
==
callback_argument_names_
);
}
// Checks if callouts installed on
pkt
6_receive
d
is able to change
// Checks if callouts installed on
buffer
6_receive is able to change
// the values and the parameters are indeed used by the server.
TEST_F
(
HooksDhcpv6SrvTest
,
valueChange_buffer6_receive
)
{
...
...
src/lib/dhcp/pkt4.cc
View file @
8ab644fc
...
...
@@ -33,7 +33,8 @@ namespace dhcp {
const
IOAddress
DEFAULT_ADDRESS
(
"0.0.0.0"
);
Pkt4
::
Pkt4
(
uint8_t
msg_type
,
uint32_t
transid
)
:
local_addr_
(
DEFAULT_ADDRESS
),
:
buffer_out_
(
DHCPV4_PKT_HDR_LEN
),
local_addr_
(
DEFAULT_ADDRESS
),
remote_addr_
(
DEFAULT_ADDRESS
),
iface_
(
""
),
ifindex_
(
0
),
...
...
@@ -48,8 +49,7 @@ Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
ciaddr_
(
DEFAULT_ADDRESS
),
yiaddr_
(
DEFAULT_ADDRESS
),
siaddr_
(
DEFAULT_ADDRESS
),
giaddr_
(
DEFAULT_ADDRESS
),
bufferOut_
(
DHCPV4_PKT_HDR_LEN
)
giaddr_
(
DEFAULT_ADDRESS
)
{
memset
(
sname_
,
0
,
MAX_SNAME_LEN
);
memset
(
file_
,
0
,
MAX_FILE_LEN
);
...
...
@@ -58,7 +58,8 @@ Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
}
Pkt4
::
Pkt4
(
const
uint8_t
*
data
,
size_t
len
)
:
local_addr_
(
DEFAULT_ADDRESS
),
:
buffer_out_
(
0
),
// not used, this is RX packet
local_addr_
(
DEFAULT_ADDRESS
),
remote_addr_
(
DEFAULT_ADDRESS
),
iface_
(
""
),
ifindex_
(
0
),
...
...
@@ -72,8 +73,7 @@ Pkt4::Pkt4(const uint8_t* data, size_t len)
ciaddr_
(
DEFAULT_ADDRESS
),
yiaddr_
(
DEFAULT_ADDRESS
),
siaddr_
(
DEFAULT_ADDRESS
),
giaddr_
(
DEFAULT_ADDRESS
),
bufferOut_
(
0
)
// not used, this is RX packet
giaddr_
(
DEFAULT_ADDRESS
)
{
if
(
len
<
DHCPV4_PKT_HDR_LEN
)
{
isc_throw
(
OutOfRange
,
"Truncated DHCPv4 packet (len="
<<
len
...
...
@@ -111,25 +111,25 @@ Pkt4::pack() {
try
{
size_t
hw_len
=
hwaddr_
->
hwaddr_
.
size
();
buffer
O
ut_
.
writeUint8
(
op_
);
buffer
O
ut_
.
writeUint8
(
hwaddr_
->
htype_
);
buffer
O
ut_
.
writeUint8
(
hw_len
<
MAX_CHADDR_LEN
?
buffer
_o
ut_
.
writeUint8
(
op_
);
buffer
_o
ut_
.
writeUint8
(
hwaddr_
->
htype_
);
buffer
_o
ut_
.
writeUint8
(
hw_len
<
MAX_CHADDR_LEN
?
hw_len
:
MAX_CHADDR_LEN
);
buffer
O
ut_
.
writeUint8
(
hops_
);
buffer
O
ut_
.
writeUint32
(
transid_
);
buffer
O
ut_
.
writeUint16
(
secs_
);
buffer
O
ut_
.
writeUint16
(
flags_
);
buffer
O
ut_
.
writeUint32
(
ciaddr_
);
buffer
O
ut_
.
writeUint32
(
yiaddr_
);
buffer
O
ut_
.
writeUint32
(
siaddr_
);
buffer
O
ut_
.
writeUint32
(
giaddr_
);
buffer
_o
ut_
.
writeUint8
(
hops_
);
buffer
_o
ut_
.
writeUint32
(
transid_
);
buffer
_o
ut_
.
writeUint16
(
secs_
);
buffer
_o
ut_
.
writeUint16
(
flags_
);
buffer
_o
ut_
.
writeUint32
(
ciaddr_
);
buffer
_o
ut_
.
writeUint32
(
yiaddr_
);
buffer
_o
ut_
.
writeUint32
(
siaddr_
);
buffer
_o
ut_
.
writeUint32
(
giaddr_
);
if
(
hw_len
<=
MAX_CHADDR_LEN
)
{
// write up to 16 bytes of the hardware address (CHADDR field is 16
// bytes long in DHCPv4 message).
buffer
O
ut_
.
writeData
(
&
hwaddr_
->
hwaddr_
[
0
],
(
hw_len
<
MAX_CHADDR_LEN
?
buffer
_o
ut_
.
writeData
(
&
hwaddr_
->
hwaddr_
[
0
],
(
hw_len
<
MAX_CHADDR_LEN
?
hw_len
:
MAX_CHADDR_LEN
)
);
hw_len
=
MAX_CHADDR_LEN
-
hw_len
;
}
else
{
...
...
@@ -138,20 +138,20 @@ Pkt4::pack() {
// write (len) bytes of padding
vector
<
uint8_t
>
zeros
(
hw_len
,
0
);
buffer
O
ut_
.
writeData
(
&
zeros
[
0
],
hw_len
);
// buffer
O
ut_.writeData(chaddr_, MAX_CHADDR_LEN);
buffer
_o
ut_
.
writeData
(
&
zeros
[
0
],
hw_len
);
// buffer
_o
ut_.writeData(chaddr_, MAX_CHADDR_LEN);
buffer
O
ut_
.
writeData
(
sname_
,
MAX_SNAME_LEN
);
buffer
O
ut_
.
writeData
(
file_
,
MAX_FILE_LEN
);
buffer
_o
ut_
.
writeData
(
sname_
,
MAX_SNAME_LEN
);
buffer
_o
ut_
.
writeData
(
file_
,
MAX_FILE_LEN
);
// write DHCP magic cookie
buffer
O
ut_
.
writeUint32
(
DHCP_OPTIONS_COOKIE
);
buffer
_o
ut_
.
writeUint32
(
DHCP_OPTIONS_COOKIE
);
LibDHCP
::
packOptions
(
buffer
O
ut_
,
options_
);
LibDHCP
::
packOptions
(
buffer
_o
ut_
,
options_
);
// add END option that indicates end of options
// (End option is very simple, just a 255 octet)
buffer
O
ut_
.
writeUint8
(
DHO_END
);
buffer
_o
ut_
.
writeUint8
(
DHO_END
);
}
catch
(
const
Exception
&
e
)
{
// An exception is thrown and message will be written to Logger
isc_throw
(
InvalidOperation
,
e
.
what
());
...
...
@@ -259,7 +259,7 @@ void Pkt4::setType(uint8_t dhcp_type) {
}
void
Pkt4
::
repack
()
{
buffer
O
ut_
.
writeData
(
&
data_
[
0
],
data_
.
size
());
buffer
_o
ut_
.
writeData
(
&
data_
[
0
],
data_
.
size
());
}
std
::
string
...
...
src/lib/dhcp/pkt4.h
View file @
8ab644fc
...
...
@@ -70,7 +70,7 @@ public:
///
/// Prepares on-wire format of message and all its options.
/// Options must be stored in options_ field.
/// Output buffer will be stored in buffer
O
ut_.
/// Output buffer will be stored in buffer
_o
ut_.
///
/// @throw InvalidOperation if packing fails
void
...
...
@@ -103,7 +103,7 @@ public:
///
/// This is mostly a diagnostic function. It is being used for sending
/// received packet. Received packet is stored in bufferIn_, but
/// transmitted data is stored in buffer
O
ut_. If we want to send packet
/// transmitted data is stored in buffer
_o
ut_. If we want to send packet
/// that we just received, a copy between those two buffers is necessary.
void
repack
();
...
...
@@ -307,11 +307,12 @@ public:
/// is only valid till Pkt4 object is valid.
///
/// RX packet or TX packet before pack() will return buffer with
/// zero length
/// zero length. This buffer is returned as non-const, so hooks
/// framework (and user's callouts) can modify them if needed
///
/// @return reference to output buffer
const
isc
::
util
::
OutputBuffer
&
getBuffer
()
const
{
return
(
buffer
O
ut_
);
};
isc
::
util
::
OutputBuffer
&
getBuffer
()
{
return
(
buffer
_o
ut_
);
};
/// @brief Add an option.
///
...
...
@@ -489,6 +490,38 @@ public:
/// @throw isc::Unexpected if timestamp update failed
void
updateTimestamp
();
/// Output buffer (used during message transmission)
///
/// @warning This public member is accessed by derived
/// classes directly. One of such derived classes is
/// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
/// behavior must be taken into consideration before making
/// changes to this member such as access scope restriction or
/// data format change etc. This field is also public, because
/// it may be modified by callouts (which are written in C++ now,
/// but we expect to also have them in Python, so any accesibility
/// methods would overly complicate things here and degrade
/// performance).
isc
::
util
::
OutputBuffer
buffer_out_
;
/// @brief That's the data of input buffer used in RX packet.
///
/// @note Note that InputBuffer does not store the data itself, but just
/// expects that data will be valid for the whole life of InputBuffer.
/// Therefore we need to keep the data around.
///
/// @warning This public member is accessed by derived
/// classes directly. One of such derived classes is
/// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
/// behavior must be taken into consideration before making
/// changes to this member such as access scope restriction or
/// data format change etc. This field is also public, because
/// it may be modified by callouts (which are written in C++ now,
/// but we expect to also have them in Python, so any accesibility
/// methods would overly complicate things here and degrade
/// performance).
std
::
vector
<
uint8_t
>
data_
;
private:
/// @brief Generic method that validates and sets HW address.
...
...
@@ -591,29 +624,6 @@ protected:
// end of real DHCPv4 fields
/// output buffer (used during message transmission)
///
/// @warning This protected member is accessed by derived
/// classes directly. One of such derived classes is
/// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
/// behavior must be taken into consideration before making
/// changes to this member such as access scope restriction or
/// data format change etc.
isc
::
util
::
OutputBuffer
bufferOut_
;
/// that's the data of input buffer used in RX packet. Note that
/// InputBuffer does not store the data itself, but just expects that
/// data will be valid for the whole life of InputBuffer. Therefore we
/// need to keep the data around.
///
/// @warning This protected member is accessed by derived
/// classes directly. One of such derived classes is
/// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
/// behavior must be taken into consideration before making
/// changes to this member such as access scope restriction or
/// data format change etc.
std
::
vector
<
uint8_t
>
data_
;
/// collection of options present in this message
///
/// @warning This protected member is accessed by derived
...
...
src/lib/dhcpsrv/alloc_engine.cc
View file @
8ab644fc
...
...
@@ -31,11 +31,13 @@ namespace {
/// Structure that holds registered hook indexes
struct
AllocEngineHooks
{
int
hook_index_lease4_select_
;
///< index for "lease4_receive" hook point
int
hook_index_lease4_renew_
;
///< index for "lease4_renew" hook point
int
hook_index_lease6_select_
;
///< index for "lease6_receive" hook point
/// Constructor that registers hook points for AllocationEngine
AllocEngineHooks
()
{
hook_index_lease4_select_
=
HooksManager
::
registerHook
(
"lease4_select"
);
hook_index_lease4_renew_
=
HooksManager
::
registerHook
(
"lease4_renew"
);
hook_index_lease6_select_
=
HooksManager
::
registerHook
(
"lease6_select"
);
}
};
...
...
@@ -351,7 +353,8 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
if
(
existing
)
{
// We have a lease already. This is a returning client, probably after
// its reboot.
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
fake_allocation
);
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
callout_handle
,
fake_allocation
);
if
(
existing
)
{
return
(
existing
);
}
...
...
@@ -365,7 +368,8 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
if
(
existing
)
{
// we have a lease already. This is a returning client, probably after
// its reboot.
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
fake_allocation
);
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
callout_handle
,
fake_allocation
);
// @todo: produce a warning. We haven't found him using MAC address, but
// we found him using client-id
if
(
existing
)
{
...
...
@@ -463,8 +467,19 @@ Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
const
ClientIdPtr
&
clientid
,
const
HWAddrPtr
&
hwaddr
,
const
Lease4Ptr
&
lease
,
const
isc
::
hooks
::
CalloutHandlePtr
&
callout_handle
,
bool
fake_allocation
/* = false */
)
{
if
(
!
lease
)
{
isc_throw
(
InvalidOperation
,
"Lease4 must be specified"
);
}
// Let's keep the old data. This is essential if we are using memfile
// (the lease returned points directly to the lease4 object in the database)
// We'll need it if we want to skip update (i.e. roll back renewal)
/// @todo: remove this once #3083 is implemented
Lease4
old_values
=
*
lease
;
lease
->
subnet_id_
=
subnet
->
getID
();
lease
->
hwaddr_
=
hwaddr
->
hwaddr_
;
lease
->
client_id_
=
clientid
;
...
...
@@ -473,10 +488,48 @@ Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
lease
->
t2_
=
subnet
->
getT2
();
lease
->
valid_lft_
=
subnet
->
getValid
();
if
(
!
fake_allocation
)
{
bool
skip
=
false
;
// Execute all callouts registered for packet6_send
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_lease4_renew_
))
{
// Delete all previous arguments
callout_handle
->
deleteAllArguments
();
// Subnet from which we do the allocation. Convert the general subnet
// pointer to a pointer to a Subnet4. Note that because we are using
// boost smart pointers here, we need to do the cast using the boost
// version of dynamic_pointer_cast.
Subnet4Ptr
subnet4
=
boost
::
dynamic_pointer_cast
<
Subnet4
>
(
subnet
);
// Pass the parameters
callout_handle
->
setArgument
(
"subnet4"
,
subnet4
);
callout_handle
->
setArgument
(
"clientid"
,
clientid
);
callout_handle
->
setArgument
(
"hwaddr"
,
hwaddr
);
// Pass the lease to be updated
callout_handle
->
setArgument
(
"lease4"
,
lease
);
// Call all installed callouts
HooksManager
::
callCallouts
(
Hooks
.
hook_index_lease4_renew_
,
*
callout_handle
);
// Callouts decided to skip the next processing step. The next
// processing step would to actually renew the lease, so skip at this
// stage means "keep the old lease as it is".
if
(
callout_handle
->
getSkip
())
{
skip
=
true
;
LOG_DEBUG
(
dhcpsrv_logger
,
DHCPSRV_DBG_HOOKS
,
DHCPSRV_HOOK_LEASE4_RENEW_SKIP
);
}
}
if
(
!
fake_allocation
&&
!
skip
)
{
// for REQUEST we do update the lease
LeaseMgrFactory
::
instance
().
updateLease4
(
lease
);
}
if
(
skip
)
{
// Rollback changes (really useful only for memfile)
/// @todo: remove this once #3083 is implemented
*
lease
=
old_values
;
}
return
(
lease
);
}
...
...
src/lib/dhcpsrv/alloc_engine.h
View file @
8ab644fc
...
...
@@ -218,6 +218,8 @@ protected:
/// @param clientid client identifier
/// @param hwaddr client's hardware address
/// @param lease lease to be renewed
/// @param callout_handle a callout handle (used in hooks). A lease callouts
/// will be executed if this parameter is passed.
/// @param fake_allocation is this real i.e. REQUEST (false) or just picking
/// an address for DISCOVER that is not really allocated (true)
Lease4Ptr
...
...
@@ -225,6 +227,7 @@ protected:
const
ClientIdPtr
&
clientid
,
const
HWAddrPtr
&
hwaddr
,
const
Lease4Ptr
&
lease
,
const
isc
::
hooks
::
CalloutHandlePtr
&
callout_handle
,
bool
fake_allocation
/* = false */
);
/// @brief Allocates an IPv6 lease
...
...
src/lib/dhcpsrv/dhcpsrv_messages.mes
View file @
8ab644fc
...
...
@@ -141,6 +141,12 @@ hook point sets the skip flag. It means that the server was told that
no lease4 should be assigned. The server will not put that lease in its
database and the client will get a NAK packet.
% DHCPSRV_HOOK_LEASE4_RENEW_SKIP DHCPv4 lease was not renewed because a callout set the skip flag.
This debug message is printed when a callout installed on lease4_renew
hook point set the skip flag. For this particular hook point, the setting
of the flag by a callout instructs the server to not renew a lease. The
server will use existing lease as it is, without extending its lifetime.
% DHCPSRV_HOOK_LEASE6_SELECT_SKIP Lease6 (non-temporary) creation was skipped, because of callout skip flag.
This debug message is printed when a callout installed on lease6_select
hook point sets the skip flag. It means that the server was told that
...
...
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
View file @
8ab644fc
...
...
@@ -1017,6 +1017,8 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
// called
TEST_F
(
AllocEngine4Test
,
renewLease4
)
{
boost
::
scoped_ptr
<
AllocEngine
>
engine
;
CalloutHandlePtr
callout_handle
=
HooksManager
::
createCalloutHandle
();
ASSERT_NO_THROW
(
engine
.
reset
(
new
AllocEngine
(
AllocEngine
::
ALLOC_ITERATIVE
,
100
)));
ASSERT_TRUE
(
engine
);
...
...
@@ -1037,7 +1039,8 @@ TEST_F(AllocEngine4Test, renewLease4) {
// Lease was assigned 45 seconds ago and is valid for 100 seconds. Let's
// renew it.
ASSERT_FALSE
(
lease
->
expired
());
lease
=
engine
->
renewLease4
(
subnet_
,
clientid_
,
hwaddr_
,
lease
,
false
);
lease
=
engine
->
renewLease4
(
subnet_
,
clientid_
,
hwaddr_
,
lease
,
callout_handle
,
false
);
// Check that he got that single lease
ASSERT_TRUE
(
lease
);
EXPECT_EQ
(
addr
.
toText
(),
lease
->
addr_
.
toText
());
...
...
@@ -1278,6 +1281,10 @@ TEST_F(HookAllocEngine6Test, change_lease6_select) {