|
@@ -44,8 +44,10 @@ AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress&
|
|
|
len = 16;
|
|
|
}
|
|
|
|
|
|
+ // Start increasing the least significant byte
|
|
|
for (int i = len - 1; i >= 0; --i) {
|
|
|
++packed[i];
|
|
|
+ // if we haven't overflowed (0xff -> 0x0), than we are done
|
|
|
if (packed[i] != 0) {
|
|
|
break;
|
|
|
}
|
|
@@ -197,6 +199,12 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
|
|
if (lease) {
|
|
|
return (lease);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ if (existing->expired()) {
|
|
|
+ return (reuseExpiredLease(existing, subnet, duid, iaid,
|
|
|
+ fake_allocation));
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -220,6 +228,11 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
|
|
// 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
|
|
@@ -231,6 +244,46 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
|
|
|
<< " tries");
|
|
|
}
|
|
|
|
|
|
+Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
|
|
|
+ const Subnet6Ptr& subnet,
|
|
|
+ const DuidPtr& duid,
|
|
|
+ uint32_t iaid,
|
|
|
+ bool fake_allocation /*= false */ ) {
|
|
|
+
|
|
|
+ if (!expired->expired()) {
|
|
|
+ isc_throw(BadValue, "Attempt to recycle lease that is still valid");
|
|
|
+ }
|
|
|
+
|
|
|
+ // address, lease type and prefixlen (0) stay the same
|
|
|
+ expired->iaid_ = iaid;
|
|
|
+ expired->duid_ = duid;
|
|
|
+ expired->preferred_lft_ = subnet->getPreferred();
|
|
|
+ expired->valid_lft_ = subnet->getValid();
|
|
|
+ expired->t1_ = subnet->getT1();
|
|
|
+ expired->t2_ = subnet->getT2();
|
|
|
+ expired->cltt_ = time(NULL);
|
|
|
+ expired->subnet_id_ = subnet->getID();
|
|
|
+ expired->fixed_ = false;
|
|
|
+ expired->hostname_ = std::string("");
|
|
|
+ expired->fqdn_fwd_ = false;
|
|
|
+ expired->fqdn_rev_ = false;
|
|
|
+
|
|
|
+ /// @todo: log here that the lease was reused (there's ticket #2524 for
|
|
|
+ /// logging in libdhcpsrv)
|
|
|
+
|
|
|
+ if (!fake_allocation) {
|
|
|
+ // for REQUEST we do update the lease
|
|
|
+ LeaseMgrFactory::instance().updateLease6(expired);
|
|
|
+ }
|
|
|
+
|
|
|
+ // We do nothing for SOLICIT. We'll just update database when
|
|
|
+ // the client gets back to us with REQUEST message.
|
|
|
+
|
|
|
+ // it's not really expired at this stage anymore - let's return it as
|
|
|
+ // an updated lease
|
|
|
+ return (expired);
|
|
|
+}
|
|
|
+
|
|
|
Lease6Ptr AllocEngine::createLease(const Subnet6Ptr& subnet,
|
|
|
const DuidPtr& duid,
|
|
|
uint32_t iaid,
|