36#include <boost/foreach.hpp>
37#include <boost/make_shared.hpp>
54namespace ph = std::placeholders;
59struct AllocEngineHooks {
60 int hook_index_lease4_select_;
61 int hook_index_lease4_renew_;
62 int hook_index_lease4_expire_;
63 int hook_index_lease4_recover_;
64 int hook_index_lease6_select_;
65 int hook_index_lease6_renew_;
66 int hook_index_lease6_rebind_;
67 int hook_index_lease6_expire_;
68 int hook_index_lease6_recover_;
88AllocEngineHooks
Hooks;
96 : attempts_(attempts), incomplete_v4_reclamations_(0),
97 incomplete_v6_reclamations_(0) {
100 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
101 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
128 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
133 reserved.push_back(host);
144 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
163 const IOAddress& address,
bool check_subnet) {
167 auto const& classes = ctx.
query_->getClasses();
169 while (current_subnet) {
170 if (current_subnet->clientSupported(classes)) {
172 if (current_subnet->inPool(lease_type, address)) {
176 if (current_subnet->inPool(lease_type, address, classes)) {
182 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
209 const std::string& hostname,
210 const bool fake_allocation,
218 ias_(), ddns_params_() {
234 const uint8_t prefix_len,
235 const uint32_t preferred,
236 const uint32_t valid) {
246 addHint(iaaddr->getAddress(), 128,
247 iaaddr->getPreferred(), iaaddr->getValid());
256 addHint(iaprefix->getAddress(), iaprefix->getLength(),
257 iaprefix->getPreferred(), iaprefix->getValid());
263 const uint8_t prefix_len) {
270 const uint8_t prefix_len)
const {
278 const uint8_t prefix_len) {
286 return (
static_cast<bool>
293 if (subnet && subnet->getReservationsInSubnet()) {
294 auto host =
hosts_.find(subnet->getID());
295 if (host !=
hosts_.cend()) {
296 return (host->second);
306 if (subnet &&
subnet_->getReservationsGlobal()) {
307 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
308 if (host !=
hosts_.cend()) {
309 return (host->second);
319 return (ghost && ghost->hasReservation(resv));
325 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
326 return (ddns_params_);
332 return (ddns_params_);
351 !subnet->getReservationsInSubnet()) {
357 subnet->getReservationsGlobal()) {
360 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
363 if (!subnet->getReservationsInSubnet()) {
369 std::map<SubnetID, ConstHostPtr> host_map;
371 subnet->getSharedNetwork(network);
380 const bool use_single_query = network &&
384 if (use_single_query) {
388 id_pair.second.size());
392 for (
auto const& host : hosts) {
393 if (host->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
394 host_map[host->getIPv6SubnetID()] = host;
400 auto const& classes = ctx.
query_->getClasses();
407 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
410 if (use_single_query) {
411 if (host_map.count(subnet->getID()) > 0) {
412 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
420 id_pair.second.size());
423 ctx.
hosts_[subnet->getID()] = host;
433 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
439 for (
auto const& host : ctx.
hosts_) {
440 host.second->encapsulateOptions();
450 &id_pair.second[0], id_pair.second.size());
484 for (
auto const& l : all_leases) {
485 if ((l)->subnet_id_ == subnet->getID()) {
490 subnet = subnet->getNextSubnet(ctx.
subnet_);
510 if (leases.empty() && !ctx.
hosts_.empty()) {
514 .arg(ctx.
query_->getLabel());
519 allocateReservedLeases6(ctx, leases);
521 leases = updateLeaseData(ctx, leases);
536 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
540 .arg(ctx.
query_->getLabel());
544 removeNonmatchingReservedLeases6(ctx, leases);
546 leases = updateLeaseData(ctx, leases);
555 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
559 .arg(ctx.
query_->getLabel());
563 allocateReservedLeases6(ctx, leases);
575 removeNonmatchingReservedLeases6(ctx, leases);
584 removeNonreservedLeases6(ctx, leases);
589 leases = updateLeaseData(ctx, leases);
602 if (leases.empty()) {
616 .arg(ctx.
query_->getLabel());
618 leases = allocateUnreservedLeases6(ctx);
621 if (!leases.empty()) {
625 for (
auto const& lease : leases) {
639 .arg(ctx.
query_->getLabel())
652 uint8_t hint_prefix_length = 128;
653 if (!ctx.currentIA().hints_.empty()) {
655 hint = ctx.currentIA().hints_[0].getAddress();
656 hint_prefix_length = ctx.currentIA().hints_[0].getPrefixLength();
665 uint64_t total_attempts = 0;
669 uint64_t subnets_with_unavail_leases = 0;
672 uint64_t subnets_with_unavail_pools = 0;
682 bool search_hint_lease =
true;
689 if (hint_prefix_length == 128) {
690 hint_prefix_length = 0;
692 if (!hint_prefix_length) {
700 Lease6Ptr lease = allocateBestMatch(ctx, hint_lease, search_hint_lease,
701 hint, hint_prefix_length, subnet,
702 network, total_attempts,
703 subnets_with_unavail_leases,
704 subnets_with_unavail_pools,
705 callout_status, prefix_length_match);
713 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
714 hint_prefix_length, subnet, network,
715 total_attempts, subnets_with_unavail_leases,
716 subnets_with_unavail_pools, callout_status,
717 prefix_length_match);
726 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
727 hint_prefix_length, subnet, network,
728 total_attempts, subnets_with_unavail_leases,
729 subnets_with_unavail_pools, callout_status,
730 prefix_length_match);
734 leases.push_back(lease);
738 auto const& classes = ctx.query_->getClasses();
744 .arg(ctx.query_->getLabel())
745 .arg(network->getName())
746 .arg(subnets_with_unavail_leases)
747 .arg(subnets_with_unavail_pools);
749 static_cast<int64_t
>(1));
752 "v6-allocation-fail-shared-network"),
753 static_cast<int64_t
>(1));
757 std::string shared_network = ctx.subnet_->getSharedNetworkName();
758 if (shared_network.empty()) {
759 shared_network =
"(none)";
762 .arg(ctx.query_->getLabel())
763 .arg(ctx.subnet_->toText())
764 .arg(ctx.subnet_->getID())
765 .arg(shared_network);
767 static_cast<int64_t
>(1));
770 "v6-allocation-fail-subnet"),
771 static_cast<int64_t
>(1));
773 if (total_attempts == 0) {
779 .arg(ctx.query_->getLabel());
781 static_cast<int64_t
>(1));
784 "v6-allocation-fail-no-pools"),
785 static_cast<int64_t
>(1));
792 .arg(ctx.query_->getLabel())
793 .arg(total_attempts);
795 static_cast<int64_t
>(1));
798 "v6-allocation-fail"),
799 static_cast<int64_t
>(1));
802 if (!classes.empty()) {
804 .arg(ctx.query_->getLabel())
805 .arg(classes.toText());
807 static_cast<int64_t
>(1));
810 "v6-allocation-fail-classes"),
811 static_cast<int64_t
>(1));
821 bool& search_hint_lease,
822 const isc::asiolink::IOAddress& hint,
823 uint8_t hint_prefix_length,
826 uint64_t& total_attempts,
827 uint64_t& subnets_with_unavail_leases,
828 uint64_t& subnets_with_unavail_pools,
831 auto const& classes = ctx.query_->getClasses();
836 if (!search_hint_lease) {
837 usable_hint_lease = hint_lease;
839 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
840 if (!subnet->clientSupported(classes)) {
844 ctx.subnet_ = subnet;
848 pool = boost::dynamic_pointer_cast<Pool6>
849 (subnet->getPool(ctx.currentIA().type_, classes, hint));
852 if (!pool || !pool->clientSupported(classes)) {
858 hint_prefix_length)) {
862 bool in_subnet = subnet->getReservationsInSubnet();
865 if (search_hint_lease) {
866 search_hint_lease =
false;
868 usable_hint_lease = hint_lease;
870 if (!usable_hint_lease) {
882 (!subnet->getReservationsOutOfPool() ||
883 !subnet->inPool(ctx.currentIA().type_, hint))) {
884 hosts = getIPv6Resrv(subnet->getID(), hint);
894 Lease6Ptr new_lease = createLease6(ctx, hint, pool->getLength(), callout_status);
907 .arg(ctx.query_->getLabel())
911 }
else if (usable_hint_lease->expired()) {
920 (!subnet->getReservationsOutOfPool() ||
921 !subnet->inPool(ctx.currentIA().type_, hint))) {
922 hosts = getIPv6Resrv(subnet->getID(), hint);
930 Lease6Ptr old_lease(
new Lease6(*usable_hint_lease));
931 ctx.currentIA().old_leases_.push_back(old_lease);
934 Lease6Ptr lease = reuseExpiredLease(usable_hint_lease, ctx,
944 .arg(ctx.query_->getLabel())
956 if (!check_reservation_first) {
970 original_subnet->getSharedNetwork(network);
977 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
980 ctx.subnet_ = subnet = original_subnet;
982 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
983 if (!subnet->clientSupported(classes)) {
994 subnet->getPoolCapacity(ctx.currentIA().type_,
1005 (attempts_ == 0 || possible_attempts < attempts_) ?
1009 if (max_attempts > 0) {
1012 ++subnets_with_unavail_leases;
1016 ++subnets_with_unavail_pools;
1020 bool in_subnet = subnet->getReservationsInSubnet();
1021 bool out_of_pool = subnet->getReservationsOutOfPool();
1026 if (ctx.callout_handle_) {
1030 for (uint64_t i = 0; i < max_attempts; ++i) {
1033 auto allocator = subnet->getAllocator(ctx.currentIA().type_);
1038 uint8_t prefix_len = 128;
1040 candidate = allocator->pickPrefix(classes, pool, ctx.duid_,
1041 prefix_length_match, hint,
1042 hint_prefix_length);
1044 prefix_len = pool->getLength();
1047 candidate = allocator->pickAddress(classes, ctx.duid_, hint);
1056 if (check_reservation_first && in_subnet && !out_of_pool) {
1057 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1058 if (!hosts.empty()) {
1066 ResourceHandler resource_handler;
1068 !resource_handler.
tryLock(ctx.currentIA().type_, candidate)) {
1081 if (!check_reservation_first && in_subnet && !out_of_pool) {
1082 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1083 if (!hosts.empty()) {
1092 ctx.subnet_ = subnet;
1093 Lease6Ptr new_lease = createLease6(ctx, candidate, prefix_len, callout_status);
1097 ctx.currentIA().old_leases_.clear();
1101 }
else if (ctx.callout_handle_ &&
1110 }
else if (existing->expired()) {
1112 if (!check_reservation_first && in_subnet && !out_of_pool) {
1113 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1114 if (!hosts.empty()) {
1122 Lease6Ptr old_lease(
new Lease6(*existing));
1123 ctx.currentIA().old_leases_.push_back(old_lease);
1125 ctx.subnet_ = subnet;
1126 existing = reuseExpiredLease(existing, ctx, prefix_len,
1141 if (ctx.hosts_.empty()) {
1144 .arg(ctx.query_->getLabel());
1155 for (
auto const& lease : existing_leases) {
1156 if ((lease->valid_lft_ != 0)) {
1157 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1158 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1163 .arg(ctx.query_->getLabel())
1164 .arg(lease->typeToText(lease->type_))
1165 .arg(lease->addr_.toText());
1171 if (!ctx.host_subnet_) {
1173 ctx.subnet_->getSharedNetwork(network);
1178 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1186 if (host && !host->getHostname().empty()) {
1193 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1194 static_cast<bool>(fqdn));
1208 auto const& classes = ctx.query_->getClasses();
1209 for (
Subnet6Ptr subnet = ctx.subnet_; subnet;
1210 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1212 SubnetID subnet_id = subnet->getID();
1215 if (!subnet->clientSupported(classes) || ctx.hosts_.count(subnet_id) == 0) {
1221 bool in_subnet = subnet->getReservationsInSubnet();
1225 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1227 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1228 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1232 if (ctx.isAllocated(addr, prefix_len)) {
1241 (subnet->getReservationsOutOfPool() &&
1242 subnet->inPool(ctx.currentIA().type_, addr))) {
1254 ctx.subnet_ = subnet;
1256 if (!ctx.host_subnet_) {
1257 ctx.host_subnet_ = subnet;
1258 if (!host->getHostname().empty()) {
1272 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1273 static_cast<bool>(fqdn));
1279 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1282 existing_leases.push_back(lease);
1287 .arg(ctx.query_->getLabel());
1291 .arg(
static_cast<int>(prefix_len))
1292 .arg(ctx.query_->getLabel());
1310 allocateGlobalReservedLeases6(ctx, existing_leases);
1325 for (
auto const& lease : existing_leases) {
1326 if ((lease->valid_lft_ != 0) &&
1332 .arg(ctx.query_->getLabel())
1333 .arg(lease->typeToText(lease->type_))
1334 .arg(lease->addr_.toText());
1340 if (!ghost->getHostname().empty()) {
1347 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1348 static_cast<bool>(fqdn));
1363 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1364 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1366 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1367 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1371 if (ctx.isAllocated(addr, prefix_len)) {
1383 bool valid_subnet =
false;
1384 auto subnet = ctx.subnet_;
1386 if (subnet->inRange(addr)) {
1387 valid_subnet =
true;
1391 subnet = subnet->getNextSubnet(ctx.subnet_);
1394 if (!valid_subnet) {
1397 .arg(ctx.query_->getLabel())
1403 ctx.subnet_ = subnet;
1406 if (!ghost->getHostname().empty()) {
1420 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1421 static_cast<bool>(fqdn));
1426 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1429 existing_leases.push_back(lease);
1434 .arg(ctx.query_->getLabel());
1438 .arg(
static_cast<int>(prefix_len))
1439 .arg(ctx.query_->getLabel());
1457AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1460 if (existing_leases.empty() || !ctx.subnet_) {
1465 if (!ctx.subnet_->getReservationsInSubnet() &&
1466 !ctx.subnet_->getReservationsGlobal()) {
1467 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1476 for (
auto const& candidate :
copy) {
1480 if ((ctx.hasGlobalReservation(resv)) ||
1481 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1482 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1491 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1496 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1497 candidate->addr_,
false)) {
1501 if (!hosts.empty()) {
1504 if (hosts.size() == 1) {
1507 .arg(ctx.query_->getLabel())
1508 .arg(candidate->addr_.
toText())
1509 .arg(ctx.duid_->toText())
1510 .arg(hosts.front()->getIdentifierAsText());
1513 .arg(ctx.query_->getLabel())
1514 .arg(candidate->addr_.
toText())
1515 .arg(
static_cast<int>(candidate->prefixlen_))
1516 .arg(ctx.duid_->toText())
1517 .arg(hosts.front()->getIdentifierAsText());
1522 .arg(ctx.query_->getLabel())
1523 .arg(candidate->addr_.
toText())
1524 .arg(ctx.duid_->toText())
1528 .arg(ctx.query_->getLabel())
1529 .arg(candidate->addr_.
toText())
1530 .arg(
static_cast<int>(candidate->prefixlen_))
1531 .arg(ctx.duid_->toText())
1552 "assigned-nas" :
"assigned-pds"),
1553 static_cast<int64_t
>(-1));
1557 auto const& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1562 ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1563 static_cast<int64_t
>(-1));
1573 ctx.currentIA().old_leases_.push_back(candidate);
1576 removeLeases(existing_leases, candidate->addr_);
1581AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1588 for (
auto const& candidate :
copy) {
1592 if (inAllowedPool(ctx, candidate->type_,
1593 candidate->addr_,
false)) {
1611 "assigned-nas" :
"assigned-pds"),
1612 static_cast<int64_t
>(-1));
1616 auto const& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1621 candidate->type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1622 static_cast<int64_t
>(-1));
1627 ctx.currentIA().old_leases_.push_back(candidate);
1630 removeLeases(existing_leases, candidate->addr_);
1635AllocEngine::removeLeases(
Lease6Collection& container,
const asiolink::IOAddress& addr) {
1637 bool removed =
false;
1638 for (Lease6Collection::iterator lease = container.begin();
1639 lease != container.end(); ++lease) {
1640 if ((*lease)->addr_ == addr) {
1647 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1658 int total = existing_leases.size();
1665 for (Lease6Collection::iterator lease = existing_leases.begin();
1666 lease != existing_leases.end(); ++lease) {
1670 if (ctx.hasGlobalReservation(resv) ||
1671 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1672 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1694 "assigned-nas" :
"assigned-pds"),
1695 static_cast<int64_t
>(-1));
1699 auto const& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1704 ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1705 static_cast<int64_t
>(-1));
1712 ctx.currentIA().old_leases_.push_back(*lease);
1727 existing_leases.erase(std::remove(existing_leases.begin(),
1728 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1736 if (!expired->expired()) {
1737 isc_throw(BadValue,
"Attempt to recycle lease that is still valid");
1744 if (!ctx.fake_allocation_) {
1748 reclaimExpiredLease(expired, ctx.callout_handle_);
1752 expired->iaid_ = ctx.currentIA().iaid_;
1753 expired->duid_ = ctx.duid_;
1756 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1757 expired->reuseable_valid_lft_ = 0;
1759 expired->cltt_ = time(NULL);
1760 expired->subnet_id_ = ctx.subnet_->getID();
1761 expired->hostname_ = ctx.hostname_;
1762 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1763 expired->fqdn_rev_ = ctx.rev_dns_update_;
1764 expired->prefixlen_ = prefix_len;
1769 .arg(ctx.query_->getLabel())
1770 .arg(expired->toText());
1773 if (ctx.callout_handle_ &&
1780 ScopedCalloutHandleState callout_handle_state(ctx.callout_handle_);
1783 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
1788 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1791 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1794 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1797 ctx.callout_handle_->setArgument(
"lease6", expired);
1802 callout_status = ctx.callout_handle_->getStatus();
1819 ctx.callout_handle_->getArgument(
"lease6", expired);
1822 if (!ctx.fake_allocation_) {
1826 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1828 expired->pool_id_ = pool->getID();
1836 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1840 "assigned-nas" :
"assigned-pds"),
1841 static_cast<int64_t
>(1));
1846 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1847 static_cast<int64_t
>(1));
1853 "pool" :
"pd-pool", pool->getID(),
1855 "assigned-nas" :
"assigned-pds")),
1856 static_cast<int64_t
>(1));
1861 "pool" :
"pd-pool", pool->getID(),
1863 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1864 static_cast<int64_t
>(1));
1868 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1869 static_cast<int64_t
>(1));
1888 if (!classes.
empty()) {
1895 for (
auto const& name : classes) {
1898 (cl && (!cl->getPreferred().unspecified()))) {
1899 candidate_preferred = cl->getPreferred();
1904 (cl && (!cl->getValid().unspecified()))) {
1905 candidate_valid = cl->getValid();
1908 if (have_both == 2) {
1915 if (!candidate_preferred) {
1916 candidate_preferred = ctx.
subnet_->getPreferred();
1920 if (!candidate_valid) {
1921 candidate_valid = ctx.
subnet_->getValid();
1925 preferred = candidate_preferred;
1926 valid = candidate_valid;
1941 if (!preferred || preferred > valid) {
1942 preferred = ((valid * 5)/8);
1945 .arg(ctx.
query_->getLabel())
1959 uint32_t preferred = 0;
1964 ctx.currentIA().iaid_, preferred,
1965 valid, ctx.subnet_->getID(),
1966 ctx.hwaddr_, prefix_len));
1968 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1969 lease->fqdn_rev_ = ctx.rev_dns_update_;
1970 lease->hostname_ = ctx.hostname_;
1973 if (ctx.callout_handle_ &&
1988 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1991 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1994 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1997 ctx.callout_handle_->setArgument(
"lease6", lease);
2002 callout_status = ctx.callout_handle_->getStatus();
2014 ctx.callout_handle_->getArgument(
"lease6", lease);
2017 if (!ctx.fake_allocation_) {
2021 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2023 lease->pool_id_ = pool->getID();
2032 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2036 "assigned-nas" :
"assigned-pds"),
2037 static_cast<int64_t
>(1));
2042 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2043 static_cast<int64_t
>(1));
2049 "pool" :
"pd-pool", pool->getID(),
2051 "assigned-nas" :
"assigned-pds")),
2052 static_cast<int64_t
>(1));
2057 "pool" :
"pd-pool", pool->getID(),
2059 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2060 static_cast<int64_t
>(1));
2064 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2065 static_cast<int64_t
>(1));
2069 ctx.currentIA().addNewResource(addr, prefix_len);
2108 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2110 subnet = subnet->getNextSubnet(ctx.
subnet_);
2113 if (!leases.empty()) {
2116 .arg(ctx.
query_->getLabel());
2120 removeNonmatchingReservedLeases6(ctx, leases);
2123 if (!ctx.
hosts_.empty()) {
2127 .arg(ctx.
query_->getLabel());
2130 allocateReservedLeases6(ctx, leases);
2136 removeNonreservedLeases6(ctx, leases);
2143 if (leases.empty()) {
2147 .arg(ctx.
query_->getLabel());
2149 leases = allocateUnreservedLeases6(ctx);
2153 for (
auto const& l : leases) {
2161 .arg(ctx.
query_->getLabel())
2162 .arg(l->typeToText(l->type_))
2164 extendLease6(ctx, l);
2167 if (!leases.empty()) {
2171 for (
auto const& lease : leases) {
2186 .arg(ctx.
query_->getLabel())
2196 if (!lease || !ctx.subnet_) {
2202 if (ctx.subnet_->getID() != lease->subnet_id_) {
2204 ctx.subnet_->getSharedNetwork(network);
2210 ctx.subnet_ = subnet;
2218 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2219 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2236 "assigned-nas" :
"assigned-pds"),
2237 static_cast<int64_t
>(-1));
2239 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2244 "pool" :
"pd-pool", pool->getID(),
2246 "assigned-nas" :
"assigned-pds")),
2247 static_cast<int64_t
>(-1));
2251 ctx.currentIA().old_leases_.push_back(lease);
2258 .arg(ctx.query_->getLabel())
2259 .arg(lease->toText());
2264 bool changed =
false;
2267 uint32_t current_preferred_lft = lease->preferred_lft_;
2268 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2271 if ((lease->preferred_lft_ != current_preferred_lft) ||
2272 (lease->valid_lft_ != lease->current_valid_lft_)) {
2276 lease->cltt_ = time(NULL);
2277 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2278 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2279 (lease->hostname_ != ctx.hostname_)) {
2281 lease->hostname_ = ctx.hostname_;
2282 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2283 lease->fqdn_rev_ = ctx.rev_dns_update_;
2285 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2287 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2289 lease->hwaddr_ = ctx.hwaddr_;
2297 .arg(ctx.query_->getLabel())
2298 .arg(lease->toText());
2302 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2303 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2311 ScopedCalloutHandleState callout_handle_state(callout_handle);
2314 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
2317 callout_handle->setArgument(
"query6", ctx.query_);
2320 callout_handle->setArgument(
"lease6", lease);
2324 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2326 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2339 .arg(ctx.query_->getName());
2346 bool update_stats =
false;
2350 if (old_data->expired()) {
2351 reclaimExpiredLease(old_data, ctx.callout_handle_);
2355 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2356 update_stats =
true;
2369 setLeaseReusable(lease, current_preferred_lft, ctx);
2374 if (lease->reuseable_valid_lft_ == 0) {
2375 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2377 lease->pool_id_ = pool->getID();
2386 "assigned-nas" :
"assigned-pds"),
2387 static_cast<int64_t
>(1));
2392 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2393 static_cast<int64_t
>(1));
2395 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2400 "pool" :
"pd-pool", pool->getID(),
2402 "assigned-nas" :
"assigned-pds")),
2403 static_cast<int64_t
>(1));
2408 "pool" :
"pd-pool", pool->getID(),
2410 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2411 static_cast<int64_t
>(1));
2415 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2416 static_cast<int64_t
>(1));
2429 ctx.currentIA().changed_leases_.push_back(old_data);
2435 for (
auto const& lease_it : leases) {
2437 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2439 updated_leases.push_back(lease);
2443 lease->reuseable_valid_lft_ = 0;
2444 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2445 lease->fqdn_rev_ = ctx.rev_dns_update_;
2446 lease->hostname_ = ctx.hostname_;
2447 uint32_t current_preferred_lft = lease->preferred_lft_;
2448 if (lease->valid_lft_ == 0) {
2450 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2452 if (!ctx.fake_allocation_) {
2453 bool update_stats =
false;
2461 if (inAllowedPool(ctx, ctx.currentIA().type_,
2462 lease->addr_,
true)) {
2463 update_stats =
true;
2468 !(lease->hasIdenticalFqdn(*lease_it)));
2470 lease->cltt_ = time(NULL);
2471 if (!fqdn_changed) {
2472 setLeaseReusable(lease, current_preferred_lft, ctx);
2474 if (lease->reuseable_valid_lft_ == 0) {
2475 ctx.currentIA().changed_leases_.push_back(lease_it);
2483 "assigned-nas" :
"assigned-pds"),
2484 static_cast<int64_t
>(1));
2489 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2490 static_cast<int64_t
>(1));
2492 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2497 "pool" :
"pd-pool", pool->getID(),
2499 "assigned-nas" :
"assigned-pds")),
2500 static_cast<int64_t
>(1));
2505 "pool" :
"pd-pool", pool->getID(),
2507 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2508 static_cast<int64_t
>(1));
2512 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2513 static_cast<int64_t
>(1));
2517 updated_leases.push_back(lease);
2520 return (updated_leases);
2525 const uint16_t timeout,
2526 const bool remove_lease,
2527 const uint16_t max_unwarned_cycles) {
2536 max_unwarned_cycles);
2537 }
catch (
const std::exception& ex) {
2546 const uint16_t timeout,
2547 const bool remove_lease,
2548 const uint16_t max_unwarned_cycles) {
2558 bool incomplete_reclamation =
false;
2561 if (max_leases > 0) {
2570 if (leases.size() > max_leases) {
2572 incomplete_reclamation =
true;
2585 if (!leases.empty() &&
2590 size_t leases_processed = 0;
2591 for (
auto const& lease : leases) {
2599 reclaimExpiredLease(lease, remove_lease, callout_handle);
2602 reclaimExpiredLease(lease, remove_lease, callout_handle);
2606 }
catch (
const std::exception& ex) {
2608 .arg(lease->addr_.toText())
2619 if (!incomplete_reclamation) {
2620 if (leases_processed < leases.size()) {
2621 incomplete_reclamation =
true;
2638 .arg(leases_processed)
2643 if (incomplete_reclamation) {
2644 ++incomplete_v6_reclamations_;
2647 if ((max_unwarned_cycles > 0) &&
2648 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2650 .arg(max_unwarned_cycles);
2652 incomplete_v6_reclamations_ = 0;
2657 incomplete_v6_reclamations_ = 0;
2670 uint64_t deleted_leases = 0;
2676 }
catch (
const std::exception& ex) {
2683 .arg(deleted_leases);
2688 const uint16_t timeout,
2689 const bool remove_lease,
2690 const uint16_t max_unwarned_cycles) {
2699 max_unwarned_cycles);
2700 }
catch (
const std::exception& ex) {
2709 const uint16_t timeout,
2710 const bool remove_lease,
2711 const uint16_t max_unwarned_cycles) {
2721 bool incomplete_reclamation =
false;
2724 if (max_leases > 0) {
2733 if (leases.size() > max_leases) {
2735 incomplete_reclamation =
true;
2748 if (!leases.empty() &&
2753 size_t leases_processed = 0;
2754 for (
auto const& lease : leases) {
2762 reclaimExpiredLease(lease, remove_lease, callout_handle);
2765 reclaimExpiredLease(lease, remove_lease, callout_handle);
2769 }
catch (
const std::exception& ex) {
2771 .arg(lease->addr_.toText())
2782 if (!incomplete_reclamation) {
2783 if (leases_processed < leases.size()) {
2784 incomplete_reclamation =
true;
2801 .arg(leases_processed)
2806 if (incomplete_reclamation) {
2807 ++incomplete_v4_reclamations_;
2810 if ((max_unwarned_cycles > 0) &&
2811 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2813 .arg(max_unwarned_cycles);
2815 incomplete_v4_reclamations_ = 0;
2820 incomplete_v4_reclamations_ = 0;
2827template<
typename LeasePtrType>
2829AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2831 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2835template<
typename LeasePtrType>
2837AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2842 if (!lease->stateExpiredReclaimed()) {
2843 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2848AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2849 const DbReclaimMode& reclaim_mode,
2855 .arg(lease->addr_.toText())
2856 .arg(
static_cast<int>(lease->prefixlen_));
2862 bool skipped =
false;
2863 if (callout_handle) {
2869 ScopedCalloutHandleState callout_handle_state(callout_handle);
2871 callout_handle->deleteAllArguments();
2872 callout_handle->setArgument(
"lease6", lease);
2873 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2893 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2903 remove_lease = reclaimDeclined(lease);
2906 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2910 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2912 &lease_mgr, ph::_1));
2924 static_cast<int64_t
>(-1));
2928 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2934 static_cast<int64_t
>(-1));
2939 "reclaimed-leases")),
2940 static_cast<int64_t
>(1));
2949 static_cast<int64_t
>(-1));
2953 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2959 static_cast<int64_t
>(-1));
2964 "reclaimed-leases")),
2965 static_cast<int64_t
>(1));
2973 "reclaimed-leases"),
2974 static_cast<int64_t
>(1));
2981AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2982 const DbReclaimMode& reclaim_mode,
2988 .arg(lease->addr_.toText());
2994 bool skipped =
false;
2995 if (callout_handle) {
3001 ScopedCalloutHandleState callout_handle_state(callout_handle);
3003 callout_handle->setArgument(
"lease4", lease);
3004 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3022 lease->hostname_.clear();
3023 lease->fqdn_fwd_ =
false;
3024 lease->fqdn_rev_ =
false;
3028 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3038 remove_lease = reclaimDeclined(lease);
3041 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3045 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3047 &lease_mgr, ph::_1));
3056 "assigned-addresses"),
3057 static_cast<int64_t
>(-1));
3062 "reclaimed-leases"),
3063 static_cast<int64_t
>(1));
3067 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3072 "assigned-addresses")),
3073 static_cast<int64_t
>(-1));
3078 "reclaimed-leases")),
3079 static_cast<int64_t
>(1));
3093 uint64_t deleted_leases = 0;
3099 }
catch (
const std::exception& ex) {
3106 .arg(deleted_leases);
3110AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3125 callout_handle->setArgument(
"lease4", lease);
3135 .arg(lease->addr_.toText());
3141 .arg(lease->addr_.toText())
3142 .arg(lease->valid_lft_);
3148 "declined-addresses"),
3149 static_cast<int64_t
>(-1));
3152 "reclaimed-declined-addresses"),
3153 static_cast<int64_t
>(1));
3157 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3161 "declined-addresses")),
3162 static_cast<int64_t
>(-1));
3166 "reclaimed-declined-addresses")),
3167 static_cast<int64_t
>(1));
3172 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3174 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3182AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3194 ScopedCalloutHandleState callout_handle_state(callout_handle);
3197 callout_handle->setArgument(
"lease6", lease);
3207 .arg(lease->addr_.toText());
3213 .arg(lease->addr_.toText())
3214 .arg(lease->valid_lft_);
3220 "declined-addresses"),
3221 static_cast<int64_t
>(-1));
3224 "reclaimed-declined-addresses"),
3225 static_cast<int64_t
>(1));
3229 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3233 "declined-addresses")),
3234 static_cast<int64_t
>(-1));
3238 "reclaimed-declined-addresses")),
3239 static_cast<int64_t
>(1));
3244 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3246 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3256 lease->relay_id_.clear();
3257 lease->remote_id_.clear();
3258 if (lease->getContext()) {
3265 if (lease->getContext()) {
3271template<
typename LeasePtrType>
3272void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3273 const bool remove_lease,
3274 const std::function<
void (
const LeasePtrType&)>&
3275 lease_update_fun)
const {
3283 }
else if (lease_update_fun) {
3286 lease->reuseable_valid_lft_ = 0;
3287 lease->hostname_.clear();
3288 lease->fqdn_fwd_ =
false;
3289 lease->fqdn_rev_ =
false;
3292 lease_update_fun(lease);
3301 .arg(lease->addr_.toText());
3307 return(
"<empty subnet>");
3311 subnet->getSharedNetwork(network);
3312 std::ostringstream ss;
3314 ss <<
"shared-network: " << network->getName();
3316 ss <<
"subnet id: " << subnet->getID();
3355 (!ctx.
subnet_->getReservationsOutOfPool() ||
3366 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3371 hosts.push_back(host);
3385 for (
auto const& host : hosts) {
3389 if (id_pair.first == host->getIdentifierType() &&
3390 id_pair.second == host->getIdentifier()) {
3398 return (!hosts.empty());
3420 if (ctx.
hosts_.empty()) {
3425 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3426 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3427 global_host->second->getIPv4Reservation() :
3436 if (subnet->getReservationsGlobal() &&
3438 (subnet->inRange(global_host_address))) {
3443 if (subnet->getReservationsInSubnet()) {
3444 auto host = ctx.
hosts_.find(subnet->getID());
3449 if (host != ctx.
hosts_.end() && host->second) {
3450 auto reservation = host->second->getIPv4Reservation();
3451 if (!reservation.isV4Zero() &&
3452 (!subnet->getReservationsOutOfPool() ||
3462 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3468 .arg(ctx.
query_->getLabel())
3469 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3496 auto const& classes = ctx.
query_->getClasses();
3500 bool try_clientid_lookup = (ctx.
clientid_ &&
3504 if (try_clientid_lookup) {
3512 for (
Subnet4Ptr subnet = original_subnet; subnet;
3513 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3518 if (subnet->getMatchClientId()) {
3519 for (
auto const& l : leases_client_id) {
3520 if (l->subnet_id_ == subnet->getID()) {
3533 if (!client_lease && ctx.
hwaddr_) {
3538 for (
Subnet4Ptr subnet = original_subnet; subnet;
3539 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3541 if (subnet->getMatchClientId()) {
3547 for (
auto const& client_lease_it : leases_hw_address) {
3548 Lease4Ptr existing_lease = client_lease_it;
3549 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3550 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3552 client_lease = existing_lease;
3580 auto const& classes = ctx.
query_->getClasses();
3582 while (current_subnet) {
3591 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3618 const bool fwd_dns_update,
3619 const bool rev_dns_update,
3620 const std::string& hostname,
3621 const bool fake_allocation,
3622 const uint32_t offer_lft)
3642 if (host !=
hosts_.cend()) {
3643 return (host->second);
3653 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
3654 if (host !=
hosts_.cend()) {
3655 return (host->second);
3665 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
3666 return (ddns_params_);
3672 return (ddns_params_);
3694 auto const& classes = ctx.
query_->getClasses();
3695 if (subnet && !subnet->clientSupported(classes)) {
3696 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3720 .arg(ctx.
query_->getLabel())
3738 !subnet->getReservationsInSubnet()) {
3744 subnet->getReservationsGlobal()) {
3747 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3750 if (!subnet->getReservationsInSubnet()) {
3756 std::map<SubnetID, ConstHostPtr> host_map;
3758 subnet->getSharedNetwork(network);
3767 const bool use_single_query = network &&
3771 if (use_single_query) {
3775 id_pair.second.size());
3779 for (
auto const& host : hosts) {
3780 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3781 host_map[host->getIPv4SubnetID()] = host;
3787 auto const& classes = ctx.
query_->getClasses();
3793 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3796 if (use_single_query) {
3797 if (host_map.count(subnet->getID()) > 0) {
3798 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3806 id_pair.second.size());
3809 ctx.
hosts_[subnet->getID()] = host;
3819 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3825 for (
auto const& host : ctx.
hosts_) {
3826 host.second->encapsulateOptions();
3836 &id_pair.second[0], id_pair.second.size());
3853 findClientLease(ctx, client_lease);
3866 if (hasAddressReservation(ctx)) {
3870 .arg(ctx.
query_->getLabel())
3871 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3877 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3884 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3888 .arg(ctx.
query_->getLabel())
3889 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3894 "v4-reservation-conflicts"),
3895 static_cast<int64_t
>(1));
3897 static_cast<int64_t
>(1));
3901 new_lease = renewLease4(client_lease, ctx);
3914 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3915 !addressReserved(client_lease->addr_, ctx)) {
3919 .arg(ctx.
query_->getLabel());
3925 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3929 new_lease = renewLease4(client_lease, ctx);
3946 .arg(ctx.
query_->getLabel());
3959 .arg(ctx.
query_->getLabel());
3961 new_lease = allocateUnreservedLease4(ctx);
3976AllocEngine::requestLease4(AllocEngine::ClientContext4& ctx) {
3981 findClientLease(ctx, client_lease);
3997 .arg(ctx.
query_->getLabel())
4003 }
else if (hasAddressReservation(ctx)) {
4012 .arg(ctx.
query_->getLabel())
4024 if (existing && !existing->expired() &&
4025 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4030 .arg(ctx.
query_->getLabel())
4040 if (hasAddressReservation(ctx) &&
4048 if (!existing || existing->expired()) {
4052 .arg(ctx.
query_->getLabel())
4053 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4063 if ((!hasAddressReservation(ctx) ||
4069 .arg(ctx.
query_->getLabel())
4089 ((hasAddressReservation(ctx) &&
4091 inAllowedPool(ctx, client_lease->addr_))) {
4095 .arg(ctx.
query_->getLabel())
4098 return (renewLease4(client_lease, ctx));
4112 .arg(ctx.
query_->getLabel())
4128 .arg(ctx.
query_->getLabel());
4133 new_lease = allocateUnreservedLease4(ctx);
4139 if (new_lease && client_lease) {
4144 .arg(ctx.
query_->getLabel())
4145 .arg(client_lease->addr_.toText());
4151 "assigned-addresses"),
4152 static_cast<int64_t
>(-1));
4156 auto const& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4161 "assigned-addresses")),
4162 static_cast<int64_t
>(-1));
4185 if (!classes.
empty()) {
4191 for (
auto const& name : classes) {
4193 if (cl && (!cl->getOfferLft().unspecified())) {
4194 offer_lft = cl->getOfferLft();
4202 offer_lft = ctx.
subnet_->getOfferLft();
4211 if (ctx.
query_->inClass(
"BOOTP")) {
4216 uint32_t requested_lft = 0;
4219 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4221 requested_lft = opt_lft->getValue();
4229 if (!classes.
empty()) {
4235 for (
auto const& name : classes) {
4237 if (cl && (!cl->getValid().unspecified())) {
4238 candidate_lft = cl->getValid();
4245 if (!candidate_lft) {
4246 candidate_lft = ctx.
subnet_->getValid();
4251 if (requested_lft > 0) {
4252 return (candidate_lft.
get(requested_lft));
4256 return (candidate_lft.
get());
4260AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4270 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4272 time_t now = time(NULL);
4275 if (ctx.subnet_->getMatchClientId()) {
4276 client_id = ctx.clientid_;
4279 Lease4Ptr lease(
new Lease4(addr, ctx.hwaddr_, client_id,
4280 valid_lft, now, ctx.subnet_->getID()));
4283 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4284 lease->fqdn_rev_ = ctx.rev_dns_update_;
4285 lease->hostname_ = ctx.hostname_;
4291 if (ctx.callout_handle_ &&
4298 ScopedCalloutHandleState callout_handle_state(ctx.callout_handle_);
4301 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.query_);
4305 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4311 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4312 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4315 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4318 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4321 ctx.callout_handle_->setArgument(
"lease4", lease);
4326 callout_status = ctx.callout_handle_->getStatus();
4338 ctx.callout_handle_->getArgument(
"lease4", lease);
4341 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4345 lease->fqdn_fwd_ =
false;
4346 lease->fqdn_rev_ =
false;
4349 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4350 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4352 lease->pool_id_ = pool->getID();
4361 "assigned-addresses"),
4362 static_cast<int64_t
>(1));
4366 "cumulative-assigned-addresses"),
4367 static_cast<int64_t
>(1));
4373 "assigned-addresses")),
4374 static_cast<int64_t
>(1));
4379 "cumulative-assigned-addresses")),
4380 static_cast<int64_t
>(1));
4384 static_cast<int64_t
>(1));
4403AllocEngine::renewLease4(
const Lease4Ptr& lease,
4404 AllocEngine::ClientContext4& ctx) {
4406 isc_throw(BadValue,
"null lease specified for renewLease4");
4413 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4414 ctx.
old_lease_.reset(
new Lease4(*old_values));
4418 lease->reuseable_valid_lft_ = 0;
4419 if (!updateLease4Information(lease, ctx)) {
4420 setLeaseReusable(lease, ctx);
4445 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4460 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4486 lease->pool_id_ = pool->getID();
4496 "assigned-addresses"),
4497 static_cast<int64_t
>(1));
4501 "cumulative-assigned-addresses"),
4502 static_cast<int64_t
>(1));
4508 "assigned-addresses")),
4509 static_cast<int64_t
>(1));
4514 "cumulative-assigned-addresses")),
4515 static_cast<int64_t
>(1));
4519 static_cast<int64_t
>(1));
4525 *lease = *old_values;
4532AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4533 AllocEngine::ClientContext4& ctx,
4536 isc_throw(BadValue,
"null lease specified for reuseExpiredLease");
4540 isc_throw(BadValue,
"null subnet specified for the reuseExpiredLease");
4551 expired->reuseable_valid_lft_ = 0;
4552 static_cast<void>(updateLease4Information(expired, ctx));
4556 .arg(ctx.
query_->getLabel())
4557 .arg(expired->toText());
4564 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4614 expired->pool_id_ = pool->getID();
4622 "assigned-addresses"),
4623 static_cast<int64_t
>(1));
4627 "cumulative-assigned-addresses"),
4628 static_cast<int64_t
>(1));
4634 "assigned-addresses")),
4635 static_cast<int64_t
>(1));
4640 "cumulative-assigned-addresses")),
4641 static_cast<int64_t
>(1));
4645 static_cast<int64_t
>(1));
4657AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate,
ClientContext4& ctx,
4659 ctx.conflicting_lease_.reset();
4663 if (exist_lease->expired()) {
4664 ctx.old_lease_ =
Lease4Ptr(
new Lease4(*exist_lease));
4668 ctx.old_lease_->hostname_.clear();
4669 ctx.old_lease_->fqdn_fwd_ =
false;
4670 ctx.old_lease_->fqdn_rev_ =
false;
4671 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4677 ctx.conflicting_lease_ = exist_lease;
4681 return (createLease4(ctx, candidate, callout_status));
4701 ctx.subnet_->getSharedNetwork(network);
4708 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4722 uint64_t subnets_with_unavail_leases = 0;
4725 uint64_t subnets_with_unavail_pools = 0;
4727 auto const& classes = ctx.query_->getClasses();
4731 if (subnet->getMatchClientId()) {
4732 client_id = ctx.clientid_;
4744 (attempts_ == 0 || possible_attempts < attempts_) ?
4748 if (max_attempts > 0) {
4751 ++subnets_with_unavail_leases;
4755 ++subnets_with_unavail_pools;
4758 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4763 for (
uint128_t i = 0; i < max_attempts; ++i) {
4768 IOAddress candidate = allocator->pickAddress(classes,
4770 ctx.requested_address_);
4777 if (exclude_first_last_24) {
4779 auto const& bytes = candidate.
toBytes();
4780 if ((bytes.size() != 4) ||
4781 (bytes[3] == 0) || (bytes[3] == 255U)) {
4788 if (check_reservation_first && addressReserved(candidate, ctx)) {
4795 ResourceHandler4 resource_handler;
4797 !resource_handler.
tryLock4(candidate)) {
4806 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4808 new_lease = createLease4(ctx, candidate, callout_status);
4812 if (exist_lease->expired() &&
4813 (check_reservation_first || !addressReserved(candidate, ctx))) {
4814 ctx.old_lease_ =
Lease4Ptr(
new Lease4(*exist_lease));
4815 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4833 subnet = subnet->getNextSubnet(original_subnet, classes);
4836 ctx.subnet_ = subnet;
4845 .arg(ctx.query_->getLabel())
4846 .arg(network->getName())
4847 .arg(subnets_with_unavail_leases)
4848 .arg(subnets_with_unavail_pools);
4850 static_cast<int64_t
>(1));
4853 "v4-allocation-fail-shared-network"),
4854 static_cast<int64_t
>(1));
4858 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4859 if (shared_network.empty()) {
4860 shared_network =
"(none)";
4863 .arg(ctx.query_->getLabel())
4864 .arg(ctx.subnet_->toText())
4865 .arg(ctx.subnet_->getID())
4866 .arg(shared_network);
4868 static_cast<int64_t
>(1));
4871 "v4-allocation-fail-subnet"),
4872 static_cast<int64_t
>(1));
4874 if (total_attempts == 0) {
4880 .arg(ctx.query_->getLabel());
4882 static_cast<int64_t
>(1));
4885 "v4-allocation-fail-no-pools"),
4886 static_cast<int64_t
>(1));
4893 .arg(ctx.query_->getLabel())
4894 .arg(total_attempts);
4896 static_cast<int64_t
>(1));
4899 "v4-allocation-fail"),
4900 static_cast<int64_t
>(1));
4903 if (!classes.empty()) {
4905 .arg(ctx.query_->getLabel())
4906 .arg(classes.toText());
4908 static_cast<int64_t
>(1));
4911 "v4-allocation-fail-classes"),
4912 static_cast<int64_t
>(1));
4919AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4920 AllocEngine::ClientContext4& ctx)
const {
4921 bool changed =
false;
4922 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4924 lease->subnet_id_ = ctx.
subnet_->getID();
4926 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4928 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4933 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4937 }
else if (lease->client_id_) {
4941 lease->cltt_ = time(NULL);
4947 if (lease->valid_lft_ != lease->current_valid_lft_) {
4971 bool changed =
false;
4974 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4989 sao->boolValue() && ctx.
query_->inClass(
"STASH_AGENT_OPTIONS")) {
4998 extended_info->set(
"sub-options", relay_agent);
5002 std::vector<uint8_t> bytes = remote_id->toBinary();
5003 lease->remote_id_ = bytes;
5004 if (bytes.size() > 0) {
5005 extended_info->set(
"remote-id",
5012 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5013 lease->relay_id_ = bytes;
5014 if (bytes.size() > 0) {
5015 extended_info->set(
"relay-id",
5023 if (user_context && (user_context->getType() ==
Element::map)) {
5024 mutable_user_context =
copy(user_context, 0);
5039 ConstElementPtr old_extended_info = mutable_isc->get(
"relay-agent-info");
5040 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5042 mutable_isc->set(
"relay-agent-info", extended_info);
5043 mutable_user_context->set(
"ISC", mutable_isc);
5047 lease->setContext(mutable_user_context);
5059 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5064 if (ctx.
query_->relay_info_.empty()) {
5079 for (
auto const& relay : ctx.
query_->relay_info_) {
5088 if (!relay.options_.empty()) {
5093 const uint8_t* cp = buf.
getData();
5094 std::vector<uint8_t> bytes;
5095 std::stringstream ss;
5103 if (remote_id_it != relay.options_.end()) {
5104 OptionPtr remote_id = remote_id_it->second;
5106 std::vector<uint8_t> bytes = remote_id->toBinary();
5107 if (bytes.size() > 0) {
5108 relay_elem->set(
"remote-id",
5115 if (relay_id_it != relay.options_.end()) {
5116 OptionPtr relay_id = relay_id_it->second;
5118 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5119 if (bytes.size() > 0) {
5120 relay_elem->set(
"relay-id",
5127 extended_info->add(relay_elem);
5133 if (user_context && (user_context->getType() ==
Element::map)) {
5134 mutable_user_context =
copy(user_context, 0);
5150 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5152 mutable_isc->set(
"relay-info", extended_info);
5153 mutable_user_context->set(
"ISC", mutable_isc);
5157 lease->setContext(mutable_user_context);
5161AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5162 const ClientContext4& ctx)
const {
5164 lease->reuseable_valid_lft_ = 0;
5180 if (lease->cltt_ < lease->current_cltt_) {
5184 uint32_t age = lease->cltt_ - lease->current_cltt_;
5186 if (age >= lease->current_valid_lft_) {
5191 uint32_t max_age = 0;
5192 if (!subnet->getCacheMaxAge().unspecified()) {
5193 max_age = subnet->getCacheMaxAge().get();
5194 if ((max_age == 0) || (age > max_age)) {
5200 if (!subnet->getCacheThreshold().unspecified()) {
5201 double threshold = subnet->getCacheThreshold().get();
5202 if ((threshold <= 0.) || (threshold > 1.)) {
5205 max_age = lease->valid_lft_ * threshold;
5206 if (age > max_age) {
5217 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5221AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5222 uint32_t current_preferred_lft,
5225 lease->reuseable_valid_lft_ = 0;
5226 lease->reuseable_preferred_lft_ = 0;
5236 if (lease->cltt_ < lease->current_cltt_) {
5240 uint32_t age = lease->cltt_ - lease->current_cltt_;
5242 if (age >= lease->current_valid_lft_) {
5247 uint32_t max_age = 0;
5248 if (!subnet->getCacheMaxAge().unspecified()) {
5249 max_age = subnet->getCacheMaxAge().get();
5250 if ((max_age == 0) || (age > max_age)) {
5256 if (!subnet->getCacheThreshold().unspecified()) {
5257 double threshold = subnet->getCacheThreshold().get();
5258 if ((threshold <= 0.) || (threshold > 1.)) {
5261 max_age = lease->valid_lft_ * threshold;
5262 if (age > max_age) {
5274 (current_preferred_lft == 0)) {
5276 lease->reuseable_preferred_lft_ = current_preferred_lft;
5277 }
else if (current_preferred_lft > age) {
5278 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5286 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.
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
std::string toText() const
Convert the address to a string.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
bool isV6Zero() const
Convenience function to check if it is an IPv4 zero address.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
static ElementPtr create(const Position &pos=ZERO_POSITION())
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.
Multiple lease records found where one expected.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
void updateLease6ExtendedInfo(const Lease6Ptr &lease, const ClientContext6 &ctx) const
Stores additional client query parameters on a V6 lease.
void reclaimExpiredLeases6Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases6.
bool updateLease4ExtendedInfo(const Lease4Ptr &lease, const ClientContext4 &ctx) const
Stores additional client query parameters on a V4 lease.
static uint32_t getOfferLft(const ClientContext4 &ctx)
Returns the offer lifetime based on the v4 context.
static std::string labelNetworkOrSubnet(SubnetPtr subnet)
Generates a label for subnet or shared-network from subnet.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
AllocEngine(isc::util::uint128_t const &attempts)
Constructor.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
void clearReclaimedExtendedInfo(const Lease4Ptr &lease) const
Clear extended info from a reclaimed V4 lease.
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)
void reclaimExpiredLeases4Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases4.
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.
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.
PrefixLenMatchType
Type of preferred PD-pool prefix length selection criteria.
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length.
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.
bool empty() const
Check if classes is empty.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
ConstHostCollection getAll6(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv6 subnet.
ConstHostCollection getAll4(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv4 subnet.
ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) 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.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv4 subnet.
ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv6 subnet.
IPv6 reservation for a host.
Type
Type of the reservation.
static TrackingLeaseMgr & 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.
Attempt to update lease that was not there.
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.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
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.
@ NEXT_STEP_CONTINUE
continue normally
@ NEXT_STEP_SKIP
skip the next processing step
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static boost::shared_ptr< CalloutHandle > createCalloutHandle()
Return callout handle.
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Wrapper class around callout handle which automatically resets handle's state.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
bool getMode() const
Get the multi-threading mode.
A template representing an optional value.
T get() const
Retrieves the encapsulated value.
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.
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
size_t getLength() const
Return the length of data written 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.
This template specifies a parameter value.
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 ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6
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_IGNORING_UNSUITABLE_GLOBAL_ADDRESS
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.
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 DHCPSRV_CFGMGR_IP_RESERVATIONS_UNIQUE_DUPLICATES_DETECTED
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
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_LEASES_RECLAMATION_FAILED
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_V4_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_CALCULATED_PREFERRED_LIFETIME
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_UNRESERVED
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 format.
boost::multiprecision::checked_uint128_t uint128_t
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 ...
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.
uint32_t offer_lft_
If not zero, then we will allocate on DISCOVER for this amount of time.
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.
Lease6Collection old_leases_
A pointer to any old leases that the client had before update but are no longer valid after the updat...
Option6IAPtr ia_rsp_
A pointer to the IA_NA/IA_PD option to be sent in response.
Lease::Type type_
Lease type (IA or PD)
ResourceContainer new_resources_
Holds addresses and prefixes allocated for this IA.
bool isNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was new.
Lease6Collection changed_leases_
A pointer to any leases that have changed FQDN information.
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.
std::vector< IAContext > ias_
Container holding IA specific contexts.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
bool fake_allocation_
Indicates if this is a real or fake allocation.
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.
HWAddrPtr hwaddr_
Hardware/MAC address (if available, may be NULL)
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
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.
bool rev_dns_update_
A boolean value which indicates that server takes responsibility for the reverse DNS Update for this ...
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.
std::string hostname_
Hostname.
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.
bool fwd_dns_update_
A boolean value which indicates that server takes responsibility for the forward DNS Update for this ...
Structure that holds a lease for IPv6 address and/or prefix.
@ ACTION_UPDATE
update extended info tables.
@ ACTION_DELETE
delete reference to the lease
@ ACTION_IGNORE
ignore extended info,
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_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address