Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
9ce50790
Commit
9ce50790
authored
Feb 13, 2015
by
Tomek Mrugalski
🛰
Browse files
[master] Merge branch 'trac3677' (DHCPv6 renewals with reservations)
Conflicts: src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
parents
b7407dd5
a339db38
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp6/dhcp6_messages.mes
View file @
9ce50790
# Copyright (C) 2012-201
4
Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2012-201
5
Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
...
...
@@ -91,8 +91,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
New values: hostname = %2, reverse mapping = %3, forward mapping = %4
% 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.
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
9ce50790
This diff is collapsed.
Click to expand it.
src/bin/dhcp6/dhcp6_srv.h
View file @
9ce50790
// Copyright (C) 2011-201
4
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
5
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -667,6 +667,21 @@ private:
/// as a programmatic error.
void
generateFqdn
(
const
Pkt6Ptr
&
answer
);
/// @brief Triggers removal Name Change Request if FQDN data changes in leases
///
/// If there are any differences (different fwd or rev flags, or different
/// hostname) a DNS update for removing entry will be generated.
///
/// @param old_lease old version of the lease
/// @param new_lease new version of the lease (may be NULL)
/// @param hostname specifies hostname (for printing purposes)
/// @param do_fwd specifies if reverse updates are enabled (for printing purposes)
/// @param do_rev specifies if reverse updates are enabled (for printing purposes)
void
conditionalNCRRemoval
(
Lease6Ptr
&
old_lease
,
Lease6Ptr
&
new_lease
,
const
std
::
string
&
hostname
,
bool
do_fwd
,
bool
do_rev
);
/// @brief Allocation Engine.
/// Pointer to the allocation engine that we are currently using
/// It must be a pointer, because we will support changing engines
...
...
src/bin/dhcp6/tests/dhcp6_client.cc
View file @
9ce50790
...
...
@@ -88,7 +88,8 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
case
D6O_IAADDR
:
{
Option6IAAddrPtr
iaaddr
=
boost
::
dynamic_pointer_cast
<
Option6IAAddr
>
(
ia
->
getOption
(
D6O_IAADDR
));
Option6IAAddr
>
(
ia_opt
);
if
(
!
iaaddr
)
{
// There is no address. This IA option may simply
// contain a status code, so let's just reset the
...
...
@@ -113,7 +114,7 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
case
D6O_IAPREFIX
:
{
Option6IAPrefixPtr
iaprefix
=
boost
::
dynamic_pointer_cast
<
Option6IAPrefix
>
(
ia
->
getOption
(
D6O_IAPREFIX
)
);
Option6IAPrefix
>
(
ia
_opt
);
if
(
!
iaprefix
)
{
// There is no prefix. This IA option may simply
// contain a status code, so let's just reset the
...
...
src/bin/dhcp6/tests/dhcp6_client.h
View file @
9ce50790
...
...
@@ -406,6 +406,12 @@ public:
oro_
.
push_back
(
option_code
);
}
/// @brief returns client-id
/// @return client-id
DuidPtr
getDuid
()
const
{
return
(
duid_
);
}
private:
/// @brief Applies the new leases for the client.
...
...
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
9ce50790
...
...
@@ -81,7 +81,8 @@ TEST_F(NakedDhcpv6SrvTest, SolicitNoSubnet) {
Pkt6Ptr
reply
=
srv
.
processSolicit
(
sol
);
// check that we get the right NAK
checkNakResponse
(
reply
,
DHCPV6_ADVERTISE
,
1234
,
STATUS_NoAddrsAvail
);
checkNakResponse
(
reply
,
DHCPV6_ADVERTISE
,
1234
,
STATUS_NoAddrsAvail
,
0
,
0
);
}
// This test verifies that incoming REQUEST can be handled properly when
...
...
@@ -113,7 +114,8 @@ TEST_F(NakedDhcpv6SrvTest, RequestNoSubnet) {
Pkt6Ptr
reply
=
srv
.
processRequest
(
req
);
// check that we get the right NAK
checkNakResponse
(
reply
,
DHCPV6_REPLY
,
1234
,
STATUS_NoAddrsAvail
);
checkNakResponse
(
reply
,
DHCPV6_REPLY
,
1234
,
STATUS_NoAddrsAvail
,
0
,
0
);
}
// This test verifies that incoming RENEW can be handled properly, even when
...
...
@@ -148,7 +150,8 @@ TEST_F(NakedDhcpv6SrvTest, RenewNoSubnet) {
Pkt6Ptr
reply
=
srv
.
processRenew
(
req
);
// check that we get the right NAK
checkNakResponse
(
reply
,
DHCPV6_REPLY
,
1234
,
STATUS_NoBinding
);
checkNakResponse
(
reply
,
DHCPV6_REPLY
,
1234
,
STATUS_NoBinding
,
0
,
0
);
}
// This test verifies that incoming RELEASE can be handled properly, even when
...
...
@@ -183,7 +186,7 @@ TEST_F(NakedDhcpv6SrvTest, ReleaseNoSubnet) {
Pkt6Ptr
reply
=
srv
.
processRelease
(
req
);
// check that we get the right NAK
checkNakResponse
(
reply
,
DHCPV6_REPLY
,
1234
,
STATUS_NoBinding
);
checkNakResponse
(
reply
,
DHCPV6_REPLY
,
1234
,
STATUS_NoBinding
,
0
,
0
);
}
// Test verifies that the Dhcpv6_srv class can be instantiated. It checks a mode
...
...
src/bin/dhcp6/tests/dhcp6_test_utils.cc
View file @
9ce50790
...
...
@@ -285,10 +285,10 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type, const std::string& existing_addr
}
// Check that T1, T2, preferred, valid and cltt were really updated
EXPECT_EQ
(
l
->
t1_
,
subnet_
->
getT1
());
EXPECT_EQ
(
l
->
t2_
,
subnet_
->
getT2
());
EXPECT_EQ
(
l
->
preferred_lft_
,
subnet_
->
getPreferred
());
EXPECT_EQ
(
l
->
valid_lft_
,
subnet_
->
getValid
());
EXPECT_EQ
(
subnet_
->
getT1
()
,
l
->
t1_
);
EXPECT_EQ
(
subnet_
->
getT2
()
,
l
->
t2_
);
EXPECT_EQ
(
subnet_
->
getPreferred
()
,
l
->
preferred_lft_
);
EXPECT_EQ
(
subnet_
->
getValid
()
,
l
->
valid_lft_
);
// Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
int32_t
cltt
=
static_cast
<
int32_t
>
(
l
->
cltt_
);
...
...
@@ -349,7 +349,7 @@ Dhcpv6SrvTest::testRenewReject(Lease::Type type, const IOAddress& addr) {
// Check that IA_?? was returned and that there's proper status code
boost
::
shared_ptr
<
Option6IA
>
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
,
subnet_
->
getT1
(),
subnet_
->
getT2
()
);
// Check that there is no lease added
l
=
LeaseMgrFactory
::
instance
().
getLease6
(
type
,
addr
);
...
...
@@ -375,7 +375,7 @@ Dhcpv6SrvTest::testRenewReject(Lease::Type type, const IOAddress& addr) {
// Check that IA_?? was returned and that there's proper status code
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
,
subnet_
->
getT1
(),
subnet_
->
getT2
()
);
// There is a iaid mis-match, so server should respond that there is
// no such address to renew.
...
...
@@ -395,7 +395,7 @@ Dhcpv6SrvTest::testRenewReject(Lease::Type type, const IOAddress& addr) {
// Check that IA_?? was returned and that there's proper status code
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
,
subnet_
->
getT1
(),
subnet_
->
getT2
()
);
lease
=
LeaseMgrFactory
::
instance
().
getLease6
(
type
,
addr
);
ASSERT_TRUE
(
lease
);
...
...
@@ -457,7 +457,7 @@ Dhcpv6SrvTest::testReleaseBasic(Lease::Type type, const IOAddress& existing,
// Check that IA_NA was returned and that there's an address included
boost
::
shared_ptr
<
Option6IA
>
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
checkIA_NAStatusCode
(
ia
,
STATUS_Success
);
checkIA_NAStatusCode
(
ia
,
STATUS_Success
,
0
,
0
);
checkMsgStatusCode
(
reply
,
STATUS_Success
);
// There should be no address returned in RELEASE (see RFC3315, 18.2.6)
...
...
@@ -528,7 +528,7 @@ Dhcpv6SrvTest::testReleaseReject(Lease::Type type, const IOAddress& addr) {
// Check that IA_NA/IA_PD was returned and that there's status code in it
boost
::
shared_ptr
<
Option6IA
>
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
,
0
,
0
);
checkMsgStatusCode
(
reply
,
STATUS_NoBinding
);
// Check that the lease is not there
...
...
@@ -556,7 +556,7 @@ Dhcpv6SrvTest::testReleaseReject(Lease::Type type, const IOAddress& addr) {
// Check that IA_?? was returned and that there's proper status code
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
,
0
,
0
);
checkMsgStatusCode
(
reply
,
STATUS_NoBinding
);
// Check that the lease is still there
...
...
@@ -580,7 +580,7 @@ Dhcpv6SrvTest::testReleaseReject(Lease::Type type, const IOAddress& addr) {
// Check that IA_?? was returned and that there's proper status code
ia
=
boost
::
dynamic_pointer_cast
<
Option6IA
>
(
tmp
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
);
checkIA_NAStatusCode
(
ia
,
STATUS_NoBinding
,
0
,
0
);
checkMsgStatusCode
(
reply
,
STATUS_NoBinding
);
// Check that the lease is still there
...
...
@@ -651,6 +651,56 @@ Dhcpv6SrvTest::compareOptions(const isc::dhcp::OptionPtr& option1,
return
(
!
memcmp
(
buf1
.
getData
(),
buf2
.
getData
(),
buf1
.
getLength
()));
}
void
NakedDhcpv6SrvTest
::
checkIA_NAStatusCode
(
const
boost
::
shared_ptr
<
isc
::
dhcp
::
Option6IA
>&
ia
,
uint16_t
expected_status_code
,
uint32_t
expected_t1
,
uint32_t
expected_t2
)
{
// Make sure there is no address assigned. Depending on the situation,
// the server will either not return the address at all and sometimes
// it will return it with zeroed lifetimes.
dhcp
::
OptionCollection
options
=
ia
->
getOptions
();
for
(
isc
::
dhcp
::
OptionCollection
::
iterator
opt
=
options
.
begin
();
opt
!=
options
.
end
();
++
opt
)
{
if
(
opt
->
second
->
getType
()
!=
D6O_IAADDR
)
{
continue
;
}
dhcp
::
Option6IAAddrPtr
addr
=
boost
::
dynamic_pointer_cast
<
isc
::
dhcp
::
Option6IAAddr
>
(
opt
->
second
);
ASSERT_TRUE
(
addr
);
EXPECT_EQ
(
0
,
addr
->
getPreferred
());
EXPECT_EQ
(
0
,
addr
->
getValid
());
}
// T1, T2 should NOT be zeroed. draft-ietf-dhc-dhcpv6-stateful-issues-10,
// section 4.4.6 says says that T1,T2 should be consistent along all
// provided IA options.
EXPECT_EQ
(
expected_t1
,
ia
->
getT1
());
EXPECT_EQ
(
expected_t2
,
ia
->
getT2
());
isc
::
dhcp
::
OptionCustomPtr
status
=
boost
::
dynamic_pointer_cast
<
isc
::
dhcp
::
OptionCustom
>
(
ia
->
getOption
(
D6O_STATUS_CODE
));
// It is ok to not include status success as this is the default
// behavior
if
(
expected_status_code
==
STATUS_Success
&&
!
status
)
{
return
;
}
EXPECT_TRUE
(
status
);
if
(
status
)
{
// We don't have dedicated class for status code, so let's
// just interpret first 2 bytes as status. Remainder of the
// status code option content is just a text explanation
// what went wrong.
EXPECT_EQ
(
static_cast
<
uint16_t
>
(
expected_status_code
),
status
->
readInteger
<
uint16_t
>
(
0
));
}
}
};
// end of isc::test namespace
};
// end of isc namespace
src/bin/dhcp6/tests/dhcp6_test_utils.h
View file @
9ce50790
...
...
@@ -27,6 +27,7 @@
#include <dhcp/option6_iaprefix.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_custom.h>
#include <dhcp/option.h>
#include <dhcp/iface_mgr.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease_mgr.h>
...
...
@@ -211,7 +212,8 @@ public:
void
checkNakResponse
(
const
isc
::
dhcp
::
Pkt6Ptr
&
rsp
,
uint8_t
expected_message_type
,
uint32_t
expected_transid
,
uint16_t
expected_status_code
)
uint16_t
expected_status_code
,
uint32_t
expected_t1
,
uint32_t
expected_t2
)
{
// Check if we get response at all
checkResponse
(
rsp
,
expected_message_type
,
expected_transid
);
...
...
@@ -225,7 +227,8 @@ public:
boost
::
dynamic_pointer_cast
<
isc
::
dhcp
::
Option6IA
>
(
option_ia_na
);
ASSERT_TRUE
(
ia
);
checkIA_NAStatusCode
(
ia
,
expected_status_code
);
checkIA_NAStatusCode
(
ia
,
expected_status_code
,
expected_t1
,
expected_t2
);
}
// Checks that server rejected IA_NA, i.e. that it has no addresses and
...
...
@@ -238,36 +241,8 @@ public:
// as this is the default result and it saves bandwidth)
void
checkIA_NAStatusCode
(
const
boost
::
shared_ptr
<
isc
::
dhcp
::
Option6IA
>&
ia
,
uint16_t
expected_status_code
)
{
// Make sure there is no address assigned.
EXPECT_FALSE
(
ia
->
getOption
(
D6O_IAADDR
));
// T1, T2 should be zeroed
EXPECT_EQ
(
0
,
ia
->
getT1
());
EXPECT_EQ
(
0
,
ia
->
getT2
());
isc
::
dhcp
::
OptionCustomPtr
status
=
boost
::
dynamic_pointer_cast
<
isc
::
dhcp
::
OptionCustom
>
(
ia
->
getOption
(
D6O_STATUS_CODE
));
// It is ok to not include status success as this is the default
// behavior
if
(
expected_status_code
==
STATUS_Success
&&
!
status
)
{
return
;
}
EXPECT_TRUE
(
status
);
if
(
status
)
{
// We don't have dedicated class for status code, so let's
// just interpret first 2 bytes as status. Remainder of the
// status code option content is just a text explanation
// what went wrong.
EXPECT_EQ
(
static_cast
<
uint16_t
>
(
expected_status_code
),
status
->
readInteger
<
uint16_t
>
(
0
));
}
}
uint16_t
expected_status_code
,
uint32_t
expected_t1
,
uint32_t
expected_t2
);
void
checkMsgStatusCode
(
const
isc
::
dhcp
::
Pkt6Ptr
&
msg
,
uint16_t
expected_status
)
...
...
@@ -397,8 +372,8 @@ public:
// an ostream, which means it can't be used in EXPECT_EQ.
EXPECT_TRUE
(
subnet_
->
inPool
(
type
,
addr
->
getAddress
()));
EXPECT_EQ
(
expected_addr
.
toText
(),
addr
->
getAddress
().
toText
());
EXPECT_EQ
(
addr
->
getPreferred
(),
subnet_
->
getPreferred
());
EXPECT_EQ
(
addr
->
getValid
(),
subnet_
->
getValid
());
EXPECT_EQ
(
subnet_
->
getPreferred
(),
addr
->
getPreferred
());
EXPECT_EQ
(
subnet_
->
getValid
(),
addr
->
getValid
());
}
// Checks if the lease sent to client is present in the database
...
...
src/bin/dhcp6/tests/fqdn_unittest.cc
View file @
9ce50790
// Copyright (C) 2013-201
4
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-201
5
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -414,7 +414,7 @@ public:
ASSERT_NO_THROW
(
reply
=
srv_
->
processRequest
(
req
));
}
else
if
(
msg_type
==
DHCPV6_RENEW
)
{
ASSERT_NO_THROW
(
reply
=
srv_
->
processRe
quest
(
req
));
ASSERT_NO_THROW
(
reply
=
srv_
->
processRe
new
(
req
));
}
else
if
(
msg_type
==
DHCPV6_RELEASE
)
{
// For Release no lease will be acquired so we have to leave
...
...
src/bin/dhcp6/tests/rebind_unittest.cc
View file @
9ce50790
...
...
@@ -262,15 +262,21 @@ TEST_F(RebindTest, directClientChangingSubnet) {
configure
(
REBIND_CONFIGS
[
1
],
*
client
.
getServer
());
// Try to rebind, using the address that the client had acquired using
// previous server configuration.
ASSERT_NO_THROW
(
client
.
doRebind
());
// We are expecting that the server didn't extend the lease because
// the address that client is using doesn't match the new subnet.
// But, the client still has an old lease.
ASSERT_EQ
(
1
,
client
.
getLeaseNum
());
Lease6
lease_client2
=
client
.
getLease
(
0
);
// The current lease should be exactly the same as old lease,
// because server shouldn't have extended.
EXPECT_TRUE
(
lease_client
==
lease_client2
);
EXPECT_TRUE
(
lease_client
.
addr_
==
lease_client2
.
addr_
);
EXPECT_EQ
(
0
,
lease_client2
.
preferred_lft_
);
EXPECT_EQ
(
0
,
lease_client2
.
valid_lft_
);
// Make sure, that the lease that client has, is matching the lease
// in the lease database.
Lease6Ptr
lease_server2
=
checkLease
(
lease_client2
);
...
...
@@ -480,13 +486,31 @@ TEST_F(RebindTest, relayedClientChangingAddress) {
<<
"The server discarded the Rebind message, while it should have"
" sent a response indicating that the client should stop using the"
" lease, by setting lifetime values to 0."
;
// Get the client's lease.
ASSERT_EQ
(
1
,
client
.
getLeaseNum
());
Lease6
lease_client2
=
client
.
getLease
(
0
);
// Get the client's leases. He should get two addresses:
// the first one for the bogus 3000::100 address with 0 lifetimes.
// the second one with the actual lease with non-zero lifetimes.
ASSERT_EQ
(
2
,
client
.
getLeaseNum
());
// Let's check the first one
Lease6
lease_client1
=
client
.
getLease
(
0
);
Lease6
lease_client2
=
client
.
getLease
(
1
);
if
(
lease_client1
.
addr_
.
toText
()
!=
"3000::100"
)
{
lease_client1
=
client
.
getLease
(
1
);
lease_client2
=
client
.
getLease
(
0
);
}
// The lifetimes should be set to 0, as an explicit notification to the
// client to stop using invalid prefix.
EXPECT_EQ
(
0
,
lease_client2
.
valid_lft_
);
EXPECT_EQ
(
0
,
lease_client2
.
preferred_lft_
);
EXPECT_EQ
(
0
,
lease_client1
.
valid_lft_
);
EXPECT_EQ
(
0
,
lease_client1
.
preferred_lft_
);
// Let's check the second lease
// The lifetimes should be set to 0, as an explicit notification to the
// client to stop using invalid prefix.
EXPECT_NE
(
0
,
lease_client2
.
valid_lft_
);
EXPECT_NE
(
0
,
lease_client2
.
preferred_lft_
);
// Check that server still has the same lease.
Lease6Ptr
lease_server
=
checkLease
(
lease_client
);
EXPECT_TRUE
(
lease_server
);
...
...
@@ -616,12 +640,24 @@ TEST_F(RebindTest, directClientPDChangingPrefix) {
" sent a response indicating that the client should stop using the"
" lease, by setting lifetime values to 0."
;
// Get the client's lease.
ASSERT_EQ
(
1
,
client
.
getLeaseNum
());
Lease6
lease_client2
=
client
.
getLease
(
0
);
ASSERT_EQ
(
2
,
client
.
getLeaseNum
());
// Client should get two entries. One with the invalid address he requested
// with zeroed lifetimes and a second one with the actual prefix he has
// with non-zero lifetimes.
Lease6
lease_client1
=
client
.
getLease
(
0
);
Lease6
lease_client2
=
client
.
getLease
(
1
);
// The lifetimes should be set to 0, as an explicit notification to the
// client to stop using invalid prefix.
EXPECT_EQ
(
0
,
lease_client2
.
valid_lft_
);
EXPECT_EQ
(
0
,
lease_client2
.
preferred_lft_
);
EXPECT_EQ
(
0
,
lease_client1
.
valid_lft_
);
EXPECT_EQ
(
0
,
lease_client1
.
preferred_lft_
);
// The lifetimes should be set to 0, as an explicit notification to the
// client to stop using invalid prefix.
EXPECT_NE
(
0
,
lease_client2
.
valid_lft_
);
EXPECT_NE
(
0
,
lease_client2
.
preferred_lft_
);
// Check that server still has the same lease.
Lease6Ptr
lease_server
=
checkLease
(
lease_client
);
ASSERT_TRUE
(
lease_server
);
...
...
src/lib/dhcpsrv/alloc_engine.cc
View file @
9ce50790
...
...
@@ -17,6 +17,7 @@
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcp/dhcp6.h>
#include <hooks/server_hooks.h>
#include <hooks/hooks_manager.h>
...
...
@@ -37,12 +38,16 @@ 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
int
hook_index_lease6_renew_
;
///< index for "lease6_renew" hook point
int
hook_index_lease6_rebind_
;
///< index for "lease6_rebind" 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"
);
hook_index_lease6_renew_
=
HooksManager
::
registerHook
(
"lease6_renew"
);
hook_index_lease6_rebind_
=
HooksManager
::
registerHook
(
"lease6_rebind"
);
}
};
...
...
@@ -381,9 +386,7 @@ AllocEngine::allocateLeases6(ClientContext6& ctx) {
if
(
!
leases
.
empty
())
{
// Return old leases so the server can see what has changed.
return
(
updateFqdnData
(
leases
,
ctx
.
fwd_dns_update_
,
ctx
.
rev_dns_update_
,
ctx
.
hostname_
,
ctx
.
fake_allocation_
));
return
(
updateFqdnData
(
ctx
,
leases
));
}
// If leases are empty at this stage, it means that we used to have
...
...
@@ -485,7 +488,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
IOAddress
hint
(
"::"
);
if
(
!
ctx
.
hints_
.
empty
())
{
/// @todo: We support only one hint for now
hint
=
ctx
.
hints_
[
0
];
hint
=
ctx
.
hints_
[
0
]
.
first
;
}
// check if the hint is in pool and is available
...
...
@@ -598,6 +601,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
if
(
ctx
.
type_
==
Lease
::
TYPE_PD
)
{
Pool6Ptr
pool
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
ctx
.
subnet_
->
getPool
(
ctx
.
type_
,
candidate
,
false
));
/// @todo: verify that the pool is non-null
prefix_len
=
pool
->
getLength
();
}
...
...
@@ -666,17 +670,45 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& exis
IOAddress
addr
=
resv
->
second
.
getPrefix
();
uint8_t
prefix_len
=
resv
->
second
.
getPrefixLen
();
// Check if already have this lease on the existing_leases list.
for
(
Lease6Collection
::
const_iterator
l
=
existing_leases
.
begin
();
l
!=
existing_leases
.
end
();
++
l
)
{
// Ok, we already have a lease for this reservation and it's usable
if
(((
*
l
)
->
addr_
==
addr
)
&&
(
*
l
)
->
valid_lft_
!=
0
)
{
return
;
}
}
// If there's a lease for this address, let's not create it.
// It doesn't matter whether it is for this client or for someone else.
if
(
LeaseMgrFactory
::
instance
().
getLease6
(
ctx
.
type_
,
addr
))
{
continue
;
}
if
(
!
LeaseMgrFactory
::
instance
().
getLease6
(
ctx
.
type_
,
addr
))
{
// Ok, let's create a new lease...
Lease6Ptr
lease
=
createLease6
(
ctx
,
addr
,
prefix_len
);
// ... and add it to the existing leases list.
existing_leases
.
push_back
(
lease
);
// Ok, let's create a new lease...
Lease6Ptr
lease
=
createLease6
(
ctx
,
addr
,
prefix_len
);
if
(
ctx
.
type_
==
Lease
::
TYPE_NA
)
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_HR_RESERVED_ADDR_GRANTED
)
.
arg
(
addr
.
toText
()).
arg
(
ctx
.
duid_
->
toText
());
}
else
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_HR_RESERVED_PREFIX_GRANTED
)
.
arg
(
addr
.
toText
()).
arg
(
static_cast
<
int
>
(
prefix_len
))
.
arg
(
ctx
.
duid_
->
toText
());
}
// ... and add it to the existing leases list.
existing_leases
.
push_back
(
lease
);
// We found a lease for this client and this IA. Let's return.
// Returning after the first lease was assigned is useful if we
// have multiple reservations for the same client. If the client
// sends 2 IAs, the first time we call allocateReservedLeases6 will
// use the first reservation and return. The second time, we'll
// go over the first reservation, but will discover that there's
// a lease corresponding to it and will skip it and then pick
// the second reservation and turn it into the lease. This approach
// would work for any number of reservations.
return
;
}
}
}
...
...
@@ -710,11 +742,25 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
// Ok, we have a problem. This host has a lease that is reserved
// for someone else. We need to recover from this.
if
(
ctx
.
type_
==
Lease
::
TYPE_NA
)
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_HR_REVOKED_ADDR6_LEASE
)
.
arg
((
*
candidate
)
->
addr_
.
toText
()).
arg
(
ctx
.
duid_
->
toText
())
.
arg
(
host
->
getIdentifierAsText
());
}
else
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_HR_REVOKED_PREFIX6_LEASE
)
.
arg
((
*
candidate
)
->
addr_
.
toText
())
.
arg
(
static_cast
<
int
>
((
*
candidate
)
->
prefixlen_
))
.
arg
(
ctx
.
duid_
->
toText
())
.
arg
(
host
->
getIdentifierAsText
());
}
// Remove this lease from LeaseMgr
LeaseMgrFactory
::
instance
().
deleteLease
((
*
candidate
)
->
addr_
);
/// @todo: Probably trigger a hook here
// In principle, we could trigger a hook here, but we will do this
// only if we get serious complaints from actual users. We want the
// conflict resolution procedure to really work and user libraries
// should not interfere with it.
// Add this to the list of removed leases.
ctx
.
old_leases_
.
push_back
(
*
candidate
);
...
...
@@ -1603,22 +1649,19 @@ AllocEngine::updateLease4Information(const Lease4Ptr& lease,
}
Lease6Collection
AllocEngine
::
updateFqdnData
(
const
Lease6Collection
&
leases
,
const
bool
fwd_dns_update
,
const
bool
rev_dns_update
,
const
std
::
string
&
hostname
,
const
bool
fake_allocation
)
{
AllocEngine
::
updateFqdnData
(
ClientContext6
&
ctx
,
const
Lease6Collection
&
leases
)
{
Lease6Collection
updated_leases
;
for
(
Lease6Collection
::
const_iterator
lease_it
=
leases
.
begin
();
lease_it
!=
leases
.
end
();
++
lease_it
)
{
Lease6Ptr
lease
(
new
Lease6
(
**
lease_it
));
lease
->
fqdn_fwd_
=
fwd_dns_update
;
lease
->
fqdn_rev_
=
rev_dns_update
;
lease
->
hostname_
=
hostname
;
if
(
!
fake_allocation
&&
lease
->
fqdn_fwd_
=
ctx
.
fwd_dns_update
_
;
lease
->
fqdn_rev_
=
ctx
.
rev_dns_update
_
;
lease
->
hostname_
=
ctx
.
hostname
_
;
if
(
!
ctx
.
fake_allocation
_
&&
((
lease
->
fqdn_fwd_
!=
(
*
lease_it
)
->
fqdn_fwd_
)
||
(
lease
->
fqdn_rev_
!=
(
*
lease_it
)
->
fqdn_rev_
)
||
(
lease
->
hostname_
!=
(
*
lease_it
)
->
hostname_
)))
{
ctx
.
changed_leases_
.
push_back
(
*
lease_it
);
LeaseMgrFactory
::
instance
().
updateLease6
(
lease
);
}
updated_leases
.
push_back
(
lease
);
...
...
@@ -1636,6 +1679,158 @@ AllocEngine::AllocatorPtr AllocEngine::getAllocator(Lease::Type type) {
return
(
alloc
->
second
);
}
Lease6Collection
AllocEngine
::
renewLeases6
(
ClientContext6
&
ctx
)
{
try
{
if
(
!
ctx
.
subnet_
)
{
isc_throw
(
InvalidOperation
,
"Subnet is required for allocation"
);
}
if
(
!
ctx
.
duid_
)
{
isc_throw
(
InvalidOperation
,
"DUID is mandatory for allocation"
);
}
// Check which host reservation mode is supported in this subnet.
Subnet
::
HRMode
hr_mode
=
ctx
.
subnet_
->
getHostReservationMode
();
// Check if there's a host reservation for this client. Attempt to get
// host info only if reservations are not disabled.