31 #include <boost/foreach.hpp> 51 struct AllocEngineHooks {
52 int hook_index_lease4_select_;
53 int hook_index_lease4_renew_;
54 int hook_index_lease4_expire_;
55 int hook_index_lease4_recover_;
56 int hook_index_lease6_select_;
57 int hook_index_lease6_renew_;
58 int hook_index_lease6_rebind_;
59 int hook_index_lease6_expire_;
60 int hook_index_lease6_recover_;
64 hook_index_lease4_select_ = HooksManager::registerHook(
"lease4_select");
65 hook_index_lease4_renew_ = HooksManager::registerHook(
"lease4_renew");
66 hook_index_lease4_expire_ = HooksManager::registerHook(
"lease4_expire");
67 hook_index_lease4_recover_= HooksManager::registerHook(
"lease4_recover");
68 hook_index_lease6_select_ = HooksManager::registerHook(
"lease6_select");
69 hook_index_lease6_renew_ = HooksManager::registerHook(
"lease6_renew");
70 hook_index_lease6_rebind_ = HooksManager::registerHook(
"lease6_rebind");
71 hook_index_lease6_expire_ = HooksManager::registerHook(
"lease6_expire");
72 hook_index_lease6_recover_= HooksManager::registerHook(
"lease6_recover");
80 AllocEngineHooks
Hooks;
87 AllocEngine::IterativeAllocator::IterativeAllocator(
Lease::Type lease_type)
93 const uint8_t prefix_len) {
96 "increase prefix " << prefix <<
")");
100 const std::vector<uint8_t>& vec = prefix.
toBytes();
102 if (prefix_len < 1 || prefix_len > 128) {
110 uint8_t n_bytes = (prefix_len - 1)/8;
111 uint8_t n_bits = 8 - (prefix_len - n_bytes*8);
112 uint8_t mask = 1 << n_bits;
121 uint8_t packed[V6ADDRESS_LEN];
124 std::memcpy(packed, &vec[0], V6ADDRESS_LEN);
127 if (packed[n_bytes] + uint16_t(mask) < 256u) {
128 packed[n_bytes] += mask;
133 packed[n_bytes] += mask;
136 for (
int i = n_bytes - 1; i >= 0; --i) {
139 if (packed[i] != 0) {
150 const uint8_t prefix_len) {
154 return (increasePrefix(address, prefix_len));
166 uint8_t prefix_len = 0;
171 IOAddress last = subnet->getLastAllocated(pool_type_);
173 bool retrying =
false;
182 PoolCollection::const_iterator it;
183 PoolCollection::const_iterator first = pools.end();
185 for (it = pools.begin(); it != pools.end(); ++it) {
186 if (!(*it)->clientSupported(client_classes)) {
189 if (first == pools.end()) {
192 if ((*it)->inRange(last)) {
198 if (first == pools.end()) {
207 if (it == pools.end()) {
214 for (; it != pools.end(); ++it) {
215 if ((*it)->clientSupported(client_classes)) {
219 if (it == pools.end()) {
225 last = (*it)->getLastAllocated();
226 valid = (*it)->isLastAllocatedValid();
227 if (!valid && (last == (*it)->getFirstAddress())) {
229 (*it)->setLastAllocated(last);
230 subnet->setLastAllocated(pool_type_, last);
234 if (valid && !(*it)->inRange(last)) {
236 (*it)->resetLastAllocated();
237 (*it)->setLastAllocated((*it)->getFirstAddress());
243 Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(*it);
252 prefix_len = pool6->getLength();
255 IOAddress next = increaseAddress(last, prefix, prefix_len);
256 if ((*it)->inRange(next)) {
259 (*it)->setLastAllocated(next);
260 subnet->setLastAllocated(pool_type_, next);
265 (*it)->resetLastAllocated();
273 for (it = first; it != pools.end(); ++it) {
274 if ((*it)->clientSupported(client_classes)) {
275 (*it)->setLastAllocated((*it)->getFirstAddress());
276 (*it)->resetLastAllocated();
281 last = (*first)->getLastAllocated();
282 (*first)->setLastAllocated(last);
283 subnet->setLastAllocated(pool_type_, last);
318 : attempts_(attempts), incomplete_v4_reclamations_(0),
319 incomplete_v6_reclamations_(0) {
325 switch (engine_type) {
342 switch (engine_type) {
361 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
362 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
366 std::map<Lease::Type, AllocatorPtr>::const_iterator alloc = allocators_.find(type);
368 if (alloc == allocators_.end()) {
372 return (alloc->second);
394 const IOAddress& address,
bool check_subnet) {
398 while (current_subnet) {
400 if (current_subnet->clientSupported(ctx.
query_->getClasses())) {
402 if (current_subnet->inPool(lease_type, address)) {
406 if (current_subnet->inPool(lease_type, address,
407 ctx.
query_->getClasses())) {
413 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
430 : query_(), fake_allocation_(false), subnet_(), host_subnet_(), duid_(),
431 hwaddr_(), host_identifiers_(), hosts_(), fwd_dns_update_(false),
432 rev_dns_update_(false), hostname_(), callout_handle_(), ias_() {
439 const std::string& hostname,
440 const bool fake_allocation,
443 : query_(query), fake_allocation_(fake_allocation), subnet_(subnet),
444 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
445 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
446 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
456 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
457 changed_leases_(), ia_rsp_() {
463 const uint8_t prefix_len) {
464 hints_.push_back(std::make_pair(prefix, prefix_len));
470 const uint8_t prefix_len) {
478 return (static_cast<bool>
487 SUBNET_ID_GLOBAL : subnet->getID());
489 auto host =
hosts_.find(
id);
490 if (host !=
hosts_.cend()) {
491 return (host->second);
502 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
503 if (host !=
hosts_.cend()) {
504 return (host->second);
514 return (ghost && ghost->hasReservation(resv));
527 std::map<SubnetID, ConstHostPtr> host_map;
529 subnet->getSharedNetwork(network);
534 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
547 const bool use_single_query = network &&
550 if (use_single_query) {
554 id_pair.second.size());
558 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
559 if ((*host)->getIPv6SubnetID()) {
560 host_map[(*host)->getIPv6SubnetID()] = *host;
571 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
576 if (use_single_query) {
577 if (host_map.count(subnet->getID()) > 0) {
578 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
586 id_pair.second.size());
589 ctx.
hosts_[subnet->getID()] = host;
600 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
610 &id_pair.second[0], id_pair.second.size());
645 for (
auto l : all_leases) {
646 if ((l)->subnet_id_ == subnet->getID()) {
651 subnet = subnet->getNextSubnet(ctx.
subnet_);
671 if (leases.empty() && !ctx.
hosts_.empty()) {
674 ALLOC_ENGINE_V6_ALLOC_NO_LEASES_HR)
675 .arg(ctx.
query_->getLabel());
680 allocateReservedLeases6(ctx, leases);
695 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
698 ALLOC_ENGINE_V6_ALLOC_LEASES_NO_HR)
699 .arg(ctx.
query_->getLabel());
703 removeNonmatchingReservedLeases6(ctx, leases);
705 leases = updateLeaseData(ctx, leases);
714 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
717 ALLOC_ENGINE_V6_ALLOC_LEASES_HR)
718 .arg(ctx.
query_->getLabel());
722 allocateReservedLeases6(ctx, leases);
734 removeNonmatchingReservedLeases6(ctx, leases);
743 removeNonreservedLeases6(ctx, leases);
758 if (leases.empty()) {
771 ALLOC_ENGINE_V6_ALLOC_UNRESERVED)
772 .arg(ctx.
query_->getLabel());
774 leases = allocateUnreservedLeases6(ctx);
777 if (!leases.empty()) {
793 .arg(ctx.
query_->getLabel())
813 if (!ctx.currentIA().hints_.empty()) {
815 hint = ctx.currentIA().hints_[0].first;
827 if (!subnet->clientSupported(ctx.query_->getClasses())) {
828 subnet = subnet->getNextSubnet(original_subnet);
832 ctx.subnet_ = subnet;
836 pool = boost::dynamic_pointer_cast<Pool6>
837 (subnet->getPool(ctx.currentIA().type_, ctx.query_->getClasses(),
841 if (pool && !pool->clientSupported(ctx.query_->getClasses())) {
870 lease = createLease6(ctx, hint, pool->getLength(), callout_status);
880 collection.push_back(lease);
885 ALLOC_ENGINE_V6_HINT_RESERVED)
886 .arg(ctx.query_->getLabel())
893 if (lease->expired()) {
906 ctx.currentIA().old_leases_.push_back(old_lease);
909 lease = reuseExpiredLease(lease, ctx, pool->getLength(),
913 leases.push_back(lease);
918 ALLOC_ENGINE_V6_EXPIRED_HINT_RESERVED)
919 .arg(ctx.query_->getLabel())
926 subnet = subnet->getNextSubnet(original_subnet);
929 uint64_t total_attempts = 0;
941 original_subnet->getSharedNetwork(network);
948 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
951 ctx.subnet_ = subnet = original_subnet;
955 if (!subnet->clientSupported(ctx.query_->getClasses())) {
956 subnet = subnet->getNextSubnet(original_subnet);
966 uint64_t possible_attempts =
967 subnet->getPoolCapacity(ctx.currentIA().type_,
968 ctx.query_->getClasses());
970 if (possible_attempts == 0) {
971 subnet = subnet->getNextSubnet(original_subnet);
974 uint64_t max_attempts = (attempts_ > 0 ? attempts_ : possible_attempts);
980 if (ctx.callout_handle_) {
981 ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
984 for (uint64_t i = 0; i < max_attempts; ++i) {
988 IOAddress candidate = allocator->pickAddress(subnet,
989 ctx.query_->getClasses(),
1005 uint8_t prefix_len = 128;
1007 pool = boost::dynamic_pointer_cast<Pool6>(
1008 subnet->getPool(ctx.currentIA().type_,
1009 ctx.query_->getClasses(),
1012 prefix_len = pool->getLength();
1023 ctx.subnet_ = subnet;
1024 Lease6Ptr lease = createLease6(ctx, candidate, prefix_len, callout_status);
1028 ctx.currentIA().old_leases_.clear();
1030 leases.push_back(lease);
1033 }
else if (ctx.callout_handle_ &&
1034 (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
1043 if (existing->expired()) {
1047 ctx.currentIA().old_leases_.push_back(old_lease);
1049 ctx.subnet_ = subnet;
1050 existing = reuseExpiredLease(existing, ctx, prefix_len,
1053 leases.push_back(existing);
1059 subnet = subnet->getNextSubnet(original_subnet);
1064 .arg(ctx.query_->getLabel())
1065 .arg(total_attempts);
1076 if (ctx.hosts_.empty()) {
1078 ALLOC_ENGINE_V6_ALLOC_NO_V6_HR)
1079 .arg(ctx.query_->getLabel());
1083 if (allocateGlobalReservedLeases6(ctx, existing_leases)) {
1095 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1096 if ((lease->valid_lft_ != 0)) {
1097 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1098 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1102 ALLOC_ENGINE_V6_ALLOC_HR_LEASE_EXISTS)
1103 .arg(ctx.query_->getLabel())
1104 .arg(lease->typeToText(lease->type_))
1105 .arg(lease->addr_.toText());
1111 if (!ctx.host_subnet_) {
1113 ctx.subnet_->getSharedNetwork(network);
1118 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1126 if (host && !host->getHostname().empty()) {
1133 qualifyName(host->getHostname(), static_cast<bool>(fqdn));
1140 if (!ctx.fake_allocation_ && conditionalExtendLifetime(*lease)) {
1155 SubnetID subnet_id = subnet->getID();
1158 if (!subnet->clientSupported(ctx.query_->getClasses()) ||
1159 ctx.hosts_.count(subnet_id) == 0) {
1160 subnet = subnet->getNextSubnet(ctx.subnet_);
1170 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1171 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1175 if (ctx.isAllocated(addr, prefix_len)) {
1187 ctx.subnet_ = subnet;
1189 if (!ctx.host_subnet_) {
1190 ctx.host_subnet_ = subnet;
1191 if (!host->getHostname().empty()) {
1205 qualifyName(host->getHostname(), static_cast<bool>(fqdn));
1211 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1214 existing_leases.push_back(lease);
1220 .arg(ctx.query_->getLabel());
1224 .arg(static_cast<int>(prefix_len))
1225 .arg(ctx.query_->getLabel());
1242 subnet = subnet->getNextSubnet(ctx.subnet_);
1258 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1259 if ((lease->valid_lft_ != 0) &&
1264 ALLOC_ENGINE_V6_ALLOC_HR_LEASE_EXISTS)
1265 .arg(ctx.query_->getLabel())
1266 .arg(lease->typeToText(lease->type_))
1267 .arg(lease->addr_.toText());
1273 if (!ghost->getHostname().empty()) {
1280 qualifyName(ghost->getHostname(), static_cast<bool>(fqdn));
1285 if (!ctx.fake_allocation_ && conditionalExtendLifetime(*lease)) {
1300 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1303 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1304 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1308 if (ctx.isAllocated(addr, prefix_len)) {
1316 if (!ghost->getHostname().empty()) {
1330 qualifyName(ghost->getHostname(), static_cast<bool>(fqdn));
1335 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1338 existing_leases.push_back(lease);
1343 .arg(ctx.query_->getLabel());
1347 .arg(static_cast<int>(prefix_len))
1348 .arg(ctx.query_->getLabel());
1368 AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1371 if (existing_leases.empty() || !ctx.subnet_) {
1377 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1390 if ((ctx.hasGlobalReservation(resv)) ||
1391 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1392 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1407 if (!host && inAllowedPool(ctx, candidate->type_,
1408 candidate->addr_,
false)) {
1417 .arg(candidate->addr_.toText()).arg(ctx.duid_->toText())
1418 .arg(host->getIdentifierAsText());
1421 .arg(candidate->addr_.toText())
1422 .arg(static_cast<int>(candidate->prefixlen_))
1423 .arg(ctx.duid_->toText())
1424 .arg(host->getIdentifierAsText());
1436 StatsMgr::instance().addValue(
1437 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1439 "assigned-nas" :
"assigned-pds"),
1440 static_cast<int64_t>(-1));
1448 ctx.currentIA().old_leases_.push_back(candidate);
1451 removeLeases(existing_leases, candidate->addr_);
1456 AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1467 if (inAllowedPool(ctx, candidate->type_,
1468 candidate->addr_,
false)) {
1479 StatsMgr::instance().addValue(
1480 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1482 "assigned-nas" :
"assigned-pds"),
1483 static_cast<int64_t>(-1));
1486 ctx.currentIA().old_leases_.push_back(candidate);
1489 removeLeases(existing_leases, candidate->addr_);
1494 AllocEngine::removeLeases(
Lease6Collection& container,
const asiolink::IOAddress& addr) {
1496 bool removed =
false;
1497 for (Lease6Collection::iterator lease = container.begin();
1498 lease != container.end(); ++lease) {
1499 if ((*lease)->addr_ == addr) {
1506 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1517 if (existing_leases.empty()) {
1522 int total = existing_leases.size();
1526 for (Lease6Collection::iterator lease = existing_leases.begin();
1527 lease != existing_leases.end(); ++lease) {
1531 if (ctx.hasGlobalReservation(resv) ||
1532 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1533 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1545 StatsMgr::instance().addValue(
1546 StatsMgr::generateName(
"subnet", (*lease)->subnet_id_,
1548 "assigned-nas" :
"assigned-pds"),
1549 static_cast<int64_t>(-1));
1554 ctx.currentIA().old_leases_.push_back(*lease);
1570 existing_leases.erase(std::remove(existing_leases.begin(),
1571 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1579 if (!expired->expired()) {
1580 isc_throw(BadValue,
"Attempt to recycle lease that is still valid");
1587 if (!ctx.fake_allocation_) {
1591 reclaimExpiredLease(expired, ctx.callout_handle_);
1595 expired->iaid_ = ctx.currentIA().iaid_;
1596 expired->duid_ = ctx.duid_;
1597 expired->preferred_lft_ = ctx.subnet_->getPreferred();
1598 expired->valid_lft_ = ctx.subnet_->getValid();
1599 expired->t1_ = ctx.subnet_->getT1();
1600 expired->t2_ = ctx.subnet_->getT2();
1601 expired->cltt_ = time(NULL);
1602 expired->subnet_id_ = ctx.subnet_->getID();
1603 expired->hostname_ = ctx.hostname_;
1604 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1605 expired->fqdn_rev_ = ctx.rev_dns_update_;
1606 expired->prefixlen_ = prefix_len;
1610 ALLOC_ENGINE_V6_REUSE_EXPIRED_LEASE_DATA)
1611 .arg(ctx.query_->getLabel())
1612 .arg(expired->toText());
1615 if (ctx.callout_handle_ &&
1616 HooksManager::getHooksManager().calloutsPresent(hook_index_lease6_select_)) {
1630 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1633 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1636 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1639 ctx.callout_handle_->setArgument(
"lease6", expired);
1642 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1644 callout_status = ctx.callout_handle_->getStatus();
1649 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1661 ctx.callout_handle_->getArgument(
"lease6", expired);
1664 if (!ctx.fake_allocation_) {
1670 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1671 StatsMgr::instance().addValue(
1672 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1674 "assigned-nas" :
"assigned-pds"),
1675 static_cast<int64_t>(1));
1697 ctx.currentIA().iaid_, ctx.subnet_->getPreferred(),
1698 ctx.subnet_->getValid(), ctx.subnet_->getT1(),
1699 ctx.subnet_->getT2(), ctx.subnet_->getID(),
1700 ctx.hwaddr_, prefix_len));
1702 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1703 lease->fqdn_rev_ = ctx.rev_dns_update_;
1704 lease->hostname_ = ctx.hostname_;
1707 if (ctx.callout_handle_ &&
1708 HooksManager::getHooksManager().calloutsPresent(hook_index_lease6_select_)) {
1722 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1725 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1728 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1729 ctx.callout_handle_->setArgument(
"lease6", lease);
1732 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1734 callout_status = ctx.callout_handle_->getStatus();
1739 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1746 ctx.callout_handle_->getArgument(
"lease6", lease);
1749 if (!ctx.fake_allocation_) {
1756 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
1757 StatsMgr::instance().addValue(
1758 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1760 "assigned-nas" :
"assigned-pds"),
1761 static_cast<int64_t>(1));
1778 ctx.currentIA().type_, addr);
1807 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
1809 subnet = subnet->getNextSubnet(ctx.
subnet_);
1813 if (!leases.empty()) {
1815 ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED)
1816 .arg(ctx.
query_->getLabel());
1820 removeNonmatchingReservedLeases6(ctx, leases);
1823 if (!ctx.
hosts_.empty()) {
1826 ALLOC_ENGINE_V6_RENEW_HR)
1827 .arg(ctx.
query_->getLabel());
1830 allocateReservedLeases6(ctx, leases);
1836 removeNonreservedLeases6(ctx, leases);
1843 if (leases.empty()) {
1846 ALLOC_ENGINE_V6_EXTEND_ALLOC_UNRESERVED)
1847 .arg(ctx.
query_->getLabel());
1849 leases = allocateUnreservedLeases6(ctx);
1853 for (Lease6Collection::iterator l = leases.begin(); l != leases.end(); ++l) {
1855 ALLOC_ENGINE_V6_EXTEND_LEASE)
1856 .arg(ctx.
query_->getLabel())
1857 .arg((*l)->typeToText((*l)->type_))
1859 extendLease6(ctx, *l);
1862 if (!leases.empty()) {
1866 BOOST_FOREACH(
Lease6Ptr lease, leases) {
1878 .arg(ctx.
query_->getLabel())
1888 if (!lease || !ctx.subnet_) {
1894 if (ctx.subnet_->getID() != lease->subnet_id_) {
1896 ctx.subnet_->getSharedNetwork(network);
1902 ctx.subnet_ = subnet;
1910 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
1911 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
1921 StatsMgr::instance().addValue(
1922 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
"assigned-nas"),
1923 static_cast<int64_t>(-1));
1926 ctx.currentIA().old_leases_.push_back(lease);
1932 ALLOC_ENGINE_V6_EXTEND_LEASE_DATA)
1933 .arg(ctx.query_->getLabel())
1934 .arg(lease->toText());
1939 lease->preferred_lft_ = ctx.subnet_->getPreferred();
1940 lease->valid_lft_ = ctx.subnet_->getValid();
1941 lease->t1_ = ctx.subnet_->getT1();
1942 lease->t2_ = ctx.subnet_->getT2();
1943 lease->hostname_ = ctx.hostname_;
1944 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1945 lease->fqdn_rev_ = ctx.rev_dns_update_;
1946 lease->hwaddr_ = ctx.hwaddr_;
1950 conditionalExtendLifetime(*lease);
1953 ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA)
1954 .arg(ctx.query_->getLabel())
1955 .arg(lease->toText());
1959 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
1960 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
1961 if (HooksManager::calloutsPresent(hook_point)) {
1974 callout_handle->setArgument(
"query6", ctx.query_);
1977 callout_handle->setArgument(
"lease6", lease);
1981 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
1983 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
1987 HooksManager::callCallouts(hook_point, *callout_handle);
1992 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
1995 DHCPSRV_HOOK_LEASE6_EXTEND_SKIP)
1996 .arg(ctx.query_->getName());
2005 if (old_data->expired()) {
2006 reclaimExpiredLease(old_data, ctx.callout_handle_);
2010 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2011 StatsMgr::instance().addValue(
2012 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2014 "assigned-nas" :
"assigned-pds"),
2015 static_cast<int64_t>(1));
2018 if (!lease->hasIdenticalFqdn(*old_data)) {
2039 ctx.currentIA().changed_leases_.push_back(old_data);
2046 bool remove_queued =
false;
2047 for (Lease6Collection::const_iterator lease_it = leases.begin();
2048 lease_it != leases.end(); ++lease_it) {
2050 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2051 lease->fqdn_rev_ = ctx.rev_dns_update_;
2052 lease->hostname_ = ctx.hostname_;
2053 if (!ctx.fake_allocation_) {
2061 if (inAllowedPool(ctx, ctx.currentIA().type_,
2062 lease->addr_,
true)) {
2063 StatsMgr::instance().addValue(
2064 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2066 "assigned-nas" :
"assigned-pds"),
2067 static_cast<int64_t>(1));
2072 !(lease->hasIdenticalFqdn(**lease_it)));
2074 if (conditionalExtendLifetime(*lease) || fqdn_changed) {
2075 ctx.currentIA().changed_leases_.push_back(*lease_it);
2080 if (fqdn_changed && !remove_queued) {
2082 remove_queued =
true;
2087 updated_leases.push_back(lease);
2090 return (updated_leases);
2095 const bool remove_lease,
2096 const uint16_t max_unwarned_cycles) {
2099 ALLOC_ENGINE_V6_LEASES_RECLAMATION_START)
2111 bool incomplete_reclamation =
false;
2114 if (max_leases > 0) {
2123 if (leases.size() > max_leases) {
2125 incomplete_reclamation =
true;
2138 if (!leases.empty() &&
2139 HooksManager::getHooksManager().calloutsPresent(
Hooks.hook_index_lease6_expire_)) {
2140 callout_handle = HooksManager::createCalloutHandle();
2143 size_t leases_processed = 0;
2144 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2148 reclaimExpiredLease(lease, remove_lease, callout_handle);
2151 }
catch (
const std::exception& ex) {
2153 .arg(lease->addr_.toText())
2164 if (!incomplete_reclamation) {
2165 if (leases_processed < leases.size()) {
2166 incomplete_reclamation =
true;
2171 ALLOC_ENGINE_V6_LEASES_RECLAMATION_TIMEOUT)
2182 ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE)
2183 .arg(leases_processed)
2188 if (incomplete_reclamation) {
2189 ++incomplete_v6_reclamations_;
2192 if ((max_unwarned_cycles > 0) &&
2193 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2195 .arg(max_unwarned_cycles);
2197 incomplete_v6_reclamations_ = 0;
2202 incomplete_v6_reclamations_ = 0;
2205 ALLOC_ENGINE_V6_NO_MORE_EXPIRED_LEASES);
2212 ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE)
2215 uint64_t deleted_leases = 0;
2221 }
catch (
const std::exception& ex) {
2227 ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_COMPLETE)
2228 .arg(deleted_leases);
2234 const bool remove_lease,
2235 const uint16_t max_unwarned_cycles) {
2238 ALLOC_ENGINE_V4_LEASES_RECLAMATION_START)
2250 bool incomplete_reclamation =
false;
2253 if (max_leases > 0) {
2262 if (leases.size() > max_leases) {
2264 incomplete_reclamation =
true;
2278 if (!leases.empty() &&
2279 HooksManager::getHooksManager().calloutsPresent(
Hooks.hook_index_lease4_expire_)) {
2280 callout_handle = HooksManager::createCalloutHandle();
2283 size_t leases_processed = 0;
2284 BOOST_FOREACH(
Lease4Ptr lease, leases) {
2288 reclaimExpiredLease(lease, remove_lease, callout_handle);
2291 }
catch (
const std::exception& ex) {
2293 .arg(lease->addr_.toText())
2304 if (!incomplete_reclamation) {
2305 if (leases_processed < leases.size()) {
2306 incomplete_reclamation =
true;
2311 ALLOC_ENGINE_V4_LEASES_RECLAMATION_TIMEOUT)
2322 ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE)
2323 .arg(leases_processed)
2328 if (incomplete_reclamation) {
2329 ++incomplete_v4_reclamations_;
2332 if ((max_unwarned_cycles > 0) &&
2333 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2335 .arg(max_unwarned_cycles);
2337 incomplete_v4_reclamations_ = 0;
2342 incomplete_v4_reclamations_ = 0;
2345 ALLOC_ENGINE_V4_NO_MORE_EXPIRED_LEASES);
2349 template<
typename LeasePtrType>
2351 AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2353 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2357 template<
typename LeasePtrType>
2359 AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2364 if (!lease->stateExpiredReclaimed()) {
2365 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2370 AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2371 const DbReclaimMode& reclaim_mode,
2375 ALLOC_ENGINE_V6_LEASE_RECLAIM)
2377 .arg(lease->addr_.toText())
2378 .arg(static_cast<int>(lease->prefixlen_));
2384 bool skipped =
false;
2385 if (callout_handle) {
2393 callout_handle->deleteAllArguments();
2394 callout_handle->setArgument(
"lease6", lease);
2395 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2397 HooksManager::callCallouts(
Hooks.hook_index_lease6_expire_,
2400 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2415 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2425 remove_lease = reclaimDeclined(lease);
2428 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2432 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2443 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2450 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2458 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2461 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2463 "reclaimed-leases"),
2468 AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2469 const DbReclaimMode& reclaim_mode,
2473 ALLOC_ENGINE_V4_LEASE_RECLAIM)
2475 .arg(lease->addr_.toText());
2481 bool skipped =
false;
2482 if (callout_handle) {
2490 callout_handle->setArgument(
"lease4", lease);
2491 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2493 HooksManager::callCallouts(
Hooks.hook_index_lease4_expire_,
2496 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2511 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2521 remove_lease = reclaimDeclined(lease);
2524 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2528 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
2537 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2539 "assigned-addresses"),
2543 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2546 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2548 "reclaimed-leases"),
2555 ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE)
2558 uint64_t deleted_leases = 0;
2564 }
catch (
const std::exception& ex) {
2570 ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_COMPLETE)
2571 .arg(deleted_leases);
2575 AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
2581 if (HooksManager::getHooksManager().calloutsPresent(
Hooks.hook_index_lease4_recover_)) {
2586 if (!callout_handle) {
2587 callout_handle = HooksManager::createCalloutHandle();
2597 callout_handle->setArgument(
"lease4", lease);
2600 HooksManager::callCallouts(
Hooks.hook_index_lease4_recover_, *callout_handle);
2605 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2607 .arg(lease->addr_.toText());
2613 .arg(lease->addr_.toText())
2614 .arg(lease->valid_lft_);
2616 StatsMgr& stats_mgr = StatsMgr::instance();
2619 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
2620 "declined-addresses"), static_cast<int64_t>(-1));
2623 stats_mgr.
addValue(
"declined-addresses", static_cast<int64_t>(-1));
2625 stats_mgr.
addValue(
"reclaimed-declined-addresses", static_cast<int64_t>(1));
2627 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
2628 "reclaimed-declined-addresses"), static_cast<int64_t>(1));
2636 AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
2642 if (HooksManager::getHooksManager().calloutsPresent(
Hooks.hook_index_lease6_recover_)) {
2647 if (!callout_handle) {
2648 callout_handle = HooksManager::createCalloutHandle();
2658 callout_handle->setArgument(
"lease6", lease);
2661 HooksManager::callCallouts(
Hooks.hook_index_lease6_recover_, *callout_handle);
2666 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2668 .arg(lease->addr_.toText());
2674 .arg(lease->addr_.toText())
2675 .arg(lease->valid_lft_);
2677 StatsMgr& stats_mgr = StatsMgr::instance();
2680 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
2681 "declined-addresses"), static_cast<int64_t>(-1));
2684 stats_mgr.
addValue(
"declined-addresses", static_cast<int64_t>(-1));
2686 stats_mgr.
addValue(
"reclaimed-declined-addresses", static_cast<int64_t>(1));
2688 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
2689 "reclaimed-declined-addresses"), static_cast<int64_t>(1));
2698 template<
typename LeasePtrType>
2699 void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
2700 const bool remove_lease,
2701 const boost::function<
void (
const LeasePtrType&)>&
2702 lease_update_fun)
const {
2711 }
else if (!lease_update_fun.empty()) {
2714 lease->hostname_.clear();
2715 lease->fqdn_fwd_ =
false;
2716 lease->fqdn_rev_ =
false;
2718 lease_update_fun(lease);
2726 ALLOC_ENGINE_LEASE_RECLAIMED)
2727 .arg(lease->addr_.toText());
2763 if (id->first == host->getIdentifierType()) {
2764 return (id->second != host->getIdentifier());
2790 if (ctx.
hosts_.empty()) {
2797 auto host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
2798 return (host != ctx.
hosts_.end() &&
2799 !(host->second->getIPv4Reservation().isV4Zero()));
2804 auto host = ctx.
hosts_.find(subnet->getID());
2805 if ((host != ctx.
hosts_.end()) &&
2806 !(host->second->getIPv4Reservation().isV4Zero()) &&
2809 (!subnet->inPool(
Lease::TYPE_V4, host->second->getIPv4Reservation()))))) {
2816 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
2858 if (ctx.
clientid_ && subnet->getMatchClientId()) {
2859 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
2860 if ((*l)->subnet_id_ == subnet->getID()) {
2862 client_lease = (*l);
2871 subnet = subnet->getNextSubnet(original_subnet, ctx.
query_->getClasses());
2877 if (!client_lease && ctx.
hwaddr_) {
2880 subnet = original_subnet;
2887 if (subnet->getMatchClientId()) {
2893 for (Lease4Collection::const_iterator client_lease_it = leases_hw_address.begin();
2894 client_lease_it != leases_hw_address.end(); ++client_lease_it) {
2895 Lease4Ptr existing_lease = *client_lease_it;
2896 if ((existing_lease->subnet_id_ == subnet->getID()) &&
2897 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
2899 client_lease = existing_lease;
2909 subnet = subnet->getNextSubnet(original_subnet, ctx.
query_->getClasses());
2931 while (current_subnet) {
2934 ctx.
query_->getClasses())) {
2942 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_,
2943 ctx.
query_->getClasses());
2955 : subnet_(), clientid_(), hwaddr_(),
2956 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
2957 fwd_dns_update_(false), rev_dns_update_(false),
2958 hostname_(
""), callout_handle_(), fake_allocation_(false),
2959 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
2960 query_(), host_identifiers_() {
2967 const bool fwd_dns_update,
2968 const bool rev_dns_update,
2969 const std::string& hostname,
2970 const bool fake_allocation)
2971 : subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
2972 requested_address_(requested_addr),
2973 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
2974 hostname_(hostname), callout_handle_(),
2975 fake_allocation_(fake_allocation), old_lease_(), new_lease_(),
2976 hosts_(), host_identifiers_() {
2988 SUBNET_ID_GLOBAL : subnet_->getID());
2990 auto host = hosts_.find(
id);
2991 if (host != hosts_.cend()) {
2992 return (host->second);
3012 if (subnet && !subnet->clientSupported(ctx.
query_->getClasses())) {
3013 ctx.
subnet_ = subnet->getNextSubnet(subnet, ctx.
query_->getClasses());
3026 return (discoverLease4(ctx));
3035 .arg(ctx.
query_->getLabel())
3053 std::map<SubnetID, ConstHostPtr> host_map;
3055 subnet->getSharedNetwork(network);
3060 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3073 const bool use_single_query = network &&
3076 if (use_single_query) {
3081 &id_pair->second[0],
3082 id_pair->second.size());
3086 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
3087 if ((*host)->getIPv4SubnetID() > 0) {
3088 host_map[(*host)->getIPv4SubnetID()] = *host;
3099 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
3104 if (use_single_query) {
3105 if (host_map.count(subnet->getID()) > 0) {
3106 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3115 id_pair.second.size());
3118 ctx.
hosts_[subnet->getID()] = host;
3128 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3138 &id_pair.second[0], id_pair.second.size());
3156 findClientLease(ctx, client_lease);
3166 if (hasAddressReservation(ctx)) {
3169 ALLOC_ENGINE_V4_DISCOVER_HR)
3170 .arg(ctx.
query_->getLabel())
3171 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3177 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3184 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3188 .arg(ctx.
query_->getLabel())
3189 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3195 new_lease = renewLease4(client_lease, ctx);
3208 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3209 !addressReserved(client_lease->addr_, ctx)) {
3212 ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE)
3213 .arg(ctx.
query_->getLabel());
3215 new_lease = renewLease4(client_lease, ctx);
3230 ALLOC_ENGINE_V4_OFFER_REQUESTED_LEASE)
3232 .arg(ctx.
query_->getLabel());
3244 ALLOC_ENGINE_V4_OFFER_NEW_LEASE)
3245 .arg(ctx.
query_->getLabel());
3247 new_lease = allocateUnreservedLease4(ctx);
3267 findClientLease(ctx, client_lease);
3285 ALLOC_ENGINE_V4_REQUEST_ADDRESS_RESERVED)
3286 .arg(ctx.
query_->getLabel())
3292 }
else if (hasAddressReservation(ctx)) {
3300 ALLOC_ENGINE_V4_REQUEST_USE_HR)
3301 .arg(ctx.
query_->getLabel())
3313 if (existing && !existing->expired() &&
3314 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
3318 ALLOC_ENGINE_V4_REQUEST_IN_USE)
3319 .arg(ctx.
query_->getLabel())
3329 if (hasAddressReservation(ctx) &&
3337 if (!existing || existing->expired()) {
3340 ALLOC_ENGINE_V4_REQUEST_INVALID)
3341 .arg(ctx.
query_->getLabel())
3342 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3352 if ((!hasAddressReservation(ctx) ||
3357 ALLOC_ENGINE_V4_REQUEST_OUT_OF_POOL)
3358 .arg(ctx.
query_->getLabel())
3376 (hasAddressReservation(ctx) ||
3377 inAllowedPool(ctx, client_lease->addr_))) {
3380 ALLOC_ENGINE_V4_REQUEST_EXTEND_LEASE)
3381 .arg(ctx.
query_->getLabel())
3384 return (renewLease4(client_lease, ctx));
3397 ALLOC_ENGINE_V4_REQUEST_ALLOC_REQUESTED)
3398 .arg(ctx.
query_->getLabel())
3413 ALLOC_ENGINE_V4_REQUEST_PICK_ADDRESS)
3414 .arg(ctx.
query_->getLabel());
3419 new_lease = allocateUnreservedLease4(ctx);
3425 if (new_lease && client_lease) {
3429 ALLOC_ENGINE_V4_REQUEST_REMOVE_LEASE)
3430 .arg(ctx.
query_->getLabel())
3431 .arg(client_lease->addr_.toText());
3436 StatsMgr::instance().addValue(
3437 StatsMgr::generateName(
"subnet", client_lease->subnet_id_,
"assigned-addresses"),
3438 static_cast<int64_t>(-1));
3447 AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
3450 isc_throw(BadValue,
"Can't create a lease with NULL HW address");
3453 isc_throw(BadValue,
"Can't create a lease without a subnet");
3456 time_t now = time(NULL);
3459 std::vector<uint8_t> local_copy;
3460 if (ctx.clientid_ && ctx.subnet_->getMatchClientId()) {
3461 local_copy = ctx.clientid_->getDuid();
3463 const uint8_t* local_copy0 = local_copy.empty() ? 0 : &local_copy[0];
3465 Lease4Ptr lease(
new Lease4(addr, ctx.hwaddr_, local_copy0, local_copy.size(),
3466 ctx.subnet_->getValid(), ctx.subnet_->getT1(),
3467 ctx.subnet_->getT2(),
3468 now, ctx.subnet_->getID()));
3471 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
3472 lease->fqdn_rev_ = ctx.rev_dns_update_;
3473 lease->hostname_ = ctx.hostname_;
3476 if (ctx.callout_handle_ &&
3477 HooksManager::getHooksManager().calloutsPresent(hook_index_lease4_select_)) {
3490 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
3496 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
3497 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
3500 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
3503 ctx.callout_handle_->setArgument(
"lease4", lease);
3506 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.callout_handle_);
3508 callout_status = ctx.callout_handle_->getStatus();
3513 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
3520 ctx.callout_handle_->getArgument(
"lease4", lease);
3523 if (!ctx.fake_allocation_) {
3529 StatsMgr::instance().addValue(
3530 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
"assigned-addresses"),
3531 static_cast<int64_t>(1));
3556 AllocEngine::renewLease4(
const Lease4Ptr& lease,
3559 isc_throw(BadValue,
"null lease specified for renewLease4");
3566 Lease4 old_values = *lease;
3570 updateLease4Information(lease, ctx);
3586 if (HooksManager::getHooksManager().
3587 calloutsPresent(
Hooks.hook_index_lease4_renew_)) {
3611 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
3619 HooksManager::callCallouts(
Hooks.hook_index_lease4_renew_,
3625 if (ctx.
callout_handle_->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3628 DHCPSRV_HOOK_LEASE4_RENEW_SKIP);
3640 StatsMgr::instance().addValue(
3641 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
"assigned-addresses"),
3642 static_cast<int64_t>(1));
3648 *lease = old_values;
3655 AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
3659 isc_throw(BadValue,
"null lease specified for reuseExpiredLease");
3663 isc_throw(BadValue,
"null subnet specified for the reuseExpiredLease");
3674 updateLease4Information(expired, ctx);
3677 ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA)
3678 .arg(ctx.
query_->getLabel())
3679 .arg(expired->toText());
3683 .calloutsPresent(hook_index_lease4_select_)) {
3713 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.
callout_handle_);
3720 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
3722 DHCPSRV_HOOK_LEASE4_SELECT_SKIP);
3738 StatsMgr::instance().addValue(
3739 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
"assigned-addresses"),
3740 static_cast<int64_t>(1));
3752 AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
3754 ctx.conflicting_lease_.reset();
3758 if (exist_lease->expired()) {
3760 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
3766 ctx.conflicting_lease_ = exist_lease;
3770 return (createLease4(ctx, candidate, callout_status));
3776 AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
3791 ctx.subnet_->getSharedNetwork(network);
3798 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
3803 uint64_t total_attempts = 0;
3807 if (subnet->getMatchClientId()) {
3808 client_id = ctx.clientid_;
3811 uint64_t possible_attempts =
3813 ctx.query_->getClasses());
3814 uint64_t max_attempts = (attempts_ > 0 ? attempts_ : possible_attempts);
3816 if (possible_attempts == 0) {
3822 for (uint64_t i = 0; i < max_attempts; ++i) {
3823 IOAddress candidate = allocator->pickAddress(subnet,
3824 ctx.query_->getClasses(),
3826 ctx.requested_address_);
3828 if (!addressReserved(candidate, ctx)) {
3833 new_lease = allocateOrReuseLease4(candidate, ctx, callout_status);
3837 }
else if (ctx.callout_handle_ &&
3838 (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
3849 subnet = subnet->getNextSubnet(original_subnet, ctx.query_->getClasses());
3852 ctx.subnet_ = subnet;
3859 .arg(ctx.query_->getLabel())
3860 .arg(total_attempts);
3866 AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
3868 lease->subnet_id_ = ctx.
subnet_->getID();
3871 lease->cltt_ = time(NULL);
3872 lease->t1_ = ctx.
subnet_->getT1();
3873 lease->t2_ = ctx.
subnet_->getT2();
3874 lease->valid_lft_ = ctx.
subnet_->getValid();
3881 AllocEngine::conditionalExtendLifetime(
Lease& lease)
const {
3882 lease.
cltt_ = time(NULL);
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
bool fake_allocation_
Indicates if this is a real or fake allocation.
boost::shared_ptr< DUID > DuidPtr
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
const int ALLOC_ENGINE_DBG_TRACE
Logging levels for the AllocEngine.
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
Both out-of-pool and in-pool reservations are allowed.
A generic exception that is thrown when a function is not implemented.
static const uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Structure that holds a lease for IPv4 address.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
virtual bool deleteLease(const isc::asiolink::IOAddress &addr)=0
Deletes a lease.
static void findReservation(ClientContext6 &ctx)
Attempts to find appropriate host reservation.
void addHint(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding new hint.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Only global reservations are allowed.
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
static std::string typeToText(Type type)
returns text representation of a lease type
void addAllocatedResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding allocated prefix or address.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
static isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress &address, bool prefix, const uint8_t prefix_len)
Returns the next address or prefix.
time_t cltt_
Client last transmission time.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
static CfgMgr & instance()
returns a single instance of Configuration Manager
const int DHCPSRV_DBG_HOOKS
Only out-of-pool reservations is allowed.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
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...
boost::shared_ptr< Option > OptionPtr
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
the lease contains IPv6 prefix (for prefix delegation)
const int ALLOC_ENGINE_DBG_TRACE_DETAIL
Record detailed traces.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv4 leases.
DuidPtr duid_
Client identifier.
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
long getTotalMilliseconds() const
Retrieves the total measured duration in milliseconds.
Lease4Ptr allocateLease4(ClientContext4 &ctx)
Returns IPv4 lease.
virtual isc::asiolink::IOAddress pickAddress(const SubnetPtr &subnet, const ClientClasses &client_classes, const DuidPtr &duid, const isc::asiolink::IOAddress &hint)
returns an address based on hash calculated from client's DUID.
bool isAllocated(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was allocated.
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
IPv6 reservation for a host.
AllocEngine(AllocType engine_type, uint64_t attempts, bool ipv6=true)
Constructor.
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
RAII object enabling copying options retrieved from the packet.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
An exception that is thrown when allocation module fails (e.g.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv6 leases.
Statistics Manager class.
asiolink::IOAddress requested_address_
An address that the client desires.
void deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
AllocType
specifies allocation type
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
void stop()
Stops the stopwatch.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
Subnet6Ptr subnet_
Subnet selected for the client by the server.
ResourceContainer allocated_resources_
Holds addresses and prefixes allocated for all IAs.
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
const int ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA
Records detailed results of various operations.
virtual isc::asiolink::IOAddress pickAddress(const SubnetPtr &subnet, const ClientClasses &client_classes, const DuidPtr &duid, const isc::asiolink::IOAddress &hint)
returns a random address from pool of specified subnet
Lease4Ptr conflicting_lease_
A pointer to the object representing a lease in conflict.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Lease4Ptr old_lease_
A pointer to an old lease that the client had before update.
Utility class to measure code execution times.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
Random allocator that picks address randomly.
Context information for the DHCPv6 leases allocation.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
Subnet6Ptr host_subnet_
Subnet from which host reservations should be retrieved.
A generic exception that is thrown when an unexpected error condition occurs.
Lease6Collection renewLeases6(ClientContext6 &ctx)
Renews existing DHCPv6 leases for a given IA.
Wrapper class around callout handle which automatically resets handle's state.
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.
Subnet4Ptr subnet_
Subnet selected for the client by the server.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
Pkt4Ptr query_
A pointer to the client's message.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
CalloutNextStep
Specifies allowed next steps.
ClientContext4()
Default constructor.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
Structure that holds a lease for IPv6 address and/or prefix.
Address/prefix allocator that iterates over all addresses.
None - host reservation is disabled.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Type
Type of the reservation.
bool isV6() const
Convenience function to check for an IPv6 address.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv4 leases.
the lease contains temporary IPv6 address
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
the lease contains non-temporary IPv6 address
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
HRMode
Specifies allowed host reservation mode.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
ConstHostPtr currentHost() const
Returns host for currently selected subnet.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
Lease6Collection new_leases_
A collection of newly allocated leases.
ClientIdPtr clientid_
Client identifier from the DHCP message.
uint32_t iaid_
iaid IAID field from IA_NA or IA_PD that is being processed
std::string toText() const
Convert the address to a string.
Lease::Type type_
Lease type (IA or PD)
boost::shared_ptr< Allocator > AllocatorPtr
defines a pointer to allocator
Address/prefix allocator that gets an address based on a hash.
Pkt6Ptr query_
A pointer to the client's message.
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.
Lease6Collection allocateLeases6(ClientContext6 &ctx)
Allocates IPv6 leases for a given IA container.
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
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.
Lease4Ptr new_lease_
A pointer to a newly allocated lease.
HashedAllocator(Lease::Type type)
default constructor (does nothing)
a common structure for IPv4 and IPv6 leases
Type
Type of lease or pool.
IAContext()
Default constructor.
bool fwd_dns_update_
Perform forward DNS update.
isc::log::Logger alloc_engine_logger("alloc-engine")
Logger for the AllocEngine.
base class for all address/prefix allocation algorithms
A generic exception that is thrown if a function is called in a prohibited way.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
void deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
IAContext & currentIA()
Returns IA specific context for the currently processed IA.
static const uint32_t STATE_DEFAULT
A lease in the default state.
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.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
std::string hostname_
Hostname.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
static const uint32_t STATE_DECLINED
Declined lease.
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
bool hasGlobalReservation(const IPv6Resrv &resv) const
Determines if a global reservation exists.
static isc::asiolink::IOAddress increasePrefix(const isc::asiolink::IOAddress &prefix, const uint8_t prefix_len)
Returns the next prefix.
std::pair< IPv6Resrv::Type, IPv6Resrv > IPv6ResrvTuple
HWAddrPtr hwaddr_
HW address from the DHCP message.
The IOAddress class represents an IP addresses (version agnostic)
static LeaseMgr & instance()
Return current lease manager.
virtual isc::asiolink::IOAddress pickAddress(const SubnetPtr &subnet, const ClientClasses &client_classes, const DuidPtr &duid, const isc::asiolink::IOAddress &hint)
returns the next address from pools in a subnet
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
RandomAllocator(Lease::Type type)
default constructor (does nothing)
Context information for the DHCPv4 lease allocation.
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv6 leases.
std::string logFormatTotalDuration() const
Returns the total measured duration in the format directly usable in the log messages.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
ConstHostPtr currentHost() const
Returns host from the most preferred subnet.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
Container for storing client class names.
static IOAddress increase(const IOAddress &addr)
Returns an address increased by one.
bool rev_dns_update_
Perform reverse DNS update.
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
AllocatorPtr getAllocator(Lease::Type type)
Returns allocator for a given pool type.
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
ClientContext6()
Default constructor.