Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
1197c10b
Commit
1197c10b
authored
Feb 12, 2013
by
Thomas Markwalder
Browse files
Merge branch 'master' into trac2699_2
parents
97371cff
aff7100a
Changes
23
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
1197c10b
573. [bug] stephen
Fixed problem whereby the DHCP server crashed if it ran out of
addresses. Such a condition now causes a packet to be returned
to the client refusing the allocation of an address.
(Trac #2681, git 87ce14cdb121b37afb5b1931af51bed7f6323dd6)
572. [bug] marcin
perfdhcp: Fixed bug where the command line switches used to
run the perfdhcp where printed as ASCII codes.
(Trac #2700, git b8d6b949eb7f4705e32fbdfd7694ca2e6a6a5cdc)
571. [build] jinmei
The ./configure script can now handle output from python-config
--ldflags that contains a space after -L switches. This fixes
failure reported on some Solaris environments.
(Trac #2661, git e6f86f2f5eec8e6003c13d36804a767a840d96d6)
570. [bug] tmark, marcin, tomek
b10-dhcp4: Address renewal now works properly for DHCPv4 clients
that do not send client ID.
...
...
configure.ac
View file @
1197c10b
...
...
@@ -313,8 +313,16 @@ AC_SUBST(COMMON_PYTHON_PATH)
if test -x ${PYTHON}-config; then
PYTHON_INCLUDES=`${PYTHON}-config --includes`
for flag in `${PYTHON}-config --ldflags`; do
# add any '-L..." flags to PYTHON_LDFLAGS
# Add any '-L..." flags to PYTHON_LDFLAGS. We first make a copy of
# python-config --ldflags, removing any spaces and tabs
# between "-L" and its argument (some instances of python-config
# insert a space, which would confuse the code below).
# Notes: if -L isn't contained at all we can simply skip this process,
# so we only go through the flag if it's contained; also, protecting
# the output with [] seems necessary for environment to avoid getting
# an empty output accidentally.
python_config_ldflags=[`${PYTHON}-config --ldflags | sed -ne 's/\([ \t]*-L\)[ ]*\([^ \t]*[ \t]*\)/\1\2/pg'`]
for flag in $python_config_ldflags; do
flag=`echo $flag | sed -ne 's/^\(\-L.*\)$/\1/p'`
if test "X${flag}" != X; then
PYTHON_LDFLAGS="$PYTHON_LDFLAGS ${flag}"
...
...
src/bin/dhcp4/dhcp4_messages.mes
View file @
1197c10b
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2012
-2013
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
...
...
@@ -94,6 +94,11 @@ server is about to open sockets on the specified port.
The IPv4 DHCP server has received a packet that it is unable to
interpret. The reason why the packet is invalid is included in the message.
% DHCP4_PACKET_PROCESS_FAIL failed to process packet received from %1: %2
This is a general catch-all message indicating that the processing of a
received packet failed. The reason is given in the message. The server
will not send a response but will instead ignore the packet.
% DHCP4_PACKET_RECEIVED %1 (type %2) packet received on interface %3
A debug message noting that the server has received the specified type of
packet on the specified interface. Note that a packet marked as UNKNOWN
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
1197c10b
...
...
@@ -149,32 +149,53 @@ Dhcpv4Srv::run() {
LOG_DEBUG
(
dhcp4_logger
,
DBG_DHCP4_DETAIL_DATA
,
DHCP4_QUERY_DATA
)
.
arg
(
query
->
toText
());
switch
(
query
->
getType
())
{
case
DHCPDISCOVER
:
rsp
=
processDiscover
(
query
);
break
;
case
DHCPREQUEST
:
rsp
=
processRequest
(
query
);
break
;
case
DHCPRELEASE
:
processRelease
(
query
);
break
;
case
DHCPDECLINE
:
processDecline
(
query
);
break
;
case
DHCPINFORM
:
processInform
(
query
);
break
;
default:
// Only action is to output a message if debug is enabled,
// and that will be covered by the debug statement before
// the "switch" statement.
;
try
{
switch
(
query
->
getType
())
{
case
DHCPDISCOVER
:
rsp
=
processDiscover
(
query
);
break
;
case
DHCPREQUEST
:
rsp
=
processRequest
(
query
);
break
;
case
DHCPRELEASE
:
processRelease
(
query
);
break
;
case
DHCPDECLINE
:
processDecline
(
query
);
break
;
case
DHCPINFORM
:
processInform
(
query
);
break
;
default:
// Only action is to output a message if debug is enabled,
// and that is covered by the debug statement before the
// "switch" statement.
;
}
}
catch
(
const
isc
::
Exception
&
e
)
{
// Catch-all exception (at least for ones based on the isc
// Exception class, which covers more or less all that
// are explicitly raised in the BIND 10 code). Just log
// the problem and ignore the packet. (The problem is logged
// as a debug message because debug is disabled by default -
// it prevents a DDOS attack based on the sending of problem
// packets.)
if
(
dhcp4_logger
.
isDebugEnabled
(
DBG_DHCP4_BASIC
))
{
std
::
string
source
=
"unknown"
;
HWAddrPtr
hwptr
=
query
->
getHWAddr
();
if
(
hwptr
)
{
source
=
hwptr
->
toText
();
}
LOG_DEBUG
(
dhcp4_logger
,
DBG_DHCP4_BASIC
,
DHCP4_PACKET_PROCESS_FAIL
)
.
arg
(
source
).
arg
(
e
.
what
());
}
}
if
(
rsp
)
{
...
...
src/bin/dhcp6/dhcp6_messages.mes
View file @
1197c10b
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2012
-2013
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
...
...
@@ -93,6 +93,11 @@ 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_PACKET_PROCESS_FAIL processing of %1 message received from %2 failed: %3
This is a general catch-all message indicating that the processing of the
specified packet type from the indicated address failed. The reason is given in the
message. The server will not send a response but will instead ignore the packet.
% DHCP6_RELEASE 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.
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
1197c10b
...
...
@@ -182,8 +182,8 @@ bool Dhcpv6Srv::run() {
break
;
case
DHCPV6_RELEASE
:
rsp
=
processRelease
(
query
);
break
;
rsp
=
processRelease
(
query
);
break
;
case
DHCPV6_DECLINE
:
rsp
=
processDecline
(
query
);
...
...
@@ -199,11 +199,26 @@ bool Dhcpv6Srv::run() {
// the "switch" statement.
;
}
}
catch
(
const
RFCViolation
&
e
)
{
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_BASIC
,
DHCP6_REQUIRED_OPTIONS_CHECK_FAIL
)
.
arg
(
query
->
getName
())
.
arg
(
query
->
getRemoteAddr
())
.
arg
(
e
.
what
());
}
catch
(
const
isc
::
Exception
&
e
)
{
// Catch-all exception (at least for ones based on the isc
// Exception class, which covers more or less all that
// are explicitly raised in the BIND 10 code). Just log
// the problem and ignore the packet. (The problem is logged
// as a debug message because debug is disabled by default -
// it prevents a DDOS attack based on the sending of problem
// packets.)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_BASIC
,
DHCP6_PACKET_PROCESS_FAIL
)
.
arg
(
query
->
getName
())
.
arg
(
query
->
getRemoteAddr
())
.
arg
(
e
.
what
());
}
if
(
rsp
)
{
...
...
@@ -685,11 +700,10 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
// cause of that failure. The only thing left is to insert
// status code to pass the sad news to the client.
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
fake_allocation
?
DHCP6_LEASE_ADVERT_FAIL
:
DHCP6_LEASE_ALLOC_FAIL
)
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_DETAIL
,
fake_allocation
?
DHCP6_LEASE_ADVERT_FAIL
:
DHCP6_LEASE_ALLOC_FAIL
)
.
arg
(
duid
?
duid
->
toText
()
:
"(no-duid)"
)
.
arg
(
ia
->
getIAID
())
.
arg
(
subnet
->
toText
());
.
arg
(
ia
->
getIAID
());
ia_rsp
->
addOption
(
createStatusCode
(
STATUS_NoAddrsAvail
,
"Sorry, no address could be allocated."
));
...
...
src/lib/asiodns/tcp_server.cc
View file @
1197c10b
...
...
@@ -184,7 +184,6 @@ TCPServer::operator()(asio::error_code ec, size_t length) {
// provides the appropriate operator() but is otherwise functionless.
iosock_
.
reset
(
new
TCPSocket
<
DummyIOCallback
>
(
*
socket_
));
io_message_
.
reset
(
new
IOMessage
(
data_
.
get
(),
length
,
*
iosock_
,
*
peer_
));
bytes_
=
length
;
// Perform any necessary operations prior to processing the incoming
// packet (e.g., checking for queued configuration messages).
...
...
src/lib/asiodns/tcp_server.h
View file @
1197c10b
...
...
@@ -122,7 +122,6 @@ private:
// State information that is entirely internal to a given instance
// of the coroutine can be declared here.
size_t
bytes_
;
bool
done_
;
// Callback functions provided by the caller
...
...
src/lib/asiodns/udp_server.cc
View file @
1197c10b
...
...
@@ -61,7 +61,7 @@ struct UDPServer::Data {
*/
Data
(
io_service
&
io_service
,
const
ip
::
address
&
addr
,
const
uint16_t
port
,
SimpleCallback
*
checkin
,
DNSLookup
*
lookup
,
DNSAnswer
*
answer
)
:
io_
(
io_service
),
done_
(
false
),
io_
(
io_service
),
bytes_
(
0
),
done_
(
false
),
checkin_callback_
(
checkin
),
lookup_callback_
(
lookup
),
answer_callback_
(
answer
)
{
...
...
@@ -77,7 +77,7 @@ struct UDPServer::Data {
}
Data
(
io_service
&
io_service
,
int
fd
,
int
af
,
SimpleCallback
*
checkin
,
DNSLookup
*
lookup
,
DNSAnswer
*
answer
)
:
io_
(
io_service
),
done_
(
false
),
io_
(
io_service
),
bytes_
(
0
),
done_
(
false
),
checkin_callback_
(
checkin
),
lookup_callback_
(
lookup
),
answer_callback_
(
answer
)
{
...
...
@@ -104,7 +104,7 @@ struct UDPServer::Data {
* We also allocate data for receiving the packet here.
*/
Data
(
const
Data
&
other
)
:
io_
(
other
.
io_
),
socket_
(
other
.
socket_
),
done_
(
false
),
io_
(
other
.
io_
),
socket_
(
other
.
socket_
),
bytes_
(
0
),
done_
(
false
),
checkin_callback_
(
other
.
checkin_callback_
),
lookup_callback_
(
other
.
lookup_callback_
),
answer_callback_
(
other
.
answer_callback_
)
...
...
@@ -168,7 +168,6 @@ struct UDPServer::Data {
size_t
bytes_
;
bool
done_
;
// Callback functions provided by the caller
const
SimpleCallback
*
checkin_callback_
;
const
DNSLookup
*
lookup_callback_
;
...
...
src/lib/cc/data.cc
View file @
1197c10b
...
...
@@ -261,7 +261,7 @@ skipChars(std::istream& in, const char* chars, int& line, int& pos) {
}
else
{
++
pos
;
}
in
.
get
();
in
.
ignore
();
c
=
in
.
peek
();
}
}
...
...
@@ -291,7 +291,7 @@ skipTo(std::istream& in, const std::string& file, int& line,
pos
=
1
;
++
line
;
}
in
.
get
();
in
.
ignore
();
++
pos
;
}
in
.
putback
(
c
);
...
...
@@ -352,7 +352,7 @@ strFromStringstream(std::istream& in, const std::string& file,
throwJSONError
(
"Bad escape"
,
file
,
line
,
pos
);
}
// drop the escaped char
in
.
get
();
in
.
ignore
();
++
pos
;
}
ss
.
put
(
c
);
...
...
@@ -490,14 +490,14 @@ fromStringstreamMap(std::istream& in, const std::string& file, int& line,
throwJSONError
(
std
::
string
(
"Unterminated map, <string> or } expected"
),
file
,
line
,
pos
);
}
else
if
(
c
==
'}'
)
{
// empty map, skip closing curly
c
=
in
.
get
();
in
.
ignore
();
}
else
{
while
(
c
!=
EOF
&&
c
!=
'}'
)
{
std
::
string
key
=
strFromStringstream
(
in
,
file
,
line
,
pos
);
skipTo
(
in
,
file
,
line
,
pos
,
":"
,
WHITESPACE
);
// skip the :
in
.
get
();
in
.
ignore
();
pos
++
;
ConstElementPtr
value
=
Element
::
fromJSON
(
in
,
file
,
line
,
pos
);
...
...
src/lib/config/tests/ccsession_unittests.cc
View file @
1197c10b
...
...
@@ -343,6 +343,7 @@ TEST_F(CCSessionTest, checkCommand) {
session
.
addMessage
(
el
(
"{
\"
command
\"
:
\"
bad_command
\"
}"
),
"Spec29"
,
"*"
);
result
=
mccs
.
checkCommand
();
EXPECT_EQ
(
0
,
session
.
getMsgQueue
()
->
size
());
EXPECT_EQ
(
0
,
result
);
session
.
addMessage
(
el
(
"{
\"
command
\"
: [
\"
bad_command
\"
] }"
),
"Spec29"
,
"*"
);
...
...
@@ -627,6 +628,7 @@ TEST_F(CCSessionTest, ignoreRemoteConfigCommands) {
EXPECT_EQ
(
1
,
session
.
getMsgQueue
()
->
size
());
result
=
mccs
.
checkCommand
();
EXPECT_EQ
(
0
,
session
.
getMsgQueue
()
->
size
());
EXPECT_EQ
(
0
,
result
);
}
TEST_F
(
CCSessionTest
,
initializationFail
)
{
...
...
src/lib/datasrc/memory/zone_finder.cc
View file @
1197c10b
...
...
@@ -573,6 +573,7 @@ FindNodeResult findNode(const ZoneData& zone_data,
/// For (successful) type ANY query, found_node points to the
/// corresponding zone node, which is recorded within this specialized
/// context.
// cppcheck-suppress noConstructor
class
InMemoryZoneFinder
::
Context
:
public
ZoneFinder
::
Context
{
public:
Context
(
InMemoryZoneFinder
&
finder
,
ZoneFinder
::
FindOptions
options
,
...
...
src/lib/datasrc/memory_datasrc.cc
View file @
1197c10b
...
...
@@ -782,6 +782,7 @@ struct RBNodeResultContext {
};
}
// cppcheck-suppress noConstructor
class
InMemoryZoneFinder
::
Context
:
public
ZoneFinder
::
Context
{
public:
/// \brief Constructor.
...
...
src/lib/datasrc/sqlite3_accessor.cc
View file @
1197c10b
...
...
@@ -682,6 +682,8 @@ convertToPlainChar(const unsigned char* ucp, sqlite3 *db) {
}
}
// cppcheck-suppress noConstructor
class
SQLite3Accessor
::
Context
:
public
DatabaseAccessor
::
IteratorContext
{
public:
// Construct an iterator for all records. When constructed this
...
...
@@ -887,6 +889,7 @@ SQLite3Accessor::getAllRecords(int id) const {
/// This iterator is used to search through the differences table for the
/// resouce records making up an IXFR between two versions of a zone.
// cppcheck-suppress noConstructor
class
SQLite3Accessor
::
DiffContext
:
public
DatabaseAccessor
::
IteratorContext
{
public:
...
...
src/lib/dhcpsrv/alloc_engine.cc
View file @
1197c10b
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012
-2013
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
...
...
@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include
<dhcpsrv/alloc_engine.h>
#include
<dhcpsrv/dhcpsrv_log.h>
#include
<dhcpsrv/lease_mgr_factory.h>
#include
<cstring>
...
...
@@ -169,95 +170,104 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
const
IOAddress
&
hint
,
bool
fake_allocation
/* = false */
)
{
// That check is not necessary. We create allocator in AllocEngine
// constructor
if
(
!
allocator_
)
{
isc_throw
(
InvalidOperation
,
"No allocator selected"
);
}
// check if there's existing lease for that subnet/duid/iaid combination.
Lease6Ptr
existing
=
LeaseMgrFactory
::
instance
().
getLease6
(
*
duid
,
iaid
,
subnet
->
getID
());
if
(
existing
)
{
// we have a lease already. This is a returning client, probably after
// his reboot.
return
(
existing
);
}
try
{
// That check is not necessary. We create allocator in AllocEngine
// constructor
if
(
!
allocator_
)
{
isc_throw
(
InvalidOperation
,
"No allocator selected"
);
}
// check if the hint is in pool and is available
if
(
subnet
->
inPool
(
hint
))
{
existing
=
LeaseMgrFactory
::
instance
().
getLease6
(
hint
);
if
(
!
existing
)
{
/// @todo: check if the hint is reserved once we have host support
/// implemented
// check if there's existing lease for that subnet/duid/iaid combination.
Lease6Ptr
existing
=
LeaseMgrFactory
::
instance
().
getLease6
(
*
duid
,
iaid
,
subnet
->
getID
());
if
(
existing
)
{
// we have a lease already. This is a returning client, probably after
// his reboot.
return
(
existing
);
}
// the hint is valid and not currently used, let's create a lease for it
Lease6Ptr
lease
=
createLease6
(
subnet
,
duid
,
iaid
,
hint
,
fake_allocation
);
// check if the hint is in pool and is available
if
(
subnet
->
inPool
(
hint
))
{
existing
=
LeaseMgrFactory
::
instance
().
getLease6
(
hint
);
if
(
!
existing
)
{
/// @todo: check if the hint is reserved once we have host support
/// implemented
// the hint is valid and not currently used, let's create a lease for it
Lease6Ptr
lease
=
createLease6
(
subnet
,
duid
,
iaid
,
hint
,
fake_allocation
);
// It can happen that the lease allocation failed (we could have lost
// the race condition. That means that the hint is lo longer usable and
// we need to continue the regular allocation path.
if
(
lease
)
{
return
(
lease
);
}
}
else
{
if
(
existing
->
expired
())
{
return
(
reuseExpiredLease
(
existing
,
subnet
,
duid
,
iaid
,
fake_allocation
));
}
// It can happen that the lease allocation failed (we could have lost
// the race condition. That means that the hint is lo longer usable and
// we need to continue the regular allocation path.
if
(
lease
)
{
return
(
lease
);
}
}
else
{
if
(
existing
->
expired
())
{
return
(
reuseExpiredLease
(
existing
,
subnet
,
duid
,
iaid
,
fake_allocation
));
}
}
}
// Hint is in the pool but is not available. Search the pool until first of
// the following occurs:
// - we find a free address
// - we find an address for which the lease has expired
// - we exhaust number of tries
//
// @todo: Current code does not handle pool exhaustion well. It will be
// improved. Current problems:
// 1. with attempts set to too large value (e.g. 1000) and a small pool (e.g.
// 10 addresses), we will iterate over it 100 times before giving up
// 2. attempts 0 mean unlimited (this is really UINT_MAX, not infinite)
// 3. the whole concept of infinite attempts is just asking for infinite loop
// We may consider some form or reference counting (this pool has X addresses
// left), but this has one major problem. We exactly control allocation
// moment, but we currently do not control expiration time at all
unsigned
int
i
=
attempts_
;
do
{
IOAddress
candidate
=
allocator_
->
pickAddress
(
subnet
,
duid
,
hint
);
/// @todo: check if the address is reserved once we have host support
/// implemented
Lease6Ptr
existing
=
LeaseMgrFactory
::
instance
().
getLease6
(
candidate
);
if
(
!
existing
)
{
// there's no existing lease for selected candidate, so it is
// free. Let's allocate it.
Lease6Ptr
lease
=
createLease6
(
subnet
,
duid
,
iaid
,
candidate
,
fake_allocation
);
if
(
lease
)
{
return
(
lease
);
}
// Hint is in the pool but is not available. Search the pool until first of
// the following occurs:
// - we find a free address
// - we find an address for which the lease has expired
// - we exhaust number of tries
//
// @todo: Current code does not handle pool exhaustion well. It will be
// improved. Current problems:
// 1. with attempts set to too large value (e.g. 1000) and a small pool (e.g.
// 10 addresses), we will iterate over it 100 times before giving up
// 2. attempts 0 mean unlimited (this is really UINT_MAX, not infinite)
// 3. the whole concept of infinite attempts is just asking for infinite loop
// We may consider some form or reference counting (this pool has X addresses
// left), but this has one major problem. We exactly control allocation
// moment, but we currently do not control expiration time at all
unsigned
int
i
=
attempts_
;
do
{
IOAddress
candidate
=
allocator_
->
pickAddress
(
subnet
,
duid
,
hint
);
/// @todo: check if the address is reserved once we have host support
/// implemented
// Although the address was free just microseconds ago, it may have
// been taken just now. If the lease insertion fails, we continue
// allocation attempts.
}
else
{
if
(
existing
->
expired
())
{
return
(
reuseExpiredLease
(
existing
,
subnet
,
duid
,
iaid
,
fake_allocation
));
Lease6Ptr
existing
=
LeaseMgrFactory
::
instance
().
getLease6
(
candidate
);
if
(
!
existing
)
{
// there's no existing lease for selected candidate, so it is
// free. Let's allocate it.
Lease6Ptr
lease
=
createLease6
(
subnet
,
duid
,
iaid
,
candidate
,
fake_allocation
);
if
(
lease
)
{
return
(
lease
);
}
// Although the address was free just microseconds ago, it may have
// been taken just now. If the lease insertion fails, we continue
// allocation attempts.
}
else
{
if
(
existing
->
expired
())
{
return
(
reuseExpiredLease
(
existing
,
subnet
,
duid
,
iaid
,
fake_allocation
));
}
}
}
//
c
ontinue trying allocation until we run out of attempts
// (or attempts are set to 0, which means infinite)
--
i
;
}
while
(
i
||
!
attempts_
);
//
C
ontinue trying allocation until we run out of attempts
// (or attempts are set to 0, which means infinite)
--
i
;
}
while
(
(
i
>
0
)
||
!
attempts_
);
isc_throw
(
AllocFailed
,
"Failed to allocate address after "
<<
attempts_
<<
" tries"
);
// Unable to allocate an address, return an empty lease.
LOG_WARN
(
dhcpsrv_logger
,
DHCPSRV_ADDRESS6_ALLOC_FAIL
).
arg
(
attempts_
);
}
catch
(
const
isc
::
Exception
&
e
)
{
// Some other error, return an empty lease.
LOG_ERROR
(
dhcpsrv_logger
,
DHCPSRV_ADDRESS6_ALLOC_ERROR
).
arg
(
e
.
what
());
}
return
(
Lease6Ptr
());
}
Lease4Ptr
...
...
@@ -267,115 +277,123 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
const
IOAddress
&
hint
,
bool
fake_allocation
/* = false */
)
{
// Allocator is always created in AllocEngine constructor and there is
// currently no other way to set it, so that check is not really necessary.
if
(
!
allocator_
)
{
isc_throw
(
InvalidOperation
,
"No allocator selected"
);
}
// Check if there's existing lease for that subnet/clientid/hwaddr combination.
Lease4Ptr
existing
=
LeaseMgrFactory
::
instance
().
getLease4
(
*
hwaddr
,
subnet
->
getID
());
if
(
existing
)
{
// We have a lease already. This is a returning client, probably after
// its reboot.
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
fake_allocation
);
if
(
existing
)
{
return
(
existing
);
try
{
// Allocator is always created in AllocEngine constructor and there is
// currently no other way to set it, so that check is not really necessary.
if
(
!
allocator_
)
{
isc_throw
(
InvalidOperation
,
"No allocator selected"
);
}
// If renewal failed (e.g. the lease no longer matches current configuration)
// let's continue the allocation process
}
if
(
clientid
)
{
existing
=
LeaseMgrFactory
::
instance
().
getLease4
(
*
clientid
,
subnet
->
getID
());
// Check if there's existing lease for that subnet/clientid/hwaddr combination.
Lease4Ptr
existing
=
LeaseMgrFactory
::
instance
().
getLease4
(
hwaddr
->
hwaddr_
,
subnet
->
getID
());
if
(
existing
)
{
//
w
e have a lease already. This is a returning client, probably after
//
W
e have a lease already. This is a returning client, probably after
// its reboot.
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
fake_allocation
);
// @todo: produce a warning. We haven't found him using MAC address, but
// we found him using client-id
if
(
existing
)
{
return
(
existing
);
}
// If renewal failed (e.g. the lease no longer matches current configuration)
// let's continue the allocation process
}
}
// check if the hint is in pool and is available
if
(
subnet
->
inPool
(
hint
))
{
existing
=
LeaseMgrFactory
::
instance
().
getLease4
(
hint
);
if
(
!
existing
)
{
/// @todo: Check if the hint is reserved once we have host support
/// implemented
if
(
clientid
)
{
existing
=
LeaseMgrFactory
::
instance
().
getLease4
(
*
clientid
,
subnet
->
getID
());
if
(
existing
)
{
// we have a lease already. This is a returning client, probably after
// its reboot.
existing
=
renewLease4
(
subnet
,
clientid
,
hwaddr
,
existing
,
fake_allocation
);
// @todo: produce a warning. We haven't found him using MAC address, but
// we found him using client-id