33#include <boost/foreach.hpp>
34#include <boost/make_shared.hpp>
52namespace ph = std::placeholders;
57struct AllocEngineHooks {
58 int hook_index_lease4_select_;
59 int hook_index_lease4_renew_;
60 int hook_index_lease4_expire_;
61 int hook_index_lease4_recover_;
62 int hook_index_lease6_select_;
63 int hook_index_lease6_renew_;
64 int hook_index_lease6_rebind_;
65 int hook_index_lease6_expire_;
66 int hook_index_lease6_recover_;
70 hook_index_lease4_select_ = HooksManager::registerHook(
"lease4_select");
71 hook_index_lease4_renew_ = HooksManager::registerHook(
"lease4_renew");
72 hook_index_lease4_expire_ = HooksManager::registerHook(
"lease4_expire");
73 hook_index_lease4_recover_= HooksManager::registerHook(
"lease4_recover");
74 hook_index_lease6_select_ = HooksManager::registerHook(
"lease6_select");
75 hook_index_lease6_renew_ = HooksManager::registerHook(
"lease6_renew");
76 hook_index_lease6_rebind_ = HooksManager::registerHook(
"lease6_rebind");
77 hook_index_lease6_expire_ = HooksManager::registerHook(
"lease6_expire");
78 hook_index_lease6_recover_= HooksManager::registerHook(
"lease6_recover");
86AllocEngineHooks
Hooks;
99 const uint8_t prefix_len) {
100 if (!prefix.
isV6()) {
102 "increase prefix " << prefix <<
")");
106 const std::vector<uint8_t>& vec = prefix.
toBytes();
108 if (prefix_len < 1 || prefix_len > 128) {
113 uint8_t n_bytes = (prefix_len - 1)/8;
114 uint8_t n_bits = 8 - (prefix_len - n_bytes*8);
115 uint8_t mask = 1 << n_bits;
124 uint8_t packed[V6ADDRESS_LEN];
127 std::memcpy(packed, &vec[0], V6ADDRESS_LEN);
130 if (packed[n_bytes] + uint16_t(mask) < 256u) {
131 packed[n_bytes] += mask;
136 packed[n_bytes] += mask;
139 for (
int i = n_bytes - 1; i >= 0; --i) {
142 if (packed[i] != 0) {
153 const uint8_t prefix_len) {
157 return (increasePrefix(address, prefix_len));
162AllocEngine::IterativeAllocator::pickAddressInternal(
const SubnetPtr& subnet,
168 uint8_t prefix_len = 0;
173 IOAddress last = subnet->getLastAllocated(pool_type_);
175 bool retrying =
false;
184 PoolCollection::const_iterator it;
185 PoolCollection::const_iterator first = pools.end();
187 for (it = pools.begin(); it != pools.end(); ++it) {
188 if (!(*it)->clientSupported(client_classes)) {
191 if (first == pools.end()) {
194 if ((*it)->inRange(last)) {
200 if (first == pools.end()) {
209 if (it == pools.end()) {
216 for (; it != pools.end(); ++it) {
217 if ((*it)->clientSupported(client_classes)) {
221 if (it == pools.end()) {
227 last = (*it)->getLastAllocated();
228 valid = (*it)->isLastAllocatedValid();
229 if (!valid && (last == (*it)->getFirstAddress())) {
231 (*it)->setLastAllocated(last);
232 subnet->setLastAllocated(pool_type_, last);
236 if (valid && !(*it)->inRange(last)) {
238 (*it)->resetLastAllocated();
239 (*it)->setLastAllocated((*it)->getFirstAddress());
245 Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(*it);
249 isc_throw(Unexpected,
"Wrong type of pool: "
254 prefix_len = pool6->getLength();
257 IOAddress next = increaseAddress(last, prefix, prefix_len);
258 if ((*it)->inRange(next)) {
261 (*it)->setLastAllocated(next);
262 subnet->setLastAllocated(pool_type_, next);
267 (*it)->resetLastAllocated();
275 for (it = first; it != pools.end(); ++it) {
276 if ((*it)->clientSupported(client_classes)) {
277 (*it)->setLastAllocated((*it)->getFirstAddress());
278 (*it)->resetLastAllocated();
283 last = (*first)->getLastAllocated();
284 (*first)->setLastAllocated(last);
285 subnet->setLastAllocated(pool_type_, last);
295AllocEngine::HashedAllocator::pickAddressInternal(
const SubnetPtr&,
308AllocEngine::RandomAllocator::pickAddressInternal(
const SubnetPtr&,
317 : attempts_(attempts), incomplete_v4_reclamations_(0),
318 incomplete_v6_reclamations_(0) {
324 switch (engine_type) {
341 switch (engine_type) {
360 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
361 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
365 std::map<Lease::Type, AllocatorPtr>::const_iterator alloc = allocators_.find(type);
367 if (alloc == allocators_.end()) {
371 return (alloc->second);
398 if (CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
399 auto host = HostMgr::instance().get6(subnet_id, address);
401 reserved.push_back(host);
404 auto hosts = HostMgr::instance().getAll6(subnet_id, address);
405 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
424 const IOAddress& address,
bool check_subnet) {
428 while (current_subnet) {
430 if (current_subnet->clientSupported(ctx.
query_->getClasses())) {
432 if (current_subnet->inPool(lease_type, address)) {
436 if (current_subnet->inPool(lease_type, address,
437 ctx.
query_->getClasses())) {
443 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
459 : query_(), fake_allocation_(false),
460 early_global_reservations_lookup_(false), subnet_(), host_subnet_(),
461 duid_(), hwaddr_(), host_identifiers_(), hosts_(),
462 fwd_dns_update_(false), rev_dns_update_(false), hostname_(),
463 callout_handle_(), ias_(), ddns_params_() {
470 const std::string& hostname,
471 const bool fake_allocation,
474 : query_(query), fake_allocation_(fake_allocation),
475 early_global_reservations_lookup_(false), subnet_(subnet),
476 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
477 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
478 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
479 ias_(), ddns_params_() {
488 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
489 changed_leases_(), new_resources_(), ia_rsp_() {
495 const uint8_t prefix_len,
496 const uint32_t preferred,
497 const uint32_t valid) {
498 hints_.push_back(
Resource(prefix, prefix_len, preferred, valid));
507 addHint(iaaddr->getAddress(), 128,
508 iaaddr->getPreferred(), iaaddr->getValid());
517 addHint(iaprefix->getAddress(), iaprefix->getLength(),
518 iaprefix->getPreferred(), iaprefix->getValid());
524 const uint8_t prefix_len) {
525 static_cast<void>(new_resources_.insert(
Resource(prefix, prefix_len)));
531 const uint8_t prefix_len)
const {
532 return (
static_cast<bool>(new_resources_.count(
Resource(prefix,
539 const uint8_t prefix_len) {
547 return (
static_cast<bool>
554 if (subnet && subnet->getReservationsInSubnet()) {
555 auto host =
hosts_.find(subnet->getID());
556 if (host !=
hosts_.cend()) {
557 return (host->second);
567 if (subnet &&
subnet_->getReservationsGlobal()) {
568 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
569 if (host !=
hosts_.cend()) {
570 return (host->second);
580 return (ghost && ghost->hasReservation(resv));
586 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
587 return (ddns_params_);
593 return (ddns_params_);
612 !subnet->getReservationsInSubnet()) {
618 subnet->getReservationsGlobal()) {
621 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
624 if (!subnet->getReservationsInSubnet()) {
630 std::map<SubnetID, ConstHostPtr> host_map;
632 subnet->getSharedNetwork(network);
641 const bool use_single_query = network &&
645 if (use_single_query) {
649 id_pair.second.size());
653 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
654 if ((*host)->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
655 host_map[(*host)->getIPv6SubnetID()] = *host;
666 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
667 subnet->getReservationsInSubnet()) {
670 if (use_single_query) {
671 if (host_map.count(subnet->getID()) > 0) {
672 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
680 id_pair.second.size());
683 ctx.
hosts_[subnet->getID()] = host;
693 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
703 &id_pair.second[0], id_pair.second.size());
737 for (
auto l : all_leases) {
738 if ((l)->subnet_id_ == subnet->getID()) {
743 subnet = subnet->getNextSubnet(ctx.
subnet_);
763 if (leases.empty() && !ctx.
hosts_.empty()) {
767 .arg(ctx.
query_->getLabel());
772 allocateReservedLeases6(ctx, leases);
774 leases = updateLeaseData(ctx, leases);
789 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
793 .arg(ctx.
query_->getLabel());
797 removeNonmatchingReservedLeases6(ctx, leases);
799 leases = updateLeaseData(ctx, leases);
808 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
812 .arg(ctx.
query_->getLabel());
816 allocateReservedLeases6(ctx, leases);
828 removeNonmatchingReservedLeases6(ctx, leases);
837 removeNonreservedLeases6(ctx, leases);
842 leases = updateLeaseData(ctx, leases);
855 if (leases.empty()) {
869 .arg(ctx.
query_->getLabel());
871 leases = allocateUnreservedLeases6(ctx);
874 if (!leases.empty()) {
889 .arg(ctx.
query_->getLabel())
909 if (!ctx.currentIA().hints_.empty()) {
911 hint = ctx.currentIA().hints_[0].getAddress();
921 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
923 if (!subnet->clientSupported(ctx.query_->getClasses())) {
927 ctx.subnet_ = subnet;
931 pool = boost::dynamic_pointer_cast<Pool6>
932 (subnet->getPool(ctx.currentIA().type_, ctx.query_->getClasses(),
936 if (!pool || !pool->clientSupported(ctx.query_->getClasses())) {
940 bool in_subnet = subnet->getReservationsInSubnet();
957 (!subnet->getReservationsOutOfPool() ||
958 !subnet->inPool(ctx.currentIA().type_, hint))) {
959 hosts = getIPv6Resrv(subnet->getID(), hint);
968 lease = createLease6(ctx, hint, pool->getLength(), callout_status);
978 collection.push_back(lease);
984 .arg(ctx.query_->getLabel())
988 }
else if (lease->expired()) {
997 (!subnet->getReservationsOutOfPool() ||
998 !subnet->inPool(ctx.currentIA().type_, hint))) {
999 hosts = getIPv6Resrv(subnet->getID(), hint);
1003 if (hosts.empty()) {
1008 ctx.currentIA().old_leases_.push_back(old_lease);
1011 lease = reuseExpiredLease(lease, ctx, pool->getLength(),
1015 leases.push_back(lease);
1021 .arg(ctx.query_->getLabel())
1030 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
1033 if (!check_reservation_first) {
1037 uint64_t total_attempts = 0;
1049 original_subnet->getSharedNetwork(network);
1056 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
1059 ctx.subnet_ = subnet = original_subnet;
1063 uint64_t subnets_with_unavail_leases = 0;
1066 uint64_t subnets_with_unavail_pools = 0;
1068 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
1070 if (!subnet->clientSupported(ctx.query_->getClasses())) {
1080 uint64_t possible_attempts =
1081 subnet->getPoolCapacity(ctx.currentIA().type_,
1082 ctx.query_->getClasses());
1089 uint64_t max_attempts = ((attempts_ == 0) || (possible_attempts < attempts_)) ? possible_attempts : attempts_;
1091 if (max_attempts > 0) {
1094 ++subnets_with_unavail_leases;
1098 ++subnets_with_unavail_pools;
1102 bool in_subnet = subnet->getReservationsInSubnet();
1103 bool out_of_pool = subnet->getReservationsOutOfPool();
1108 if (ctx.callout_handle_) {
1109 ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
1112 for (uint64_t i = 0; i < max_attempts; ++i) {
1116 IOAddress candidate = allocator->pickAddress(subnet,
1117 ctx.query_->getClasses(),
1122 uint8_t prefix_len = 128;
1124 pool = boost::dynamic_pointer_cast<Pool6>(
1125 subnet->getPool(ctx.currentIA().type_,
1126 ctx.query_->getClasses(),
1129 prefix_len = pool->getLength();
1134 if (check_reservation_first && in_subnet && !out_of_pool) {
1135 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1136 if (!hosts.empty()) {
1145 if (MultiThreadingMgr::instance().getMode() &&
1146 !resource_handler.
tryLock(ctx.currentIA().type_, candidate)) {
1159 if (!check_reservation_first && in_subnet && !out_of_pool) {
1160 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1161 if (!hosts.empty()) {
1170 ctx.subnet_ = subnet;
1171 Lease6Ptr lease = createLease6(ctx, candidate, prefix_len, callout_status);
1175 ctx.currentIA().old_leases_.clear();
1177 leases.push_back(lease);
1180 }
else if (ctx.callout_handle_ &&
1181 (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
1189 }
else if (existing->expired()) {
1191 if (!check_reservation_first && in_subnet && !out_of_pool) {
1192 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1193 if (!hosts.empty()) {
1202 ctx.currentIA().old_leases_.push_back(old_lease);
1204 ctx.subnet_ = subnet;
1205 existing = reuseExpiredLease(existing, ctx, prefix_len,
1208 leases.push_back(existing);
1218 .arg(ctx.query_->getLabel())
1219 .arg(network->getName())
1220 .arg(subnets_with_unavail_leases)
1221 .arg(subnets_with_unavail_pools);
1222 StatsMgr::instance().addValue(
"v6-allocation-fail-shared-network",
1223 static_cast<int64_t
>(1));
1224 StatsMgr::instance().addValue(
1225 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1226 "v6-allocation-fail-shared-network"),
1227 static_cast<int64_t
>(1));
1231 std::string shared_network = ctx.subnet_->getSharedNetworkName();
1232 if (shared_network.empty()) {
1233 shared_network =
"(none)";
1236 .arg(ctx.query_->getLabel())
1237 .arg(ctx.subnet_->toText())
1238 .arg(ctx.subnet_->getID())
1239 .arg(shared_network);
1240 StatsMgr::instance().addValue(
"v6-allocation-fail-subnet",
1241 static_cast<int64_t
>(1));
1242 StatsMgr::instance().addValue(
1243 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1244 "v6-allocation-fail-subnet"),
1245 static_cast<int64_t
>(1));
1247 if (total_attempts == 0) {
1253 .arg(ctx.query_->getLabel());
1254 StatsMgr::instance().addValue(
"v6-allocation-fail-no-pools",
1255 static_cast<int64_t
>(1));
1256 StatsMgr::instance().addValue(
1257 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1258 "v6-allocation-fail-no-pools"),
1259 static_cast<int64_t
>(1));
1266 .arg(ctx.query_->getLabel())
1267 .arg(total_attempts);
1268 StatsMgr::instance().addValue(
"v6-allocation-fail",
1269 static_cast<int64_t
>(1));
1270 StatsMgr::instance().addValue(
1271 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1272 "v6-allocation-fail"),
1273 static_cast<int64_t
>(1));
1277 if (!classes.
empty()) {
1279 .arg(ctx.query_->getLabel())
1281 StatsMgr::instance().addValue(
"v6-allocation-fail-classes",
1282 static_cast<int64_t
>(1));
1283 StatsMgr::instance().addValue(
1284 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1285 "v6-allocation-fail-classes"),
1286 static_cast<int64_t
>(1));
1298 if (ctx.hosts_.empty()) {
1301 .arg(ctx.query_->getLabel());
1312 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1313 if ((lease->valid_lft_ != 0)) {
1314 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1315 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1320 .arg(ctx.query_->getLabel())
1321 .arg(lease->typeToText(lease->type_))
1322 .arg(lease->addr_.toText());
1328 if (!ctx.host_subnet_) {
1330 ctx.subnet_->getSharedNetwork(network);
1335 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1343 if (host && !host->getHostname().empty()) {
1350 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1351 static_cast<bool>(fqdn));
1365 for (
Subnet6Ptr subnet = ctx.subnet_; subnet;
1366 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1368 SubnetID subnet_id = subnet->getID();
1371 if (!subnet->clientSupported(ctx.query_->getClasses()) ||
1372 ctx.hosts_.count(subnet_id) == 0) {
1378 bool in_subnet = subnet->getReservationsInSubnet();
1384 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1385 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1389 if (ctx.isAllocated(addr, prefix_len)) {
1398 (subnet->getReservationsOutOfPool() &&
1399 subnet->inPool(ctx.currentIA().type_, addr))) {
1411 ctx.subnet_ = subnet;
1413 if (!ctx.host_subnet_) {
1414 ctx.host_subnet_ = subnet;
1415 if (!host->getHostname().empty()) {
1429 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1430 static_cast<bool>(fqdn));
1436 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1439 existing_leases.push_back(lease);
1444 .arg(ctx.query_->getLabel());
1448 .arg(
static_cast<int>(prefix_len))
1449 .arg(ctx.query_->getLabel());
1467 allocateGlobalReservedLeases6(ctx, existing_leases);
1482 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1483 if ((lease->valid_lft_ != 0) &&
1489 .arg(ctx.query_->getLabel())
1490 .arg(lease->typeToText(lease->type_))
1491 .arg(lease->addr_.toText());
1497 if (!ghost->getHostname().empty()) {
1504 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1505 static_cast<bool>(fqdn));
1520 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1523 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1524 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1528 if (ctx.isAllocated(addr, prefix_len)) {
1536 if (!ghost->getHostname().empty()) {
1550 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1551 static_cast<bool>(fqdn));
1556 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1559 existing_leases.push_back(lease);
1564 .arg(ctx.query_->getLabel());
1568 .arg(
static_cast<int>(prefix_len))
1569 .arg(ctx.query_->getLabel());
1587AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1590 if (existing_leases.empty() || !ctx.subnet_) {
1595 if (!ctx.subnet_->getReservationsInSubnet() &&
1596 !ctx.subnet_->getReservationsGlobal()) {
1597 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1610 if ((ctx.hasGlobalReservation(resv)) ||
1611 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1612 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1621 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1626 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1627 candidate->addr_,
false)) {
1631 if (!hosts.empty()) {
1634 if (hosts.size() == 1) {
1637 .arg(candidate->addr_.toText())
1638 .arg(ctx.duid_->toText())
1639 .arg(hosts.front()->getIdentifierAsText());
1642 .arg(candidate->addr_.toText())
1643 .arg(
static_cast<int>(candidate->prefixlen_))
1644 .arg(ctx.duid_->toText())
1645 .arg(hosts.front()->getIdentifierAsText());
1650 .arg(candidate->addr_.toText())
1651 .arg(ctx.duid_->toText())
1655 .arg(candidate->addr_.toText())
1656 .arg(
static_cast<int>(candidate->prefixlen_))
1657 .arg(ctx.duid_->toText())
1675 StatsMgr::instance().addValue(
1676 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1678 "assigned-nas" :
"assigned-pds"),
1679 static_cast<int64_t
>(-1));
1687 ctx.currentIA().old_leases_.push_back(candidate);
1690 removeLeases(existing_leases, candidate->addr_);
1695AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1706 if (inAllowedPool(ctx, candidate->type_,
1707 candidate->addr_,
false)) {
1722 StatsMgr::instance().addValue(
1723 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1725 "assigned-nas" :
"assigned-pds"),
1726 static_cast<int64_t
>(-1));
1729 ctx.currentIA().old_leases_.push_back(candidate);
1732 removeLeases(existing_leases, candidate->addr_);
1737AllocEngine::removeLeases(
Lease6Collection& container,
const asiolink::IOAddress& addr) {
1739 bool removed =
false;
1740 for (Lease6Collection::iterator lease = container.begin();
1741 lease != container.end(); ++lease) {
1742 if ((*lease)->addr_ == addr) {
1749 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1760 int total = existing_leases.size();
1767 for (Lease6Collection::iterator lease = existing_leases.begin();
1768 lease != existing_leases.end(); ++lease) {
1772 if (ctx.hasGlobalReservation(resv) ||
1773 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1774 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1793 StatsMgr::instance().addValue(
1794 StatsMgr::generateName(
"subnet", (*lease)->subnet_id_,
1796 "assigned-nas" :
"assigned-pds"),
1797 static_cast<int64_t
>(-1));
1802 ctx.currentIA().old_leases_.push_back(*lease);
1818 existing_leases.erase(std::remove(existing_leases.begin(),
1819 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1827 if (!expired->expired()) {
1828 isc_throw(BadValue,
"Attempt to recycle lease that is still valid");
1835 if (!ctx.fake_allocation_) {
1839 reclaimExpiredLease(expired, ctx.callout_handle_);
1843 expired->iaid_ = ctx.currentIA().iaid_;
1844 expired->duid_ = ctx.duid_;
1847 if (!ctx.currentIA().hints_.empty() &&
1848 ctx.currentIA().hints_[0].getPreferred()) {
1849 uint32_t preferred = ctx.currentIA().hints_[0].getPreferred();
1850 expired->preferred_lft_ = ctx.subnet_->getPreferred().get(preferred);
1852 expired->preferred_lft_ = ctx.subnet_->getPreferred();
1856 expired->reuseable_valid_lft_ = 0;
1857 if (!ctx.currentIA().hints_.empty() &&
1858 ctx.currentIA().hints_[0].getValid()) {
1859 uint32_t valid = ctx.currentIA().hints_[0].getValid();
1860 expired->valid_lft_ = ctx.subnet_->getValid().get(valid);
1862 expired->valid_lft_ = ctx.subnet_->getValid();
1864 expired->cltt_ = time(NULL);
1865 expired->subnet_id_ = ctx.subnet_->getID();
1866 expired->hostname_ = ctx.hostname_;
1867 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1868 expired->fqdn_rev_ = ctx.rev_dns_update_;
1869 expired->prefixlen_ = prefix_len;
1874 .arg(ctx.query_->getLabel())
1875 .arg(expired->toText());
1878 if (ctx.callout_handle_ &&
1879 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
1893 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1896 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1899 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1902 ctx.callout_handle_->setArgument(
"lease6", expired);
1905 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1907 callout_status = ctx.callout_handle_->getStatus();
1912 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1924 ctx.callout_handle_->getArgument(
"lease6", expired);
1927 if (!ctx.fake_allocation_) {
1936 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1937 StatsMgr::instance().addValue(
1938 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1940 "assigned-nas" :
"assigned-pds"),
1941 static_cast<int64_t
>(1));
1942 StatsMgr::instance().addValue(
1943 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1945 "cumulative-assigned-nas" :
1946 "cumulative-assigned-pds"),
1947 static_cast<int64_t
>(1));
1948 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
1949 "cumulative-assigned-nas" :
1950 "cumulative-assigned-pds",
1951 static_cast<int64_t
>(1));
1970 if (!classes.
empty()) {
1977 for (
auto name = classes.
cbegin();
1978 name != classes.
cend() && have_both < 2; ++name) {
1981 (cl && (!cl->getPreferred().unspecified()))) {
1982 candidate_preferred = cl->getPreferred();
1987 (cl && (!cl->getValid().unspecified()))) {
1988 candidate_valid = cl->getValid();
1995 if (!candidate_preferred) {
1996 candidate_preferred = ctx.
subnet_->getPreferred();
2000 if (!candidate_valid) {
2001 candidate_valid = ctx.
subnet_->getValid();
2005 preferred = candidate_preferred;
2006 valid = candidate_valid;
2030 uint32_t preferred = 0;
2035 ctx.currentIA().iaid_, preferred,
2036 valid, ctx.subnet_->getID(),
2037 ctx.hwaddr_, prefix_len));
2039 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2040 lease->fqdn_rev_ = ctx.rev_dns_update_;
2041 lease->hostname_ = ctx.hostname_;
2044 if (ctx.callout_handle_ &&
2045 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
2059 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
2062 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
2065 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
2068 ctx.callout_handle_->setArgument(
"lease6", lease);
2071 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
2073 callout_status = ctx.callout_handle_->getStatus();
2078 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
2085 ctx.callout_handle_->getArgument(
"lease6", lease);
2088 if (!ctx.fake_allocation_) {
2098 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2099 StatsMgr::instance().addValue(
2100 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2102 "assigned-nas" :
"assigned-pds"),
2103 static_cast<int64_t
>(1));
2104 StatsMgr::instance().addValue(
2105 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2107 "cumulative-assigned-nas" :
2108 "cumulative-assigned-pds"),
2109 static_cast<int64_t
>(1));
2110 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2111 "cumulative-assigned-nas" :
2112 "cumulative-assigned-pds",
2113 static_cast<int64_t
>(1));
2117 ctx.currentIA().addNewResource(addr, prefix_len);
2156 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2158 subnet = subnet->getNextSubnet(ctx.
subnet_);
2161 if (!leases.empty()) {
2164 .arg(ctx.
query_->getLabel());
2168 removeNonmatchingReservedLeases6(ctx, leases);
2171 if (!ctx.
hosts_.empty()) {
2175 .arg(ctx.
query_->getLabel());
2178 allocateReservedLeases6(ctx, leases);
2184 removeNonreservedLeases6(ctx, leases);
2191 if (leases.empty()) {
2195 .arg(ctx.
query_->getLabel());
2197 leases = allocateUnreservedLeases6(ctx);
2201 for (Lease6Collection::iterator l = leases.begin(); l != leases.end(); ++l) {
2203 (*l)->prefixlen_)) {
2209 .arg(ctx.
query_->getLabel())
2210 .arg((*l)->typeToText((*l)->type_))
2212 extendLease6(ctx, *l);
2215 if (!leases.empty()) {
2219 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2231 .arg(ctx.
query_->getLabel())
2241 if (!lease || !ctx.subnet_) {
2247 if (ctx.subnet_->getID() != lease->subnet_id_) {
2249 ctx.subnet_->getSharedNetwork(network);
2255 ctx.subnet_ = subnet;
2263 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2264 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2278 StatsMgr::instance().addValue(
2279 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
"assigned-nas"),
2280 static_cast<int64_t
>(-1));
2283 ctx.currentIA().old_leases_.push_back(lease);
2290 .arg(ctx.query_->getLabel())
2291 .arg(lease->toText());
2296 bool changed =
false;
2297 uint32_t current_preferred_lft = lease->preferred_lft_;
2298 if (!ctx.currentIA().hints_.empty() &&
2299 ctx.currentIA().hints_[0].getPreferred()) {
2300 uint32_t preferred = ctx.currentIA().hints_[0].getPreferred();
2301 lease->preferred_lft_ = ctx.subnet_->getPreferred().get(preferred);
2303 lease->preferred_lft_ = ctx.subnet_->getPreferred();
2305 if (lease->preferred_lft_ < current_preferred_lft) {
2308 lease->reuseable_valid_lft_ = 0;
2309 if (!ctx.currentIA().hints_.empty() &&
2310 ctx.currentIA().hints_[0].getValid()) {
2311 uint32_t valid = ctx.currentIA().hints_[0].getValid();
2312 lease->valid_lft_ = ctx.subnet_->getValid().get(valid);
2314 lease->valid_lft_ = ctx.subnet_->getValid();
2316 if (lease->valid_lft_ < lease->current_valid_lft_) {
2320 lease->cltt_ = time(NULL);
2321 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2322 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2323 (lease->hostname_ != ctx.hostname_)) {
2325 lease->hostname_ = ctx.hostname_;
2326 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2327 lease->fqdn_rev_ = ctx.rev_dns_update_;
2329 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2331 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2333 lease->hwaddr_ = ctx.hwaddr_;
2341 .arg(ctx.query_->getLabel())
2342 .arg(lease->toText());
2346 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2347 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2348 if (HooksManager::calloutsPresent(hook_point)) {
2361 callout_handle->setArgument(
"query6", ctx.query_);
2364 callout_handle->setArgument(
"lease6", lease);
2368 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2370 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2374 HooksManager::callCallouts(hook_point, *callout_handle);
2379 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2383 .arg(ctx.query_->getName());
2390 bool update_stats =
false;
2394 if (old_data->expired()) {
2395 reclaimExpiredLease(old_data, ctx.callout_handle_);
2399 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2400 update_stats =
true;
2412 setLeaseReusable(lease, current_preferred_lft, ctx);
2418 if (lease->reuseable_valid_lft_ == 0) {
2423 StatsMgr::instance().addValue(
2424 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2426 "assigned-nas" :
"assigned-pds"),
2427 static_cast<int64_t
>(1));
2428 StatsMgr::instance().addValue(
2429 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2431 "cumulative-assigned-nas" :
2432 "cumulative-assigned-pds"),
2433 static_cast<int64_t
>(1));
2434 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2435 "cumulative-assigned-nas" :
2436 "cumulative-assigned-pds",
2437 static_cast<int64_t
>(1));
2450 ctx.currentIA().changed_leases_.push_back(old_data);
2456 for (Lease6Collection::const_iterator lease_it = leases.begin();
2457 lease_it != leases.end(); ++lease_it) {
2459 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2461 updated_leases.push_back(lease);
2465 lease->reuseable_valid_lft_ = 0;
2466 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2467 lease->fqdn_rev_ = ctx.rev_dns_update_;
2468 lease->hostname_ = ctx.hostname_;
2469 if (!ctx.fake_allocation_) {
2470 bool update_stats =
false;
2478 if (inAllowedPool(ctx, ctx.currentIA().type_,
2479 lease->addr_,
true)) {
2480 update_stats =
true;
2485 !(lease->hasIdenticalFqdn(**lease_it)));
2487 lease->cltt_ = time(NULL);
2488 if (!fqdn_changed) {
2489 uint32_t current_preferred_lft = lease->preferred_lft_;
2490 setLeaseReusable(lease, current_preferred_lft, ctx);
2492 if (lease->reuseable_valid_lft_ == 0) {
2493 ctx.currentIA().changed_leases_.push_back(*lease_it);
2498 StatsMgr::instance().addValue(
2499 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2501 "assigned-nas" :
"assigned-pds"),
2502 static_cast<int64_t
>(1));
2503 StatsMgr::instance().addValue(
2504 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2506 "cumulative-assigned-nas" :
2507 "cumulative-assigned-pds"),
2508 static_cast<int64_t
>(1));
2509 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2510 "cumulative-assigned-nas" :
2511 "cumulative-assigned-pds",
2512 static_cast<int64_t
>(1));
2516 updated_leases.push_back(lease);
2519 return (updated_leases);
2524 const bool remove_lease,
2525 const uint16_t max_unwarned_cycles) {
2540 bool incomplete_reclamation =
false;
2543 if (max_leases > 0) {
2552 if (leases.size() > max_leases) {
2554 incomplete_reclamation =
true;
2567 if (!leases.empty() &&
2568 HooksManager::calloutsPresent(
Hooks.hook_index_lease6_expire_)) {
2569 callout_handle = HooksManager::createCalloutHandle();
2572 size_t leases_processed = 0;
2573 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2577 if (MultiThreadingMgr::instance().getMode()) {
2581 reclaimExpiredLease(lease, remove_lease, callout_handle);
2584 reclaimExpiredLease(lease, remove_lease, callout_handle);
2588 }
catch (
const std::exception& ex) {
2590 .arg(lease->addr_.toText())
2601 if (!incomplete_reclamation) {
2602 if (leases_processed < leases.size()) {
2603 incomplete_reclamation =
true;
2620 .arg(leases_processed)
2625 if (incomplete_reclamation) {
2626 ++incomplete_v6_reclamations_;
2629 if ((max_unwarned_cycles > 0) &&
2630 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2632 .arg(max_unwarned_cycles);
2634 incomplete_v6_reclamations_ = 0;
2639 incomplete_v6_reclamations_ = 0;
2652 uint64_t deleted_leases = 0;
2658 }
catch (
const std::exception& ex) {
2665 .arg(deleted_leases);
2670 const bool remove_lease,
2671 const uint16_t max_unwarned_cycles) {
2686 bool incomplete_reclamation =
false;
2689 if (max_leases > 0) {
2698 if (leases.size() > max_leases) {
2700 incomplete_reclamation =
true;
2713 if (!leases.empty() &&
2714 HooksManager::calloutsPresent(
Hooks.hook_index_lease4_expire_)) {
2715 callout_handle = HooksManager::createCalloutHandle();
2718 size_t leases_processed = 0;
2719 BOOST_FOREACH(
Lease4Ptr lease, leases) {
2723 if (MultiThreadingMgr::instance().getMode()) {
2727 reclaimExpiredLease(lease, remove_lease, callout_handle);
2730 reclaimExpiredLease(lease, remove_lease, callout_handle);
2734 }
catch (
const std::exception& ex) {
2736 .arg(lease->addr_.toText())
2747 if (!incomplete_reclamation) {
2748 if (leases_processed < leases.size()) {
2749 incomplete_reclamation =
true;
2766 .arg(leases_processed)
2771 if (incomplete_reclamation) {
2772 ++incomplete_v4_reclamations_;
2775 if ((max_unwarned_cycles > 0) &&
2776 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2778 .arg(max_unwarned_cycles);
2780 incomplete_v4_reclamations_ = 0;
2785 incomplete_v4_reclamations_ = 0;
2792template<
typename LeasePtrType>
2794AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2796 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2800template<
typename LeasePtrType>
2802AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2807 if (!lease->stateExpiredReclaimed()) {
2808 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2813AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2814 const DbReclaimMode& reclaim_mode,
2820 .arg(lease->addr_.toText())
2821 .arg(
static_cast<int>(lease->prefixlen_));
2827 bool skipped =
false;
2828 if (callout_handle) {
2836 callout_handle->deleteAllArguments();
2837 callout_handle->setArgument(
"lease6", lease);
2838 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2840 HooksManager::callCallouts(
Hooks.hook_index_lease6_expire_,
2843 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2858 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2868 remove_lease = reclaimDeclined(lease);
2871 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2875 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2877 &lease_mgr, ph::_1));
2886 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2893 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2901 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2904 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2906 "reclaimed-leases"),
2911AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2912 const DbReclaimMode& reclaim_mode,
2918 .arg(lease->addr_.toText());
2924 bool skipped =
false;
2925 if (callout_handle) {
2933 callout_handle->setArgument(
"lease4", lease);
2934 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2936 HooksManager::callCallouts(
Hooks.hook_index_lease4_expire_,
2939 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2952 lease->hostname_.clear();
2953 lease->fqdn_fwd_ =
false;
2954 lease->fqdn_rev_ =
false;
2958 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2968 remove_lease = reclaimDeclined(lease);
2971 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2975 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
2977 &lease_mgr, ph::_1));
2984 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2986 "assigned-addresses"),
2990 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2993 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2995 "reclaimed-leases"),
3005 uint64_t deleted_leases = 0;
3011 }
catch (
const std::exception& ex) {
3018 .arg(deleted_leases);
3022AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3027 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_recover_)) {
3037 callout_handle->setArgument(
"lease4", lease);
3040 HooksManager::callCallouts(
Hooks.hook_index_lease4_recover_, *callout_handle);
3045 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3047 .arg(lease->addr_.toText());
3053 .arg(lease->addr_.toText())
3054 .arg(lease->valid_lft_);
3056 StatsMgr& stats_mgr = StatsMgr::instance();
3059 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3060 "declined-addresses"),
static_cast<int64_t
>(-1));
3063 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3065 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3067 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3068 "reclaimed-declined-addresses"),
static_cast<int64_t
>(1));
3076AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3081 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_recover_)) {
3091 callout_handle->setArgument(
"lease6", lease);
3094 HooksManager::callCallouts(
Hooks.hook_index_lease6_recover_, *callout_handle);
3099 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3101 .arg(lease->addr_.toText());
3107 .arg(lease->addr_.toText())
3108 .arg(lease->valid_lft_);
3110 StatsMgr& stats_mgr = StatsMgr::instance();
3113 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3114 "declined-addresses"),
static_cast<int64_t
>(-1));
3117 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3119 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3121 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3122 "reclaimed-declined-addresses"),
static_cast<int64_t
>(1));
3130template<
typename LeasePtrType>
3131void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3132 const bool remove_lease,
3133 const std::function<
void (
const LeasePtrType&)>&
3134 lease_update_fun)
const {
3142 }
else if (lease_update_fun) {
3145 lease->reuseable_valid_lft_ = 0;
3146 lease->hostname_.clear();
3147 lease->fqdn_fwd_ =
false;
3148 lease->fqdn_rev_ =
false;
3150 lease_update_fun(lease);
3159 .arg(lease->addr_.toText());
3195 (!ctx.
subnet_->getReservationsOutOfPool() ||
3206 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3210 hosts.push_back(host);
3217 for (
auto host : hosts) {
3221 if (id_pair.first == host->getIdentifierType() &&
3222 id_pair.second == host->getIdentifier()) {
3230 return (!hosts.empty());
3252 if (ctx.
hosts_.empty()) {
3257 bool search_global_done =
false;
3262 if (!search_global_done && subnet->getReservationsGlobal()) {
3263 auto host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3266 if (host != ctx.
hosts_.end() && host->second &&
3267 !host->second->getIPv4Reservation().isV4Zero()) {
3272 search_global_done =
true;
3275 if (subnet->getReservationsInSubnet()) {
3276 auto host = ctx.
hosts_.find(subnet->getID());
3281 if (host != ctx.
hosts_.end() && host->second) {
3282 auto reservation = host->second->getIPv4Reservation();
3283 if (!reservation.isV4Zero() &&
3284 (!subnet->getReservationsOutOfPool() ||
3294 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3322 bool try_clientid_lookup = (ctx.
clientid_ &&
3324 ctx.
query_->getClasses()));
3327 if (try_clientid_lookup) {
3335 for (
Subnet4Ptr subnet = original_subnet; subnet;
3336 subnet = subnet->getNextSubnet(original_subnet,
3337 ctx.
query_->getClasses())) {
3342 if (subnet->getMatchClientId()) {
3343 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
3344 if ((*l)->subnet_id_ == subnet->getID()) {
3346 client_lease = (*l);
3357 if (!client_lease && ctx.
hwaddr_) {
3362 for (
Subnet4Ptr subnet = original_subnet; subnet;
3363 subnet = subnet->getNextSubnet(original_subnet,
3364 ctx.
query_->getClasses())) {
3366 if (subnet->getMatchClientId()) {
3372 for (Lease4Collection::const_iterator client_lease_it = leases_hw_address.begin();
3373 client_lease_it != leases_hw_address.end(); ++client_lease_it) {
3374 Lease4Ptr existing_lease = *client_lease_it;
3375 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3376 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3378 client_lease = existing_lease;
3406 while (current_subnet) {
3409 ctx.
query_->getClasses())) {
3417 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_,
3418 ctx.
query_->getClasses());
3430 : early_global_reservations_lookup_(false),
3431 subnet_(), clientid_(), hwaddr_(),
3432 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3433 fwd_dns_update_(false), rev_dns_update_(false),
3434 hostname_(
""), callout_handle_(), fake_allocation_(false),
3435 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3436 query_(), host_identifiers_(), unknown_requested_addr_(false),
3444 const bool fwd_dns_update,
3445 const bool rev_dns_update,
3446 const std::string& hostname,
3447 const bool fake_allocation)
3448 : early_global_reservations_lookup_(false),
3449 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3450 requested_address_(requested_addr),
3451 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3452 hostname_(hostname), callout_handle_(),
3453 fake_allocation_(fake_allocation), old_lease_(), new_lease_(),
3454 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3465 if (subnet_ && subnet_->getReservationsInSubnet()) {
3466 auto host = hosts_.find(subnet_->getID());
3467 if (host != hosts_.cend()) {
3468 return (host->second);
3472 return (globalHost());
3477 if (subnet_ && subnet_->getReservationsGlobal()) {
3478 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3479 if (host != hosts_.cend()) {
3480 return (host->second);
3490 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3491 return (ddns_params_);
3497 return (ddns_params_);
3519 if (subnet && !subnet->clientSupported(ctx.
query_->getClasses())) {
3520 ctx.
subnet_ = subnet->getNextSubnet(subnet, ctx.
query_->getClasses());
3533 return (discoverLease4(ctx));
3542 .arg(ctx.
query_->getLabel())
3560 !subnet->getReservationsInSubnet()) {
3566 subnet->getReservationsGlobal()) {
3569 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3572 if (!subnet->getReservationsInSubnet()) {
3578 std::map<SubnetID, ConstHostPtr> host_map;
3580 subnet->getSharedNetwork(network);
3589 const bool use_single_query = network &&
3593 if (use_single_query) {
3597 id_pair.second.size());
3601 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
3602 if ((*host)->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3603 host_map[(*host)->getIPv4SubnetID()] = *host;
3614 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
3615 subnet->getReservationsInSubnet()) {
3618 if (use_single_query) {
3619 if (host_map.count(subnet->getID()) > 0) {
3620 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3628 id_pair.second.size());
3631 ctx.
hosts_[subnet->getID()] = host;
3641 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3651 &id_pair.second[0], id_pair.second.size());
3668 findClientLease(ctx, client_lease);
3678 if (hasAddressReservation(ctx)) {
3682 .arg(ctx.
query_->getLabel())
3683 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3689 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3696 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3700 .arg(ctx.
query_->getLabel())
3701 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3704 StatsMgr::instance().addValue(StatsMgr::generateName(
3707 "v4-reservation-conflicts"),
3708 static_cast<int64_t
>(1));
3709 StatsMgr::instance().addValue(
"v4-reservation-conflicts",
3710 static_cast<int64_t
>(1));
3714 new_lease = renewLease4(client_lease, ctx);
3727 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3728 !addressReserved(client_lease->addr_, ctx)) {
3732 .arg(ctx.
query_->getLabel());
3734 new_lease = renewLease4(client_lease, ctx);
3751 .arg(ctx.
query_->getLabel());
3764 .arg(ctx.
query_->getLabel());
3766 new_lease = allocateUnreservedLease4(ctx);
3786 findClientLease(ctx, client_lease);
3802 .arg(ctx.
query_->getLabel())
3808 }
else if (hasAddressReservation(ctx)) {
3817 .arg(ctx.
query_->getLabel())
3829 if (existing && !existing->expired() &&
3830 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
3835 .arg(ctx.
query_->getLabel())
3845 if (hasAddressReservation(ctx) &&
3853 if (!existing || existing->expired()) {
3857 .arg(ctx.
query_->getLabel())
3858 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3868 if ((!hasAddressReservation(ctx) ||
3874 .arg(ctx.
query_->getLabel())
3894 ((hasAddressReservation(ctx) &&
3896 inAllowedPool(ctx, client_lease->addr_))) {
3900 .arg(ctx.
query_->getLabel())
3903 return (renewLease4(client_lease, ctx));
3917 .arg(ctx.
query_->getLabel())
3933 .arg(ctx.
query_->getLabel());
3938 new_lease = allocateUnreservedLease4(ctx);
3944 if (new_lease && client_lease) {
3949 .arg(ctx.
query_->getLabel())
3950 .arg(client_lease->addr_.toText());
3954 StatsMgr::instance().addValue(
3955 StatsMgr::generateName(
"subnet", client_lease->subnet_id_,
3956 "assigned-addresses"),
3957 static_cast<int64_t
>(-1));
3970 if (ctx.
query_->inClass(
"BOOTP")) {
3975 uint32_t requested_lft = 0;
3978 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
3980 requested_lft = opt_lft->getValue();
3988 if (!classes.
empty()) {
3995 name != classes.
cend(); ++name) {
3997 if (cl && (!cl->getValid().unspecified())) {
3998 candidate_lft = cl->getValid();
4005 if (!candidate_lft) {
4006 candidate_lft = ctx.
subnet_->getValid();
4011 if (requested_lft > 0) {
4012 return (candidate_lft.
get(requested_lft));
4016 return (candidate_lft.
get());
4020AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4032 time_t now = time(NULL);
4035 if (ctx.subnet_->getMatchClientId()) {
4036 client_id = ctx.clientid_;
4040 valid_lft, now, ctx.subnet_->getID()));
4043 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4044 lease->fqdn_rev_ = ctx.rev_dns_update_;
4045 lease->hostname_ = ctx.hostname_;
4051 if (ctx.callout_handle_ &&
4052 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
4065 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4071 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4072 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4075 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4078 ctx.callout_handle_->setArgument(
"lease4", lease);
4081 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.callout_handle_);
4083 callout_status = ctx.callout_handle_->getStatus();
4088 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4095 ctx.callout_handle_->getArgument(
"lease4", lease);
4098 if (!ctx.fake_allocation_) {
4104 StatsMgr::instance().addValue(
4105 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4106 "assigned-addresses"),
4107 static_cast<int64_t
>(1));
4108 StatsMgr::instance().addValue(
4109 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4110 "cumulative-assigned-addresses"),
4111 static_cast<int64_t
>(1));
4112 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4113 static_cast<int64_t
>(1));
4133AllocEngine::renewLease4(
const Lease4Ptr& lease,
4136 isc_throw(BadValue,
"null lease specified for renewLease4");
4143 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4148 lease->reuseable_valid_lft_ = 0;
4149 if (!updateLease4Information(lease, ctx)) {
4150 setLeaseReusable(lease, ctx);
4166 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_renew_)) {
4190 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4198 HooksManager::callCallouts(
Hooks.hook_index_lease4_renew_,
4204 if (ctx.
callout_handle_->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
4213 if (!ctx.
fake_allocation_ && !skip && (lease->reuseable_valid_lft_ == 0)) {
4219 StatsMgr::instance().addValue(
4220 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4221 "assigned-addresses"),
4222 static_cast<int64_t
>(1));
4223 StatsMgr::instance().addValue(
4224 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4225 "cumulative-assigned-addresses"),
4226 static_cast<int64_t
>(1));
4227 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4228 static_cast<int64_t
>(1));
4234 *lease = *old_values;
4241AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4245 isc_throw(BadValue,
"null lease specified for reuseExpiredLease");
4249 isc_throw(BadValue,
"null subnet specified for the reuseExpiredLease");
4260 expired->reuseable_valid_lft_ = 0;
4261 static_cast<void>(updateLease4Information(expired, ctx));
4265 .arg(ctx.
query_->getLabel())
4266 .arg(expired->toText());
4270 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
4299 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.
callout_handle_);
4306 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4324 StatsMgr::instance().addValue(
4325 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4326 "assigned-addresses"),
4327 static_cast<int64_t
>(1));
4328 StatsMgr::instance().addValue(
4329 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4330 "cumulative-assigned-addresses"),
4331 static_cast<int64_t
>(1));
4332 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4333 static_cast<int64_t
>(1));
4345AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4347 ctx.conflicting_lease_.reset();
4351 if (exist_lease->expired()) {
4356 ctx.old_lease_->hostname_.clear();
4357 ctx.old_lease_->fqdn_fwd_ =
false;
4358 ctx.old_lease_->fqdn_rev_ =
false;
4359 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4365 ctx.conflicting_lease_ = exist_lease;
4369 return (createLease4(ctx, candidate, callout_status));
4375AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4390 ctx.subnet_->getSharedNetwork(network);
4397 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4403 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
4407 uint64_t total_attempts = 0;
4411 uint64_t subnets_with_unavail_leases = 0;
4414 uint64_t subnets_with_unavail_pools = 0;
4418 if (subnet->getMatchClientId()) {
4419 client_id = ctx.clientid_;
4422 uint64_t possible_attempts =
4424 ctx.query_->getClasses());
4431 uint64_t max_attempts = ((attempts_ == 0 || possible_attempts < attempts_) ? possible_attempts : attempts_);
4433 if (max_attempts > 0) {
4436 ++subnets_with_unavail_leases;
4440 ++subnets_with_unavail_pools;
4445 for (uint64_t i = 0; i < max_attempts; ++i) {
4449 IOAddress candidate = allocator->pickAddress(subnet,
4450 ctx.query_->getClasses(),
4452 ctx.requested_address_);
4454 if (check_reservation_first && addressReserved(candidate, ctx)) {
4462 if (MultiThreadingMgr::instance().getMode() &&
4463 !resource_handler.
tryLock4(candidate)) {
4472 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4474 new_lease = createLease4(ctx, candidate, callout_status);
4478 if (exist_lease->expired() &&
4479 (check_reservation_first || !addressReserved(candidate, ctx))) {
4481 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4490 if (ctx.callout_handle_ && (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
4499 subnet = subnet->getNextSubnet(original_subnet, ctx.query_->getClasses());
4502 ctx.subnet_ = subnet;
4511 .arg(ctx.query_->getLabel())
4512 .arg(network->getName())
4513 .arg(subnets_with_unavail_leases)
4514 .arg(subnets_with_unavail_pools);
4515 StatsMgr::instance().addValue(
"v4-allocation-fail-shared-network",
4516 static_cast<int64_t
>(1));
4517 StatsMgr::instance().addValue(
4518 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4519 "v4-allocation-fail-shared-network"),
4520 static_cast<int64_t
>(1));
4524 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4525 if (shared_network.empty()) {
4526 shared_network =
"(none)";
4529 .arg(ctx.query_->getLabel())
4530 .arg(ctx.subnet_->toText())
4531 .arg(ctx.subnet_->getID())
4532 .arg(shared_network);
4533 StatsMgr::instance().addValue(
"v4-allocation-fail-subnet",
4534 static_cast<int64_t
>(1));
4535 StatsMgr::instance().addValue(
4536 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4537 "v4-allocation-fail-subnet"),
4538 static_cast<int64_t
>(1));
4540 if (total_attempts == 0) {
4546 .arg(ctx.query_->getLabel());
4547 StatsMgr::instance().addValue(
"v4-allocation-fail-no-pools",
4548 static_cast<int64_t
>(1));
4549 StatsMgr::instance().addValue(
4550 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4551 "v4-allocation-fail-no-pools"),
4552 static_cast<int64_t
>(1));
4559 .arg(ctx.query_->getLabel())
4560 .arg(total_attempts);
4561 StatsMgr::instance().addValue(
"v4-allocation-fail",
4562 static_cast<int64_t
>(1));
4563 StatsMgr::instance().addValue(
4564 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4565 "v4-allocation-fail"),
4566 static_cast<int64_t
>(1));
4570 if (!classes.
empty()) {
4572 .arg(ctx.query_->getLabel())
4574 StatsMgr::instance().addValue(
"v4-allocation-fail-classes",
4575 static_cast<int64_t
>(1));
4576 StatsMgr::instance().addValue(
4577 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4578 "v4-allocation-fail-classes"),
4579 static_cast<int64_t
>(1));
4586AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4588 bool changed =
false;
4589 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4591 lease->subnet_id_ = ctx.
subnet_->getID();
4593 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4595 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4600 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4604 }
else if (lease->client_id_) {
4608 lease->cltt_ = time(NULL);
4614 if (lease->valid_lft_ < lease->current_valid_lft_) {
4638 bool changed =
false;
4641 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4657 extended_info->set(
"relay-agent-info", relay_agent);
4661 if (lease->getContext()) {
4669 if (!old_extended_info || (*old_extended_info != *extended_info)) {
4671 user_context->set(
"ISC", extended_info);
4675 lease->setContext(user_context);
4683 bool changed =
false;
4686 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4691 if (ctx.
query_->relay_info_.empty()) {
4706 for (
auto relay : ctx.
query_->relay_info_) {
4715 if (!relay.options_.empty()) {
4720 const uint8_t* cp =
static_cast<const uint8_t*
>(buf.
getData());
4721 std::vector<uint8_t>bytes;
4722 std::stringstream ss;
4730 relay_list->add(relay_elem);
4735 extended_info->set(
"relays", relay_list);
4739 if (lease->getContext()) {
4747 if (!old_extended_info || (*old_extended_info != *extended_info)) {
4749 user_context->set(
"ISC", extended_info);
4753 lease->setContext(user_context);
4759AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
4760 const ClientContext4& ctx)
const {
4762 lease->reuseable_valid_lft_ = 0;
4778 if (lease->cltt_ < lease->current_cltt_) {
4782 uint32_t age = lease->cltt_ - lease->current_cltt_;
4784 if (age >= lease->current_valid_lft_) {
4789 uint32_t max_age = 0;
4790 if (!subnet->getCacheMaxAge().unspecified()) {
4791 max_age = subnet->getCacheMaxAge().get();
4792 if ((max_age == 0) || (age > max_age)) {
4798 if (!subnet->getCacheThreshold().unspecified()) {
4799 double threshold = subnet->getCacheThreshold().get();
4800 if ((threshold <= 0.) || (threshold > 1.)) {
4803 max_age = lease->valid_lft_ * threshold;
4804 if (age > max_age) {
4815 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
4819AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
4820 uint32_t current_preferred_lft,
4821 const ClientContext6& ctx)
const {
4823 lease->reuseable_valid_lft_ = 0;
4824 lease->reuseable_preferred_lft_ = 0;
4834 if (lease->cltt_ < lease->current_cltt_) {
4838 uint32_t age = lease->cltt_ - lease->current_cltt_;
4840 if (age >= lease->current_valid_lft_) {
4845 uint32_t max_age = 0;
4846 if (!subnet->getCacheMaxAge().unspecified()) {
4847 max_age = subnet->getCacheMaxAge().get();
4848 if ((max_age == 0) || (age > max_age)) {
4854 if (!subnet->getCacheThreshold().unspecified()) {
4855 double threshold = subnet->getCacheThreshold().get();
4856 if ((threshold <= 0.) || (threshold > 1.)) {
4859 max_age = lease->valid_lft_ * threshold;
4860 if (age > max_age) {
4872 (current_preferred_lft == 0)) {
4874 lease->reuseable_preferred_lft_ = current_preferred_lft;
4875 }
else if (current_preferred_lft > age) {
4876 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
4884 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when a function is not implemented.
The IOAddress class represents an IP addresses (version agnostic)
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
std::string toText() const
Convert the address to a string.
bool isV6() const
Convenience function to check for an IPv6 address.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
static IOAddress increase(const IOAddress &addr)
Returns an address increased by one.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Notes: IntElement type is changed to int64_t.
Base class for all address/prefix allocation algorithms.
Address/prefix allocator that gets an address based on a hash.
HashedAllocator(Lease::Type type)
Default constructor (does nothing)
Address/prefix allocator that iterates over all addresses.
static isc::asiolink::IOAddress increasePrefix(const isc::asiolink::IOAddress &prefix, const uint8_t prefix_len)
Returns the next prefix.
static isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress &address, bool prefix, const uint8_t prefix_len)
Returns the next address or prefix.
IterativeAllocator(Lease::Type type)
Default constructor.
Random allocator that picks address randomly.
RandomAllocator(Lease::Type type)
Default constructor (does nothing)
bool updateLease6ExtendedInfo(const Lease6Ptr &lease, const ClientContext6 &ctx) const
Stores additional client query parameters on a V6 lease.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
bool updateLease4ExtendedInfo(const Lease4Ptr &lease, const ClientContext4 &ctx) const
Stores additional client query parameters on a V4 lease.
AllocType
Specifies allocation type.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
isc::util::ReadWriteMutex rw_mutex_
The read-write mutex.
static void getLifetimes6(ClientContext6 &ctx, uint32_t &preferred, uint32_t &valid)
Determines the preferred and valid v6 lease lifetimes.
static void findReservation(ClientContext6 &ctx)
boost::shared_ptr< Allocator > AllocatorPtr
defines a pointer to allocator
void deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
static uint32_t getValidLft(const ClientContext4 &ctx)
Returns the valid lifetime based on the v4 context.
AllocEngine(AllocType engine_type, uint64_t attempts, bool ipv6=true)
Constructor.
void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv6 leases.
void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv4 leases.
Lease4Ptr allocateLease4(ClientContext4 &ctx)
Returns IPv4 lease.
void deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
Lease6Collection allocateLeases6(ClientContext6 &ctx)
Allocates IPv6 leases for a given IA container.
Lease6Collection renewLeases6(ClientContext6 &ctx)
Renews existing DHCPv6 leases for a given IA.
AllocatorPtr getAllocator(Lease::Type type)
Returns allocator for a given pool type.
An exception that is thrown when allocation module fails (e.g.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Container for storing client class names.
ClientClassContainer::const_iterator const_iterator
Type of iterators.
bool empty() const
Check if classes is empty.
std::string toText(const std::string &separator=", ") const
Returns all class names as text.
const_iterator cbegin() const
Iterators to the first element.
const_iterator cend() const
Iterators to the past the end element.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
bool getDisableSingleQuery() const
Returns the disable single query flag.
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv6 subnet.
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv4 subnet.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const
Return all hosts in a DHCPv4 subnet.
IPv6 reservation for a host.
Type
Type of the reservation.
static LeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv6 leases.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv6 leases.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv4 leases.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv4 leases.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
Resource race avoidance RAII handler for DHCPv4.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
Resource race avoidance RAII handler.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
RAII object enabling copying options retrieved from the packet.
static bool subnetsIncludeMatchClientId(const Subnet4Ptr &first_subnet, const ClientClasses &client_classes)
Checks if the shared network includes a subnet with the match client ID flag set to true.
CalloutNextStep
Specifies allowed next steps.
Wrapper class around callout handle which automatically resets handle's state.
Statistics Manager class.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
size_t getLength() const
Return the length of data written in the buffer.
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
Utility class to measure code execution times.
long getTotalMilliseconds() const
Retrieves the total measured duration in milliseconds.
void stop()
Stops the stopwatch.
std::string logFormatTotalDuration() const
Returns the total measured duration in the format directly usable in the log messages.
T get(T hint) const
Returns value with a hint.
Write mutex RAII handler.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_LEASES_HR
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_INVALID
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_EXTEND_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_IN_USE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_HR_LEASE_EXISTS
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_HR
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_V6_HR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_HINT_RESERVED
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_OUT_OF_POOL
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ADDRESS_RESERVED
isc::log::Logger alloc_engine_logger("alloc-engine")
Logger for the AllocEngine.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_REQUESTED_LEASE
const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED
const int ALLOC_ENGINE_DBG_TRACE
Logging levels for the AllocEngine.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_COMPLETE
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ERROR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_HR
boost::shared_ptr< DUID > DuidPtr
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ALLOC_UNRESERVED
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_DECLINED_RECOVERED
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_TIMEOUT
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
boost::shared_ptr< DdnsParams > DdnsParamsPtr
Defines a pointer for DdnsParams instances.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_START
boost::shared_ptr< Option6IAPrefix > Option6IAPrefixPtr
Pointer to the Option6IAPrefix object.
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_HR
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_TIMEOUT
const isc::log::MessageID ALLOC_ENGINE_V6_HR_ADDR_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES
const isc::log::MessageID ALLOC_ENGINE_V6_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_EXPIRED_HINT_RESERVED
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
const int ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA
Records detailed results of various operations.
const int DHCPSRV_DBG_HOOKS
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_COMPLETE
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_PREFIX_LEASE
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
const isc::log::MessageID ALLOC_ENGINE_V4_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_PICK_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_NEW_LEASE
boost::shared_ptr< Option6IAAddr > Option6IAAddrPtr
A pointer to the isc::dhcp::Option6IAAddr object.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_UNRESERVED
std::pair< IPv6Resrv::Type, IPv6Resrv > IPv6ResrvTuple
const isc::log::MessageID ALLOC_ENGINE_V6_DECLINED_RECOVERED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_START
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ALLOC_REQUESTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_NO_HR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SUBNET
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_ADDRESS_CONFLICT
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RENEW_SKIP
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_REMOVE_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET
const int ALLOC_ENGINE_DBG_TRACE_DETAIL
Record detailed traces.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_HR_PREFIX_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_CLASSES
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Defines the logger used by the top-level component of kea-lfc.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
static data::ElementPtr toElement(data::ConstElementPtr map)
Copy an Element map.
Context information for the DHCPv4 lease allocation.
ClientIdPtr clientid_
Client identifier from the DHCP message.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
ConstHostPtr currentHost() const
Returns host for currently selected subnet.
ClientContext4()
Default constructor.
Pkt4Ptr query_
A pointer to the client's message.
Subnet4Ptr subnet_
Subnet selected for the client by the server.
Lease4Ptr new_lease_
A pointer to a newly allocated lease.
std::string hostname_
Hostname.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
bool rev_dns_update_
Perform reverse DNS update.
bool fake_allocation_
Indicates if this is a real or fake allocation.
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
bool unknown_requested_addr_
True when the address DHCPREQUEST'ed by client is not within a dynamic pool the server knows about.
Lease4Ptr old_lease_
A pointer to an old lease that the client had before update.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
bool fwd_dns_update_
Perform forward DNS update.
asiolink::IOAddress requested_address_
An address that the client desires.
Lease4Ptr conflicting_lease_
A pointer to the object representing a lease in conflict.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
HWAddrPtr hwaddr_
HW address from the DHCP message.
IAContext()
Default constructor.
Lease::Type type_
Lease type (IA or PD)
bool isNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was new.
void addHint(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128, const uint32_t preferred=0, const uint32_t valid=0)
Convenience method adding new hint.
void addNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding new prefix or address.
HintContainer hints_
Client's hints.
uint32_t iaid_
The IAID field from IA_NA or IA_PD that is being processed.
Context information for the DHCPv6 leases allocation.
IAContext & currentIA()
Returns IA specific context for the currently processed IA.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
ConstHostPtr currentHost() const
Returns host from the most preferred subnet.
ClientContext6()
Default constructor.
DuidPtr duid_
Client identifier.
void addAllocatedResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding allocated prefix or address.
Lease6Collection new_leases_
A collection of newly allocated leases.
bool isAllocated(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was allocated.
Subnet6Ptr subnet_
Subnet selected for the client by the server.
Subnet6Ptr host_subnet_
Subnet from which host reservations should be retrieved.
bool hasGlobalReservation(const IPv6Resrv &resv) const
Determines if a global reservation exists.
ResourceContainer allocated_resources_
Holds addresses and prefixes allocated for all IAs.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
Pkt6Ptr query_
A pointer to the client's message.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
Structure that holds a lease for IPv4 address.
Structure that holds a lease for IPv6 address and/or prefix.
a common structure for IPv4 and IPv6 leases
static const uint32_t INFINITY_LFT
Infinity (means static, i.e. never expire)
static const uint32_t STATE_DEFAULT
A lease in the default state.
static const uint32_t STATE_DECLINED
Declined lease.
static const uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Type
Type of lease or pool.
@ TYPE_TA
the lease contains temporary IPv6 address
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address
static std::string typeToText(Type type)
returns text representation of a lease type