35#include <boost/foreach.hpp>
36#include <boost/make_shared.hpp>
53namespace ph = std::placeholders;
58struct AllocEngineHooks {
59 int hook_index_lease4_select_;
60 int hook_index_lease4_renew_;
61 int hook_index_lease4_expire_;
62 int hook_index_lease4_recover_;
63 int hook_index_lease6_select_;
64 int hook_index_lease6_renew_;
65 int hook_index_lease6_rebind_;
66 int hook_index_lease6_expire_;
67 int hook_index_lease6_recover_;
87AllocEngineHooks
Hooks;
95 : attempts_(attempts), incomplete_v4_reclamations_(0),
96 incomplete_v6_reclamations_(0) {
99 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
100 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
127 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
132 reserved.push_back(host);
143 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
162 const IOAddress& address,
bool check_subnet) {
166 auto const& classes = ctx.
query_->getClasses();
168 while (current_subnet) {
169 if (current_subnet->clientSupported(classes)) {
171 if (current_subnet->inPool(lease_type, address)) {
175 if (current_subnet->inPool(lease_type, address, classes)) {
181 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
197 : query_(), fake_allocation_(false),
198 early_global_reservations_lookup_(false), subnet_(), host_subnet_(),
199 duid_(), hwaddr_(), host_identifiers_(), hosts_(),
200 fwd_dns_update_(false), rev_dns_update_(false), hostname_(),
201 callout_handle_(), ias_(), ddns_params_() {
208 const std::string& hostname,
209 const bool fake_allocation,
212 : query_(query), fake_allocation_(fake_allocation),
213 early_global_reservations_lookup_(false), subnet_(subnet),
214 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
215 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
216 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
217 ias_(), ddns_params_() {
226 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
227 changed_leases_(),reused_leases_(), new_resources_(), ia_rsp_() {
233 const uint8_t prefix_len,
234 const uint32_t preferred,
235 const uint32_t valid) {
236 hints_.push_back(
Resource(prefix, prefix_len, preferred, valid));
245 addHint(iaaddr->getAddress(), 128,
246 iaaddr->getPreferred(), iaaddr->getValid());
255 addHint(iaprefix->getAddress(), iaprefix->getLength(),
256 iaprefix->getPreferred(), iaprefix->getValid());
262 const uint8_t prefix_len) {
263 static_cast<void>(new_resources_.insert(
Resource(prefix, prefix_len)));
269 const uint8_t prefix_len)
const {
270 return (
static_cast<bool>(new_resources_.count(
Resource(prefix,
277 const uint8_t prefix_len) {
285 return (
static_cast<bool>
292 if (subnet && subnet->getReservationsInSubnet()) {
293 auto host =
hosts_.find(subnet->getID());
294 if (host !=
hosts_.cend()) {
295 return (host->second);
305 if (subnet &&
subnet_->getReservationsGlobal()) {
306 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
307 if (host !=
hosts_.cend()) {
308 return (host->second);
318 return (ghost && ghost->hasReservation(resv));
324 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
325 return (ddns_params_);
331 return (ddns_params_);
350 !subnet->getReservationsInSubnet()) {
356 subnet->getReservationsGlobal()) {
359 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
362 if (!subnet->getReservationsInSubnet()) {
368 std::map<SubnetID, ConstHostPtr> host_map;
370 subnet->getSharedNetwork(network);
379 const bool use_single_query = network &&
383 if (use_single_query) {
387 id_pair.second.size());
391 for (
auto const& host : hosts) {
392 if (host->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
393 host_map[host->getIPv6SubnetID()] = host;
399 auto const& classes = ctx.
query_->getClasses();
406 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
409 if (use_single_query) {
410 if (host_map.count(subnet->getID()) > 0) {
411 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
419 id_pair.second.size());
422 ctx.
hosts_[subnet->getID()] = host;
432 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
438 for (
auto const& host : ctx.
hosts_) {
439 host.second->encapsulateOptions();
449 &id_pair.second[0], id_pair.second.size());
483 for (
auto const& l : all_leases) {
484 if ((l)->subnet_id_ == subnet->getID()) {
489 subnet = subnet->getNextSubnet(ctx.
subnet_);
509 if (leases.empty() && !ctx.
hosts_.empty()) {
513 .arg(ctx.
query_->getLabel());
518 allocateReservedLeases6(ctx, leases);
520 leases = updateLeaseData(ctx, leases);
535 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
539 .arg(ctx.
query_->getLabel());
543 removeNonmatchingReservedLeases6(ctx, leases);
545 leases = updateLeaseData(ctx, leases);
554 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
558 .arg(ctx.
query_->getLabel());
562 allocateReservedLeases6(ctx, leases);
574 removeNonmatchingReservedLeases6(ctx, leases);
583 removeNonreservedLeases6(ctx, leases);
588 leases = updateLeaseData(ctx, leases);
601 if (leases.empty()) {
615 .arg(ctx.
query_->getLabel());
617 leases = allocateUnreservedLeases6(ctx);
620 if (!leases.empty()) {
624 for (
auto const& lease : leases) {
635 .arg(ctx.
query_->getLabel())
648 uint8_t hint_prefix_length = 128;
649 if (!ctx.currentIA().hints_.empty()) {
651 hint = ctx.currentIA().hints_[0].getAddress();
652 hint_prefix_length = ctx.currentIA().hints_[0].getPrefixLength();
661 uint64_t total_attempts = 0;
665 uint64_t subnets_with_unavail_leases = 0;
668 uint64_t subnets_with_unavail_pools = 0;
678 bool search_hint_lease =
true;
685 if (hint_prefix_length == 128) {
686 hint_prefix_length = 0;
688 if (!hint_prefix_length) {
696 Lease6Ptr lease = allocateBestMatch(ctx, hint_lease, search_hint_lease,
697 hint, hint_prefix_length, subnet,
698 network, total_attempts,
699 subnets_with_unavail_leases,
700 subnets_with_unavail_pools,
701 callout_status, prefix_length_match);
709 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
710 hint_prefix_length, subnet, network,
711 total_attempts, subnets_with_unavail_leases,
712 subnets_with_unavail_pools, callout_status,
713 prefix_length_match);
722 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
723 hint_prefix_length, subnet, network,
724 total_attempts, subnets_with_unavail_leases,
725 subnets_with_unavail_pools, callout_status,
726 prefix_length_match);
730 leases.push_back(lease);
734 auto const& classes = ctx.query_->getClasses();
740 .arg(ctx.query_->getLabel())
741 .arg(network->getName())
742 .arg(subnets_with_unavail_leases)
743 .arg(subnets_with_unavail_pools);
745 static_cast<int64_t
>(1));
748 "v6-allocation-fail-shared-network"),
749 static_cast<int64_t
>(1));
753 std::string shared_network = ctx.subnet_->getSharedNetworkName();
754 if (shared_network.empty()) {
755 shared_network =
"(none)";
758 .arg(ctx.query_->getLabel())
759 .arg(ctx.subnet_->toText())
760 .arg(ctx.subnet_->getID())
761 .arg(shared_network);
763 static_cast<int64_t
>(1));
766 "v6-allocation-fail-subnet"),
767 static_cast<int64_t
>(1));
769 if (total_attempts == 0) {
775 .arg(ctx.query_->getLabel());
777 static_cast<int64_t
>(1));
780 "v6-allocation-fail-no-pools"),
781 static_cast<int64_t
>(1));
788 .arg(ctx.query_->getLabel())
789 .arg(total_attempts);
791 static_cast<int64_t
>(1));
794 "v6-allocation-fail"),
795 static_cast<int64_t
>(1));
798 if (!classes.empty()) {
800 .arg(ctx.query_->getLabel())
801 .arg(classes.toText());
803 static_cast<int64_t
>(1));
806 "v6-allocation-fail-classes"),
807 static_cast<int64_t
>(1));
817 bool& search_hint_lease,
819 uint8_t hint_prefix_length,
822 uint64_t& total_attempts,
823 uint64_t& subnets_with_unavail_leases,
824 uint64_t& subnets_with_unavail_pools,
827 auto const& classes = ctx.query_->getClasses();
832 if (!search_hint_lease) {
833 usable_hint_lease = hint_lease;
835 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
836 if (!subnet->clientSupported(classes)) {
840 ctx.subnet_ = subnet;
844 pool = boost::dynamic_pointer_cast<Pool6>
845 (subnet->getPool(ctx.currentIA().type_, classes, hint));
848 if (!pool || !pool->clientSupported(classes)) {
854 hint_prefix_length)) {
858 bool in_subnet = subnet->getReservationsInSubnet();
861 if (search_hint_lease) {
862 search_hint_lease =
false;
864 usable_hint_lease = hint_lease;
866 if (!usable_hint_lease) {
878 (!subnet->getReservationsOutOfPool() ||
879 !subnet->inPool(ctx.currentIA().type_, hint))) {
880 hosts = getIPv6Resrv(subnet->getID(), hint);
890 Lease6Ptr new_lease = createLease6(ctx, hint, pool->getLength(), callout_status);
903 .arg(ctx.query_->getLabel())
907 }
else if (usable_hint_lease->expired()) {
916 (!subnet->getReservationsOutOfPool() ||
917 !subnet->inPool(ctx.currentIA().type_, hint))) {
918 hosts = getIPv6Resrv(subnet->getID(), hint);
927 ctx.currentIA().old_leases_.push_back(old_lease);
930 Lease6Ptr lease = reuseExpiredLease(usable_hint_lease, ctx,
940 .arg(ctx.query_->getLabel())
952 if (!check_reservation_first) {
953 check_reservation_first =
CfgMgr::instance().getCurrentCfg()->getReservationsLookupFirst();
966 original_subnet->getSharedNetwork(network);
973 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
976 ctx.subnet_ = subnet = original_subnet;
978 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
979 if (!subnet->clientSupported(classes)) {
990 subnet->getPoolCapacity(ctx.currentIA().type_,
1001 (attempts_ == 0 || possible_attempts < attempts_) ?
1005 if (max_attempts > 0) {
1008 ++subnets_with_unavail_leases;
1012 ++subnets_with_unavail_pools;
1016 bool in_subnet = subnet->getReservationsInSubnet();
1017 bool out_of_pool = subnet->getReservationsOutOfPool();
1022 if (ctx.callout_handle_) {
1026 for (uint64_t i = 0; i < max_attempts; ++i) {
1029 auto allocator = subnet->getAllocator(ctx.currentIA().type_);
1034 uint8_t prefix_len = 128;
1036 candidate = allocator->pickPrefix(classes, pool, ctx.duid_,
1037 prefix_length_match, hint,
1038 hint_prefix_length);
1040 prefix_len = pool->getLength();
1043 candidate = allocator->pickAddress(classes, ctx.duid_, hint);
1047 if (candidate.isV6Zero()) {
1052 if (check_reservation_first && in_subnet && !out_of_pool) {
1053 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1054 if (!hosts.empty()) {
1064 !resource_handler.tryLock(ctx.currentIA().type_, candidate)) {
1077 if (!check_reservation_first && in_subnet && !out_of_pool) {
1078 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1079 if (!hosts.empty()) {
1088 ctx.subnet_ = subnet;
1089 Lease6Ptr new_lease = createLease6(ctx, candidate, prefix_len, callout_status);
1093 ctx.currentIA().old_leases_.clear();
1097 }
else if (ctx.callout_handle_ &&
1106 }
else if (existing->expired()) {
1108 if (!check_reservation_first && in_subnet && !out_of_pool) {
1109 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1110 if (!hosts.empty()) {
1119 ctx.currentIA().old_leases_.push_back(old_lease);
1121 ctx.subnet_ = subnet;
1122 existing = reuseExpiredLease(existing, ctx, prefix_len,
1137 if (ctx.hosts_.empty()) {
1140 .arg(ctx.query_->getLabel());
1151 for (
auto const& lease : existing_leases) {
1152 if ((lease->valid_lft_ != 0)) {
1153 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1154 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1159 .arg(ctx.query_->getLabel())
1160 .arg(lease->typeToText(lease->type_))
1161 .arg(lease->addr_.toText());
1167 if (!ctx.host_subnet_) {
1169 ctx.subnet_->getSharedNetwork(network);
1174 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1182 if (host && !host->getHostname().empty()) {
1189 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1190 static_cast<bool>(fqdn));
1204 auto const& classes = ctx.query_->getClasses();
1206 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1208 SubnetID subnet_id = subnet->getID();
1211 if (!subnet->clientSupported(classes) || ctx.hosts_.count(subnet_id) == 0) {
1217 bool in_subnet = subnet->getReservationsInSubnet();
1221 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1223 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1224 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1228 if (ctx.isAllocated(addr, prefix_len)) {
1237 (subnet->getReservationsOutOfPool() &&
1238 subnet->inPool(ctx.currentIA().type_, addr))) {
1250 ctx.subnet_ = subnet;
1252 if (!ctx.host_subnet_) {
1253 ctx.host_subnet_ = subnet;
1254 if (!host->getHostname().empty()) {
1268 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1269 static_cast<bool>(fqdn));
1275 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1278 existing_leases.push_back(lease);
1283 .arg(ctx.query_->getLabel());
1287 .arg(
static_cast<int>(prefix_len))
1288 .arg(ctx.query_->getLabel());
1306 allocateGlobalReservedLeases6(ctx, existing_leases);
1321 for (
auto const& lease : existing_leases) {
1322 if ((lease->valid_lft_ != 0) &&
1328 .arg(ctx.query_->getLabel())
1329 .arg(lease->typeToText(lease->type_))
1330 .arg(lease->addr_.toText());
1336 if (!ghost->getHostname().empty()) {
1343 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1344 static_cast<bool>(fqdn));
1359 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1360 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1362 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1363 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1367 if (ctx.isAllocated(addr, prefix_len)) {
1379 bool valid_subnet =
false;
1380 auto subnet = ctx.subnet_;
1382 if (subnet->inRange(addr)) {
1383 valid_subnet =
true;
1387 subnet = subnet->getNextSubnet(ctx.subnet_);
1390 if (!valid_subnet) {
1393 .arg(ctx.query_->getLabel())
1399 ctx.subnet_ = subnet;
1402 if (!ghost->getHostname().empty()) {
1416 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1417 static_cast<bool>(fqdn));
1422 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1425 existing_leases.push_back(lease);
1430 .arg(ctx.query_->getLabel());
1434 .arg(
static_cast<int>(prefix_len))
1435 .arg(ctx.query_->getLabel());
1453AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1456 if (existing_leases.empty() || !ctx.subnet_) {
1461 if (!ctx.subnet_->getReservationsInSubnet() &&
1462 !ctx.subnet_->getReservationsGlobal()) {
1463 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1472 for (
auto const& candidate :
copy) {
1476 if ((ctx.hasGlobalReservation(resv)) ||
1477 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1478 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1487 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1492 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1493 candidate->addr_,
false)) {
1497 if (!hosts.empty()) {
1500 if (hosts.size() == 1) {
1503 .arg(ctx.query_->getLabel())
1504 .arg(candidate->addr_.toText())
1505 .arg(ctx.duid_->toText())
1506 .arg(hosts.front()->getIdentifierAsText());
1509 .arg(ctx.query_->getLabel())
1510 .arg(candidate->addr_.toText())
1511 .arg(
static_cast<int>(candidate->prefixlen_))
1512 .arg(ctx.duid_->toText())
1513 .arg(hosts.front()->getIdentifierAsText());
1518 .arg(ctx.query_->getLabel())
1519 .arg(candidate->addr_.toText())
1520 .arg(ctx.duid_->toText())
1524 .arg(ctx.query_->getLabel())
1525 .arg(candidate->addr_.toText())
1526 .arg(
static_cast<int>(candidate->prefixlen_))
1527 .arg(ctx.duid_->toText())
1548 "assigned-nas" :
"assigned-pds"),
1549 static_cast<int64_t>(-1));
1551 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(candidate->subnet_id_);
1553 auto const& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1558 ctx.
currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1559 static_cast<int64_t>(-1));
1569 ctx.currentIA().old_leases_.push_back(candidate);
1572 removeLeases(existing_leases, candidate->addr_);
1577AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1584 for (
auto const& candidate :
copy) {
1588 if (inAllowedPool(ctx, candidate->type_,
1589 candidate->addr_,
false)) {
1607 "assigned-nas" :
"assigned-pds"),
1608 static_cast<int64_t>(-1));
1610 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(candidate->subnet_id_);
1612 auto const& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1617 candidate->type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1618 static_cast<int64_t>(-1));
1623 ctx.currentIA().old_leases_.push_back(candidate);
1626 removeLeases(existing_leases, candidate->addr_);
1633 bool removed =
false;
1634 for (Lease6Collection::iterator lease = container.begin();
1635 lease != container.end(); ++lease) {
1636 if ((*lease)->addr_ == addr) {
1643 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1654 int total = existing_leases.size();
1661 for (Lease6Collection::iterator lease = existing_leases.begin();
1662 lease != existing_leases.end(); ++lease) {
1666 if (ctx.hasGlobalReservation(resv) ||
1667 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1668 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1690 "assigned-nas" :
"assigned-pds"),
1691 static_cast<int64_t>(-1));
1693 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId((*lease)->subnet_id_);
1695 auto const& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1700 ctx.
currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1701 static_cast<int64_t>(-1));
1708 ctx.currentIA().old_leases_.push_back(*lease);
1723 existing_leases.erase(std::remove(existing_leases.begin(),
1724 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1732 if (!expired->expired()) {
1740 if (!ctx.fake_allocation_) {
1744 reclaimExpiredLease(expired, ctx.callout_handle_);
1748 expired->iaid_ = ctx.currentIA().iaid_;
1749 expired->duid_ = ctx.duid_;
1752 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1753 expired->reuseable_valid_lft_ = 0;
1755 expired->cltt_ = time(NULL);
1756 expired->subnet_id_ = ctx.subnet_->getID();
1757 expired->hostname_ = ctx.hostname_;
1758 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1759 expired->fqdn_rev_ = ctx.rev_dns_update_;
1760 expired->prefixlen_ = prefix_len;
1765 .arg(ctx.query_->getLabel())
1766 .arg(expired->toText());
1769 if (ctx.callout_handle_ &&
1779 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
1784 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1787 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1790 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1793 ctx.callout_handle_->setArgument(
"lease6", expired);
1798 callout_status = ctx.callout_handle_->getStatus();
1815 ctx.callout_handle_->getArgument(
"lease6", expired);
1818 if (!ctx.fake_allocation_) {
1822 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1824 expired->pool_id_ = pool->getID();
1832 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1836 "assigned-nas" :
"assigned-pds"),
1837 static_cast<int64_t>(1));
1842 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1843 static_cast<int64_t>(1));
1849 "pool" :
"pd-pool", pool->getID(),
1851 "assigned-nas" :
"assigned-pds")),
1852 static_cast<int64_t>(1));
1857 "pool" :
"pd-pool", pool->getID(),
1859 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1860 static_cast<int64_t>(1));
1864 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1865 static_cast<int64_t>(1));
1881 Triplet<uint32_t> candidate_preferred;
1882 Triplet<uint32_t> candidate_valid;
1884 if (!classes.empty()) {
1891 for (
auto const& name : classes) {
1893 if (candidate_preferred.unspecified() &&
1894 (cl && (!cl->getPreferred().unspecified()))) {
1895 candidate_preferred = cl->getPreferred();
1899 if (candidate_valid.unspecified() &&
1900 (cl && (!cl->getValid().unspecified()))) {
1901 candidate_valid = cl->getValid();
1904 if (have_both == 2) {
1911 if (!candidate_preferred) {
1912 candidate_preferred = ctx.
subnet_->getPreferred();
1916 if (!candidate_valid) {
1917 candidate_valid = ctx.
subnet_->getValid();
1921 preferred = candidate_preferred;
1922 valid = candidate_valid;
1928 preferred = candidate_preferred.get(ctx.
currentIA().
hints_[0].getPreferred());
1937 if (!preferred || preferred > valid) {
1938 preferred = ((valid * 5)/8);
1941 .arg(ctx.
query_->getLabel())
1955 uint32_t preferred = 0;
1960 ctx.currentIA().iaid_, preferred,
1961 valid, ctx.subnet_->getID(),
1962 ctx.hwaddr_, prefix_len));
1964 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1965 lease->fqdn_rev_ = ctx.rev_dns_update_;
1966 lease->hostname_ = ctx.hostname_;
1969 if (ctx.callout_handle_ &&
1979 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
1984 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1987 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1990 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1993 ctx.callout_handle_->setArgument(
"lease6", lease);
1998 callout_status = ctx.callout_handle_->getStatus();
2010 ctx.callout_handle_->getArgument(
"lease6", lease);
2013 if (!ctx.fake_allocation_) {
2017 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2019 lease->pool_id_ = pool->getID();
2028 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2032 "assigned-nas" :
"assigned-pds"),
2033 static_cast<int64_t>(1));
2038 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2039 static_cast<int64_t>(1));
2045 "pool" :
"pd-pool", pool->getID(),
2047 "assigned-nas" :
"assigned-pds")),
2048 static_cast<int64_t>(1));
2053 "pool" :
"pd-pool", pool->getID(),
2055 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2056 static_cast<int64_t>(1));
2060 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2061 static_cast<int64_t>(1));
2065 ctx.currentIA().addNewResource(addr, prefix_len);
2104 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2106 subnet = subnet->getNextSubnet(ctx.
subnet_);
2109 if (!leases.empty()) {
2112 .arg(ctx.
query_->getLabel());
2116 removeNonmatchingReservedLeases6(ctx, leases);
2119 if (!ctx.
hosts_.empty()) {
2123 .arg(ctx.
query_->getLabel());
2126 allocateReservedLeases6(ctx, leases);
2132 removeNonreservedLeases6(ctx, leases);
2139 if (leases.empty()) {
2143 .arg(ctx.
query_->getLabel());
2145 leases = allocateUnreservedLeases6(ctx);
2149 for (
auto const& l : leases) {
2157 .arg(ctx.
query_->getLabel())
2158 .arg(l->typeToText(l->type_))
2160 extendLease6(ctx, l);
2163 if (!leases.empty()) {
2167 for (
auto const& lease : leases) {
2179 .arg(ctx.
query_->getLabel())
2189 if (!lease || !ctx.subnet_) {
2195 if (ctx.subnet_->getID() != lease->subnet_id_) {
2197 ctx.subnet_->getSharedNetwork(network);
2200 network->getSubnet(
SubnetID(lease->subnet_id_));
2204 ctx.subnet_ = subnet;
2212 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2213 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2230 "assigned-nas" :
"assigned-pds"),
2231 static_cast<int64_t>(-1));
2233 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2238 "pool" :
"pd-pool", pool->getID(),
2240 "assigned-nas" :
"assigned-pds")),
2241 static_cast<int64_t>(-1));
2245 ctx.currentIA().old_leases_.push_back(lease);
2252 .arg(ctx.query_->getLabel())
2253 .arg(lease->toText());
2258 bool changed =
false;
2261 uint32_t current_preferred_lft = lease->preferred_lft_;
2262 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2265 if ((lease->preferred_lft_ != current_preferred_lft) ||
2266 (lease->valid_lft_ != lease->current_valid_lft_)) {
2270 lease->cltt_ = time(NULL);
2271 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2272 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2273 (lease->hostname_ != ctx.hostname_)) {
2275 lease->hostname_ = ctx.hostname_;
2276 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2277 lease->fqdn_rev_ = ctx.rev_dns_update_;
2279 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2281 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2283 lease->hwaddr_ = ctx.hwaddr_;
2291 .arg(ctx.query_->getLabel())
2292 .arg(lease->toText());
2296 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2297 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2308 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
2311 callout_handle->setArgument(
"query6", ctx.query_);
2314 callout_handle->setArgument(
"lease6", lease);
2318 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2320 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2333 .arg(ctx.query_->getName());
2340 bool update_stats =
false;
2344 if (old_data->expired()) {
2345 reclaimExpiredLease(old_data, ctx.callout_handle_);
2349 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2350 update_stats =
true;
2363 setLeaseReusable(lease, current_preferred_lft, ctx);
2368 if (lease->reuseable_valid_lft_ == 0) {
2369 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2371 lease->pool_id_ = pool->getID();
2377 old_data->reuseable_valid_lft_ = lease->reuseable_valid_lft_;
2384 "assigned-nas" :
"assigned-pds"),
2385 static_cast<int64_t>(1));
2390 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2391 static_cast<int64_t>(1));
2393 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2398 "pool" :
"pd-pool", pool->getID(),
2400 "assigned-nas" :
"assigned-pds")),
2401 static_cast<int64_t>(1));
2406 "pool" :
"pd-pool", pool->getID(),
2408 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2409 static_cast<int64_t>(1));
2413 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2414 static_cast<int64_t>(1));
2427 ctx.currentIA().changed_leases_.push_back(old_data);
2433 for (
auto const& lease_it : leases) {
2435 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2437 updated_leases.push_back(lease);
2441 lease->reuseable_valid_lft_ = 0;
2442 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2443 lease->fqdn_rev_ = ctx.rev_dns_update_;
2444 lease->hostname_ = ctx.hostname_;
2445 uint32_t current_preferred_lft = lease->preferred_lft_;
2446 if (lease->valid_lft_ == 0) {
2448 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2450 if (!ctx.fake_allocation_) {
2451 bool update_stats =
false;
2459 if (inAllowedPool(ctx, ctx.currentIA().type_,
2460 lease->addr_,
true)) {
2461 update_stats =
true;
2466 !(lease->hasIdenticalFqdn(*lease_it)));
2468 lease->cltt_ = time(NULL);
2469 if (!fqdn_changed) {
2470 setLeaseReusable(lease, current_preferred_lft, ctx);
2473 if (lease->reuseable_valid_lft_ == 0) {
2474 ctx.currentIA().changed_leases_.push_back(lease_it);
2478 ctx.currentIA().reused_leases_.push_back(lease_it);
2485 "assigned-nas" :
"assigned-pds"),
2486 static_cast<int64_t>(1));
2491 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2492 static_cast<int64_t>(1));
2494 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2499 "pool" :
"pd-pool", pool->getID(),
2501 "assigned-nas" :
"assigned-pds")),
2502 static_cast<int64_t>(1));
2507 "pool" :
"pd-pool", pool->getID(),
2509 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2510 static_cast<int64_t>(1));
2514 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2515 static_cast<int64_t>(1));
2519 updated_leases.push_back(lease);
2522 return (updated_leases);
2527 const uint16_t timeout,
2528 const bool remove_lease,
2529 const uint16_t max_unwarned_cycles) {
2538 max_unwarned_cycles);
2539 }
catch (
const std::exception& ex) {
2548 const uint16_t timeout,
2549 const bool remove_lease,
2550 const uint16_t max_unwarned_cycles) {
2560 bool incomplete_reclamation =
false;
2563 if (max_leases > 0) {
2567 lease_mgr.getExpiredLeases6(leases, max_leases + 1);
2572 if (leases.size() > max_leases) {
2574 incomplete_reclamation =
true;
2581 lease_mgr.getExpiredLeases6(leases, max_leases);
2587 if (!leases.empty() &&
2592 size_t leases_processed = 0;
2593 for (
auto const& lease : leases) {
2601 reclaimExpiredLease(lease, remove_lease, callout_handle);
2604 reclaimExpiredLease(lease, remove_lease, callout_handle);
2608 }
catch (
const std::exception& ex) {
2610 .arg(lease->addr_.toText())
2617 if ((timeout > 0) && (stopwatch.getTotalMilliseconds() >= timeout)) {
2621 if (!incomplete_reclamation) {
2622 if (leases_processed < leases.size()) {
2623 incomplete_reclamation =
true;
2640 .arg(leases_processed)
2641 .arg(stopwatch.logFormatTotalDuration());
2645 if (incomplete_reclamation) {
2646 ++incomplete_v6_reclamations_;
2649 if ((max_unwarned_cycles > 0) &&
2650 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2652 .arg(max_unwarned_cycles);
2654 incomplete_v6_reclamations_ = 0;
2659 incomplete_v6_reclamations_ = 0;
2672 uint64_t deleted_leases = 0;
2676 deleted_leases = lease_mgr.deleteExpiredReclaimedLeases6(secs);
2678 }
catch (
const std::exception& ex) {
2685 .arg(deleted_leases);
2690 const uint16_t timeout,
2691 const bool remove_lease,
2692 const uint16_t max_unwarned_cycles) {
2701 max_unwarned_cycles);
2702 }
catch (
const std::exception& ex) {
2711 const uint16_t timeout,
2712 const bool remove_lease,
2713 const uint16_t max_unwarned_cycles) {
2723 bool incomplete_reclamation =
false;
2726 if (max_leases > 0) {
2730 lease_mgr.getExpiredLeases4(leases, max_leases + 1);
2735 if (leases.size() > max_leases) {
2737 incomplete_reclamation =
true;
2744 lease_mgr.getExpiredLeases4(leases, max_leases);
2750 if (!leases.empty() &&
2755 size_t leases_processed = 0;
2756 for (
auto const& lease : leases) {
2764 reclaimExpiredLease(lease, remove_lease, callout_handle);
2767 reclaimExpiredLease(lease, remove_lease, callout_handle);
2771 }
catch (
const std::exception& ex) {
2773 .arg(lease->addr_.toText())
2780 if ((timeout > 0) && (stopwatch.getTotalMilliseconds() >= timeout)) {
2784 if (!incomplete_reclamation) {
2785 if (leases_processed < leases.size()) {
2786 incomplete_reclamation =
true;
2803 .arg(leases_processed)
2804 .arg(stopwatch.logFormatTotalDuration());
2808 if (incomplete_reclamation) {
2809 ++incomplete_v4_reclamations_;
2812 if ((max_unwarned_cycles > 0) &&
2813 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2815 .arg(max_unwarned_cycles);
2817 incomplete_v4_reclamations_ = 0;
2822 incomplete_v4_reclamations_ = 0;
2829template<
typename LeasePtrType>
2831AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2833 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2837template<
typename LeasePtrType>
2839AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2844 if (!lease->stateExpiredReclaimed()) {
2845 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2850AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2851 const DbReclaimMode& reclaim_mode,
2857 .arg(lease->addr_.toText())
2858 .arg(
static_cast<int>(lease->prefixlen_));
2864 bool skipped =
false;
2865 if (callout_handle) {
2873 callout_handle->deleteAllArguments();
2874 callout_handle->setArgument(
"lease6", lease);
2875 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2895 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2905 remove_lease = reclaimDeclined(lease);
2908 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2912 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2914 &lease_mgr, ph::_1));
2923 "reclaimed-leases"),
2924 static_cast<int64_t
>(1));
2940 static_cast<int64_t
>(-1));
2942 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2944 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2950 static_cast<int64_t
>(-1));
2955 "reclaimed-leases")),
2956 static_cast<int64_t
>(1));
2965 static_cast<int64_t
>(-1));
2967 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2969 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2975 static_cast<int64_t
>(-1));
2980 "reclaimed-leases")),
2981 static_cast<int64_t
>(1));
2988AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2989 const DbReclaimMode& reclaim_mode,
2995 .arg(lease->addr_.toText());
3001 bool skipped =
false;
3002 if (callout_handle) {
3010 callout_handle->setArgument(
"lease4", lease);
3011 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3029 lease->hostname_.clear();
3030 lease->fqdn_fwd_ =
false;
3031 lease->fqdn_rev_ =
false;
3035 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3045 remove_lease = reclaimDeclined(lease);
3048 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3052 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3054 &lease_mgr, ph::_1));
3066 "reclaimed-leases"),
3067 static_cast<int64_t
>(1));
3077 "assigned-addresses"),
3078 static_cast<int64_t
>(-1));
3080 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
3082 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3087 "assigned-addresses")),
3088 static_cast<int64_t
>(-1));
3093 "reclaimed-leases")),
3094 static_cast<int64_t
>(1));
3105 uint64_t deleted_leases = 0;
3109 deleted_leases = lease_mgr.deleteExpiredReclaimedLeases4(secs);
3111 }
catch (
const std::exception& ex) {
3118 .arg(deleted_leases);
3122AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3137 callout_handle->setArgument(
"lease4", lease);
3147 .arg(lease->addr_.toText());
3153 .arg(lease->addr_.toText())
3154 .arg(lease->valid_lft_);
3160 "declined-addresses"),
3161 static_cast<int64_t
>(-1));
3164 "reclaimed-declined-addresses"),
3165 static_cast<int64_t
>(1));
3167 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
3169 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3173 "declined-addresses")),
3174 static_cast<int64_t
>(-1));
3178 "reclaimed-declined-addresses")),
3179 static_cast<int64_t
>(1));
3184 stats_mgr.addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3186 stats_mgr.addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3194AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3209 callout_handle->setArgument(
"lease6", lease);
3219 .arg(lease->addr_.toText());
3225 .arg(lease->addr_.toText())
3226 .arg(lease->valid_lft_);
3232 "declined-addresses"),
3233 static_cast<int64_t
>(-1));
3236 "reclaimed-declined-addresses"),
3237 static_cast<int64_t
>(1));
3239 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
3241 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3245 "declined-addresses")),
3246 static_cast<int64_t
>(-1));
3250 "reclaimed-declined-addresses")),
3251 static_cast<int64_t
>(1));
3256 stats_mgr.addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3258 stats_mgr.addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3268 lease->relay_id_.clear();
3269 lease->remote_id_.clear();
3270 if (lease->getContext()) {
3277 if (lease->getContext()) {
3283template<
typename LeasePtrType>
3284void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3285 const bool remove_lease,
3286 const std::function<
void (
const LeasePtrType&)>&
3287 lease_update_fun)
const {
3294 lease_mgr.deleteLease(lease);
3295 }
else if (lease_update_fun) {
3298 lease->reuseable_valid_lft_ = 0;
3299 lease->hostname_.clear();
3300 lease->fqdn_fwd_ =
false;
3301 lease->fqdn_rev_ =
false;
3304 lease_update_fun(lease);
3313 .arg(lease->addr_.toText());
3319 return(
"<empty subnet>");
3323 subnet->getSharedNetwork(network);
3324 std::ostringstream ss;
3326 ss <<
"shared-network: " << network->getName();
3328 ss <<
"subnet id: " << subnet->getID();
3367 (!ctx.
subnet_->getReservationsOutOfPool() ||
3378 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3383 hosts.push_back(host);
3397 for (
auto const& host : hosts) {
3401 if (id_pair.first == host->getIdentifierType() &&
3402 id_pair.second == host->getIdentifier()) {
3410 return (!hosts.empty());
3432 if (ctx.
hosts_.empty()) {
3437 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3438 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3439 global_host->second->getIPv4Reservation() :
3448 if (subnet->getReservationsGlobal() &&
3450 (subnet->inRange(global_host_address))) {
3455 if (subnet->getReservationsInSubnet()) {
3456 auto host = ctx.
hosts_.find(subnet->getID());
3461 if (host != ctx.
hosts_.end() && host->second) {
3462 auto reservation = host->second->getIPv4Reservation();
3463 if (!reservation.isV4Zero() &&
3464 (!subnet->getReservationsOutOfPool() ||
3474 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3480 .arg(ctx.
query_->getLabel())
3481 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3508 auto const& classes = ctx.
query_->getClasses();
3512 bool try_clientid_lookup = (ctx.
clientid_ &&
3516 if (try_clientid_lookup) {
3525 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3530 if (subnet->getMatchClientId()) {
3531 for (
auto const& l : leases_client_id) {
3532 if (l->subnet_id_ == subnet->getID()) {
3545 if (!client_lease && ctx.
hwaddr_) {
3551 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3553 if (subnet->getMatchClientId()) {
3559 for (
auto const& client_lease_it : leases_hw_address) {
3560 Lease4Ptr existing_lease = client_lease_it;
3561 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3562 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3564 client_lease = existing_lease;
3592 auto const& classes = ctx.
query_->getClasses();
3594 while (current_subnet) {
3603 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3615 : early_global_reservations_lookup_(false),
3616 subnet_(), clientid_(), hwaddr_(),
3617 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3618 fwd_dns_update_(false), rev_dns_update_(false),
3619 hostname_(
""), callout_handle_(), fake_allocation_(false), offer_lft_(0),
3620 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3621 query_(), host_identifiers_(), unknown_requested_addr_(false),
3630 const bool fwd_dns_update,
3631 const bool rev_dns_update,
3632 const std::string& hostname,
3633 const bool fake_allocation,
3634 const uint32_t offer_lft)
3635 : early_global_reservations_lookup_(false),
3636 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3637 requested_address_(requested_addr),
3638 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3639 hostname_(hostname), callout_handle_(),
3640 fake_allocation_(fake_allocation), offer_lft_(offer_lft), old_lease_(), new_lease_(),
3641 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3652 if (subnet_ && subnet_->getReservationsInSubnet()) {
3653 auto host = hosts_.find(subnet_->getID());
3654 if (host != hosts_.cend()) {
3655 return (host->second);
3659 return (globalHost());
3664 if (subnet_ && subnet_->getReservationsGlobal()) {
3665 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3666 if (host != hosts_.cend()) {
3667 return (host->second);
3677 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3678 return (ddns_params_);
3684 return (ddns_params_);
3706 auto const& classes = ctx.
query_->getClasses();
3707 if (subnet && !subnet->clientSupported(classes)) {
3708 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3729 .arg(ctx.
query_->getLabel())
3747 !subnet->getReservationsInSubnet()) {
3753 subnet->getReservationsGlobal()) {
3756 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3759 if (!subnet->getReservationsInSubnet()) {
3765 std::map<SubnetID, ConstHostPtr> host_map;
3767 subnet->getSharedNetwork(network);
3776 const bool use_single_query = network &&
3780 if (use_single_query) {
3784 id_pair.second.size());
3788 for (
auto const& host : hosts) {
3789 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3790 host_map[host->getIPv4SubnetID()] = host;
3796 auto const& classes = ctx.
query_->getClasses();
3802 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3805 if (use_single_query) {
3806 if (host_map.count(subnet->getID()) > 0) {
3807 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3815 id_pair.second.size());
3818 ctx.
hosts_[subnet->getID()] = host;
3828 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3834 for (
auto const& host : ctx.
hosts_) {
3835 host.second->encapsulateOptions();
3845 &id_pair.second[0], id_pair.second.size());
3862 findClientLease(ctx, client_lease);
3875 if (hasAddressReservation(ctx)) {
3879 .arg(ctx.
query_->getLabel())
3880 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3886 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3893 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3897 .arg(ctx.
query_->getLabel())
3898 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3903 "v4-reservation-conflicts"),
3904 static_cast<int64_t
>(1));
3906 static_cast<int64_t
>(1));
3910 new_lease = renewLease4(client_lease, ctx);
3923 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3924 !addressReserved(client_lease->addr_, ctx)) {
3928 .arg(ctx.
query_->getLabel());
3934 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3938 new_lease = renewLease4(client_lease, ctx);
3955 .arg(ctx.
query_->getLabel());
3968 .arg(ctx.
query_->getLabel());
3970 new_lease = allocateUnreservedLease4(ctx);
3990 findClientLease(ctx, client_lease);
4006 .arg(ctx.
query_->getLabel())
4012 }
else if (hasAddressReservation(ctx)) {
4021 .arg(ctx.
query_->getLabel())
4033 if (existing && !existing->expired() &&
4034 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4039 .arg(ctx.
query_->getLabel())
4049 if (hasAddressReservation(ctx) &&
4057 if (!existing || existing->expired()) {
4061 .arg(ctx.
query_->getLabel())
4062 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4072 if ((!hasAddressReservation(ctx) ||
4078 .arg(ctx.
query_->getLabel())
4098 ((hasAddressReservation(ctx) &&
4100 inAllowedPool(ctx, client_lease->addr_))) {
4104 .arg(ctx.
query_->getLabel())
4107 return (renewLease4(client_lease, ctx));
4121 .arg(ctx.
query_->getLabel())
4137 .arg(ctx.
query_->getLabel());
4142 new_lease = allocateUnreservedLease4(ctx);
4148 if (new_lease && client_lease) {
4153 .arg(ctx.
query_->getLabel())
4154 .arg(client_lease->addr_.toText());
4160 "assigned-addresses"),
4161 static_cast<int64_t
>(-1));
4163 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(client_lease->subnet_id_);
4165 auto const& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4170 "assigned-addresses")),
4171 static_cast<int64_t
>(-1));
4194 if (!classes.empty()) {
4200 for (
auto const& name : classes) {
4202 if (cl && (!cl->getOfferLft().unspecified())) {
4203 offer_lft = cl->getOfferLft();
4210 if (offer_lft.unspecified()) {
4211 offer_lft = ctx.
subnet_->getOfferLft();
4214 return (offer_lft.unspecified() ? 0 : offer_lft.get());
4220 if (ctx.
query_->inClass(
"BOOTP")) {
4225 uint32_t requested_lft = 0;
4228 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4230 requested_lft = opt_lft->getValue();
4236 Triplet<uint32_t> candidate_lft;
4238 if (!classes.empty()) {
4244 for (
auto const& name : classes) {
4246 if (cl && (!cl->getValid().unspecified())) {
4247 candidate_lft = cl->getValid();
4254 if (!candidate_lft) {
4255 candidate_lft = ctx.
subnet_->getValid();
4260 if (requested_lft > 0) {
4261 return (candidate_lft.get(requested_lft));
4265 return (candidate_lft.get());
4269AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4279 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4281 time_t now = time(NULL);
4284 if (ctx.subnet_->getMatchClientId()) {
4285 client_id = ctx.clientid_;
4289 valid_lft, now, ctx.subnet_->getID()));
4292 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4293 lease->fqdn_rev_ = ctx.rev_dns_update_;
4294 lease->hostname_ = ctx.hostname_;
4300 if (ctx.callout_handle_ &&
4310 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.query_);
4314 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4321 boost::dynamic_pointer_cast<const Subnet4>(ctx.subnet_);
4322 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4325 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4328 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4331 ctx.callout_handle_->setArgument(
"lease4", lease);
4336 callout_status = ctx.callout_handle_->getStatus();
4348 ctx.callout_handle_->getArgument(
"lease4", lease);
4351 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4355 lease->fqdn_fwd_ =
false;
4356 lease->fqdn_rev_ =
false;
4359 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4360 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4362 lease->pool_id_ = pool->getID();
4371 "assigned-addresses"),
4372 static_cast<int64_t
>(1));
4376 "cumulative-assigned-addresses"),
4377 static_cast<int64_t
>(1));
4383 "assigned-addresses")),
4384 static_cast<int64_t
>(1));
4389 "cumulative-assigned-addresses")),
4390 static_cast<int64_t
>(1));
4394 static_cast<int64_t
>(1));
4413AllocEngine::renewLease4(
const Lease4Ptr& lease,
4423 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4428 lease->reuseable_valid_lft_ = 0;
4429 if (!updateLease4Information(lease, ctx)) {
4430 setLeaseReusable(lease, ctx);
4455 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4462 boost::dynamic_pointer_cast<const Subnet4>(ctx.
subnet_);
4471 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4497 lease->pool_id_ = pool->getID();
4507 "assigned-addresses"),
4508 static_cast<int64_t
>(1));
4512 "cumulative-assigned-addresses"),
4513 static_cast<int64_t
>(1));
4519 "assigned-addresses")),
4520 static_cast<int64_t
>(1));
4525 "cumulative-assigned-addresses")),
4526 static_cast<int64_t
>(1));
4530 static_cast<int64_t
>(1));
4536 *lease = *old_values;
4543AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4562 expired->reuseable_valid_lft_ = 0;
4563 static_cast<void>(updateLease4Information(expired, ctx));
4567 .arg(ctx.
query_->getLabel())
4568 .arg(expired->toText());
4575 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4592 boost::dynamic_pointer_cast<const Subnet4>(ctx.
subnet_);
4626 expired->pool_id_ = pool->getID();
4634 "assigned-addresses"),
4635 static_cast<int64_t
>(1));
4639 "cumulative-assigned-addresses"),
4640 static_cast<int64_t
>(1));
4646 "assigned-addresses")),
4647 static_cast<int64_t
>(1));
4652 "cumulative-assigned-addresses")),
4653 static_cast<int64_t
>(1));
4657 static_cast<int64_t
>(1));
4669AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4671 ctx.conflicting_lease_.reset();
4675 if (exist_lease->expired()) {
4680 ctx.old_lease_->hostname_.clear();
4681 ctx.old_lease_->fqdn_fwd_ =
false;
4682 ctx.old_lease_->fqdn_rev_ =
false;
4683 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4689 ctx.conflicting_lease_ = exist_lease;
4693 return (createLease4(ctx, candidate, callout_status));
4699AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4713 ctx.subnet_->getSharedNetwork(network);
4720 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4734 uint64_t subnets_with_unavail_leases = 0;
4737 uint64_t subnets_with_unavail_pools = 0;
4739 auto const& classes = ctx.query_->getClasses();
4743 if (subnet->getMatchClientId()) {
4744 client_id = ctx.clientid_;
4756 (attempts_ == 0 || possible_attempts < attempts_) ?
4760 if (max_attempts > 0) {
4763 ++subnets_with_unavail_leases;
4767 ++subnets_with_unavail_pools;
4770 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4775 for (
uint128_t i = 0; i < max_attempts; ++i) {
4780 IOAddress candidate = allocator->pickAddress(classes,
4782 ctx.requested_address_);
4785 if (candidate.isV4Zero()) {
4789 if (exclude_first_last_24) {
4791 auto const& bytes = candidate.
toBytes();
4792 if ((bytes.size() != 4) ||
4793 (bytes[3] == 0) || (bytes[3] == 255U)) {
4800 if (check_reservation_first && addressReserved(candidate, ctx)) {
4809 !resource_handler.tryLock4(candidate)) {
4818 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4820 new_lease = createLease4(ctx, candidate, callout_status);
4824 if (exist_lease->expired() &&
4825 (check_reservation_first || !addressReserved(candidate, ctx))) {
4827 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4845 subnet = subnet->getNextSubnet(original_subnet, classes);
4848 ctx.subnet_ = subnet;
4857 .arg(ctx.query_->getLabel())
4858 .arg(network->getName())
4859 .arg(subnets_with_unavail_leases)
4860 .arg(subnets_with_unavail_pools);
4862 static_cast<int64_t
>(1));
4865 "v4-allocation-fail-shared-network"),
4866 static_cast<int64_t
>(1));
4870 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4871 if (shared_network.empty()) {
4872 shared_network =
"(none)";
4875 .arg(ctx.query_->getLabel())
4876 .arg(ctx.subnet_->toText())
4877 .arg(ctx.subnet_->getID())
4878 .arg(shared_network);
4880 static_cast<int64_t
>(1));
4883 "v4-allocation-fail-subnet"),
4884 static_cast<int64_t
>(1));
4886 if (total_attempts == 0) {
4892 .arg(ctx.query_->getLabel());
4894 static_cast<int64_t
>(1));
4897 "v4-allocation-fail-no-pools"),
4898 static_cast<int64_t
>(1));
4905 .arg(ctx.query_->getLabel())
4906 .arg(total_attempts);
4908 static_cast<int64_t
>(1));
4911 "v4-allocation-fail"),
4912 static_cast<int64_t
>(1));
4915 if (!classes.empty()) {
4917 .arg(ctx.query_->getLabel())
4918 .arg(classes.toText());
4920 static_cast<int64_t
>(1));
4923 "v4-allocation-fail-classes"),
4924 static_cast<int64_t
>(1));
4931AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4933 bool changed =
false;
4934 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4936 lease->subnet_id_ = ctx.
subnet_->getID();
4938 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4940 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4945 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4949 }
else if (lease->client_id_) {
4953 lease->cltt_ = time(NULL);
4959 if (lease->valid_lft_ != lease->current_valid_lft_) {
4983 bool changed =
false;
4986 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5001 sao->boolValue() && ctx.
query_->inClass(
"STASH_AGENT_OPTIONS")) {
5010 extended_info->set(
"sub-options", relay_agent);
5014 std::vector<uint8_t> bytes = remote_id->toBinary();
5015 lease->remote_id_ = bytes;
5016 if (bytes.size() > 0) {
5017 extended_info->set(
"remote-id",
5024 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5025 lease->relay_id_ = bytes;
5026 if (bytes.size() > 0) {
5027 extended_info->set(
"relay-id",
5035 if (user_context && (user_context->getType() ==
Element::map)) {
5036 mutable_user_context =
copy(user_context, 0);
5051 ConstElementPtr old_extended_info = mutable_isc->get(
"relay-agent-info");
5052 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5054 mutable_isc->set(
"relay-agent-info", extended_info);
5055 mutable_user_context->set(
"ISC", mutable_isc);
5059 lease->setContext(mutable_user_context);
5071 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5076 if (ctx.
query_->relay_info_.empty()) {
5091 for (
auto const& relay : ctx.
query_->relay_info_) {
5100 if (!relay.options_.empty()) {
5104 if (buf.getLength() > 0) {
5105 const uint8_t* cp = buf.getData();
5106 std::vector<uint8_t> bytes;
5107 std::stringstream ss;
5109 bytes.assign(cp, cp + buf.getLength());
5115 if (remote_id_it != relay.options_.end()) {
5116 OptionPtr remote_id = remote_id_it->second;
5118 std::vector<uint8_t> bytes = remote_id->toBinary();
5119 if (bytes.size() > 0) {
5120 relay_elem->set(
"remote-id",
5127 if (relay_id_it != relay.options_.end()) {
5128 OptionPtr relay_id = relay_id_it->second;
5130 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5131 if (bytes.size() > 0) {
5132 relay_elem->set(
"relay-id",
5139 extended_info->add(relay_elem);
5145 if (user_context && (user_context->getType() ==
Element::map)) {
5146 mutable_user_context =
copy(user_context, 0);
5162 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5164 mutable_isc->set(
"relay-info", extended_info);
5165 mutable_user_context->set(
"ISC", mutable_isc);
5169 lease->setContext(mutable_user_context);
5173AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5174 const ClientContext4& ctx)
const {
5176 lease->reuseable_valid_lft_ = 0;
5192 if (lease->cltt_ < lease->current_cltt_) {
5196 uint32_t age = lease->cltt_ - lease->current_cltt_;
5198 if (age >= lease->current_valid_lft_) {
5203 uint32_t max_age = 0;
5204 if (!subnet->getCacheMaxAge().unspecified()) {
5205 max_age = subnet->getCacheMaxAge().get();
5206 if ((max_age == 0) || (age > max_age)) {
5212 if (!subnet->getCacheThreshold().unspecified()) {
5213 double threshold = subnet->getCacheThreshold().get();
5214 if ((threshold <= 0.) || (threshold > 1.)) {
5217 max_age = lease->valid_lft_ * threshold;
5218 if (age > max_age) {
5229 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5233AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5234 uint32_t current_preferred_lft,
5235 const ClientContext6& ctx)
const {
5237 lease->reuseable_valid_lft_ = 0;
5238 lease->reuseable_preferred_lft_ = 0;
5248 if (lease->cltt_ < lease->current_cltt_) {
5252 uint32_t age = lease->cltt_ - lease->current_cltt_;
5254 if (age >= lease->current_valid_lft_) {
5259 uint32_t max_age = 0;
5260 if (!subnet->getCacheMaxAge().unspecified()) {
5261 max_age = subnet->getCacheMaxAge().get();
5262 if ((max_age == 0) || (age > max_age)) {
5268 if (!subnet->getCacheThreshold().unspecified()) {
5269 double threshold = subnet->getCacheThreshold().get();
5270 if ((threshold <= 0.) || (threshold > 1.)) {
5273 max_age = lease->valid_lft_ * threshold;
5274 if (age > max_age) {
5286 (current_preferred_lft == 0)) {
5288 lease->reuseable_preferred_lft_ = current_preferred_lft;
5289 }
else if (current_preferred_lft > age) {
5290 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5298 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.
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.
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 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.
static std::string labelNetworkOrSubnet(ConstSubnetPtr subnet)
Generates a label for subnet or shared-network from subnet.
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.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Container for storing client class names.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
static HostMgr & instance()
Returns a sole instance of the HostMgr.
IPv6 reservation for a host.
Type
Type of the reservation.
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
Resource race avoidance RAII handler for DHCPv4.
Resource race avoidance RAII handler.
static bool subnetsIncludeMatchClientId(const ConstSubnet4Ptr &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.
Statistics Manager class.
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.
A template representing an optional value.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Utility class to measure code execution times.
Write mutex RAII handler.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
#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
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
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.
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
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.
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
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< 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
boost::shared_ptr< const Subnet > ConstSubnetPtr
A generic pointer to either const Subnet4 or const Subnet6 object.
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.
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.
ConstSubnet4Ptr subnet_
Subnet selected for the client by the server.
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.
Lease::Type type_
Lease type (IA or PD)
bool isNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was new.
void addHint(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128, const uint32_t preferred=0, const uint32_t valid=0)
Convenience method adding new hint.
void addNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding new prefix or address.
HintContainer hints_
Client's hints.
uint32_t iaid_
The IAID field from IA_NA or IA_PD that is being processed.
Context information for the DHCPv6 leases allocation.
IAContext & currentIA()
Returns IA specific context for the currently processed IA.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
ConstHostPtr currentHost() const
Returns host from the most preferred subnet.
ClientContext6()
Default constructor.
DuidPtr duid_
Client identifier.
void addAllocatedResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding allocated prefix or address.
Lease6Collection new_leases_
A collection of newly allocated leases.
bool isAllocated(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was allocated.
bool hasGlobalReservation(const IPv6Resrv &resv) const
Determines if a global reservation exists.
ResourceContainer allocated_resources_
Holds addresses and prefixes allocated for all IAs.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
Pkt6Ptr query_
A pointer to the client's message.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
ConstSubnet6Ptr host_subnet_
Subnet from which host reservations should be retrieved.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
ConstSubnet6Ptr subnet_
Subnet selected for the client by the server.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
Structure that holds a lease for IPv4 address.
Structure that holds a lease for IPv6 address and/or prefix.
@ 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_RELEASED
Released lease held in the database for lease affinity.
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