Commit 9b7cc4af authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[master] Merge branch 'trac3171' (DHCPv6-PD support in Allocation Engine)

Conflicts:
	ChangeLog
parents b825c117 7d1431b4
685. [func] tomek
libdhcpsrv: Allocation Engine is now able to handle IPv6 prefixes.
This will be used in Prefix Delegation.
(Trac #3171, git 7d1431b4c887f0c7ee1b26b9b82d3d3b8464b34f)
684. [func] muks, vorner
API support to delete zone data has been added. With this,
DomainTree and RdataSet which form the central zone data
......
......@@ -718,11 +718,11 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
// be inserted into the LeaseMgr as well.
// @todo pass the actual FQDN data.
Lease4Ptr old_lease;
Lease4Ptr lease = alloc_engine_->allocateAddress4(subnet, client_id, hwaddr,
hint, false, false, "",
fake_allocation,
callout_handle,
old_lease);
Lease4Ptr lease = alloc_engine_->allocateLease4(subnet, client_id, hwaddr,
hint, false, false, "",
fake_allocation,
callout_handle,
old_lease);
if (lease) {
// We have a lease! Let's set it in the packet and send it back to
......
......@@ -390,7 +390,7 @@ public:
// Technically inPool implies inRange, but let's be on the safe
// side and check both.
EXPECT_TRUE(subnet->inRange(rsp->getYiaddr()));
EXPECT_TRUE(subnet->inPool(rsp->getYiaddr()));
EXPECT_TRUE(subnet->inPool(Lease::TYPE_V4, rsp->getYiaddr()));
// Check lease time
OptionPtr opt = rsp->getOption(DHO_DHCP_LEASE_TIME);
......@@ -1333,7 +1333,7 @@ TEST_F(Dhcpv4SrvTest, RenewBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
......@@ -1444,7 +1444,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
......@@ -1520,7 +1520,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseReject) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a RELEASE
// Generate client-id also duid_
......@@ -2696,7 +2696,7 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectChange) {
// Advertised address must belong to the second pool (in subnet's range,
// in dynamic pool)
EXPECT_TRUE((*subnets)[1]->inRange(addr));
EXPECT_TRUE((*subnets)[1]->inPool(addr));
EXPECT_TRUE((*subnets)[1]->inPool(Lease::TYPE_V4, addr));
}
// This test verifies that incoming (positive) REQUEST/Renewing can be handled
......@@ -2718,7 +2718,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSimple) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
......@@ -2802,7 +2802,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSkip) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
......@@ -2866,7 +2866,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSimple) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
......@@ -2951,7 +2951,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// Let's create a lease and put it in the LeaseMgr
uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
......
......@@ -1223,13 +1223,13 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
// will try to honour the hint, but it is just a hint - some other address
// may be used instead. If fake_allocation is set to false, the lease will
// be inserted into the LeaseMgr as well.
Lease6Collection leases = alloc_engine_->allocateAddress6(subnet, duid,
ia->getIAID(),
hint, Lease::TYPE_NA,
do_fwd, do_rev,
hostname,
fake_allocation,
callout_handle);
Lease6Collection leases = alloc_engine_->allocateLeases6(subnet, duid,
ia->getIAID(),
hint, Lease::TYPE_NA,
do_fwd, do_rev,
hostname,
fake_allocation,
callout_handle);
/// @todo: Handle more than one lease
Lease6Ptr lease;
if (!leases.empty()) {
......
......@@ -265,7 +265,7 @@ public:
// Check that we have got the address we requested.
checkIAAddr(addr, IOAddress("2001:db8:1:1::dead:beef"),
subnet_->getPreferred(),
Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
if (msg_type != DHCPV6_SOLICIT) {
......@@ -663,7 +663,8 @@ TEST_F(Dhcpv6SrvTest, SolicitBasic) {
ASSERT_TRUE(addr);
// Check that the assigned address is indeed from the configured pool
checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr, addr->getAddress(), Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
// check DUIDs
checkServerId(reply, srv.getServerID());
......@@ -695,7 +696,7 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
// with a valid hint
IOAddress hint("2001:db8:1:1::dead:beef");
ASSERT_TRUE(subnet_->inPool(hint));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
sol->addOption(ia);
......@@ -717,7 +718,8 @@ TEST_F(Dhcpv6SrvTest, SolicitHint) {
ASSERT_TRUE(addr);
// check that we've got the address we requested
checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr, hint, Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
// check DUIDs
checkServerId(reply, srv.getServerID());
......@@ -747,7 +749,7 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
sol->setRemoteAddr(IOAddress("fe80::abcd"));
boost::shared_ptr<Option6IA> ia = generateIA(234, 1500, 3000);
IOAddress hint("2001:db8:1::cafe:babe");
ASSERT_FALSE(subnet_->inPool(hint));
ASSERT_FALSE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
sol->addOption(ia);
......@@ -766,8 +768,9 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
ASSERT_TRUE(addr);
// Check that the assigned address is indeed from the configured pool
checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
checkIAAddr(addr, addr->getAddress(), Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
EXPECT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr->getAddress()));
// check DUIDs
checkServerId(reply, srv.getServerID());
......@@ -830,9 +833,12 @@ TEST_F(Dhcpv6SrvTest, ManySolicits) {
ASSERT_TRUE(addr3);
// Check that the assigned address is indeed from the configured pool
checkIAAddr(addr1, addr1->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr2, addr2->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr1, addr1->getAddress(), Lease::TYPE_NA,
subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr2, addr2->getAddress(), Lease::TYPE_NA,
subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr3, addr3->getAddress(), Lease::TYPE_NA,
subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
checkServerId(reply1, srv.getServerID());
......@@ -876,7 +882,7 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
// with a valid hint
IOAddress hint("2001:db8:1:1::dead:beef");
ASSERT_TRUE(subnet_->inPool(hint));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
req->addOption(ia);
......@@ -896,12 +902,14 @@ TEST_F(Dhcpv6SrvTest, RequestBasic) {
ASSERT_TRUE(tmp);
// check that IA_NA was returned and that there's an address included
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
subnet_->getT2());
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
subnet_->getT1(),
subnet_->getT2());
ASSERT_TRUE(addr);
// check that we've got the address we requested
checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr, hint, Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
// check DUIDs
checkServerId(reply, srv.getServerID());
......@@ -974,9 +982,12 @@ TEST_F(Dhcpv6SrvTest, ManyRequests) {
ASSERT_TRUE(addr3);
// Check that the assigned address is indeed from the configured pool
checkIAAddr(addr1, addr1->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr2, addr2->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr1, addr1->getAddress(), Lease::TYPE_NA,
subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr2, addr2->getAddress(), Lease::TYPE_NA,
subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr3, addr3->getAddress(), Lease::TYPE_NA,
subnet_->getPreferred(), subnet_->getValid());
// check DUIDs
checkServerId(reply1, srv.getServerID());
......@@ -1014,7 +1025,7 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......@@ -1065,7 +1076,8 @@ TEST_F(Dhcpv6SrvTest, RenewBasic) {
ASSERT_TRUE(addr_opt);
// Check that we've got the address we requested
checkIAAddr(addr_opt, addr, subnet_->getPreferred(), subnet_->getValid());
checkIAAddr(addr_opt, addr, Lease::TYPE_NA, subnet_->getPreferred(),
subnet_->getValid());
// Check DUIDs
checkServerId(reply, srv.getServerID());
......@@ -1111,7 +1123,7 @@ TEST_F(Dhcpv6SrvTest, RenewReject) {
const uint32_t bogus_iaid = 456;
// Quick sanity check that the address we're about to use is ok
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
......@@ -1218,7 +1230,7 @@ TEST_F(Dhcpv6SrvTest, ReleaseBasic) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......@@ -1299,7 +1311,7 @@ TEST_F(Dhcpv6SrvTest, ReleaseReject) {
const uint32_t bogus_iaid = 456;
// Quick sanity check that the address we're about to use is ok
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// GenerateClientId() also sets duid_
OptionPtr clientid = generateClientId();
......
......@@ -358,6 +358,7 @@ public:
// and lifetime values match the configured subnet
void checkIAAddr(const boost::shared_ptr<Option6IAAddr>& addr,
const IOAddress& expected_addr,
Lease::Type type,
uint32_t /* expected_preferred */,
uint32_t /* expected_valid */) {
......@@ -365,7 +366,7 @@ public:
// Note that when comparing addresses, we compare the textual
// representation. IOAddress does not support being streamed to
// an ostream, which means it can't be used in EXPECT_EQ.
EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
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());
......
......@@ -1047,7 +1047,7 @@ TEST_F(HooksDhcpv6SrvTest, subnet_select_change) {
// Advertised address must belong to the second pool (in subnet's range,
// in dynamic pool)
EXPECT_TRUE((*subnets)[1]->inRange(addr_opt->getAddress()));
EXPECT_TRUE((*subnets)[1]->inPool(addr_opt->getAddress()));
EXPECT_TRUE((*subnets)[1]->inPool(Lease::TYPE_NA, addr_opt->getAddress()));
}
// This test verifies that incoming (positive) RENEW can be handled properly,
......@@ -1066,7 +1066,7 @@ TEST_F(HooksDhcpv6SrvTest, basic_lease6_renew) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......@@ -1163,7 +1163,7 @@ TEST_F(HooksDhcpv6SrvTest, leaseUpdate_lease6_renew) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......@@ -1254,7 +1254,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_lease6_renew) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......@@ -1330,7 +1330,7 @@ TEST_F(HooksDhcpv6SrvTest, basic_lease6_release) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......@@ -1411,7 +1411,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_lease6_release) {
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(addr));
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
// Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
// value on purpose. They should be updated during RENEW.
......
......@@ -85,12 +85,71 @@ AllocEngine::IterativeAllocator::increaseAddress(const isc::asiolink::IOAddress&
return (IOAddress::fromBytes(addr.getFamily(), packed));
}
isc::asiolink::IOAddress
AllocEngine::IterativeAllocator::increasePrefix(const isc::asiolink::IOAddress& prefix,
const uint8_t prefix_len) {
if (!prefix.isV6()) {
isc_throw(BadValue, "Prefix operations are for IPv6 only (attempted to "
"increase prefix " << prefix.toText() << ")");
}
// Get a buffer holding an address.
const std::vector<uint8_t>& vec = prefix.toBytes();
if (prefix_len < 1 || prefix_len > 128) {
isc_throw(BadValue, "Cannot increase prefix: invalid prefix length: "
<< prefix_len);
}
// Brief explanation what happens here:
// http://www.youtube.com/watch?v=NFQCYpIHLNQ
uint8_t n_bytes = (prefix_len - 1)/8;
uint8_t n_bits = 8 - (prefix_len - n_bytes*8);
uint8_t mask = 1 << n_bits;
// Longer explanation: n_bytes specifies number of full bytes that are
// in-prefix. They can also be used as an offset for the first byte that
// is not in prefix. n_bits specifies number of bits on the last byte that
// is (often partially) in prefix. For example for a /125 prefix, the values
// are 15 and 3, respectively. Mask is a bitmask that has the least
// significant bit from the prefix set.
uint8_t packed[V6ADDRESS_LEN];
// Copy the address. It must be V6, but we already checked that.
std::memcpy(packed, &vec[0], V6ADDRESS_LEN);
// Can we safely increase only the last byte in prefix without overflow?
if (packed[n_bytes] + uint16_t(mask) < 256u) {
packed[n_bytes] += mask;
return (IOAddress::fromBytes(AF_INET6, packed));
}
// Overflow (done on uint8_t, but the sum is greater than 255)
packed[n_bytes] += mask;
// Deal with the overflow. Start increasing the least significant byte
for (int i = n_bytes - 1; i >= 0; --i) {
++packed[i];
// If we haven't overflowed (0xff->0x0) the next byte, then we are done
if (packed[i] != 0) {
break;
}
}
return (IOAddress::fromBytes(AF_INET6, packed));
}
isc::asiolink::IOAddress
AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
const DuidPtr&,
const IOAddress&) {
// Is this prefix allocation?
bool prefix = pool_type_ == Lease::TYPE_PD;
// Let's get the last allocated address. It is usually set correctly,
// but there are times when it won't be (like after removing a pool or
// perhaps restarting the server).
......@@ -123,7 +182,19 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
// Ok, we have a pool that the last address belonged to, let's use it.
IOAddress next = increaseAddress(last); // basically addr++
IOAddress next("::");
if (!prefix) {
next = increaseAddress(last); // basically addr++
} else {
Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(*it);
if (!pool6) {
// Something is gravely wrong here
isc_throw(Unexpected, "Wrong type of pool: " << (*it)->toText()
<< " is not Pool6");
}
// Get the next prefix
next = increasePrefix(last, pool6->getLength());
}
if ((*it)->inRange(next)) {
// the next one is in the pool as well, so we haven't hit pool boundary yet
subnet->setLastAllocated(pool_type_, next);
......@@ -222,16 +293,12 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts,
}
Lease6Collection
AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
const DuidPtr& duid,
uint32_t iaid,
const IOAddress& hint,
Lease::Type type,
const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname,
bool fake_allocation,
const isc::hooks::CalloutHandlePtr& callout_handle) {
AllocEngine::allocateLeases6(const Subnet6Ptr& subnet, const DuidPtr& duid,
uint32_t iaid, const IOAddress& hint,
Lease::Type type, const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname, bool fake_allocation,
const isc::hooks::CalloutHandlePtr& callout_handle) {
try {
AllocatorPtr allocator = getAllocator(type);
......@@ -261,8 +328,10 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
}
// check if the hint is in pool and is available
if (subnet->inPool(hint)) {
// This is equivalent of subnet->inPool(hint), but returns the pool
Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>(subnet->getPool(type, hint, false));
if (pool) {
/// @todo: We support only one hint for now
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(type, hint);
if (!lease) {
......@@ -270,10 +339,9 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
/// implemented
// the hint is valid and not currently used, let's create a lease for it
/// @todo: We support only one lease per ia for now
lease = createLease6(subnet, duid, iaid, hint, type, fwd_dns_update,
rev_dns_update, hostname, callout_handle,
fake_allocation);
lease = createLease6(subnet, duid, iaid, hint, pool->getLength(),
type, fwd_dns_update, rev_dns_update,
hostname, callout_handle, 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
......@@ -288,6 +356,7 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
if (lease->expired()) {
/// We found a lease and it is expired, so we can reuse it
lease = reuseExpiredLease(lease, subnet, duid, iaid,
pool->getLength(),
fwd_dns_update, rev_dns_update,
hostname, callout_handle,
fake_allocation);
......@@ -324,13 +393,24 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
/// @todo: check if the address is reserved once we have host support
/// implemented
// The first step is to find out prefix length. It is 128 for
// non-PD leases.
uint8_t prefix_len = 128;
if (type == Lease::TYPE_PD) {
Pool6Ptr pool = boost::dynamic_pointer_cast<Pool6>(
subnet->getPool(type, candidate, false));
prefix_len = pool->getLength();
}
Lease6Ptr existing = LeaseMgrFactory::instance().getLease6(type,
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,
type, fwd_dns_update,
prefix_len, type, fwd_dns_update,
rev_dns_update, hostname,
callout_handle, fake_allocation);
if (lease) {
......@@ -345,9 +425,9 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
} else {
if (existing->expired()) {
existing = reuseExpiredLease(existing, subnet, duid, iaid,
fwd_dns_update, rev_dns_update,
hostname, callout_handle,
fake_allocation);
prefix_len, fwd_dns_update,
rev_dns_update, hostname,
callout_handle, fake_allocation);
Lease6Collection collection;
collection.push_back(existing);
return (collection);
......@@ -372,16 +452,12 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
}
Lease4Ptr
AllocEngine::allocateAddress4(const SubnetPtr& subnet,
const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr,
const IOAddress& hint,
const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname,
bool fake_allocation,
const isc::hooks::CalloutHandlePtr& callout_handle,
Lease4Ptr& old_lease) {
AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid,
const HWAddrPtr& hwaddr, const IOAddress& hint,
const bool fwd_dns_update, const bool rev_dns_update,
const std::string& hostname, bool fake_allocation,
const isc::hooks::CalloutHandlePtr& callout_handle,
Lease4Ptr& old_lease) {
// The NULL pointer indicates that the old lease didn't exist. It may
// be later set to non NULL value if existing lease is found in the
......@@ -444,7 +520,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
}
// check if the hint is in pool and is available
if (subnet->inPool(hint)) {
if (subnet->inPool(Lease::TYPE_V4, hint)) {
existing = LeaseMgrFactory::instance().getLease4(hint);
if (!existing) {
/// @todo: Check if the hint is reserved once we have host support
......@@ -620,7 +696,8 @@ Lease4Ptr AllocEngine::renewLease4(const SubnetPtr& subnet,
Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
const Subnet6Ptr& subnet,
const DuidPtr& duid,
uint32_t iaid,
const uint32_t iaid,
uint8_t prefix_len,
const bool fwd_dns_update,
const bool rev_dns_update,
const std::string& hostname,
......@@ -631,6 +708,10 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
isc_throw(BadValue, "Attempt to recycle lease that is still valid");
}
if (expired->type_ != Lease::TYPE_PD) {
prefix_len = 128; // non-PD lease types must be always /128
}
// address, lease type and prefixlen (0) stay the same
expired->iaid_ = iaid;
expired->duid_ = duid;
......@@ -644,6 +725,7 @@ Lease6Ptr AllocEngine::reuseExpiredLease(Lease6Ptr& expired,
expired->hostname_ = hostname;
expired->fqdn_fwd_ = fwd_dns_update;
expired->fqdn_rev_ = rev_dns_update;
expired->prefixlen_ = prefix_len;
/// @todo: log here that the lease was reused (there's ticket #2524 for
/// logging in libdhcpsrv)
......@@ -777,18 +859,24 @@ Lease4Ptr AllocEngine::reuseExpiredLease(Lease4Ptr& expired,
Lease6Ptr AllocEngine::createLease6(const Subnet6Ptr& subnet,
const DuidPtr& duid,
uint32_t iaid,
const uint32_t iaid,