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
Sebastian Schrader
Kea
Commits
87b3de01
Commit
87b3de01
authored
Oct 10, 2013
by
Tomek Mrugalski
🛰
Browse files
[master] Merge branch 'trac3153' PD support in renew/release
Conflicts: src/bin/dhcp6/tests/dhcp6_test_utils.h
parents
a9cd7cf1
32079328
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
87b3de01
688. [func] tomek
b10-dhcp6: Prefix Delegation support is now extended to
Renew and Release messages.
(Trac #3153,#3154, git 3207932815f58045acea84ae092e0a5aa7c4bfd7)
687. [func] tomek
b10-dhcp6: Prefix Delegation (IA_PD and IAPREFIX options) is now
supported in Solicit and Request messages.
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
87b3de01
...
...
@@ -201,8 +201,7 @@ Dhcpv4Srv::run() {
// The packet has just been received so contains the uninterpreted wire
// data; execute callouts registered for buffer4_receive.
if
(
HooksManager
::
getHooksManager
()
.
calloutsPresent
(
Hooks
.
hook_index_buffer4_receive_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_buffer4_receive_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete previously set arguments
...
...
@@ -396,8 +395,7 @@ Dhcpv4Srv::run() {
// Option objects modification does not make sense anymore. Hooks
// can only manipulate wire buffer at this stage.
// Let's execute all callouts registered for buffer4_send
if
(
HooksManager
::
getHooksManager
()
.
calloutsPresent
(
Hooks
.
hook_index_buffer4_send_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_buffer4_send_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete previously set arguments
...
...
@@ -931,8 +929,7 @@ Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
bool
skip
=
false
;
// Execute all callouts registered for lease4_release
if
(
HooksManager
::
getHooksManager
()
.
calloutsPresent
(
Hooks
.
hook_index_lease4_release_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_lease4_release_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
release
);
// Delete all previous arguments
...
...
src/bin/dhcp6/dhcp6_messages.mes
View file @
87b3de01
...
...
@@ -82,7 +82,7 @@ to perform the DNS Update, which removes RRs from the DNS.
This debug message is logged when FQDN mapping for a particular lease has
been changed by the recent Request message. This mapping will be changed in DNS.
% DHCP6_DDNS_LEASE_RENEW_FQDN_CHANGE FQDN for the renewed lease: %1 has changed
.
% DHCP6_DDNS_LEASE_RENEW_FQDN_CHANGE FQDN for the renewed lease: %1 has changed
New values: hostname = %2, reverse mapping = %3, forward mapping = %4
This debug message is logged when FQDN mapping for a particular lease has been
changed by the recent Renew message. This mapping will be changed in DNS.
...
...
@@ -112,19 +112,19 @@ that the DNS Update has been performed for it, but the FQDN held in the lease
database has invalid format and can't be transformed to the canonical on-wire
format.
% DHCP6_HOOK_BUFFER_RCVD_SKIP received DHCPv6 buffer was dropped because a callout set the skip flag
.
% DHCP6_HOOK_BUFFER_RCVD_SKIP received DHCPv6 buffer was dropped because a callout set the skip flag
This debug message is printed when a callout installed on buffer6_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.
% DHCP6_HOOK_BUFFER_SEND_SKIP prepared DHCPv6 response was dropped because a callout set the skip flag
.
% 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_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.
% DHCP6_HOOK_LEASE6_RENEW_SKIP DHCPv6 lease was not renewed because a callout set the skip flag
.
% DHCP6_HOOK_LEASE6_RENEW_SKIP DHCPv6 lease was not renewed because a callout set the skip flag
This debug message is printed when a callout installed on lease6_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. If
...
...
@@ -132,7 +132,15 @@ client requested renewal of multiples leases (by sending multiple IA
options), the server will skip the renewal of the one in question and
will proceed with other renewals as usual.
% DHCP6_HOOK_LEASE6_RELEASE_SKIP DHCPv6 lease was not released because a callout set the skip flag.
% DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP DHCPv6 address lease was not released because a callout set the skip flag
This debug message is printed when a callout installed on the
lease6_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. If a client requested the release of multiples leases
(by sending multiple IA options), the server will retain this particular
lease and proceed with other releases as usual.
% DHCP6_HOOK_LEASE6_RELEASE_PD_SKIP DHCPv6 prefix lease was not released because a callout set the skip flag
This debug message is printed when a callout installed on lease6_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
...
...
@@ -140,12 +148,12 @@ a lease. If client requested release of multiples leases (by sending
multiple IA options), the server will retains this particular lease and
will proceed with other renewals as usual.
% DHCP6_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped because a callout set the skip flag
.
% DHCP6_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped because a callout set the skip flag
This debug message is printed when a callout installed on the pkt6_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.
% DHCP6_HOOK_PACKET_SEND_SKIP prepared DHCPv6 response was not sent because a callout set the skip flag
.
% DHCP6_HOOK_PACKET_SEND_SKIP prepared DHCPv6 response was not sent because a callout set the skip flag
This debug message is printed when a callout installed on the pkt6_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. This
...
...
@@ -153,7 +161,7 @@ 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 the skip flag
.
% DHCP6_HOOK_SUBNET6_SELECT_SKIP no subnet was selected because a callout set the skip flag
This debug message is printed when a callout installed on the
subnet6_select hook point set the skip flag. For this particular hook
point, the setting of the flag instructs the server not to choose a
...
...
@@ -211,13 +219,20 @@ This message indicates that the server failed to grant (in response to
received REQUEST) a prefix lease for a given client. There may be many reasons
for such failure. Each failure is logged in a separate log entry.
% DHCP6_LEASE_WITHOUT_DUID lease for address %1 does not have a DUID
This error message indicates a database consistency
failure
. The lease
% DHCP6_LEASE_
NA_
WITHOUT_DUID
address
lease for address %1 does not have a DUID
This error message indicates a database consistency
problem
. The lease
database has an entry indicating that the given address is in use,
but the lease does not contain any client identification. This is most
likely due to a software error: please raise a bug report. As a temporary
workaround, manually remove the lease entry from the database.
% DHCP6_LEASE_PD_WITHOUT_DUID prefix lease for address %1 does not have a DUID
This error message indicates a database consistency failure. The lease
database has an entry indicating that the given prefix is in use,
but the lease does not contain any client identification. This is most
likely due to a software error: please raise a bug report. As a temporary
workaround, manually remove the lease entry from the database.
% DHCP6_NOT_RUNNING IPv6 DHCP server is not running
A warning message is issued when an attempt is made to shut down the
IPv6 DHCP server but it is not running.
...
...
@@ -314,31 +329,56 @@ as a hint for possible requested prefix.
% DHCP6_QUERY_DATA received packet length %1, data length %2, data is %3
A debug message listing the data received from the client or relay.
% DHCP6_RELEASE address %1 belonging to client duid=%2, iaid=%3 was released properly
.
% DHCP6_RELEASE
_NA
address %1 belonging to client duid=%2, iaid=%3 was released properly
This debug message indicates that an address was released properly. It
is a normal operation during client shutdown.
% DHCP6_RELEASE_FAIL failed to remove lease for address %1 for duid=%2, iaid=%3
This error message indicates that the software failed to remove a
% DHCP6_RELEASE_PD prefix %1 belonging to client duid=%2, iaid=%3 was released properly
This debug message indicates that a prefix was released properly. It
is a normal operation during client shutdown.
% DHCP6_RELEASE_NA_FAIL failed to remove address lease for address %1 for duid=%2, iaid=%3
This error message indicates that the software failed to remove an address
lease from the lease database. It probably due to an error during a
database operation: resolution will most likely require administrator
intervention (e.g. check if DHCP process has sufficient privileges to
update the database). It may also be triggered if a lease was manually
removed from the database during RELEASE message processing.
% DHCP6_RELEASE_FAIL_WRONG_DUID client (duid=%1) tried to release address %2, but it belongs to client (duid=%3)
This warning message indicates that client tried to release an address
% DHCP6_RELEASE_PD_FAIL failed to remove prefix lease for address %1 for duid=%2, iaid=%3
This error message indicates that the software failed to remove a prefix
lease from the lease database. It probably due to an error during a
database operation: resolution will most likely require administrator
intervention (e.g. check if DHCP process has sufficient privileges to
update the database). It may also be triggered if a lease was manually
removed from the database during RELEASE message processing.
% DHCP6_RELEASE_NA_FAIL_WRONG_DUID client (duid=%1) tried to release address %2, but it belongs to another client (duid=%3)
This warning message indicates that a client tried to release an address
that belongs to a different client. This should not happen in normal
circumstances and may indicate a misconfiguration of the client. However,
since the client releasing the address will stop using it anyway, there
is a good chance that the situation will correct itself.
% DHCP6_RELEASE_FAIL_WRONG_IAID client (duid=%1) tried to release address %2, but it used wrong IAID (expected %3, but got %4)
% DHCP6_RELEASE_PD_FAIL_WRONG_DUID client (duid=%1) tried to release prefix %2, but it belongs to another client (duid=%3)
This warning message indicates that client tried to release a prefix
that belongs to a different client. This should not happen in normal
circumstances and may indicate a misconfiguration of the client. However,
since the client releasing the prefix will stop using it anyway, there
is a good chance that the situation will correct itself.
% DHCP6_RELEASE_NA_FAIL_WRONG_IAID client (duid=%1) tried to release address %2, but it used wrong IAID (expected %3, but got %4)
This warning message indicates that client tried to release an address
that does belong to it, but the address was expected to be in a different
IA (identity association) container. This probably means that the client's
support for multiple addresses is flawed.
% DHCP6_RELEASE_PD_FAIL_WRONG_IAID client (duid=%1) tried to release prefix %2, but it used wrong IAID (expected %3, but got %4)
This warning message indicates that client tried to release a prefix
that does belong to it, but the address was expected to be in a different
IA (identity association) container. This probably means that the client's
support for multiple prefixes is flawed.
% DHCP6_RELEASE_MISSING_CLIENTID client (address=%1) sent RELEASE message without mandatory client-id
This warning message indicates that client sent RELEASE message without
mandatory client-id option. This is most likely caused by a buggy client
...
...
@@ -447,17 +487,39 @@ addresses or prefixes.
This debug message is printed when server receives a message of unknown type.
That could either mean missing functionality or invalid or broken relay or client.
The list of formally defined message types is available here:
www.iana.org/assignments/dhcpv6-parameters.
http://www.iana.org/assignments/dhcpv6-parameters.
% DHCP6_UNKNOWN_RELEASE_NA received RELEASE from unknown client (IA_NA, duid=%1, iaid=%2)
This warning message is printed when client attempts to release an address
lease, but no such lease is known by the server. See the explanation
of the status code DHCP6_UNKNOWN_RENEW_NA for possible reasons for
such behavior.
% DHCP6_UNKNOWN_RELEASE_PD received RELEASE from unknown client (IA_PD, duid=%1, iaid=%2)
This warning message is printed when client attempts to release an prefix
lease, but no such lease is known by the server. See the explanation
of the status code DHCP6_UNKNOWN_RENEW_PD for possible reasons for
such behavior.
% DHCP6_UNKNOWN_RENEW_NA received unknown IA_NA RENEW from client (duid=%1, iaid=%2) in subnet %3
This warning message is printed when client attempts to renew an address
lease (in the IA_NA option) but no such lease is known by the server. It
typically means that client has attempted to use its lease past its
lifetime: causes of this include a adjustment of the client's date/time
setting or poor support on the client for sleep/recovery. A properly
implemented client will recover from such a situation by restarting the
lease allocation process after receiving a negative reply from the server.
% DHCP6_UNKNOWN_RELEASE received RELEASE from unknown client (duid=%1, iaid=%2)
This warning message is printed when client attempts to release a lease,
but no such lease is known by the server. See DHCP6_UNKNOWN_RENEW for
possible reasons for such behavior.
An alternative cause could be that the server has lost its database
recently and does not recognize its well-behaving clients. This is more
probable if you see many such messages. Clients will recover from this,
but they will most likely get a different IP addresses and experience
a brief service interruption.
% DHCP6_UNKNOWN_RENEW received RENEW from client (duid=%1, iaid=%2) in subnet %3
This warning message is printed when client attempts to renew a lease
,
but no such lease is known by the server. It typically means
that
client has attempted to use its lease past its lifetime: causes of this
% DHCP6_UNKNOWN_RENEW
_PD
received
unknown IA_NA
RENEW from client (duid=%1, iaid=%2) in subnet %3
This warning message is printed when client attempts to renew a
n address
lease
(in IA_NA option),
but no such lease is known by the server. It typically means
that
client has attempted to use its lease past its lifetime: causes of this
include a adjustment of the clients date/time setting or poor support
for sleep/recovery. A properly implemented client will recover from such
a situation by restarting the lease allocation process after receiving
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
87b3de01
...
...
@@ -233,7 +233,7 @@ bool Dhcpv6Srv::run() {
// The packet has just been received so contains the uninterpreted wire
// data; execute callouts registered for buffer6_receive.
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_buffer6_receive_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_buffer6_receive_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete previously set arguments
...
...
@@ -276,7 +276,7 @@ bool Dhcpv6Srv::run() {
// At this point the information in the packet has been unpacked into
// the various packet fields and option objects has been cretated.
// Execute callouts registered for packet6_receive.
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_pkt6_receive_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_pkt6_receive_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete previously set arguments
...
...
@@ -389,7 +389,7 @@ bool Dhcpv6Srv::run() {
// Options are represented by individual objects, but the
// output wire data has not been prepared yet.
// Execute all callouts registered for packet6_send
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_pkt6_send_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_pkt6_send_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete all previous arguments
...
...
@@ -433,7 +433,7 @@ bool Dhcpv6Srv::run() {
// Option objects modification does not make sense anymore. Hooks
// can only manipulate wire buffer at this stage.
// Let's execute all callouts registered for buffer6_send
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_buffer6_send_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_buffer6_send_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete previously set arguments
...
...
@@ -785,7 +785,7 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
}
// Let's execute all callouts registered for subnet6_receive
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_subnet6_select_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_subnet6_select_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
question
);
// We're reusing callout_handle from previous calls
...
...
@@ -1451,7 +1451,7 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"Sorry, no known leases for this duid/iaid."
));
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_UNKNOWN_RENEW
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_UNKNOWN_RENEW
_NA
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
())
.
arg
(
subnet
->
toText
());
...
...
@@ -1520,7 +1520,7 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
bool
skip
=
false
;
// Execute all callouts registered for packet6_send
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_lease6_renew_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_lease6_renew_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete all previous arguments
...
...
@@ -1560,6 +1560,107 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
return
(
ia_rsp
);
}
OptionPtr
Dhcpv6Srv
::
renewIA_PD
(
const
Subnet6Ptr
&
subnet
,
const
DuidPtr
&
duid
,
const
Pkt6Ptr
&
query
,
boost
::
shared_ptr
<
Option6IA
>
ia
)
{
// Let's create a IA_NA response and fill it in later
boost
::
shared_ptr
<
Option6IA
>
ia_rsp
(
new
Option6IA
(
D6O_IA_PD
,
ia
->
getIAID
()));
if
(
!
subnet
)
{
// Insert status code NoBinding
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"Sorry, no known leases for this duid/iaid."
));
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_RENEW_UNKNOWN_SUBNET
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
());
return
(
ia_rsp
);
}
Lease6Ptr
lease
=
LeaseMgrFactory
::
instance
().
getLease6
(
Lease
::
TYPE_PD
,
*
duid
,
ia
->
getIAID
(),
subnet
->
getID
());
if
(
!
lease
)
{
// Client is renewing a lease that we don't know about.
// Insert status code NoBinding
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"Sorry, no known leases for this duid/iaid."
));
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_UNKNOWN_RENEW_PD
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
())
.
arg
(
subnet
->
toText
());
return
(
ia_rsp
);
}
// Keep the old data in case the callout tells us to skip update.
Lease6
old_data
=
*
lease
;
// Do the actual lease update
lease
->
preferred_lft_
=
subnet
->
getPreferred
();
lease
->
valid_lft_
=
subnet
->
getValid
();
lease
->
t1_
=
subnet
->
getT1
();
lease
->
t2_
=
subnet
->
getT2
();
lease
->
cltt_
=
time
(
NULL
);
// Also update IA_PD container with proper T1, T2 values
ia_rsp
->
setT1
(
subnet
->
getT1
());
ia_rsp
->
setT2
(
subnet
->
getT2
());
boost
::
shared_ptr
<
Option6IAPrefix
>
prefix
(
new
Option6IAPrefix
(
D6O_IAPREFIX
,
lease
->
addr_
,
lease
->
prefixlen_
,
lease
->
preferred_lft_
,
lease
->
valid_lft_
));
ia_rsp
->
addOption
(
prefix
);
bool
skip
=
false
;
// Execute all callouts registered for packet6_send
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_lease6_renew_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete all previous arguments
callout_handle
->
deleteAllArguments
();
// Pass the original packet
callout_handle
->
setArgument
(
"query6"
,
query
);
// Pass the lease to be updated
callout_handle
->
setArgument
(
"lease6"
,
lease
);
// Pass the IA option to be sent in response
callout_handle
->
setArgument
(
"ia_pd"
,
ia_rsp
);
// Call all installed callouts
HooksManager
::
callCallouts
(
Hooks
.
hook_index_lease6_renew_
,
*
callout_handle
);
// Remember hook's instruction whether we want to skip update or not
skip
=
callout_handle
->
getSkip
();
}
if
(
!
skip
)
{
LeaseMgrFactory
::
instance
().
updateLease6
(
lease
);
}
else
{
// 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".
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_HOOKS
,
DHCP6_HOOK_LEASE6_RENEW_SKIP
);
// Copy back the original date to the lease. For MySQL it doesn't make
// much sense, but for memfile, the Lease6Ptr points to the actual lease
// in memfile, so the actual update is performed when we manipulate
// fields of returned Lease6Ptr, the actual updateLease6() is no-op.
*
lease
=
old_data
;
}
return
(
ia_rsp
);
}
void
Dhcpv6Srv
::
renewLeases
(
const
Pkt6Ptr
&
renew
,
Pkt6Ptr
&
reply
,
const
Option6ClientFqdnPtr
&
fqdn
)
{
...
...
@@ -1604,6 +1705,7 @@ Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply,
for
(
Option
::
OptionCollection
::
iterator
opt
=
renew
->
options_
.
begin
();
opt
!=
renew
->
options_
.
end
();
++
opt
)
{
switch
(
opt
->
second
->
getType
())
{
case
D6O_IA_NA
:
{
OptionPtr
answer_opt
=
renewIA_NA
(
subnet
,
duid
,
renew
,
boost
::
dynamic_pointer_cast
<
...
...
@@ -1614,6 +1716,17 @@ Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply,
}
break
;
}
case
D6O_IA_PD
:
{
OptionPtr
answer_opt
=
renewIA_PD
(
subnet
,
duid
,
renew
,
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
opt
->
second
));
if
(
answer_opt
)
{
reply
->
addOption
(
answer_opt
);
}
break
;
}
default:
break
;
}
...
...
@@ -1650,6 +1763,11 @@ Dhcpv6Srv::releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply) {
}
DuidPtr
duid
(
new
DUID
(
opt_duid
->
getData
()));
// Let's set the status to be success by default. We can override it with
// error status if needed. The important thing to understand here is that
// the global status code may be set to success only if all IA options were
// handled properly. Therefore the releaseIA_NA and releaseIA_PD options
// may turn the status code to some error, but can't turn it back to success.
int
general_status
=
STATUS_Success
;
for
(
Option
::
OptionCollection
::
iterator
opt
=
release
->
options_
.
begin
();
opt
!=
release
->
options_
.
end
();
++
opt
)
{
...
...
@@ -1662,7 +1780,14 @@ Dhcpv6Srv::releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply) {
}
break
;
}
// @todo: add support for IA_PD
case
D6O_IA_PD
:
{
OptionPtr
answer_opt
=
releaseIA_PD
(
duid
,
release
,
general_status
,
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
opt
->
second
));
if
(
answer_opt
)
{
reply
->
addOption
(
answer_opt
);
}
break
;
}
// @todo: add support for IA_TA
default:
// remaining options are stateless and thus ignored in this context
...
...
@@ -1696,7 +1821,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
(
ia
->
getOption
(
D6O_IAADDR
));
if
(
!
release_addr
)
{
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"You did not include address in your RELEASE"
));
"You did not include
an
address in your RELEASE"
));
general_status
=
STATUS_NoBinding
;
return
(
ia_rsp
);
}
...
...
@@ -1712,7 +1837,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
"Sorry, no known leases for this duid/iaid, can't release."
));
general_status
=
STATUS_NoBinding
;
LOG_INFO
(
dhcp6_logger
,
DHCP6_UNKNOWN_RELEASE
)
LOG_INFO
(
dhcp6_logger
,
DHCP6_UNKNOWN_RELEASE
_NA
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
());
...
...
@@ -1724,7 +1849,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
// have mandatory DUID information attached. Someone was messing with our
// database.
LOG_ERROR
(
dhcp6_logger
,
DHCP6_LEASE_WITHOUT_DUID
)
LOG_ERROR
(
dhcp6_logger
,
DHCP6_LEASE_
NA_
WITHOUT_DUID
)
.
arg
(
release_addr
->
getAddress
().
toText
());
general_status
=
STATUS_UnspecFail
;
...
...
@@ -1734,9 +1859,9 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
}
if
(
*
duid
!=
*
(
lease
->
duid_
))
{
// Sorry, it's not your address. You can't release it.
LOG_INFO
(
dhcp6_logger
,
DHCP6_RELEASE_FAIL_WRONG_DUID
)
// Sorry, it's not your address. You can't release it.
LOG_INFO
(
dhcp6_logger
,
DHCP6_RELEASE_NA_FAIL_WRONG_DUID
)
.
arg
(
duid
->
toText
())
.
arg
(
release_addr
->
getAddress
().
toText
())
.
arg
(
lease
->
duid_
->
toText
());
...
...
@@ -1749,7 +1874,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
if
(
ia
->
getIAID
()
!=
lease
->
iaid_
)
{
// This address belongs to this client, but to a different IA
LOG_WARN
(
dhcp6_logger
,
DHCP6_RELEASE_FAIL_WRONG_IAID
)
LOG_WARN
(
dhcp6_logger
,
DHCP6_RELEASE_
PD_
FAIL_WRONG_IAID
)
.
arg
(
duid
->
toText
())
.
arg
(
release_addr
->
getAddress
().
toText
())
.
arg
(
lease
->
iaid_
)
...
...
@@ -1765,7 +1890,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
bool
skip
=
false
;
// Execute all callouts registered for packet6_send
if
(
HooksManager
::
getHooksManager
().
calloutsPresent
(
Hooks
.
hook_index_lease6_release_
))
{
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_lease6_release_
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete all previous arguments
...
...
@@ -1785,7 +1910,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
// stage means "drop response".
if
(
callout_handle
->
getSkip
())
{
skip
=
true
;
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_HOOKS
,
DHCP6_HOOK_LEASE6_RELEASE_SKIP
);
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_HOOKS
,
DHCP6_HOOK_LEASE6_RELEASE_
NA_
SKIP
);
}
}
...
...
@@ -1803,7 +1928,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_UnspecFail
,
"Server failed to release a lease"
));
LOG_ERROR
(
dhcp6_logger
,
DHCP6_RELEASE_FAIL
)
LOG_ERROR
(
dhcp6_logger
,
DHCP6_RELEASE_
NA_
FAIL
)
.
arg
(
lease
->
addr_
.
toText
())
.
arg
(
duid
->
toText
())
.
arg
(
lease
->
iaid_
);
...
...
@@ -1811,7 +1936,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
return
(
ia_rsp
);
}
else
{
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_RELEASE
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_RELEASE
_NA
)
.
arg
(
lease
->
addr_
.
toText
())
.
arg
(
duid
->
toText
())
.
arg
(
lease
->
iaid_
);
...
...
@@ -1828,6 +1953,148 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
}
}
OptionPtr
Dhcpv6Srv
::
releaseIA_PD
(
const
DuidPtr
&
duid
,
const
Pkt6Ptr
&
query
,
int
&
general_status
,
boost
::
shared_ptr
<
Option6IA
>
ia
)
{
// Release can be done in one of two ways:
// Approach 1: extract address from client's IA_NA and see if it belongs
// to this particular client.
// Approach 2: find a subnet for this client, get a lease for
// this subnet/duid/iaid and check if its content matches to what the
// client is asking us to release.
//
// This method implements approach 1.
// That's our response. We will fill it in as we check the lease to be
// released.
boost
::
shared_ptr
<
Option6IA
>
ia_rsp
(
new
Option6IA
(
D6O_IA_PD
,
ia
->
getIAID
()));
boost
::
shared_ptr
<
Option6IAPrefix
>
release_prefix
=
boost
::
dynamic_pointer_cast
<
Option6IAPrefix
>
(
ia
->
getOption
(
D6O_IAPREFIX
));
if
(
!
release_prefix
)
{
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"You did not include a prefix in your RELEASE"
));
general_status
=
STATUS_NoBinding
;
return
(
ia_rsp
);
}
Lease6Ptr
lease
=
LeaseMgrFactory
::
instance
().
getLease6
(
Lease
::
TYPE_PD
,
release_prefix
->
getAddress
());
if
(
!
lease
)
{
// Client releasing a lease that we don't know about.
// Insert status code NoBinding.
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"Sorry, no known leases for this duid/iaid, can't release."
));
general_status
=
STATUS_NoBinding
;
LOG_INFO
(
dhcp6_logger
,
DHCP6_UNKNOWN_RELEASE_PD
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
());
return
(
ia_rsp
);
}
if
(
!
lease
->
duid_
)
{
// Something is gravely wrong here. We do have a lease, but it does not
// have mandatory DUID information attached. Someone was messing with our
// database.
LOG_ERROR
(
dhcp6_logger
,
DHCP6_LEASE_PD_WITHOUT_DUID
)
.
arg
(
release_prefix
->
getAddress
().
toText
());
general_status
=
STATUS_UnspecFail
;
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_UnspecFail
,
"Database consistency check failed when trying to RELEASE"
));
return
(
ia_rsp
);
}
if
(
*
duid
!=
*
(
lease
->
duid_
))
{
// Sorry, it's not your address. You can't release it.
LOG_INFO
(
dhcp6_logger
,
DHCP6_RELEASE_PD_FAIL_WRONG_DUID
)
.
arg
(
duid
->
toText
())
.
arg
(
release_prefix
->
getAddress
().
toText
())
.
arg
(
lease
->
duid_
->
toText
());
general_status
=
STATUS_NoBinding
;
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"This address does not belong to you, you can't release it"
));
return
(
ia_rsp
);
}
if
(
ia
->
getIAID
()
!=
lease
->
iaid_
)
{
// This address belongs to this client, but to a different IA
LOG_WARN
(
dhcp6_logger
,
DHCP6_RELEASE_PD_FAIL_WRONG_IAID
)
.
arg
(
duid
->
toText
())
.
arg
(
release_prefix
->
getAddress
().
toText
())
.
arg
(
lease
->
iaid_
)
.
arg
(
ia
->
getIAID
());
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"This is your address, but you used wrong IAID"
));
general_status
=
STATUS_NoBinding
;