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
318530ed
Commit
318530ed
authored
Dec 14, 2012
by
Tomek Mrugalski
🛰
Browse files
[2326] RELEASE support implemented.
parent
b25d6802
Changes
4
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
318530ed
526. [bug] syephen
5XX. [func] tomek
b10-dhcp6: Support for RELEASE message has been added. Clients
are now able to release their non-temporary IPv6 addresses.
(Trac #2326, git TBD)
526. [bug] stephen
Miscellaneous fixes to DHCP code including rationalisation of
some methods in LeaseMgr and resolving some Doxygen/cppcheck
issues.
...
...
src/bin/dhcp6/dhcp6_messages.mes
View file @
318530ed
...
...
@@ -65,6 +65,13 @@ This informational message is printed every time DHCPv6 is started.
It indicates what database backend type is being to store lease and
other information.
% DHCP6_DB_ERROR_LEASE6_WITHOUT_DUID database error: DB returns a lease for address %1 without any DUID
This error message indicates database consistency failure. Database has an entry
for a given address and believes it is currently used, but it does not
contain client-id information. This is most likely a software error.
Please contact ISC. As a temporary workaround, please manually remove
lease entry from the database.
% 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 othe advertised
...
...
@@ -86,6 +93,27 @@ This message indicates that the server failed to grant (in response to
received REQUEST) a lease for a given client. There may be many reasons for
such failure. Each specific failure is logged in a separate log entry.
% DHCP6_RELEASE Address %1 belonging to client duid=%2, iaid=%3 was released properly.
This debug message indicates that an address was released properly. This
is a normal operation during client shutdown.
% DHCP6_RELEASE_FAIL Database failed to remove lease for address %1 for duid=%2, iaid=%3
This error message incidates that database failed to release a lease.
This indicates a database operation error and likely requires administrator
intervention (e.g. check if DHCP process has sufficient priviledges to update
database).
% DHCP6_RELEASE_FAIL_WRONG_DUID Client (duid=%2) tried to release address %2, but it belongs to client (duid=%3)
This warning message indicates that client tried to release an address that
does belong to a different client. This should not happen in normal circumstances,
but since the client is releasing it will stop using released addresses anyway,
so there is a good chance that the situation will correct itself.
% DHCP6_RELEASE_FAIL_WRONG_IAID Client (duid=%2) tried to release address %2, but it used wrong IAID (expected %4, but got %3)
This warning message indicates that client tried to release an address that
does belong to it, but was expected in a different IA container. This likely
means that the client's support for multiple address is buggy.
% 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,
...
...
@@ -216,3 +244,8 @@ 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_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.
src/bin/dhcp6/dhcp6_srv.cc
View file @
318530ed
...
...
@@ -436,6 +436,8 @@ void Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
// We need to allocate addresses for all IA_NA options in the client's
// question (i.e. SOLICIT or REQUEST) message.
// @todo add support for IA_TA
// @todo add support for IA_PD
// We need to select a subnet the client is connected in.
Subnet6Ptr
subnet
=
selectSubnet
(
question
);
...
...
@@ -640,6 +642,8 @@ void Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, 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 need to select a subnet the client is connected in.
Subnet6Ptr
subnet
=
selectSubnet
(
renew
);
...
...
@@ -688,11 +692,169 @@ void Dhcpv6Srv::renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply) {
break
;
}
}
}
void
Dhcpv6Srv
::
releaseLeases
(
const
Pkt6Ptr
&
release
,
Pkt6Ptr
&
reply
)
{
// We need to release addresses for all IA_NA options in the client's
// RELEASE message.
// @todo Add support for IA_TA
// @todo Add support for IA_PD
// @todo Consider supporting more than one address in a single IA_NA.
// That was envisaged by RFC3315, but it never happened. The only
// software that supports that is Dibbler, but its author seriously doubts
// if anyone is really using it. Clients that want more than one address
// just include more instances of IA_NA options.
// 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
=
release
->
getOption
(
D6O_CLIENTID
);
if
(
!
opt_duid
)
{
// This should not happen. We have checked this before.
reply
->
addOption
(
createStatusCode
(
STATUS_UnspecFail
,
"You did not include mandatory client-id"
));
return
;
}
DuidPtr
duid
(
new
DUID
(
opt_duid
->
getData
()));
int
general_status
=
STATUS_Success
;
for
(
Option
::
OptionCollection
::
iterator
opt
=
release
->
options_
.
begin
();
opt
!=
release
->
options_
.
end
();
++
opt
)
{
switch
(
opt
->
second
->
getType
())
{
case
D6O_IA_NA
:
{
OptionPtr
answer_opt
=
releaseIA_NA
(
duid
,
release
,
general_status
,
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
opt
->
second
));
if
(
answer_opt
)
{
reply
->
addOption
(
answer_opt
);
}
break
;
}
default:
break
;
}
}
// To be pedantic, we should also include status code in the top-level
// scope, not just in each IA_NA. See RFC3315, section 18.2.6.
// This behavior will likely go away in RFC3315bis.
reply
->
addOption
(
createStatusCode
(
general_status
,
"Summary status for all processed IA_NAs"
));
}
OptionPtr
Dhcpv6Srv
::
releaseIA_NA
(
const
DuidPtr
&
duid
,
Pkt6Ptr
question
,
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
boost
::
shared_ptr
<
Option6IA
>
ia_rsp
(
new
Option6IA
(
D6O_IA_NA
,
ia
->
getIAID
()));
boost
::
shared_ptr
<
Option6IAAddr
>
release_addr
=
boost
::
dynamic_pointer_cast
<
Option6IAAddr
>
(
ia
->
getOption
(
D6O_IAADDR
));
if
(
!
release_addr
)
{
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"You did not include address in your RELEASE"
));
general_status
=
STATUS_NoBinding
;
return
(
ia_rsp
);
}
Lease6Ptr
lease
=
LeaseMgrFactory
::
instance
().
getLease6
(
release_addr
->
getAddress
());
if
(
!
lease
)
{
// client releasing a lease that we don't know about.
// Insert status code NoAddrsAvail.
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"Sorry, no known leases for this duid/iaid, can't release."
));
general_status
=
STATUS_NoBinding
;
LOG_WARN
(
dhcp6_logger
,
DHCP6_UNKNOWN_RELEASE
)
.
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_DB_ERROR_LEASE6_WITHOUT_DUID
)
.
arg
(
release_addr
->
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_WARN
(
dhcp6_logger
,
DHCP6_RELEASE_FAIL_WRONG_DUID
)
.
arg
(
release_addr
->
getAddress
().
toText
())
.
arg
(
duid
->
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_FAIL_WRONG_IAID
)
.
arg
(
release_addr
->
getAddress
().
toText
())
.
arg
(
duid
->
toText
())
.
arg
(
ia
->
getIAID
())
.
arg
(
lease
->
iaid_
);
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoBinding
,
"This is your address, but you used wrong IAID"
));
general_status
=
STATUS_NoBinding
;
return
(
ia_rsp
);
}
// It is not necessary if the address matches as we used getLease6(addr)
// method that is supposed to return a proper lease.
// Ok, we've passed all checks. Let's release this address.
if
(
!
LeaseMgrFactory
::
instance
().
deleteLease
(
lease
->
addr_
))
{
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_UnspecFail
,
"Server failed to release a lease"
));
LOG_ERROR
(
dhcp6_logger
,
DHCP6_RELEASE_FAIL
)
.
arg
(
lease
->
addr_
.
toText
())
.
arg
(
duid
->
toText
())
.
arg
(
lease
->
iaid_
);
general_status
=
STATUS_UnspecFail
;
return
(
ia_rsp
);
}
else
{
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
DHCP6_RELEASE
)
.
arg
(
lease
->
addr_
.
toText
())
.
arg
(
duid
->
toText
())
.
arg
(
lease
->
iaid_
);
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_Success
,
"Lease released. Thank you, please come again."
));
return
(
ia_rsp
);
}
}
Pkt6Ptr
Dhcpv6Srv
::
processSolicit
(
const
Pkt6Ptr
&
solicit
)
{
sanityCheck
(
solicit
,
MANDATORY
,
FORBIDDEN
);
...
...
@@ -751,8 +913,16 @@ Pkt6Ptr Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
}
Pkt6Ptr
Dhcpv6Srv
::
processRelease
(
const
Pkt6Ptr
&
release
)
{
/// @todo: Implement this
sanityCheck
(
release
,
MANDATORY
,
MANDATORY
);
Pkt6Ptr
reply
(
new
Pkt6
(
DHCPV6_REPLY
,
release
->
getTransid
()));
copyDefaultOptions
(
release
,
reply
);
appendDefaultOptions
(
release
,
reply
);
releaseLeases
(
release
,
reply
);
return
reply
;
}
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
318530ed
...
...
@@ -212,17 +212,39 @@ protected:
/// @brief Renews specific IA_NA option
///
/// Generates response to IA_NA. 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
. 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 question client's message
/// @param ia IA_NA option that is being renewed
/// @return IA_NA option (server's response)
OptionPtr
renewIA_NA
(
const
Subnet6Ptr
&
subnet
,
const
DuidPtr
&
duid
,
Pkt6Ptr
question
,
boost
::
shared_ptr
<
Option6IA
>
ia
);
/// @brief Releases specific IA_NA option
///
/// Generates response to IA_NA in Release message. This covers finding and
/// removal of 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.
///
/// As RFC3315 requires to also send global (one for the whole message),
/// this method may update passed general_status. It is set to SUCCESS
/// when message processing begins, but may be update to some error code
/// if release process fails.
///
/// @param duid client's duid
/// @param question client's message
/// @param general_status a global status (it may be updated in case of errors)
/// @param ia IA_NA option that is being renewed
/// @return IA_NA option (server's response)
OptionPtr
releaseIA_NA
(
const
DuidPtr
&
duid
,
Pkt6Ptr
question
,
int
&
general_status
,
boost
::
shared_ptr
<
Option6IA
>
ia
);
/// @brief Copies required options from client message to server answer.
///
/// Copies options that must appear in any server response (ADVERTISE, REPLY)
...
...
@@ -271,6 +293,17 @@ protected:
/// @param reply server's response
void
renewLeases
(
const
Pkt6Ptr
&
renew
,
Pkt6Ptr
&
reply
);
/// @brief Attempts to release received addresses
///
/// It iterates through received IA_NA options and attempts to release
/// received addresses. If no such leases are found, or the lease fails
/// proper checks (e.g. belongs to someone else), a proper status
/// code is added to reply message. Released addresses are not added
/// to REPLY packet, just its IA_NA containers.
/// @param release client's message asking to release
/// @param reply server's response
void
releaseLeases
(
const
Pkt6Ptr
&
release
,
Pkt6Ptr
&
reply
);
/// @brief Sets server-identifier.
///
/// This method attempts to set server-identifier DUID. It loads it
...
...
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