BIND 10 master, updated. aff7100abe378e77ed36e6239a82ca483bcd2288 [master] ChangeLog for #2681
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Feb 12 12:32:52 UTC 2013
The branch, master has been updated
via aff7100abe378e77ed36e6239a82ca483bcd2288 (commit)
via 87ce14cdb121b37afb5b1931af51bed7f6323dd6 (commit)
via cf0ce4bad603660b8f0d98e76414fd5b3572e2c8 (commit)
via 5950991881a51d5b88ec6234d310adda43e11e8a (commit)
via 964547642571d9146219cf2f9d6e08fa03970a81 (commit)
from 227f2b1dab3ee9739e1c8671ca242313ad4eb796 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit aff7100abe378e77ed36e6239a82ca483bcd2288
Author: Stephen Morris <stephen at isc.org>
Date: Tue Feb 12 12:32:32 2013 +0000
[master] ChangeLog for #2681
commit 87ce14cdb121b37afb5b1931af51bed7f6323dd6
Merge: 227f2b1 cf0ce4b
Author: Stephen Morris <stephen at isc.org>
Date: Tue Feb 12 12:29:06 2013 +0000
[master] Merge branch 'trac2681'
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 6 +
src/bin/dhcp4/dhcp4_messages.mes | 7 +-
src/bin/dhcp4/dhcp4_srv.cc | 73 +++--
src/bin/dhcp6/dhcp6_messages.mes | 7 +-
src/bin/dhcp6/dhcp6_srv.cc | 26 +-
src/lib/dhcpsrv/alloc_engine.cc | 358 +++++++++++++-----------
src/lib/dhcpsrv/dhcpsrv_messages.mes | 40 +++
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc | 11 +-
8 files changed, 319 insertions(+), 209 deletions(-)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 4dbe045..d9b0ee1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+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.
diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes
index 17f9967..247d6c3 100644
--- a/src/bin/dhcp4/dhcp4_messages.mes
+++ b/src/bin/dhcp4/dhcp4_messages.mes
@@ -1,4 +1,4 @@
-# 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
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index b2a92e9..261e213 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -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) {
diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes
index 65ad74b..a2fee47 100644
--- a/src/bin/dhcp6/dhcp6_messages.mes
+++ b/src/bin/dhcp6/dhcp6_messages.mes
@@ -1,4 +1,4 @@
-# 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.
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 851f405..b37e003 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -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."));
diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc
index 3602aac..bcb7851 100644
--- a/src/lib/dhcpsrv/alloc_engine.cc
+++ b/src/lib/dhcpsrv/alloc_engine.cc
@@ -1,4 +1,4 @@
-// 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));
+ }
}
- }
- // continue trying allocation until we run out of attempts
- // (or attempts are set to 0, which means infinite)
- --i;
- } while ( i || !attempts_);
+ // Continue 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) {
- // we have a lease already. This is a returning client, probably after
+ // 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
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
+ if (existing) {
+ return (existing);
+ }
+ }
+ }
- // The hint is valid and not currently used, let's create a lease for it
- Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, hint, fake_allocation);
+ // 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
+
+ // The hint is valid and not currently used, let's create a lease for it
+ Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, 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, clientid, hwaddr,
+ 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, clientid, hwaddr,
- 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 the 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, clientid, hint);
-
- /// @todo: check if the address is reserved once we have host support
- /// implemented
-
- Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(candidate);
- if (!existing) {
- // there's no existing lease for selected candidate, so it is
- // free. Let's allocate it.
- Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, 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 the 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, clientid, 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, clientid, hwaddr,
- fake_allocation));
+ Lease4Ptr existing = LeaseMgrFactory::instance().getLease4(candidate);
+ if (!existing) {
+ // there's no existing lease for selected candidate, so it is
+ // free. Let's allocate it.
+ Lease4Ptr lease = createLease4(subnet, clientid, hwaddr, 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, clientid, hwaddr,
+ fake_allocation));
+ }
}
- }
- // Continue trying allocation until we run out of attempts
- // (or attempts are set to 0, which means infinite)
- --i;
- } while ( i || !attempts_);
+ // Continue 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_ADDRESS4_ALLOC_FAIL).arg(attempts_);
+
+ } catch (const isc::Exception& e) {
+
+ // Some other error, return an empty lease.
+ LOG_ERROR(dhcpsrv_logger, DHCPSRV_ADDRESS4_ALLOC_ERROR).arg(e.what());
+ }
+ return (Lease4Ptr());
}
Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes
index bf4e1e1..a54577f 100644
--- a/src/lib/dhcpsrv/dhcpsrv_messages.mes
+++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes
@@ -14,6 +14,46 @@
$NAMESPACE isc::dhcp
+% DHCPSRV_ADDRESS4_ALLOC_ERROR error during attempt to allocate an IPv4 address: %1
+An error occurred during an attempt to allocate an IPv4 address, the
+reason for the failure being contained in the message. The server will
+return a message to the client refusing a lease.
+
+% DHCPSRV_ADDRESS4_ALLOC_FAIL failed to allocate an IPv4 address after %1 attempt(s)
+THE DHCP allocation engine gave up trying to allocate an IPv4 address
+after the specified number of attempts. This probably means that the
+address pool from which the allocation is being attempted is either
+empty, or very nearly empty. As a result, the client will have been
+refused a lease.
+
+This message may indicate that your address pool is too small for the
+number of clients you are trying to service and should be expanded.
+Alternatively, if the you know that the number of concurrently active
+clients is less than the addresses you have available, you may want to
+consider reducing the lease lifetime. In this way, addresses allocated
+to clients that are no longer active on the network will become available
+available sooner.
+
+% DHCPSRV_ADDRESS6_ALLOC_ERROR error during attempt to allocate an IPv6 address: %1
+An error occurred during an attempt to allocate an IPv6 address, the
+reason for the failure being contained in the message. The server will
+return a message to the client refusing a lease.
+
+% DHCPSRV_ADDRESS6_ALLOC_FAIL failed to allocate an IPv6 address after %1 attempt(s)
+The DHCP allocation engine gave up trying to allocate an IPv6 address
+after the specified number of attempts. This probably means that the
+address pool from which the allocation is being attempted is either
+empty, or very nearly empty. As a result, the client will have been
+refused a lease.
+
+This message may indicate that your address pool is too small for the
+number of clients you are trying to service and should be expanded.
+Alternatively, if the you know that the number of concurrently active
+clients is less than the addresses you have available, you may want to
+consider reducing the lease lifetime. In this way, addresses allocated
+to clients that are no longer active on the network will become available
+available sooner.
+
% DHCPSRV_CFGMGR_ADD_SUBNET4 adding subnet %1
A debug message reported when the DHCP configuration manager is adding the
specified IPv4 subnet to its database.
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
index 078998d..ddc0f62 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc
@@ -461,9 +461,9 @@ TEST_F(AllocEngine6Test, outOfAddresses6) {
// There is just a single address in the pool and allocated it to someone
// else, so the allocation should fail
-
- EXPECT_THROW(engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),false),
- AllocFailed);
+ Lease6Ptr lease2 = engine->allocateAddress6(subnet_, duid_, iaid_,
+ IOAddress("::"), false);
+ EXPECT_FALSE(lease2);
}
// This test checks if an expired lease can be reused in SOLICIT (fake allocation)
@@ -838,8 +838,9 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
// There is just a single address in the pool and allocated it to someone
// else, so the allocation should fail
- EXPECT_THROW(engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),false),
- AllocFailed);
+ Lease4Ptr lease2 = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
+ IOAddress("0.0.0.0"), false);
+ EXPECT_FALSE(lease2);
}
// This test checks if an expired lease can be reused in DISCOVER (fake allocation)
More information about the bind10-changes
mailing list