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
fb010f7b
Commit
fb010f7b
authored
Feb 20, 2014
by
Marcin Siodelski
Browse files
[3232] Refactored the srv code to have common bits for IA_NA Renew/Rebind
parent
fe7ae0a7
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp6/dhcp6_messages.mes
View file @
fb010f7b
...
...
@@ -110,6 +110,48 @@ 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_EXTEND_LEASE_SUBNET_SELECTED the %1 subnet was selected for client extending its lease
This is a debug message informing that a given subnet was selected. It will
be used for extending lifetime of the lease. This is one of the early steps
in the processing of incoming client message.
% DHCP6_EXTEND_LEASE_SUBNET_SELECT_FAILED failed to select a subnet for received %1: src=%2 type=%3
This warning message is output when a Renew or Rebind was received from a
subnet for which the DHCPv6 server has not been configured. The cause is
most likely due to a misconfiguration of the server. The packet processing
will continue, but the response will only contain generic configuration
parameters and no addresses or prefixes.
% DHCP6_EXTEND_NA_UNKNOWN received unknown IA_NA from client (duid=%1, iaid=%2) in subnet %3
This warning message is printed when client attempts to extend the lease
for the address (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.
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_EXTEND_NA_UNKNOWN_SUBNET %1 message received from client on unknown subnet (duid=%2, iaid=%3)
A warning message indicating that a client is attempting to extend lease lifetime
for the address, but the server does not have any information about the subnet this
client belongs to. This may mean that faulty the mobile client changed its location
and is trying to renew its old address (client is supposed to send confirm, not rewew
in such cases, according to RFC3315) or the server configuration has changed and
information about existing subnet was removed. Note that in a sense this is worse
case of DHCP6_EXTEND_NA_UNKNOWN, as not only the lease is unknown, but also the subnet
is. Depending on the reasons of this condition, it may or may not correct on its own.
% DHCP6_EXTEND_PD_UNKNOWN_SUBNET %1 message received from client on unknown subnet (duid=%2, iaid=%3)
A warning message indicating that a client is attempting to extend lease lifetime
for the prefix, but the server doesn't have any information about the subnet this
client belongs to.
% 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
...
...
@@ -122,13 +164,13 @@ 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
renew
ed because a callout set the skip flag
% DHCP6_HOOK_LEASE6_
EXTEND
_SKIP DHCPv6 lease
lifetime
was not
extend
ed because a callout set the skip flag
for message %1
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
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.
or lease6_rebind
hook point set the skip flag. For this particular hook
point, the setting
of the flag by a callout instructs the server to not
extend the lifetime for a lease. If
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_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
...
...
@@ -396,16 +438,6 @@ mandatory client-id option. This is most likely caused by a buggy client
(or a relay that malformed forwarded message). This request will not be
processed and a response with error status code will be sent back.
% DHCP6_RENEW_UNKNOWN_SUBNET RENEW message received from client on unknown subnet (duid=%1, iaid=%2)
A warning message indicating that a client is attempting to renew his lease,
but the server does not have any information about the subnet this client belongs
to. This may mean that faulty the mobile client changed its location and is trying to
renew its old address (client is supposed to send confirm, not rewew in such cases,
according to RFC3315) or the server configuration has changed and information about
existing subnet was removed. Note that in a sense this is worse case of DHCP6_UNKNOWN_RENEW,
as not only the lease is unknown, but also the subnet is. Depending on the reasons
of this condition, it may or may not correct on its own.
% DHCP6_REQUIRED_OPTIONS_CHECK_FAIL %1 message received from %2 failed the following check: %3
This message indicates that received DHCPv6 packet is invalid. This may be due
to a number of reasons, e.g. the mandatory client-id option is missing,
...
...
@@ -515,21 +547,6 @@ 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.
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_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 an address lease
(in IA_NA option), but no such lease is known by the server. It typically means
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
fb010f7b
...
...
@@ -71,6 +71,7 @@ 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_lease6_renew_
;
///< index for "lease6_renew" hook point
int
hook_index_lease6_rebind_
;
///< index for "lease6_rebind" hook point
int
hook_index_lease6_release_
;
///< index for "lease6_release" hook point
int
hook_index_pkt6_send_
;
///< index for "pkt6_send" hook point
int
hook_index_buffer6_send_
;
///< index for "buffer6_send" hook point
...
...
@@ -81,6 +82,7 @@ struct Dhcp6Hooks {
hook_index_pkt6_receive_
=
HooksManager
::
registerHook
(
"pkt6_receive"
);
hook_index_subnet6_select_
=
HooksManager
::
registerHook
(
"subnet6_select"
);
hook_index_lease6_renew_
=
HooksManager
::
registerHook
(
"lease6_renew"
);
hook_index_lease6_rebind_
=
HooksManager
::
registerHook
(
"lease6_rebind"
);
hook_index_lease6_release_
=
HooksManager
::
registerHook
(
"lease6_release"
);
hook_index_pkt6_send_
=
HooksManager
::
registerHook
(
"pkt6_send"
);
hook_index_buffer6_send_
=
HooksManager
::
registerHook
(
"buffer6_send"
);
...
...
@@ -1499,18 +1501,26 @@ Dhcpv6Srv::assignIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
}
OptionPtr
Dhcpv6Srv
::
renew
IA_NA
(
const
Subnet6Ptr
&
subnet
,
const
DuidPtr
&
duid
,
const
Pkt6Ptr
&
query
,
const
Pkt6Ptr
&
answer
,
boost
::
shared_ptr
<
Option6IA
>
ia
)
{
Dhcpv6Srv
::
extend
IA_NA
(
const
Subnet6Ptr
&
subnet
,
const
DuidPtr
&
duid
,
const
Pkt6Ptr
&
query
,
const
Pkt6Ptr
&
answer
,
boost
::
shared_ptr
<
Option6IA
>
ia
)
{
if
(
!
subnet
)
{
// There's no subnet select for this client. There's nothing to renew.
boost
::
shared_ptr
<
Option6IA
>
ia_rsp
(
new
Option6IA
(
D6O_IA_NA
,
ia
->
getIAID
()));
// Insert status code NoAddrsAvail.
/// @todo For simpliclty and due to limitations of LeaseMgr we don't
/// get the binding for the client for which we don't get subnet id.
/// Subnet id is a required value when searching for the bindings.
/// The fact that we can't identify the subnet for the returning client
/// doesn't really mean that the client has no binding. It is possible
/// that due to server's reconfiguration the subnet has been removed
/// or modified since the client has got his lease. However, we think
/// it is fine to send NoBinding status code because this code is
/// supposed to be sent when server doesn't find the binding for
/// the client (which is the case here).
Option6IAPtr
ia_rsp
(
new
Option6IA
(
D6O_IA_NA
,
ia
->
getIAID
()));
// 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
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_EXTEND_NA_UNKNOWN_SUBNET
)
.
arg
(
query
->
getName
()
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
());
...
...
@@ -1521,17 +1531,17 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
*
duid
,
ia
->
getIAID
(),
subnet
->
getID
());
// Client extending a lease that we don't know about.
if
(
!
lease
)
{
// client renewing a lease that we don't know about.
// Create empty IA_NA option with IAID matching the request.
boost
::
shared_ptr
<
Option6IA
>
ia_rsp
(
new
Option6IA
(
D6O_IA_NA
,
ia
->
getIAID
()));
// Insert status code NoAddrsAvail.
// Insert status code NoBinding to indicate that the lease does not
// exist for this client.
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"Sorry, no known leases for this duid/iaid."
));
"Sorry, no known leases for this duid/iaid
/subnet
."
));
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_
UNKNOWN_RENEW_NA
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_
EXTEND_NA_UNKNOWN
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
())
.
arg
(
subnet
->
toText
());
...
...
@@ -1539,7 +1549,7 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
return
(
ia_rsp
);
}
// Keep the old data in case the callout tells us to skip update
// Keep the old data in case the callout tells us to skip update
.
Lease6
old_data
=
*
lease
;
// At this point, we have to make make some decisions with respect to the
...
...
@@ -1601,8 +1611,10 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
ia_rsp
->
addOption
(
addr
);
bool
skip
=
false
;
// Execute all callouts registered for packet6_send
if
(
HooksManager
::
calloutsPresent
(
Hooks
.
hook_index_lease6_renew_
))
{
// Get the callouts specific for the processed message and execute them.
int
hook_point
=
query
->
getType
()
==
DHCPV6_RENEW
?
Hooks
.
hook_index_lease6_renew_
:
Hooks
.
hook_index_lease6_rebind_
;
if
(
HooksManager
::
calloutsPresent
(
hook_point
))
{
CalloutHandlePtr
callout_handle
=
getCalloutHandle
(
query
);
// Delete all previous arguments
...
...
@@ -1618,14 +1630,16 @@ Dhcpv6Srv::renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
callout_handle
->
setArgument
(
"ia_na"
,
ia_rsp
);
// Call all installed callouts
HooksManager
::
callCallouts
(
Hooks
.
hook_index_lease6_renew_
,
*
callout_handle
);
HooksManager
::
callCallouts
(
hook_point
,
*
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
(
dhcp6_logger
,
DBG_DHCP6_HOOKS
,
DHCP6_HOOK_LEASE6_RENEW_SKIP
);
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_HOOKS
,
DHCP6_HOOK_LEASE6_EXTEND_SKIP
)
.
arg
(
query
->
getName
());
}
}
...
...
@@ -1654,7 +1668,7 @@ Dhcpv6Srv::renewIA_PD(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_
RENEW
_UNKNOWN_SUBNET
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_
EXTEND_PD
_UNKNOWN_SUBNET
)
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
());
...
...
@@ -1731,7 +1745,7 @@ Dhcpv6Srv::renewIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
// 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
);
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_HOOKS
,
DHCP6_HOOK_LEASE6_
EXTEND
_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
...
...
@@ -1744,15 +1758,16 @@ Dhcpv6Srv::renewIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
}
void
Dhcpv6Srv
::
renew
Leases
(
const
Pkt6Ptr
&
renew
,
Pkt6Ptr
&
reply
)
{
Dhcpv6Srv
::
extend
Leases
(
const
Pkt6Ptr
&
query
,
Pkt6Ptr
&
reply
)
{
// We need to renew addresses for all IA_NA options in the client's
// RENEW message.
// @todo add support for IA_TA
// @todo add support for IA_PD
// We will try to extend lease lifetime for all IA options in the client's
// Renew or Rebind message.
/// @todo add support for IA_TA
// We need to select a subnet the client is connected in.
Subnet6Ptr
subnet
=
selectSubnet
(
renew
);
// We need to select a subnet the client is connected in. This is needed
// to get the client's bindings from the lease database. The subnet id
// is one of the lease search parameters.
Subnet6Ptr
subnet
=
selectSubnet
(
query
);
if
(
!
subnet
)
{
// This particular client is out of luck today. We do not have
// information about the subnet he is connected to. This likely means
...
...
@@ -1761,20 +1776,24 @@ Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply) {
// addresses or prefixes, no subnet specific configuration etc. The only
// thing this client can get is some global information (like DNS
// servers).
LOG_WARN
(
dhcp6_logger
,
DHCP6_SUBNET_SELECTION_FAILED
)
.
arg
(
renew
->
getRemoteAddr
().
toText
())
.
arg
(
renew
->
getName
());
LOG_WARN
(
dhcp6_logger
,
DHCP6_EXTEND_LEASE_SUBNET_SELECT_FAILED
)
.
arg
(
query
->
getName
()
)
.
arg
(
query
->
getRemoteAddr
().
toText
())
.
arg
(
query
->
getName
());
}
else
{
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL_DATA
,
DHCP6_SUBNET_SELECTED
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL_DATA
,
DHCP6_EXTEND_LEASE_SUBNET_SELECTED
)
.
arg
(
subnet
->
toText
());
}
// Let's find client's DUID. Client is supposed to include its client-id
// option almost all the time (the only exception is an anonymous inf-request,
// but that is mostly a theoretical case). Our allocation engine needs DUID
// and will refuse to allocate anything to anonymous clients.
OptionPtr
opt_duid
=
renew
->
getOption
(
D6O_CLIENTID
);
// option almost all the time (the only exception is an anonymous
// inf-request, but that is mostly a theoretical case). Our allocation
// engine needs DUID and will refuse to allocate anything to anonymous
// clients.
/// @todo Consider removing this check from here and rely on what we have
/// checked on the earlier processing stage.
OptionPtr
opt_duid
=
query
->
getOption
(
D6O_CLIENTID
);
if
(
!
opt_duid
)
{
// This should not happen. We have checked this before.
reply
->
addOption
(
createStatusCode
(
STATUS_UnspecFail
,
...
...
@@ -1783,14 +1802,13 @@ Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply) {
}
DuidPtr
duid
(
new
DUID
(
opt_duid
->
getData
()));
for
(
OptionCollection
::
iterator
opt
=
renew
->
options_
.
begin
();
opt
!=
renew
->
options_
.
end
();
++
opt
)
{
for
(
OptionCollection
::
iterator
opt
=
query
->
options_
.
begin
();
opt
!=
query
->
options_
.
end
();
++
opt
)
{
switch
(
opt
->
second
->
getType
())
{
case
D6O_IA_NA
:
{
OptionPtr
answer_opt
=
renew
IA_NA
(
subnet
,
duid
,
renew
,
reply
,
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
opt
->
second
));
OptionPtr
answer_opt
=
extend
IA_NA
(
subnet
,
duid
,
query
,
reply
,
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
opt
->
second
));
if
(
answer_opt
)
{
reply
->
addOption
(
answer_opt
);
}
...
...
@@ -1798,7 +1816,7 @@ Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply) {
}
case
D6O_IA_PD
:
{
OptionPtr
answer_opt
=
renewIA_PD
(
subnet
,
duid
,
renew
,
OptionPtr
answer_opt
=
renewIA_PD
(
subnet
,
duid
,
query
,
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
opt
->
second
));
if
(
answer_opt
)
{
...
...
@@ -2230,7 +2248,7 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
appendRequestedOptions
(
renew
,
reply
);
processClientFqdn
(
renew
,
reply
);
renew
Leases
(
renew
,
reply
);
extend
Leases
(
renew
,
reply
);
generateFqdn
(
reply
);
createNameChangeRequests
(
reply
);
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
fb010f7b
...
...
@@ -253,23 +253,25 @@ protected:
const
Pkt6Ptr
&
query
,
boost
::
shared_ptr
<
Option6IA
>
ia
);
/// @brief
Renews
specific IA_NA option
/// @brief
Extends lifetime of the
specific IA_NA option
.
///
/// Generates response to IA_NA in Renew. This typically includes finding a
/// lease that corresponds to the received address. If no such lease is
/// found, an IA_NA response is generated with an appropriate status code.
/// Generates response to IA_NA in Renew or Rebind. This typically includes
/// finding a lease that corresponds to the received address. If no such
/// lease is found, an IA_NA response is generated with an appropriate
/// status code.
///
/// @param subnet subnet the sender belongs to
/// @param duid client's duid
/// @param query client's message
/// @param query client's message
(Renew or Rebind)
/// @param answer server's response to the client's message. This
/// message should contain Client FQDN option being sent by the server
/// to the client (if the client sent this option to the server).
/// @param ia IA_NA option that is being renewed
/// @param ia IA_NA option which carries adress for which lease lifetime
/// will be extended.
/// @return IA_NA option (server's response)
OptionPtr
renew
IA_NA
(
const
Subnet6Ptr
&
subnet
,
const
DuidPtr
&
duid
,
const
Pkt6Ptr
&
query
,
const
Pkt6Ptr
&
answer
,
boost
::
shared_ptr
<
Option6IA
>
ia
);
OptionPtr
extend
IA_NA
(
const
Subnet6Ptr
&
subnet
,
const
DuidPtr
&
duid
,
const
Pkt6Ptr
&
query
,
const
Pkt6Ptr
&
answer
,
boost
::
shared_ptr
<
Option6IA
>
ia
);
/// @brief Renews specific IA_PD option
///
...
...
@@ -438,15 +440,17 @@ protected:
/// NameChangeSender will be used to deliver requests to the other module.
void
sendNameChangeRequests
();
/// @brief Attempts to renew received addresses
/// @brief Attempts to extend the lifetime of IAs.
///
/// This function is called when a client sends Renew or Rebind message.
/// It iterates through received IA options and attempts to extend
/// corresponding lease lifetimes. Internally, it calls
/// @c Dhcpv6Srv::extendIA_NA and @c Dhcpv6Srv::extendIA_PD to extend
/// the lifetime of IA_NA and IA_PD leases accordingly.
///
/// It iterates through received IA_NA options and attempts to renew
/// received addresses. If no such leases are found, proper status
/// code is added to reply message. Renewed addresses are added
/// as IA_NA/IAADDR to reply packet.
/// @param renew client's message asking for renew
/// @param query client's Renew or Rebind message
/// @param reply server's response
void
renew
Leases
(
const
Pkt6Ptr
&
renew
,
Pkt6Ptr
&
reply
);
void
extend
Leases
(
const
Pkt6Ptr
&
query
,
Pkt6Ptr
&
reply
);
/// @brief Attempts to release received addresses
///
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment