// Secondly, pool specific options. Pools are defined within a subnet, so
// if there is no subnet, there is nothing to do.
if (ctx.subnet_) {
- BOOST_FOREACH(const AllocEngine::ResourceType& resource,
- ctx.allocated_resources_) {
- PoolPtr pool = ctx.subnet_->getPool(resource.second == 128 ?
- Lease::TYPE_NA : Lease::TYPE_PD,
- resource.first, false);
+ for (auto resource : ctx.allocated_resources_) {
+ PoolPtr pool =
+ ctx.subnet_->getPool(resource.getPrefixLength() == 128 ?
+ Lease::TYPE_NA : Lease::TYPE_PD,
+ resource.getAddress(),
+ false);
if (pool && !pool->getCfgOption()->empty()) {
co_list.push_back(pool->getCfgOption());
}
// Set per-IA context values.
ctx.createIAContext();
ctx.currentIA().iaid_ = ia->getIAID();
- ctx.currentIA().addHint(hint);
+ if (hint_opt) {
+ ctx.currentIA().addHint(hint_opt);
+ } else {
+ ctx.currentIA().addHint(hint);
+ }
ctx.currentIA().type_ = Lease::TYPE_NA;
// Use allocation engine to pick a lease for this client. Allocation engine
// Set per-IA context values.
ctx.createIAContext();
ctx.currentIA().iaid_ = ia->getIAID();
- ctx.currentIA().addHint(hint);
+ if (hint_opt) {
+ ctx.currentIA().addHint(hint_opt);
+ } else {
+ ctx.currentIA().addHint(hint);
+ }
ctx.currentIA().type_ = Lease::TYPE_PD;
// Use allocation engine to pick a lease for this client. Allocation engine
// There's no way to protect against this.
continue;
}
- ctx.currentIA().addHint(iaaddr->getAddress());
+ ctx.currentIA().addHint(iaaddr);
}
Lease6Collection leases = alloc_engine_->renewLeases6(ctx);
.arg(ia->getIAID());
// Now remove this prefix from the hints list.
- AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_);
+ AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
hints.end());
}
}
// Now remove this address from the hints list.
- AllocEngine::ResourceType hint_type((*l)->addr_, 128);
+ AllocEngine::Resource hint_type((*l)->addr_, 128);
hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
// If the new FQDN settings have changed for the lease, we need to
for (AllocEngine::HintContainer::const_iterator hint = hints.begin();
hint != hints.end(); ++hint) {
Option6IAAddrPtr iaaddr(new Option6IAAddr(D6O_IAADDR,
- hint->first, 0, 0));
+ hint->getAddress(), 0, 0));
ia_rsp->addOption(iaaddr);
}
}
// Put the client's prefix into the hints list.
- ctx.currentIA().addHint(prf->getAddress(), prf->getLength());
+ ctx.currentIA().addHint(prf);
}
// Call Allocation Engine and attempt to renew leases. Number of things
.arg(ia->getIAID());
// Now remove this prefix from the hints list.
- AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_);
+ AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
hints.end());
}
}
// Now remove this prefix from the hints list.
- AllocEngine::ResourceType hint_type((*l)->addr_, (*l)->prefixlen_);
+ AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
}
// Send the prefix with the zero lifetimes only if the prefix
// contains non-zero value. A zero value indicates that the hint was
// for the prefix length.
- if (!prefix->first.isV6Zero()) {
- OptionPtr prefix_opt(new Option6IAPrefix(D6O_IAPREFIX, prefix->first,
- prefix->second, 0, 0));
+ if (!prefix->getAddress().isV6Zero()) {
+ OptionPtr prefix_opt(new Option6IAPrefix(D6O_IAPREFIX,
+ prefix->getAddress(),
+ prefix->getPrefixLength(),
+ 0, 0));
ia_rsp->addOption(prefix_opt);
}
}
}
// And finish by pools
- BOOST_FOREACH(const AllocEngine::ResourceType& resource,
- ctx.allocated_resources_) {
- PoolPtr pool = ctx.subnet_->getPool(resource.second == 128 ?
- Lease::TYPE_NA :
- Lease::TYPE_PD,
- resource.first,
- false);
+ for (auto resource : ctx.allocated_resources_) {
+ PoolPtr pool =
+ ctx.subnet_->getPool(resource.getPrefixLength() == 128 ?
+ Lease::TYPE_NA : Lease::TYPE_PD,
+ resource.getAddress(),
+ false);
if (pool) {
const ClientClasses& to_add = pool->getRequiredClasses();
for (ClientClasses::const_iterator cclass = to_add.cbegin();
return (alloc->second);
}
+AllocEngine::Resource::Resource(const Option6IAAddrPtr& iaaddr)
+ : address_(iaaddr->getAddress()), prefix_len_(128),
+ preferred_(iaaddr->getPreferred()), valid_(iaaddr->getValid()) {
+}
+
+AllocEngine::Resource::Resource(const Option6IAPrefixPtr& iaprefix)
+ : address_(iaprefix->getAddress()), prefix_len_(iaprefix->getLength()),
+ preferred_(iaprefix->getPreferred()), valid_(iaprefix->getValid()) {
+}
+
} // end of namespace isc::dhcp
} // end of namespace isc
void
AllocEngine::ClientContext6::
IAContext::addHint(const asiolink::IOAddress& prefix,
- const uint8_t prefix_len) {
- hints_.push_back(std::make_pair(prefix, prefix_len));
+ const uint8_t prefix_len,
+ const uint32_t preferred,
+ const uint32_t valid) {
+ hints_.push_back(Resource(prefix, prefix_len, preferred, valid));
+}
+
+void
+AllocEngine::ClientContext6::
+IAContext::addHint(const Option6IAAddrPtr& iaaddr) {
+ hints_.push_back(Resource(iaaddr));
+}
+
+void
+AllocEngine::ClientContext6::
+IAContext::addHint(const Option6IAPrefixPtr& iaprefix) {
+ hints_.push_back(Resource(iaprefix));
}
void
AllocEngine::ClientContext6::
addAllocatedResource(const asiolink::IOAddress& prefix,
const uint8_t prefix_len) {
- static_cast<void>(allocated_resources_.insert(std::make_pair(prefix,
- prefix_len)));
+ static_cast<void>(allocated_resources_.insert(Resource(prefix,
+ prefix_len)));
}
bool
AllocEngine::ClientContext6::
isAllocated(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const {
return (static_cast<bool>
- (allocated_resources_.count(std::make_pair(prefix, prefix_len))));
+ (allocated_resources_.count(Resource(prefix, prefix_len))));
}
ConstHostPtr
IOAddress hint = IOAddress::IPV6_ZERO_ADDRESS();
if (!ctx.currentIA().hints_.empty()) {
/// @todo: We support only one hint for now
- hint = ctx.currentIA().hints_[0].first;
+ hint = ctx.currentIA().hints_[0].getAddress();
}
Subnet6Ptr original_subnet = ctx.subnet_;
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
#include <dhcp/option6_ia.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_iaprefix.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/lease_mgr.h>
public:
- /// @brief Defines a single hint (an address + prefix-length).
+ /// @brief Defines a single hint
///
/// This is an entry that represents what the client had requested,
/// either an address or a prefix. Prefix length is 128 for regular
- /// addresses.
- typedef std::pair<isc::asiolink::IOAddress, uint8_t> ResourceType;
+ /// addresses. Optionally it provides wanted preferred and valid
+ /// lifetimes.
+ ///
+ /// @note Seems to be used only for DHCPv6.
+ class Resource {
+ public:
+
+ /// @brief Default constructor.
+ ///
+ /// @param address the address or prefix
+ /// @param prefix_len the prefix length (128 for addresses)
+ /// @param preferred the optional preferred lifetime
+ /// @param valid the optional valid lifetime
+ Resource(const isc::asiolink::IOAddress& address,
+ const uint8_t prefix_len,
+ const uint32_t preferred = 0,
+ const uint32_t valid = 0)
+ : address_(address), prefix_len_(prefix_len),
+ preferred_(preferred), valid_(valid) {
+ }
+
+ /// @brief Constructor from an IAADDR DHCPv6 option.
+ ///
+ /// @param iaaddr The pointer to the IAADDR option
+ Resource(const Option6IAAddrPtr& iaaddr);
+
+ /// @brief Constructor from an IAPREFIX DHCPv6 option.
+ ///
+ /// @param iaprefix The pointer to the IAPREFIX option
+ Resource(const Option6IAPrefixPtr& iaprefix);
+
+ /// @brief Returns the address.
+ ///
+ /// @return the address or prefix
+ isc::asiolink::IOAddress getAddress() const {
+ return (address_);
+ }
+
+ /// @brief Returns the prefix length.
+ ///
+ /// @return the prefix length
+ uint8_t getPrefixLength() const {
+ return (prefix_len_);
+ }
+
+ /// @brief Returns the optional preferred lifetime.
+ ///
+ /// @return the preferred lifetime (0 if not set)
+ uint32_t getPreferred() const {
+ return (preferred_);
+ }
+
+ /// @brief Returns the optional valid lifetime.
+ ///
+ /// @return the valid lifetime (0 if not set)
+ uint32_t getValid() const {
+ return (valid_);
+ }
+
+ /// @brief Compares two @c AllocEngine::Resource objects for equality.
+ ///
+ /// @param other object to be compared with this object
+ /// @return true if objects are equal, false otherwise.
+ bool equals(const Resource& other) const {
+ return (address_ == other.address_ &&
+ prefix_len_ == other.prefix_len_);
+ }
+
+ /// @brief Equality operator.
+ ///
+ /// @param other object to be compared with this object
+ /// @return true if objects are equal, false otherwise.
+ bool operator==(const Resource& other) const {
+ return (equals(other));
+ }
+
+ protected:
+
+ /// @brief The address or prefix.
+ isc::asiolink::IOAddress address_;
+
+ /// @brief The prefix length (128 for an address).
+ uint8_t prefix_len_;
+
+ /// @brief The preferred lifetime (0 when not set).
+ uint32_t preferred_;
+
+ /// @brief The valid lifetime (0 when not set).
+ uint32_t valid_;
+ };
+
+ /// @brief Resource compare class.
+ ///
+ /// Needed for using sets of Resource objets.
+ struct ResourceCompare {
+ /// @brief Compare operator
+ ///
+ /// @note Only the address/prefix part of resources is used.
+ /// @param lhr Left hand resource objet
+ /// @param rhr Right hand resource objet
+ /// @return true if lhr is less than rhr, false otherwise
+ bool operator() (const Resource& lhr, const Resource& rhr) const {
+ if (lhr.getAddress() == rhr.getAddress()) {
+ return (lhr.getPrefixLength() < rhr.getPrefixLength());
+ } else {
+ return (lhr.getAddress() < rhr.getAddress());
+ }
+ }
+ };
/// @brief Container for client's hints.
- typedef std::vector<ResourceType> HintContainer;
+ typedef std::vector<Resource> HintContainer;
/// @brief Container holding allocated prefixes or addresses.
- typedef std::set<ResourceType> ResourceContainer;
+ typedef std::set<Resource, ResourceCompare> ResourceContainer;
/// @brief A tuple holding host identifier type and value.
typedef std::pair<Host::IdentifierType, std::vector<uint8_t> > IdentifierPair;
///
/// @param prefix Prefix or address.
/// @param prefix_len Prefix length. Default is 128 for addresses.
+ /// @param preferred Wanted preferred lifetime. Default 0.
+ /// @param valid Wanted valid lifetime. Default 0.
void addHint(const asiolink::IOAddress& prefix,
- const uint8_t prefix_len = 128);
+ const uint8_t prefix_len = 128,
+ const uint32_t preferred = 0,
+ const uint32_t valid = 0);
+
+ /// @brief Convenience method adding new hint from IAADDR option.
+ ///
+ /// @param iaaddr Pointer to IAADDR.
+ void addHint(const Option6IAAddrPtr& iaaddr);
+
+ /// @brief Convenience method adding new hint from IAPREFIX option.
+ ///
+ /// @param iaprefix Pointer to IAPREFIX.
+ void addHint(const Option6IAPrefixPtr& iaprefix);
};
/// @brief Container holding IA specific contexts.
ctx.currentIA().addHint(IOAddress("3000:1::"), 64);
ASSERT_EQ(2, ctx.currentIA().hints_.size());
- EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].first.toText());
- EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].first.toText());
+ EXPECT_EQ("2001:db8:1::1", ctx.currentIA().hints_[0].getAddress().toText());
+ EXPECT_EQ("3000:1::", ctx.currentIA().hints_[1].getAddress().toText());
}
// Test convenience method adding allocated prefixes and addresses to
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128));
+ hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(IOAddress("2001:db8:1::15"), 128));
+ hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::15"), 128));
// Client should receive a lease.
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(leases[0]->addr_, 128));
+ hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
ASSERT_EQ(1, renewed.size());
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(leases[0]->addr_, 128));
+ hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
Lease6Collection renewed = renewTest(engine, pool_, hints, true);
ASSERT_EQ(1, renewed.size());
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(leases[0]->addr_, 128));
+ hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
// Create reservation for the client. This is in-pool reservation,
// as the pool is 2001:db8:1::10 - 2001:db8:1::20.
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(leases[0]->addr_, 128));
+ hints.push_back(AllocEngine::Resource(leases[0]->addr_, 128));
// Create reservation for this address, but for another client.
// This is in-pool reservation, as the pool is 2001:db8:1::10 - 2001:db8:1::20.
// Now, try requesting this address by providing a hint. The engine
// should try to honor the hint even though we start from the subnet2.
ctx.subnet_ = subnet2_;
- ctx.currentIA().hints_.push_back(make_pair(IOAddress("2001:db8:1::1"), 128));
+ ctx.currentIA().addHint(IOAddress("2001:db8:1::1"));
ASSERT_NO_THROW(lease2 = expectOneLease(engine_.allocateLeases6(ctx)));
ASSERT_TRUE(lease2);
ASSERT_TRUE(subnet1_->inRange(lease2->addr_));
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(IOAddress("2001:db8:1::10"), 128));
+ hints.push_back(AllocEngine::Resource(IOAddress("2001:db8:1::10"), 128));
// Set test fixture hostname_ to the expected value. This gets checked in
// renewTest.
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(IOAddress("3001::1"), 128));
+ hints.push_back(AllocEngine::Resource(IOAddress("3001::1"), 128));
// Set test fixture hostname_ to the expected value. This gets checked in
// renewTest.
// This is what the client will send in his renew message.
AllocEngine::HintContainer hints;
- hints.push_back(make_pair(IOAddress("3001::"), 64));
+ hints.push_back(AllocEngine::Resource(IOAddress("3001::"), 64));
// Set test fixture hostname_ to the expected value. This gets checked via
// renewTest.
-// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
msg_type == DHCPV6_SOLICIT,
Pkt6Ptr(new Pkt6(msg_type, 0x1234)));
ctx.currentIA().iaid_ = 1;
- ctx.currentIA().hints_.push_back(std::make_pair(leases_[i]->addr_, 128));
+ ctx.currentIA().addHint(leases_[i]->addr_);
// Depending on the message type, we will call a different function.
if (msg_type == DHCPV6_RENEW) {