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_);
198 : query_(), fake_allocation_(false),
199 early_global_reservations_lookup_(false), subnet_(), host_subnet_(),
200 duid_(), hwaddr_(), host_identifiers_(), hosts_(),
201 fwd_dns_update_(false), rev_dns_update_(false), hostname_(),
202 callout_handle_(), ias_(), ddns_params_() {
209 const std::string& hostname,
210 const bool fake_allocation,
213 : query_(query), fake_allocation_(fake_allocation),
214 early_global_reservations_lookup_(false), subnet_(subnet),
215 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
216 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
217 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
218 ias_(), ddns_params_() {
227 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
228 changed_leases_(),reused_leases_(), new_resources_(), ia_rsp_() {
234 const uint8_t prefix_len,
235 const uint32_t preferred,
236 const uint32_t valid) {
237 hints_.push_back(
Resource(prefix, prefix_len, preferred, 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) {
264 static_cast<void>(new_resources_.insert(
Resource(prefix, prefix_len)));
270 const uint8_t prefix_len)
const {
271 return (
static_cast<bool>(new_resources_.count(
Resource(prefix,
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) {
486 ((l)->subnet_id_ == subnet->getID())) {
491 subnet = subnet->getNextSubnet(ctx.
subnet_);
511 if (leases.empty() && !ctx.
hosts_.empty()) {
515 .arg(ctx.
query_->getLabel());
520 allocateReservedLeases6(ctx, leases);
522 leases = updateLeaseData(ctx, leases);
537 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
541 .arg(ctx.
query_->getLabel());
545 removeNonmatchingReservedLeases6(ctx, leases);
547 leases = updateLeaseData(ctx, leases);
556 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
560 .arg(ctx.
query_->getLabel());
564 allocateReservedLeases6(ctx, leases);
576 removeNonmatchingReservedLeases6(ctx, leases);
585 removeNonreservedLeases6(ctx, leases);
590 leases = updateLeaseData(ctx, leases);
603 if (leases.empty()) {
617 .arg(ctx.
query_->getLabel());
619 leases = allocateUnreservedLeases6(ctx);
622 if (!leases.empty()) {
626 for (
auto const& lease : leases) {
640 .arg(ctx.
query_->getLabel())
653 uint8_t hint_prefix_length = 128;
654 if (!ctx.currentIA().hints_.empty()) {
656 hint = ctx.currentIA().hints_[0].getAddress();
657 hint_prefix_length = ctx.currentIA().hints_[0].getPrefixLength();
666 uint64_t total_attempts = 0;
670 uint64_t subnets_with_unavail_leases = 0;
673 uint64_t subnets_with_unavail_pools = 0;
683 bool search_hint_lease =
true;
690 if (hint_prefix_length == 128) {
691 hint_prefix_length = 0;
693 if (!hint_prefix_length) {
701 Lease6Ptr lease = allocateBestMatch(ctx, hint_lease, search_hint_lease,
702 hint, hint_prefix_length, subnet,
703 network, total_attempts,
704 subnets_with_unavail_leases,
705 subnets_with_unavail_pools,
706 callout_status, prefix_length_match);
714 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
715 hint_prefix_length, subnet, network,
716 total_attempts, subnets_with_unavail_leases,
717 subnets_with_unavail_pools, callout_status,
718 prefix_length_match);
727 lease = allocateBestMatch(ctx, hint_lease, search_hint_lease, hint,
728 hint_prefix_length, subnet, network,
729 total_attempts, subnets_with_unavail_leases,
730 subnets_with_unavail_pools, callout_status,
731 prefix_length_match);
735 leases.push_back(lease);
739 auto const& classes = ctx.query_->getClasses();
745 .arg(ctx.query_->getLabel())
746 .arg(network->getName())
747 .arg(subnets_with_unavail_leases)
748 .arg(subnets_with_unavail_pools);
750 static_cast<int64_t
>(1));
753 "v6-allocation-fail-shared-network"),
754 static_cast<int64_t
>(1));
758 std::string shared_network = ctx.subnet_->getSharedNetworkName();
759 if (shared_network.empty()) {
760 shared_network =
"(none)";
763 .arg(ctx.query_->getLabel())
764 .arg(ctx.subnet_->toText())
765 .arg(ctx.subnet_->getID())
766 .arg(shared_network);
768 static_cast<int64_t
>(1));
771 "v6-allocation-fail-subnet"),
772 static_cast<int64_t
>(1));
774 if (total_attempts == 0) {
780 .arg(ctx.query_->getLabel());
782 static_cast<int64_t
>(1));
785 "v6-allocation-fail-no-pools"),
786 static_cast<int64_t
>(1));
793 .arg(ctx.query_->getLabel())
794 .arg(total_attempts);
796 static_cast<int64_t
>(1));
799 "v6-allocation-fail"),
800 static_cast<int64_t
>(1));
803 if (!classes.empty()) {
805 .arg(ctx.query_->getLabel())
806 .arg(classes.toText());
808 static_cast<int64_t
>(1));
811 "v6-allocation-fail-classes"),
812 static_cast<int64_t
>(1));
822 bool& search_hint_lease,
824 uint8_t hint_prefix_length,
827 uint64_t& total_attempts,
828 uint64_t& subnets_with_unavail_leases,
829 uint64_t& subnets_with_unavail_pools,
832 auto const& classes = ctx.query_->getClasses();
837 if (!search_hint_lease) {
838 usable_hint_lease = hint_lease;
840 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
841 if (!subnet->clientSupported(classes)) {
845 ctx.subnet_ = subnet;
849 pool = boost::dynamic_pointer_cast<Pool6>
850 (subnet->getPool(ctx.currentIA().type_, classes, hint));
853 if (!pool || !pool->clientSupported(classes)) {
859 hint_prefix_length)) {
863 bool in_subnet = subnet->getReservationsInSubnet();
866 if (search_hint_lease) {
867 search_hint_lease =
false;
869 usable_hint_lease = hint_lease;
871 if (!usable_hint_lease) {
883 (!subnet->getReservationsOutOfPool() ||
884 !subnet->inPool(ctx.currentIA().type_, hint))) {
885 hosts = getIPv6Resrv(subnet->getID(), hint);
895 Lease6Ptr new_lease = createLease6(ctx, hint, pool->getLength(), callout_status);
908 .arg(ctx.query_->getLabel())
912 }
else if (usable_hint_lease->expired() &&
922 (!subnet->getReservationsOutOfPool() ||
923 !subnet->inPool(ctx.currentIA().type_, hint))) {
924 hosts = getIPv6Resrv(subnet->getID(), hint);
933 ctx.currentIA().old_leases_.push_back(old_lease);
936 Lease6Ptr lease = reuseExpiredLease(usable_hint_lease, ctx,
946 .arg(ctx.query_->getLabel())
958 if (!check_reservation_first) {
972 original_subnet->getSharedNetwork(network);
979 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
982 ctx.subnet_ = subnet = original_subnet;
984 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
985 if (!subnet->clientSupported(classes)) {
996 subnet->getPoolCapacity(ctx.currentIA().type_,
1007 (attempts_ == 0 || possible_attempts < attempts_) ?
1011 if (max_attempts > 0) {
1014 ++subnets_with_unavail_leases;
1018 ++subnets_with_unavail_pools;
1022 bool in_subnet = subnet->getReservationsInSubnet();
1023 bool out_of_pool = subnet->getReservationsOutOfPool();
1028 if (ctx.callout_handle_) {
1032 for (uint64_t i = 0; i < max_attempts; ++i) {
1035 auto allocator = subnet->getAllocator(ctx.currentIA().type_);
1040 uint8_t prefix_len = 128;
1042 candidate = allocator->pickPrefix(classes, pool, ctx.duid_,
1043 prefix_length_match, hint,
1044 hint_prefix_length);
1046 prefix_len = pool->getLength();
1049 candidate = allocator->pickAddress(classes, ctx.duid_, hint);
1058 if (check_reservation_first && in_subnet && !out_of_pool) {
1059 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1060 if (!hosts.empty()) {
1070 !resource_handler.
tryLock(ctx.currentIA().type_, candidate)) {
1083 if (!check_reservation_first && in_subnet && !out_of_pool) {
1084 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1085 if (!hosts.empty()) {
1094 ctx.subnet_ = subnet;
1095 Lease6Ptr new_lease = createLease6(ctx, candidate, prefix_len, callout_status);
1099 ctx.currentIA().old_leases_.clear();
1103 }
else if (ctx.callout_handle_ &&
1112 }
else if (existing->expired() &&
1115 if (!check_reservation_first && in_subnet && !out_of_pool) {
1116 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1117 if (!hosts.empty()) {
1126 ctx.currentIA().old_leases_.push_back(old_lease);
1128 ctx.subnet_ = subnet;
1129 existing = reuseExpiredLease(existing, ctx, prefix_len,
1144 if (ctx.hosts_.empty()) {
1147 .arg(ctx.query_->getLabel());
1158 for (
auto const& lease : existing_leases) {
1159 if ((lease->valid_lft_ != 0)) {
1160 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1161 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1166 .arg(ctx.query_->getLabel())
1167 .arg(lease->typeToText(lease->type_))
1168 .arg(lease->addr_.toText());
1174 if (!ctx.host_subnet_) {
1176 ctx.subnet_->getSharedNetwork(network);
1181 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1189 if (host && !host->getHostname().empty()) {
1196 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1197 static_cast<bool>(fqdn));
1211 auto const& classes = ctx.query_->getClasses();
1213 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1215 SubnetID subnet_id = subnet->getID();
1218 if (!subnet->clientSupported(classes) || ctx.hosts_.count(subnet_id) == 0) {
1224 bool in_subnet = subnet->getReservationsInSubnet();
1228 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1230 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1231 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1235 if (ctx.isAllocated(addr, prefix_len)) {
1244 (subnet->getReservationsOutOfPool() &&
1245 subnet->inPool(ctx.currentIA().type_, addr))) {
1257 ctx.subnet_ = subnet;
1259 if (!ctx.host_subnet_) {
1260 ctx.host_subnet_ = subnet;
1261 if (!host->getHostname().empty()) {
1275 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1276 static_cast<bool>(fqdn));
1282 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1285 existing_leases.push_back(lease);
1290 .arg(ctx.query_->getLabel());
1294 .arg(
static_cast<int>(prefix_len))
1295 .arg(ctx.query_->getLabel());
1313 allocateGlobalReservedLeases6(ctx, existing_leases);
1328 for (
auto const& lease : existing_leases) {
1329 if ((lease->valid_lft_ != 0) &&
1335 .arg(ctx.query_->getLabel())
1336 .arg(lease->typeToText(lease->type_))
1337 .arg(lease->addr_.toText());
1343 if (!ghost->getHostname().empty()) {
1350 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1351 static_cast<bool>(fqdn));
1366 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1367 BOOST_FOREACH(
auto const& type_lease_tuple, reservs) {
1369 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1370 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1374 if (ctx.isAllocated(addr, prefix_len)) {
1386 bool valid_subnet =
false;
1387 auto subnet = ctx.subnet_;
1389 if (subnet->inRange(addr)) {
1390 valid_subnet =
true;
1394 subnet = subnet->getNextSubnet(ctx.subnet_);
1397 if (!valid_subnet) {
1400 .arg(ctx.query_->getLabel())
1406 ctx.subnet_ = subnet;
1409 if (!ghost->getHostname().empty()) {
1423 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1424 static_cast<bool>(fqdn));
1429 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1432 existing_leases.push_back(lease);
1437 .arg(ctx.query_->getLabel());
1441 .arg(
static_cast<int>(prefix_len))
1442 .arg(ctx.query_->getLabel());
1460AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1463 if (existing_leases.empty() || !ctx.subnet_) {
1468 if (!ctx.subnet_->getReservationsInSubnet() &&
1469 !ctx.subnet_->getReservationsGlobal()) {
1470 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1479 for (
auto const& candidate :
copy) {
1483 if ((ctx.hasGlobalReservation(resv)) ||
1484 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1485 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1494 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1499 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1500 candidate->addr_,
false)) {
1504 if (!hosts.empty()) {
1507 if (hosts.size() == 1) {
1510 .arg(ctx.query_->getLabel())
1511 .arg(candidate->addr_.
toText())
1512 .arg(ctx.duid_->toText())
1513 .arg(hosts.front()->getIdentifierAsText());
1516 .arg(ctx.query_->getLabel())
1517 .arg(candidate->addr_.
toText())
1518 .arg(
static_cast<int>(candidate->prefixlen_))
1519 .arg(ctx.duid_->toText())
1520 .arg(hosts.front()->getIdentifierAsText());
1525 .arg(ctx.query_->getLabel())
1526 .arg(candidate->addr_.
toText())
1527 .arg(ctx.duid_->toText())
1531 .arg(ctx.query_->getLabel())
1532 .arg(candidate->addr_.
toText())
1533 .arg(
static_cast<int>(candidate->prefixlen_))
1534 .arg(ctx.duid_->toText())
1555 "assigned-nas" :
"assigned-pds"),
1556 static_cast<int64_t
>(-1));
1560 auto const& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1565 "pool" :
"pd-pool", pool->getID(),
1567 "assigned-nas" :
"assigned-pds")),
1568 static_cast<int64_t
>(-1));
1578 ctx.currentIA().old_leases_.push_back(candidate);
1581 removeLeases(existing_leases, candidate->addr_);
1586AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1593 for (
auto const& candidate :
copy) {
1597 if (inAllowedPool(ctx, candidate->type_,
1598 candidate->addr_,
false)) {
1616 "assigned-nas" :
"assigned-pds"),
1617 static_cast<int64_t
>(-1));
1621 auto const& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1626 "pool" :
"pd-pool", pool->getID(),
1628 "assigned-nas" :
"assigned-pds")),
1629 static_cast<int64_t
>(-1));
1634 ctx.currentIA().old_leases_.push_back(candidate);
1637 removeLeases(existing_leases, candidate->addr_);
1644 bool removed =
false;
1645 for (Lease6Collection::iterator lease = container.begin();
1646 lease != container.end(); ++lease) {
1647 if ((*lease)->addr_ == addr) {
1654 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1665 int total = existing_leases.size();
1672 for (Lease6Collection::iterator lease = existing_leases.begin();
1673 lease != existing_leases.end(); ++lease) {
1677 if (ctx.hasGlobalReservation(resv) ||
1678 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1679 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1701 "assigned-nas" :
"assigned-pds"),
1702 static_cast<int64_t
>(-1));
1706 auto const& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1711 "pool" :
"pd-pool", pool->getID(),
1713 "assigned-nas" :
"assigned-pds")),
1714 static_cast<int64_t
>(-1));
1721 ctx.currentIA().old_leases_.push_back(*lease);
1736 existing_leases.erase(std::remove(existing_leases.begin(),
1737 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1745 if (!expired->expired()) {
1757 if (!ctx.fake_allocation_) {
1761 reclaimExpiredLease(expired, ctx.callout_handle_);
1765 expired->iaid_ = ctx.currentIA().iaid_;
1766 expired->duid_ = ctx.duid_;
1769 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1770 expired->reuseable_valid_lft_ = 0;
1772 expired->cltt_ = time(NULL);
1773 expired->subnet_id_ = ctx.subnet_->getID();
1774 expired->hostname_ = ctx.hostname_;
1775 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1776 expired->fqdn_rev_ = ctx.rev_dns_update_;
1777 expired->prefixlen_ = prefix_len;
1782 .arg(ctx.query_->getLabel())
1783 .arg(expired->toText());
1786 if (ctx.callout_handle_ &&
1801 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1804 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1807 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1810 ctx.callout_handle_->setArgument(
"lease6", expired);
1815 callout_status = ctx.callout_handle_->getStatus();
1832 ctx.callout_handle_->getArgument(
"lease6", expired);
1835 if (!ctx.fake_allocation_) {
1839 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1841 expired->pool_id_ = pool->getID();
1849 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1853 "assigned-nas" :
"assigned-pds"),
1854 static_cast<int64_t
>(1));
1859 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1860 static_cast<int64_t
>(1));
1866 "pool" :
"pd-pool", pool->getID(),
1868 "assigned-nas" :
"assigned-pds")),
1869 static_cast<int64_t
>(1));
1874 "pool" :
"pd-pool", pool->getID(),
1876 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1877 static_cast<int64_t
>(1));
1881 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1882 static_cast<int64_t
>(1));
1901 if (!classes.
empty()) {
1908 for (
auto const& name : classes) {
1911 (cl && (!cl->getPreferred().unspecified()))) {
1912 candidate_preferred = cl->getPreferred();
1917 (cl && (!cl->getValid().unspecified()))) {
1918 candidate_valid = cl->getValid();
1921 if (have_both == 2) {
1928 if (!candidate_preferred) {
1929 candidate_preferred = ctx.
subnet_->getPreferred();
1933 if (!candidate_valid) {
1934 candidate_valid = ctx.
subnet_->getValid();
1938 preferred = candidate_preferred;
1939 valid = candidate_valid;
1954 if (!preferred || preferred > valid) {
1955 preferred = ((valid * 5)/8);
1958 .arg(ctx.
query_->getLabel())
1972 uint32_t preferred = 0;
1977 ctx.currentIA().iaid_, preferred,
1978 valid, ctx.subnet_->getID(),
1979 ctx.hwaddr_, prefix_len));
1981 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1982 lease->fqdn_rev_ = ctx.rev_dns_update_;
1983 lease->hostname_ = ctx.hostname_;
1986 if (ctx.callout_handle_ &&
2001 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
2004 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
2007 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
2010 ctx.callout_handle_->setArgument(
"lease6", lease);
2015 callout_status = ctx.callout_handle_->getStatus();
2027 ctx.callout_handle_->getArgument(
"lease6", lease);
2030 if (!ctx.fake_allocation_) {
2034 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2036 lease->pool_id_ = pool->getID();
2045 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2049 "assigned-nas" :
"assigned-pds"),
2050 static_cast<int64_t
>(1));
2055 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2056 static_cast<int64_t
>(1));
2062 "pool" :
"pd-pool", pool->getID(),
2064 "assigned-nas" :
"assigned-pds")),
2065 static_cast<int64_t
>(1));
2070 "pool" :
"pd-pool", pool->getID(),
2072 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2073 static_cast<int64_t
>(1));
2077 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2078 static_cast<int64_t
>(1));
2082 ctx.currentIA().addNewResource(addr, prefix_len);
2121 for (
auto const& l : leases_subnet) {
2123 leases.push_back(l);
2126 subnet = subnet->getNextSubnet(ctx.
subnet_);
2129 if (!leases.empty()) {
2132 .arg(ctx.
query_->getLabel());
2136 removeNonmatchingReservedLeases6(ctx, leases);
2139 if (!ctx.
hosts_.empty()) {
2143 .arg(ctx.
query_->getLabel());
2146 allocateReservedLeases6(ctx, leases);
2152 removeNonreservedLeases6(ctx, leases);
2159 if (leases.empty()) {
2163 .arg(ctx.
query_->getLabel());
2165 leases = allocateUnreservedLeases6(ctx);
2169 for (
auto const& l : leases) {
2177 .arg(ctx.
query_->getLabel())
2178 .arg(l->typeToText(l->type_))
2180 extendLease6(ctx, l);
2183 if (!leases.empty()) {
2187 for (
auto const& lease : leases) {
2202 .arg(ctx.
query_->getLabel())
2212 if (!lease || !ctx.subnet_) {
2218 if (ctx.subnet_->getID() != lease->subnet_id_) {
2220 ctx.subnet_->getSharedNetwork(network);
2223 network->getSubnet(
SubnetID(lease->subnet_id_));
2227 ctx.subnet_ = subnet;
2235 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2236 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2253 "assigned-nas" :
"assigned-pds"),
2254 static_cast<int64_t
>(-1));
2256 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2261 "pool" :
"pd-pool", pool->getID(),
2263 "assigned-nas" :
"assigned-pds")),
2264 static_cast<int64_t
>(-1));
2268 ctx.currentIA().old_leases_.push_back(lease);
2275 .arg(ctx.query_->getLabel())
2276 .arg(lease->toText());
2281 bool changed =
false;
2284 uint32_t current_preferred_lft = lease->preferred_lft_;
2285 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2288 if ((lease->preferred_lft_ != current_preferred_lft) ||
2289 (lease->valid_lft_ != lease->current_valid_lft_)) {
2293 lease->cltt_ = time(NULL);
2294 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2295 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2296 (lease->hostname_ != ctx.hostname_)) {
2298 lease->hostname_ = ctx.hostname_;
2299 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2300 lease->fqdn_rev_ = ctx.rev_dns_update_;
2302 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2304 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2306 lease->hwaddr_ = ctx.hwaddr_;
2314 .arg(ctx.query_->getLabel())
2315 .arg(lease->toText());
2319 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2320 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2334 callout_handle->setArgument(
"query6", ctx.query_);
2337 callout_handle->setArgument(
"lease6", lease);
2341 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2343 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2356 .arg(ctx.query_->getName());
2363 bool update_stats =
false;
2367 if (old_data->expired()) {
2368 reclaimExpiredLease(old_data, ctx.callout_handle_);
2372 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2373 update_stats =
true;
2386 setLeaseReusable(lease, current_preferred_lft, ctx);
2391 if (lease->reuseable_valid_lft_ == 0) {
2392 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2394 lease->pool_id_ = pool->getID();
2400 old_data->reuseable_valid_lft_ = lease->reuseable_valid_lft_;
2407 "assigned-nas" :
"assigned-pds"),
2408 static_cast<int64_t
>(1));
2413 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2414 static_cast<int64_t
>(1));
2416 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2421 "pool" :
"pd-pool", pool->getID(),
2423 "assigned-nas" :
"assigned-pds")),
2424 static_cast<int64_t
>(1));
2429 "pool" :
"pd-pool", pool->getID(),
2431 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2432 static_cast<int64_t
>(1));
2436 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2437 static_cast<int64_t
>(1));
2450 ctx.currentIA().changed_leases_.push_back(old_data);
2456 for (
auto const& lease_it : leases) {
2458 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2460 updated_leases.push_back(lease);
2464 lease->reuseable_valid_lft_ = 0;
2465 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2466 lease->fqdn_rev_ = ctx.rev_dns_update_;
2467 lease->hostname_ = ctx.hostname_;
2468 uint32_t current_preferred_lft = lease->preferred_lft_;
2469 if (lease->valid_lft_ == 0) {
2471 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2473 if (!ctx.fake_allocation_) {
2474 bool update_stats =
false;
2482 if (inAllowedPool(ctx, ctx.currentIA().type_,
2483 lease->addr_,
true)) {
2484 update_stats =
true;
2489 !(lease->hasIdenticalFqdn(*lease_it)));
2491 lease->cltt_ = time(NULL);
2492 if (!fqdn_changed) {
2493 setLeaseReusable(lease, current_preferred_lft, ctx);
2496 if (lease->reuseable_valid_lft_ == 0) {
2497 ctx.currentIA().changed_leases_.push_back(lease_it);
2501 ctx.currentIA().reused_leases_.push_back(lease_it);
2508 "assigned-nas" :
"assigned-pds"),
2509 static_cast<int64_t
>(1));
2514 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2515 static_cast<int64_t
>(1));
2517 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2522 "pool" :
"pd-pool", pool->getID(),
2524 "assigned-nas" :
"assigned-pds")),
2525 static_cast<int64_t
>(1));
2530 "pool" :
"pd-pool", pool->getID(),
2532 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2533 static_cast<int64_t
>(1));
2537 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2538 static_cast<int64_t
>(1));
2542 updated_leases.push_back(lease);
2545 return (updated_leases);
2550 const uint16_t timeout,
2551 const bool remove_lease,
2552 const uint16_t max_unwarned_cycles) {
2561 max_unwarned_cycles);
2562 }
catch (
const std::exception& ex) {
2571 const uint16_t timeout,
2572 const bool remove_lease,
2573 const uint16_t max_unwarned_cycles) {
2583 bool incomplete_reclamation =
false;
2586 if (max_leases > 0) {
2595 if (leases.size() > max_leases) {
2597 incomplete_reclamation =
true;
2610 if (!leases.empty() &&
2615 size_t leases_processed = 0;
2616 for (
auto const& lease : leases) {
2624 reclaimExpiredLease(lease, remove_lease, callout_handle);
2627 reclaimExpiredLease(lease, remove_lease, callout_handle);
2631 }
catch (
const std::exception& ex) {
2633 .arg(lease->addr_.toText())
2644 if (!incomplete_reclamation) {
2645 if (leases_processed < leases.size()) {
2646 incomplete_reclamation =
true;
2663 .arg(leases_processed)
2668 if (incomplete_reclamation) {
2669 ++incomplete_v6_reclamations_;
2672 if ((max_unwarned_cycles > 0) &&
2673 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2675 .arg(max_unwarned_cycles);
2677 incomplete_v6_reclamations_ = 0;
2682 incomplete_v6_reclamations_ = 0;
2695 uint64_t deleted_leases = 0;
2701 }
catch (
const std::exception& ex) {
2708 .arg(deleted_leases);
2713 const uint16_t timeout,
2714 const bool remove_lease,
2715 const uint16_t max_unwarned_cycles) {
2724 max_unwarned_cycles);
2725 }
catch (
const std::exception& ex) {
2734 const uint16_t timeout,
2735 const bool remove_lease,
2736 const uint16_t max_unwarned_cycles) {
2746 bool incomplete_reclamation =
false;
2749 if (max_leases > 0) {
2758 if (leases.size() > max_leases) {
2760 incomplete_reclamation =
true;
2773 if (!leases.empty() &&
2778 size_t leases_processed = 0;
2779 for (
auto const& lease : leases) {
2787 reclaimExpiredLease(lease, remove_lease, callout_handle);
2790 reclaimExpiredLease(lease, remove_lease, callout_handle);
2794 }
catch (
const std::exception& ex) {
2796 .arg(lease->addr_.toText())
2807 if (!incomplete_reclamation) {
2808 if (leases_processed < leases.size()) {
2809 incomplete_reclamation =
true;
2826 .arg(leases_processed)
2831 if (incomplete_reclamation) {
2832 ++incomplete_v4_reclamations_;
2835 if ((max_unwarned_cycles > 0) &&
2836 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2838 .arg(max_unwarned_cycles);
2840 incomplete_v4_reclamations_ = 0;
2845 incomplete_v4_reclamations_ = 0;
2852template<
typename LeasePtrType>
2854AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2856 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2860template<
typename LeasePtrType>
2862AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2867 if (!lease->stateExpiredReclaimed()) {
2868 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2873AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2874 const DbReclaimMode& reclaim_mode,
2880 .arg(lease->addr_.toText())
2881 .arg(
static_cast<int>(lease->prefixlen_));
2887 bool skipped =
false;
2889 if (callout_handle) {
2897 callout_handle->deleteAllArguments();
2898 callout_handle->setArgument(
"lease6", lease);
2899 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2919 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2929 remove_lease = reclaimDeclined(lease);
2931 if (reclaim_mode == DB_RECLAIM_LEAVE_UNCHANGED) {
2935 remove_lease =
true;
2938 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2942 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2944 &lease_mgr, ph::_1));
2956 "reclaimed-leases"),
2957 static_cast<int64_t
>(1));
2963 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2969 pool->getID(),
"reclaimed-leases")),
2970 static_cast<int64_t
>(1));
2986 static_cast<int64_t
>(-1));
2991 "assigned-nas" :
"assigned-pds"),
2992 static_cast<int64_t
>(-1));
2995 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3000 "pool" :
"pd-pool", pool->getID(),
3002 "assigned-nas" :
"assigned-pds")),
3003 static_cast<int64_t
>(-1));
3010AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
3011 const DbReclaimMode& reclaim_mode,
3017 .arg(lease->addr_.toText());
3023 bool skipped =
false;
3025 if (callout_handle) {
3033 callout_handle->setArgument(
"lease4", lease);
3034 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3052 lease->hostname_.clear();
3053 lease->fqdn_fwd_ =
false;
3054 lease->fqdn_rev_ =
false;
3058 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3068 remove_lease = reclaimDeclined(lease);
3071 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3075 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3077 &lease_mgr, ph::_1));
3089 "reclaimed-leases"),
3090 static_cast<int64_t
>(1));
3095 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3100 "reclaimed-leases")),
3101 static_cast<int64_t
>(1));
3113 "assigned-addresses"),
3114 static_cast<int64_t
>(-1));
3117 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3122 "assigned-addresses")),
3123 static_cast<int64_t
>(-1));
3134 uint64_t deleted_leases = 0;
3140 }
catch (
const std::exception& ex) {
3147 .arg(deleted_leases);
3151AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3166 callout_handle->setArgument(
"lease4", lease);
3176 .arg(lease->addr_.toText());
3182 .arg(lease->addr_.toText())
3183 .arg(lease->valid_lft_);
3189 "declined-addresses"),
3190 static_cast<int64_t
>(-1));
3193 "reclaimed-declined-addresses"),
3194 static_cast<int64_t
>(1));
3198 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3202 "declined-addresses")),
3203 static_cast<int64_t
>(-1));
3207 "reclaimed-declined-addresses")),
3208 static_cast<int64_t
>(1));
3213 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3215 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3223AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3238 callout_handle->setArgument(
"lease6", lease);
3248 .arg(lease->addr_.toText());
3254 .arg(lease->addr_.toText())
3255 .arg(lease->valid_lft_);
3261 "declined-addresses"),
3262 static_cast<int64_t
>(-1));
3265 "reclaimed-declined-addresses"),
3266 static_cast<int64_t
>(1));
3270 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3274 "declined-addresses")),
3275 static_cast<int64_t
>(-1));
3279 "reclaimed-declined-addresses")),
3280 static_cast<int64_t
>(1));
3285 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3287 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3297 lease->relay_id_.clear();
3298 lease->remote_id_.clear();
3299 if (lease->getContext()) {
3306 if (lease->getContext()) {
3312template<
typename LeasePtrType>
3313void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3314 const bool remove_lease,
3315 const std::function<
void (
const LeasePtrType&)>&
3316 lease_update_fun)
const {
3324 }
else if (lease_update_fun) {
3327 lease->reuseable_valid_lft_ = 0;
3328 lease->hostname_.clear();
3329 lease->fqdn_fwd_ =
false;
3330 lease->fqdn_rev_ =
false;
3333 lease_update_fun(lease);
3342 .arg(lease->addr_.toText());
3348 return(
"<empty subnet>");
3352 subnet->getSharedNetwork(network);
3353 std::ostringstream ss;
3355 ss <<
"shared-network: " << network->getName();
3357 ss <<
"subnet id: " << subnet->getID();
3396 (!ctx.
subnet_->getReservationsOutOfPool() ||
3407 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3412 hosts.push_back(host);
3426 for (
auto const& host : hosts) {
3430 if (id_pair.first == host->getIdentifierType() &&
3431 id_pair.second == host->getIdentifier()) {
3439 return (!hosts.empty());
3461 if (ctx.
hosts_.empty()) {
3466 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3467 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3468 global_host->second->getIPv4Reservation() :
3477 if (subnet->getReservationsGlobal() &&
3479 (subnet->inRange(global_host_address))) {
3484 if (subnet->getReservationsInSubnet()) {
3485 auto host = ctx.
hosts_.find(subnet->getID());
3490 if (host != ctx.
hosts_.end() && host->second) {
3491 auto reservation = host->second->getIPv4Reservation();
3492 if (!reservation.isV4Zero() &&
3493 (!subnet->getReservationsOutOfPool() ||
3503 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3509 .arg(ctx.
query_->getLabel())
3510 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3537 auto const& classes = ctx.
query_->getClasses();
3541 bool try_clientid_lookup = (ctx.
clientid_ &&
3545 if (try_clientid_lookup) {
3554 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3559 if (subnet->getMatchClientId()) {
3560 for (
auto const& l : leases_client_id) {
3561 if (l->subnet_id_ == subnet->getID()) {
3574 if (!client_lease && ctx.
hwaddr_) {
3580 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3582 if (subnet->getMatchClientId()) {
3588 for (
auto const& client_lease_it : leases_hw_address) {
3589 Lease4Ptr existing_lease = client_lease_it;
3590 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3591 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3593 client_lease = existing_lease;
3621 auto const& classes = ctx.
query_->getClasses();
3623 while (current_subnet) {
3632 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3644 : early_global_reservations_lookup_(false),
3645 subnet_(), clientid_(), hwaddr_(),
3646 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3647 fwd_dns_update_(false), rev_dns_update_(false),
3648 hostname_(
""), callout_handle_(), fake_allocation_(false), offer_lft_(0),
3649 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3650 query_(), host_identifiers_(), unknown_requested_addr_(false),
3659 const bool fwd_dns_update,
3660 const bool rev_dns_update,
3661 const std::string& hostname,
3662 const bool fake_allocation,
3663 const uint32_t offer_lft)
3664 : early_global_reservations_lookup_(false),
3665 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3666 requested_address_(requested_addr),
3667 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3668 hostname_(hostname), callout_handle_(),
3669 fake_allocation_(fake_allocation), offer_lft_(offer_lft), old_lease_(), new_lease_(),
3670 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3681 if (subnet_ && subnet_->getReservationsInSubnet()) {
3682 auto host = hosts_.find(subnet_->getID());
3683 if (host != hosts_.cend()) {
3684 return (host->second);
3688 return (globalHost());
3693 if (subnet_ && subnet_->getReservationsGlobal()) {
3694 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3695 if (host != hosts_.cend()) {
3696 return (host->second);
3706 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3707 return (ddns_params_);
3713 return (ddns_params_);
3735 auto const& classes = ctx.
query_->getClasses();
3736 if (subnet && !subnet->clientSupported(classes)) {
3737 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3761 .arg(ctx.
query_->getLabel())
3779 !subnet->getReservationsInSubnet()) {
3785 subnet->getReservationsGlobal()) {
3788 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3791 if (!subnet->getReservationsInSubnet()) {
3797 std::map<SubnetID, ConstHostPtr> host_map;
3799 subnet->getSharedNetwork(network);
3808 const bool use_single_query = network &&
3812 if (use_single_query) {
3816 id_pair.second.size());
3820 for (
auto const& host : hosts) {
3821 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3822 host_map[host->getIPv4SubnetID()] = host;
3828 auto const& classes = ctx.
query_->getClasses();
3834 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3837 if (use_single_query) {
3838 if (host_map.count(subnet->getID()) > 0) {
3839 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3847 id_pair.second.size());
3850 ctx.
hosts_[subnet->getID()] = host;
3860 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3866 for (
auto const& host : ctx.
hosts_) {
3867 host.second->encapsulateOptions();
3877 &id_pair.second[0], id_pair.second.size());
3894 findClientLease(ctx, client_lease);
3907 if (hasAddressReservation(ctx)) {
3911 .arg(ctx.
query_->getLabel())
3912 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3918 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3925 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3929 .arg(ctx.
query_->getLabel())
3930 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3935 "v4-reservation-conflicts"),
3936 static_cast<int64_t
>(1));
3938 static_cast<int64_t
>(1));
3942 new_lease = renewLease4(client_lease, ctx);
3955 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3956 !addressReserved(client_lease->addr_, ctx)) {
3960 .arg(ctx.
query_->getLabel());
3966 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3970 new_lease = renewLease4(client_lease, ctx);
3987 .arg(ctx.
query_->getLabel());
4000 .arg(ctx.
query_->getLabel());
4002 new_lease = allocateUnreservedLease4(ctx);
4022 findClientLease(ctx, client_lease);
4038 .arg(ctx.
query_->getLabel())
4044 }
else if (hasAddressReservation(ctx)) {
4053 .arg(ctx.
query_->getLabel())
4065 if (existing && !existing->expired() &&
4066 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4071 .arg(ctx.
query_->getLabel())
4081 if (hasAddressReservation(ctx) &&
4089 if (!existing || existing->expired()) {
4093 .arg(ctx.
query_->getLabel())
4094 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4104 if ((!hasAddressReservation(ctx) ||
4110 .arg(ctx.
query_->getLabel())
4130 ((hasAddressReservation(ctx) &&
4132 inAllowedPool(ctx, client_lease->addr_))) {
4136 .arg(ctx.
query_->getLabel())
4139 return (renewLease4(client_lease, ctx));
4153 .arg(ctx.
query_->getLabel())
4169 .arg(ctx.
query_->getLabel());
4174 new_lease = allocateUnreservedLease4(ctx);
4180 if (new_lease && client_lease) {
4185 .arg(ctx.
query_->getLabel())
4186 .arg(client_lease->addr_.toText());
4192 "assigned-addresses"),
4193 static_cast<int64_t
>(-1));
4197 auto const& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4202 "assigned-addresses")),
4203 static_cast<int64_t
>(-1));
4226 if (!classes.
empty()) {
4232 for (
auto const& name : classes) {
4234 if (cl && (!cl->getOfferLft().unspecified())) {
4235 offer_lft = cl->getOfferLft();
4243 offer_lft = ctx.
subnet_->getOfferLft();
4252 if (ctx.
query_->inClass(
"BOOTP")) {
4257 uint32_t requested_lft = 0;
4260 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4262 requested_lft = opt_lft->getValue();
4270 if (!classes.
empty()) {
4276 for (
auto const& name : classes) {
4278 if (cl && (!cl->getValid().unspecified())) {
4279 candidate_lft = cl->getValid();
4286 if (!candidate_lft) {
4287 candidate_lft = ctx.
subnet_->getValid();
4292 if (requested_lft > 0) {
4293 return (candidate_lft.
get(requested_lft));
4297 return (candidate_lft.
get());
4301AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4311 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4313 time_t now = time(NULL);
4316 if (ctx.subnet_->getMatchClientId()) {
4317 client_id = ctx.clientid_;
4321 valid_lft, now, ctx.subnet_->getID()));
4324 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4325 lease->fqdn_rev_ = ctx.rev_dns_update_;
4326 lease->hostname_ = ctx.hostname_;
4332 if (ctx.callout_handle_ &&
4346 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4353 boost::dynamic_pointer_cast<const Subnet4>(ctx.subnet_);
4354 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4357 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4360 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4363 ctx.callout_handle_->setArgument(
"lease4", lease);
4368 callout_status = ctx.callout_handle_->getStatus();
4380 ctx.callout_handle_->getArgument(
"lease4", lease);
4383 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4387 lease->fqdn_fwd_ =
false;
4388 lease->fqdn_rev_ =
false;
4391 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4392 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4394 lease->pool_id_ = pool->getID();
4403 "assigned-addresses"),
4404 static_cast<int64_t
>(1));
4408 "cumulative-assigned-addresses"),
4409 static_cast<int64_t
>(1));
4415 "assigned-addresses")),
4416 static_cast<int64_t
>(1));
4421 "cumulative-assigned-addresses")),
4422 static_cast<int64_t
>(1));
4426 static_cast<int64_t
>(1));
4445AllocEngine::renewLease4(
const Lease4Ptr& lease,
4455 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4460 lease->reuseable_valid_lft_ = 0;
4461 if (!updateLease4Information(lease, ctx)) {
4462 setLeaseReusable(lease, ctx);
4494 boost::dynamic_pointer_cast<const Subnet4>(ctx.
subnet_);
4503 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4529 lease->pool_id_ = pool->getID();
4539 "assigned-addresses"),
4540 static_cast<int64_t
>(1));
4544 "cumulative-assigned-addresses"),
4545 static_cast<int64_t
>(1));
4551 "assigned-addresses")),
4552 static_cast<int64_t
>(1));
4557 "cumulative-assigned-addresses")),
4558 static_cast<int64_t
>(1));
4562 static_cast<int64_t
>(1));
4568 *lease = *old_values;
4575AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4594 expired->reuseable_valid_lft_ = 0;
4595 static_cast<void>(updateLease4Information(expired, ctx));
4599 .arg(ctx.
query_->getLabel())
4600 .arg(expired->toText());
4624 boost::dynamic_pointer_cast<const Subnet4>(ctx.
subnet_);
4658 expired->pool_id_ = pool->getID();
4666 "assigned-addresses"),
4667 static_cast<int64_t
>(1));
4671 "cumulative-assigned-addresses"),
4672 static_cast<int64_t
>(1));
4678 "assigned-addresses")),
4679 static_cast<int64_t
>(1));
4684 "cumulative-assigned-addresses")),
4685 static_cast<int64_t
>(1));
4689 static_cast<int64_t
>(1));
4701AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4703 ctx.conflicting_lease_.reset();
4707 if (exist_lease->expired()) {
4712 ctx.old_lease_->hostname_.clear();
4713 ctx.old_lease_->fqdn_fwd_ =
false;
4714 ctx.old_lease_->fqdn_rev_ =
false;
4715 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4721 ctx.conflicting_lease_ = exist_lease;
4725 return (createLease4(ctx, candidate, callout_status));
4731AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4745 ctx.subnet_->getSharedNetwork(network);
4752 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4766 uint64_t subnets_with_unavail_leases = 0;
4769 uint64_t subnets_with_unavail_pools = 0;
4771 auto const& classes = ctx.query_->getClasses();
4775 if (subnet->getMatchClientId()) {
4776 client_id = ctx.clientid_;
4788 (attempts_ == 0 || possible_attempts < attempts_) ?
4792 if (max_attempts > 0) {
4795 ++subnets_with_unavail_leases;
4799 ++subnets_with_unavail_pools;
4802 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4807 for (
uint128_t i = 0; i < max_attempts; ++i) {
4812 IOAddress candidate = allocator->pickAddress(classes,
4814 ctx.requested_address_);
4821 if (exclude_first_last_24) {
4823 auto const& bytes = candidate.
toBytes();
4824 if ((bytes.size() != 4) ||
4825 (bytes[3] == 0) || (bytes[3] == 255U)) {
4832 if (check_reservation_first && addressReserved(candidate, ctx)) {
4841 !resource_handler.
tryLock4(candidate)) {
4850 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4852 new_lease = createLease4(ctx, candidate, callout_status);
4856 if (exist_lease->expired() &&
4857 (check_reservation_first || !addressReserved(candidate, ctx))) {
4859 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4877 subnet = subnet->getNextSubnet(original_subnet, classes);
4880 ctx.subnet_ = subnet;
4889 .arg(ctx.query_->getLabel())
4890 .arg(network->getName())
4891 .arg(subnets_with_unavail_leases)
4892 .arg(subnets_with_unavail_pools);
4894 static_cast<int64_t
>(1));
4897 "v4-allocation-fail-shared-network"),
4898 static_cast<int64_t
>(1));
4902 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4903 if (shared_network.empty()) {
4904 shared_network =
"(none)";
4907 .arg(ctx.query_->getLabel())
4908 .arg(ctx.subnet_->toText())
4909 .arg(ctx.subnet_->getID())
4910 .arg(shared_network);
4912 static_cast<int64_t
>(1));
4915 "v4-allocation-fail-subnet"),
4916 static_cast<int64_t
>(1));
4918 if (total_attempts == 0) {
4924 .arg(ctx.query_->getLabel());
4926 static_cast<int64_t
>(1));
4929 "v4-allocation-fail-no-pools"),
4930 static_cast<int64_t
>(1));
4937 .arg(ctx.query_->getLabel())
4938 .arg(total_attempts);
4940 static_cast<int64_t
>(1));
4943 "v4-allocation-fail"),
4944 static_cast<int64_t
>(1));
4947 if (!classes.empty()) {
4949 .arg(ctx.query_->getLabel())
4950 .arg(classes.toText());
4952 static_cast<int64_t
>(1));
4955 "v4-allocation-fail-classes"),
4956 static_cast<int64_t
>(1));
4963AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4965 bool changed =
false;
4966 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4968 lease->subnet_id_ = ctx.
subnet_->getID();
4970 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4972 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4977 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4981 }
else if (lease->client_id_) {
4985 lease->cltt_ = time(NULL);
4991 if (lease->valid_lft_ != lease->current_valid_lft_) {
5015 bool changed =
false;
5018 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5033 sao->boolValue() && ctx.
query_->inClass(
"STASH_AGENT_OPTIONS")) {
5042 extended_info->set(
"sub-options", relay_agent);
5046 std::vector<uint8_t> bytes = remote_id->toBinary();
5047 lease->remote_id_ = bytes;
5048 if (bytes.size() > 0) {
5049 extended_info->set(
"remote-id",
5056 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5057 lease->relay_id_ = bytes;
5058 if (bytes.size() > 0) {
5059 extended_info->set(
"relay-id",
5065 return (lease->updateUserContextISC(
"relay-agent-info", extended_info));
5075 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5080 if (ctx.
query_->relay_info_.empty()) {
5095 for (
auto const& relay : ctx.
query_->relay_info_) {
5104 if (!relay.options_.empty()) {
5109 const uint8_t* cp = buf.
getData();
5110 std::vector<uint8_t> bytes;
5111 std::stringstream ss;
5119 if (remote_id_it != relay.options_.end()) {
5120 OptionPtr remote_id = remote_id_it->second;
5122 std::vector<uint8_t> bytes = remote_id->toBinary();
5123 if (bytes.size() > 0) {
5124 relay_elem->set(
"remote-id",
5131 if (relay_id_it != relay.options_.end()) {
5132 OptionPtr relay_id = relay_id_it->second;
5134 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5135 if (bytes.size() > 0) {
5136 relay_elem->set(
"relay-id",
5143 extended_info->add(relay_elem);
5147 if (lease->updateUserContextISC(
"relay-info", extended_info)) {
5153AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5154 const ClientContext4& ctx)
const {
5156 lease->reuseable_valid_lft_ = 0;
5172 if (lease->cltt_ < lease->current_cltt_) {
5176 uint32_t age = lease->cltt_ - lease->current_cltt_;
5178 if (age >= lease->current_valid_lft_) {
5183 uint32_t max_age = 0;
5184 if (!subnet->getCacheMaxAge().unspecified()) {
5185 max_age = subnet->getCacheMaxAge().get();
5186 if ((max_age == 0) || (age > max_age)) {
5192 if (!subnet->getCacheThreshold().unspecified()) {
5193 double threshold = subnet->getCacheThreshold().get();
5194 if ((threshold <= 0.) || (threshold > 1.)) {
5197 max_age = lease->valid_lft_ * threshold;
5198 if (age > max_age) {
5209 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5213AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5214 uint32_t current_preferred_lft,
5215 const ClientContext6& ctx)
const {
5217 lease->reuseable_valid_lft_ = 0;
5218 lease->reuseable_preferred_lft_ = 0;
5228 if (lease->cltt_ < lease->current_cltt_) {
5232 uint32_t age = lease->cltt_ - lease->current_cltt_;
5234 if (age >= lease->current_valid_lft_) {
5239 uint32_t max_age = 0;
5240 if (!subnet->getCacheMaxAge().unspecified()) {
5241 max_age = subnet->getCacheMaxAge().get();
5242 if ((max_age == 0) || (age > max_age)) {
5248 if (!subnet->getCacheThreshold().unspecified()) {
5249 double threshold = subnet->getCacheThreshold().get();
5250 if ((threshold <= 0.) || (threshold > 1.)) {
5253 max_age = lease->valid_lft_ * threshold;
5254 if (age > max_age) {
5266 (current_preferred_lft == 0)) {
5268 lease->reuseable_preferred_lft_ = current_preferred_lft;
5269 }
else if (current_preferred_lft > age) {
5270 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5278 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
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 ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
AllocEngine(isc::util::uint128_t const &attempts)
Constructor.
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.
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.
Resource race avoidance RAII handler for DHCPv4.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
Resource race avoidance RAII handler.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
RAII object enabling copying options retrieved from the packet.
static bool subnetsIncludeMatchClientId(const 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.
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
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
static const uint32_t STATE_REGISTERED
Registered self-generated lease.