#include <dhcpsrv/alloc_engine.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/host_mgr.h>
+#include <dhcpsrv/host.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <hooks/server_hooks.h>
/// @todo: We support only one hint for now
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(ctx.type_, hint);
if (!lease) {
- /// @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
- lease = createLease6(ctx, hint, pool->getLength());
-
- // 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) {
+ // In-pool reservations: Check if this address is reserved for someone
+ // else. There is no need to check for whom it is reserved, because if
+ // it has been reserved for us we would have already allocated a lease.
+
+ /// @todo: BROKEN this call is broken. It tries to convert getID()
+ /// to IOAddress::uint32_t()
+ if (!ctx.subnet_->allowInPoolReservations() ||
+ !HostMgr::instance().get6(ctx.subnet_->getID(), hint)) {
+ // If the in-pool reservations are disabled, or there is no
+ // reservation for a given hint, we're good to go.
+
+ // The hint is valid and not currently used, let's create a
+ // lease for it
+ lease = createLease6(ctx, hint, pool->getLength());
+
+ // 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) {
- /// @todo: We support only one lease per ia for now
- Lease6Collection collection;
- collection.push_back(lease);
- return (collection);
+ /// @todo: We support only one lease per ia for now
+ Lease6Collection collection;
+ collection.push_back(lease);
+ return (collection);
+ }
}
} else {
+
+ // If the lease is expired, we may likely reuse it, but...
if (lease->expired()) {
- // Copy an existing, expired lease so as it can be returned
- // to the caller.
- Lease6Ptr old_lease(new Lease6(*lease));
- ctx.old_leases_.push_back(old_lease);
- /// We found a lease and it is expired, so we can reuse it
- lease = reuseExpiredLease(lease, ctx, pool->getLength());
+ // Let's check if there is a reservation for this address.
+ if (!ctx.subnet_->allowInPoolReservations() ||
+ !HostMgr::instance().get6(ctx.subnet_->getID(), hint)) {
- /// @todo: We support only one lease per ia for now
- leases.push_back(lease);
- return (leases);
- }
+ // Copy an existing, expired lease so as it can be returned
+ // to the caller.
+ Lease6Ptr old_lease(new Lease6(*lease));
+ ctx.old_leases_.push_back(old_lease);
+
+ /// We found a lease and it is expired, so we can reuse it
+ lease = reuseExpiredLease(lease, ctx, pool->getLength());
+ /// @todo: We support only one lease per ia for now
+ leases.push_back(lease);
+ return (leases);
+ }
+ }
}
}
do {
IOAddress candidate = allocator->pickAddress(ctx.subnet_, ctx.duid_, hint);
- /// @todo: check if the address is reserved once we have host support
- /// implemented
+ /// In-pool reservations: Check if this address is reserved for someone
+ /// else. There is no need to check for whom it is reserved, because if
+ /// it has been reserved for us we would have already allocated a lease.
+ if (ctx.subnet_->allowInPoolReservations() &&
+ HostMgr::instance().get6(ctx.subnet_->getID(), candidate)) {
+
+ // Don't allocate.
+ continue;
+ }
// The first step is to find out prefix length. It is 128 for
// non-PD leases.
void
AllocEngine::allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& existing_leases) {
- /// @todo
- if (!ctx.host_ || existing_leases.empty()) {
+
+ // If there are no reservations or the reservation is v4, there's nothing to do.
+ if (!ctx.host_ || ctx.host_->hasIPv6Reservation()) {
+ return;
+ }
+
+ // Let's convert this from Lease::Type to IPv6Reserv::Type
+ IPv6Resrv::Type type = ctx.type_ == Lease::TYPE_NA ? IPv6Resrv::TYPE_NA : IPv6Resrv::TYPE_PD;
+
+ // Get the IPv6 reservations of specified type.
+ const IPv6ResrvRange& reservs = ctx.host_->getIPv6Reservations(type);
+
+ if (std::distance(reservs.first, reservs.second) == 0) {
+ // No reservations? We're done here.
return;
}
+
+ for (IPv6ResrvIterator resv = reservs.first; resv != reservs.second; ++resv) {
+ // We do have a reservation for addr.
+ IOAddress addr = resv->second.getPrefix();
+ uint8_t prefix_len = resv->second.getPrefixLen();
+
+ // 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;
+ }
+
+ // 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);
+ }
}
void