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_(), 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();
1205 for (
Subnet6Ptr subnet = ctx.subnet_; subnet;
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);
2203 ctx.subnet_ = subnet;
2211 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2212 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2229 "assigned-nas" :
"assigned-pds"),
2230 static_cast<int64_t>(-1));
2232 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2237 "pool" :
"pd-pool", pool->getID(),
2239 "assigned-nas" :
"assigned-pds")),
2240 static_cast<int64_t>(-1));
2244 ctx.currentIA().old_leases_.push_back(lease);
2251 .arg(ctx.query_->getLabel())
2252 .arg(lease->toText());
2257 bool changed =
false;
2260 uint32_t current_preferred_lft = lease->preferred_lft_;
2261 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2264 if ((lease->preferred_lft_ != current_preferred_lft) ||
2265 (lease->valid_lft_ != lease->current_valid_lft_)) {
2269 lease->cltt_ = time(NULL);
2270 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2271 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2272 (lease->hostname_ != ctx.hostname_)) {
2274 lease->hostname_ = ctx.hostname_;
2275 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2276 lease->fqdn_rev_ = ctx.rev_dns_update_;
2278 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2280 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2282 lease->hwaddr_ = ctx.hwaddr_;
2290 .arg(ctx.query_->getLabel())
2291 .arg(lease->toText());
2295 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2296 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2307 ScopedEnableOptionsCopy<Pkt6> query6_options_copy(ctx.query_);
2310 callout_handle->setArgument(
"query6", ctx.query_);
2313 callout_handle->setArgument(
"lease6", lease);
2317 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2319 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2332 .arg(ctx.query_->getName());
2339 bool update_stats =
false;
2343 if (old_data->expired()) {
2344 reclaimExpiredLease(old_data, ctx.callout_handle_);
2348 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2349 update_stats =
true;
2362 setLeaseReusable(lease, current_preferred_lft, ctx);
2367 if (lease->reuseable_valid_lft_ == 0) {
2368 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2370 lease->pool_id_ = pool->getID();
2379 "assigned-nas" :
"assigned-pds"),
2380 static_cast<int64_t>(1));
2385 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2386 static_cast<int64_t>(1));
2388 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2393 "pool" :
"pd-pool", pool->getID(),
2395 "assigned-nas" :
"assigned-pds")),
2396 static_cast<int64_t>(1));
2401 "pool" :
"pd-pool", pool->getID(),
2403 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2404 static_cast<int64_t>(1));
2408 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2409 static_cast<int64_t>(1));
2422 ctx.currentIA().changed_leases_.push_back(old_data);
2428 for (
auto const& lease_it : leases) {
2430 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2432 updated_leases.push_back(lease);
2436 lease->reuseable_valid_lft_ = 0;
2437 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2438 lease->fqdn_rev_ = ctx.rev_dns_update_;
2439 lease->hostname_ = ctx.hostname_;
2440 uint32_t current_preferred_lft = lease->preferred_lft_;
2441 if (lease->valid_lft_ == 0) {
2443 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2445 if (!ctx.fake_allocation_) {
2446 bool update_stats =
false;
2454 if (inAllowedPool(ctx, ctx.currentIA().type_,
2455 lease->addr_,
true)) {
2456 update_stats =
true;
2461 !(lease->hasIdenticalFqdn(*lease_it)));
2463 lease->cltt_ = time(NULL);
2464 if (!fqdn_changed) {
2465 setLeaseReusable(lease, current_preferred_lft, ctx);
2467 if (lease->reuseable_valid_lft_ == 0) {
2468 ctx.currentIA().changed_leases_.push_back(lease_it);
2476 "assigned-nas" :
"assigned-pds"),
2477 static_cast<int64_t>(1));
2482 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2483 static_cast<int64_t>(1));
2485 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2490 "pool" :
"pd-pool", pool->getID(),
2492 "assigned-nas" :
"assigned-pds")),
2493 static_cast<int64_t>(1));
2498 "pool" :
"pd-pool", pool->getID(),
2500 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2501 static_cast<int64_t>(1));
2505 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2506 static_cast<int64_t>(1));
2510 updated_leases.push_back(lease);
2513 return (updated_leases);
2518 const uint16_t timeout,
2519 const bool remove_lease,
2520 const uint16_t max_unwarned_cycles) {
2529 max_unwarned_cycles);
2530 }
catch (
const std::exception& ex) {
2539 const uint16_t timeout,
2540 const bool remove_lease,
2541 const uint16_t max_unwarned_cycles) {
2551 bool incomplete_reclamation =
false;
2554 if (max_leases > 0) {
2558 lease_mgr.getExpiredLeases6(leases, max_leases + 1);
2563 if (leases.size() > max_leases) {
2565 incomplete_reclamation =
true;
2572 lease_mgr.getExpiredLeases6(leases, max_leases);
2578 if (!leases.empty() &&
2583 size_t leases_processed = 0;
2584 for (
auto const& lease : leases) {
2592 reclaimExpiredLease(lease, remove_lease, callout_handle);
2595 reclaimExpiredLease(lease, remove_lease, callout_handle);
2599 }
catch (
const std::exception& ex) {
2601 .arg(lease->addr_.toText())
2608 if ((timeout > 0) && (stopwatch.getTotalMilliseconds() >= timeout)) {
2612 if (!incomplete_reclamation) {
2613 if (leases_processed < leases.size()) {
2614 incomplete_reclamation =
true;
2631 .arg(leases_processed)
2632 .arg(stopwatch.logFormatTotalDuration());
2636 if (incomplete_reclamation) {
2637 ++incomplete_v6_reclamations_;
2640 if ((max_unwarned_cycles > 0) &&
2641 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2643 .arg(max_unwarned_cycles);
2645 incomplete_v6_reclamations_ = 0;
2650 incomplete_v6_reclamations_ = 0;
2663 uint64_t deleted_leases = 0;
2667 deleted_leases = lease_mgr.deleteExpiredReclaimedLeases6(secs);
2669 }
catch (
const std::exception& ex) {
2676 .arg(deleted_leases);
2681 const uint16_t timeout,
2682 const bool remove_lease,
2683 const uint16_t max_unwarned_cycles) {
2692 max_unwarned_cycles);
2693 }
catch (
const std::exception& ex) {
2702 const uint16_t timeout,
2703 const bool remove_lease,
2704 const uint16_t max_unwarned_cycles) {
2714 bool incomplete_reclamation =
false;
2717 if (max_leases > 0) {
2721 lease_mgr.getExpiredLeases4(leases, max_leases + 1);
2726 if (leases.size() > max_leases) {
2728 incomplete_reclamation =
true;
2735 lease_mgr.getExpiredLeases4(leases, max_leases);
2741 if (!leases.empty() &&
2746 size_t leases_processed = 0;
2747 for (
auto const& lease : leases) {
2755 reclaimExpiredLease(lease, remove_lease, callout_handle);
2758 reclaimExpiredLease(lease, remove_lease, callout_handle);
2762 }
catch (
const std::exception& ex) {
2764 .arg(lease->addr_.toText())
2771 if ((timeout > 0) && (stopwatch.getTotalMilliseconds() >= timeout)) {
2775 if (!incomplete_reclamation) {
2776 if (leases_processed < leases.size()) {
2777 incomplete_reclamation =
true;
2794 .arg(leases_processed)
2795 .arg(stopwatch.logFormatTotalDuration());
2799 if (incomplete_reclamation) {
2800 ++incomplete_v4_reclamations_;
2803 if ((max_unwarned_cycles > 0) &&
2804 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2806 .arg(max_unwarned_cycles);
2808 incomplete_v4_reclamations_ = 0;
2813 incomplete_v4_reclamations_ = 0;
2820template<
typename LeasePtrType>
2822AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2824 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2828template<
typename LeasePtrType>
2830AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2835 if (!lease->stateExpiredReclaimed()) {
2836 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2841AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2842 const DbReclaimMode& reclaim_mode,
2848 .arg(lease->addr_.toText())
2849 .arg(
static_cast<int>(lease->prefixlen_));
2855 bool skipped =
false;
2856 if (callout_handle) {
2864 callout_handle->deleteAllArguments();
2865 callout_handle->setArgument(
"lease6", lease);
2866 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2886 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2896 remove_lease = reclaimDeclined(lease);
2899 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2903 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2905 &lease_mgr, ph::_1));
2914 "reclaimed-leases"),
2915 static_cast<int64_t
>(1));
2931 static_cast<int64_t
>(-1));
2933 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2935 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2941 static_cast<int64_t
>(-1));
2946 "reclaimed-leases")),
2947 static_cast<int64_t
>(1));
2956 static_cast<int64_t
>(-1));
2958 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
2960 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2966 static_cast<int64_t
>(-1));
2971 "reclaimed-leases")),
2972 static_cast<int64_t
>(1));
2979AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2980 const DbReclaimMode& reclaim_mode,
2986 .arg(lease->addr_.toText());
2992 bool skipped =
false;
2993 if (callout_handle) {
3001 callout_handle->setArgument(
"lease4", lease);
3002 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3020 lease->hostname_.clear();
3021 lease->fqdn_fwd_ =
false;
3022 lease->fqdn_rev_ =
false;
3026 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3036 remove_lease = reclaimDeclined(lease);
3039 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3043 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3045 &lease_mgr, ph::_1));
3057 "reclaimed-leases"),
3058 static_cast<int64_t
>(1));
3068 "assigned-addresses"),
3069 static_cast<int64_t
>(-1));
3071 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
3073 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3078 "assigned-addresses")),
3079 static_cast<int64_t
>(-1));
3084 "reclaimed-leases")),
3085 static_cast<int64_t
>(1));
3096 uint64_t deleted_leases = 0;
3100 deleted_leases = lease_mgr.deleteExpiredReclaimedLeases4(secs);
3102 }
catch (
const std::exception& ex) {
3109 .arg(deleted_leases);
3113AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3128 callout_handle->setArgument(
"lease4", lease);
3138 .arg(lease->addr_.toText());
3144 .arg(lease->addr_.toText())
3145 .arg(lease->valid_lft_);
3151 "declined-addresses"),
3152 static_cast<int64_t
>(-1));
3155 "reclaimed-declined-addresses"),
3156 static_cast<int64_t
>(1));
3158 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
3160 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3164 "declined-addresses")),
3165 static_cast<int64_t
>(-1));
3169 "reclaimed-declined-addresses")),
3170 static_cast<int64_t
>(1));
3175 stats_mgr.addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3177 stats_mgr.addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3185AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3200 callout_handle->setArgument(
"lease6", lease);
3210 .arg(lease->addr_.toText());
3216 .arg(lease->addr_.toText())
3217 .arg(lease->valid_lft_);
3223 "declined-addresses"),
3224 static_cast<int64_t
>(-1));
3227 "reclaimed-declined-addresses"),
3228 static_cast<int64_t
>(1));
3230 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getBySubnetId(lease->subnet_id_);
3232 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3236 "declined-addresses")),
3237 static_cast<int64_t
>(-1));
3241 "reclaimed-declined-addresses")),
3242 static_cast<int64_t
>(1));
3247 stats_mgr.addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3249 stats_mgr.addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3259 lease->relay_id_.clear();
3260 lease->remote_id_.clear();
3261 if (lease->getContext()) {
3268 if (lease->getContext()) {
3274template<
typename LeasePtrType>
3275void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3276 const bool remove_lease,
3277 const std::function<
void (
const LeasePtrType&)>&
3278 lease_update_fun)
const {
3285 lease_mgr.deleteLease(lease);
3286 }
else if (lease_update_fun) {
3289 lease->reuseable_valid_lft_ = 0;
3290 lease->hostname_.clear();
3291 lease->fqdn_fwd_ =
false;
3292 lease->fqdn_rev_ =
false;
3295 lease_update_fun(lease);
3304 .arg(lease->addr_.toText());
3310 return(
"<empty subnet>");
3314 subnet->getSharedNetwork(network);
3315 std::ostringstream ss;
3317 ss <<
"shared-network: " << network->getName();
3319 ss <<
"subnet id: " << subnet->getID();
3358 (!ctx.
subnet_->getReservationsOutOfPool() ||
3369 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3374 hosts.push_back(host);
3388 for (
auto const& host : hosts) {
3392 if (id_pair.first == host->getIdentifierType() &&
3393 id_pair.second == host->getIdentifier()) {
3401 return (!hosts.empty());
3423 if (ctx.
hosts_.empty()) {
3428 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3429 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3430 global_host->second->getIPv4Reservation() :
3439 if (subnet->getReservationsGlobal() &&
3441 (subnet->inRange(global_host_address))) {
3446 if (subnet->getReservationsInSubnet()) {
3447 auto host = ctx.
hosts_.find(subnet->getID());
3452 if (host != ctx.
hosts_.end() && host->second) {
3453 auto reservation = host->second->getIPv4Reservation();
3454 if (!reservation.isV4Zero() &&
3455 (!subnet->getReservationsOutOfPool() ||
3465 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3471 .arg(ctx.
query_->getLabel())
3472 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3499 auto const& classes = ctx.
query_->getClasses();
3503 bool try_clientid_lookup = (ctx.
clientid_ &&
3507 if (try_clientid_lookup) {
3515 for (
Subnet4Ptr subnet = original_subnet; subnet;
3516 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3521 if (subnet->getMatchClientId()) {
3522 for (
auto const& l : leases_client_id) {
3523 if (l->subnet_id_ == subnet->getID()) {
3536 if (!client_lease && ctx.
hwaddr_) {
3541 for (
Subnet4Ptr subnet = original_subnet; subnet;
3542 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3544 if (subnet->getMatchClientId()) {
3550 for (
auto const& client_lease_it : leases_hw_address) {
3551 Lease4Ptr existing_lease = client_lease_it;
3552 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3553 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3555 client_lease = existing_lease;
3583 auto const& classes = ctx.
query_->getClasses();
3585 while (current_subnet) {
3594 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3606 : early_global_reservations_lookup_(false),
3607 subnet_(), clientid_(), hwaddr_(),
3608 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3609 fwd_dns_update_(false), rev_dns_update_(false),
3610 hostname_(
""), callout_handle_(), fake_allocation_(false), offer_lft_(0),
3611 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3612 query_(), host_identifiers_(), unknown_requested_addr_(false),
3621 const bool fwd_dns_update,
3622 const bool rev_dns_update,
3623 const std::string& hostname,
3624 const bool fake_allocation,
3625 const uint32_t offer_lft)
3626 : early_global_reservations_lookup_(false),
3627 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3628 requested_address_(requested_addr),
3629 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3630 hostname_(hostname), callout_handle_(),
3631 fake_allocation_(fake_allocation), offer_lft_(offer_lft), old_lease_(), new_lease_(),
3632 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3643 if (subnet_ && subnet_->getReservationsInSubnet()) {
3644 auto host = hosts_.find(subnet_->getID());
3645 if (host != hosts_.cend()) {
3646 return (host->second);
3650 return (globalHost());
3655 if (subnet_ && subnet_->getReservationsGlobal()) {
3656 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3657 if (host != hosts_.cend()) {
3658 return (host->second);
3668 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3669 return (ddns_params_);
3675 return (ddns_params_);
3697 auto const& classes = ctx.
query_->getClasses();
3698 if (subnet && !subnet->clientSupported(classes)) {
3699 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3720 .arg(ctx.
query_->getLabel())
3738 !subnet->getReservationsInSubnet()) {
3744 subnet->getReservationsGlobal()) {
3747 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3750 if (!subnet->getReservationsInSubnet()) {
3756 std::map<SubnetID, ConstHostPtr> host_map;
3758 subnet->getSharedNetwork(network);
3767 const bool use_single_query = network &&
3771 if (use_single_query) {
3775 id_pair.second.size());
3779 for (
auto const& host : hosts) {
3780 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3781 host_map[host->getIPv4SubnetID()] = host;
3787 auto const& classes = ctx.
query_->getClasses();
3793 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3796 if (use_single_query) {
3797 if (host_map.count(subnet->getID()) > 0) {
3798 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3806 id_pair.second.size());
3809 ctx.
hosts_[subnet->getID()] = host;
3819 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3825 for (
auto const& host : ctx.
hosts_) {
3826 host.second->encapsulateOptions();
3836 &id_pair.second[0], id_pair.second.size());
3853 findClientLease(ctx, client_lease);
3866 if (hasAddressReservation(ctx)) {
3870 .arg(ctx.
query_->getLabel())
3871 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3877 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3884 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3888 .arg(ctx.
query_->getLabel())
3889 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3894 "v4-reservation-conflicts"),
3895 static_cast<int64_t
>(1));
3897 static_cast<int64_t
>(1));
3901 new_lease = renewLease4(client_lease, ctx);
3914 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3915 !addressReserved(client_lease->addr_, ctx)) {
3919 .arg(ctx.
query_->getLabel());
3925 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3929 new_lease = renewLease4(client_lease, ctx);
3946 .arg(ctx.
query_->getLabel());
3959 .arg(ctx.
query_->getLabel());
3961 new_lease = allocateUnreservedLease4(ctx);
3981 findClientLease(ctx, client_lease);
3997 .arg(ctx.
query_->getLabel())
4003 }
else if (hasAddressReservation(ctx)) {
4012 .arg(ctx.
query_->getLabel())
4024 if (existing && !existing->expired() &&
4025 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4030 .arg(ctx.
query_->getLabel())
4040 if (hasAddressReservation(ctx) &&
4048 if (!existing || existing->expired()) {
4052 .arg(ctx.
query_->getLabel())
4053 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4063 if ((!hasAddressReservation(ctx) ||
4069 .arg(ctx.
query_->getLabel())
4089 ((hasAddressReservation(ctx) &&
4091 inAllowedPool(ctx, client_lease->addr_))) {
4095 .arg(ctx.
query_->getLabel())
4098 return (renewLease4(client_lease, ctx));
4112 .arg(ctx.
query_->getLabel())
4128 .arg(ctx.
query_->getLabel());
4133 new_lease = allocateUnreservedLease4(ctx);
4139 if (new_lease && client_lease) {
4144 .arg(ctx.
query_->getLabel())
4145 .arg(client_lease->addr_.toText());
4151 "assigned-addresses"),
4152 static_cast<int64_t
>(-1));
4154 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(client_lease->subnet_id_);
4156 auto const& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4161 "assigned-addresses")),
4162 static_cast<int64_t
>(-1));
4185 if (!classes.empty()) {
4191 for (
auto const& name : classes) {
4193 if (cl && (!cl->getOfferLft().unspecified())) {
4194 offer_lft = cl->getOfferLft();
4201 if (offer_lft.unspecified()) {
4202 offer_lft = ctx.
subnet_->getOfferLft();
4205 return (offer_lft.unspecified() ? 0 : offer_lft.get());
4211 if (ctx.
query_->inClass(
"BOOTP")) {
4216 uint32_t requested_lft = 0;
4219 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4221 requested_lft = opt_lft->getValue();
4227 Triplet<uint32_t> candidate_lft;
4229 if (!classes.empty()) {
4235 for (
auto const& name : classes) {
4237 if (cl && (!cl->getValid().unspecified())) {
4238 candidate_lft = cl->getValid();
4245 if (!candidate_lft) {
4246 candidate_lft = ctx.
subnet_->getValid();
4251 if (requested_lft > 0) {
4252 return (candidate_lft.get(requested_lft));
4256 return (candidate_lft.get());
4260AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4270 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4272 time_t now = time(NULL);
4275 if (ctx.subnet_->getMatchClientId()) {
4276 client_id = ctx.clientid_;
4280 valid_lft, now, ctx.subnet_->getID()));
4283 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4284 lease->fqdn_rev_ = ctx.rev_dns_update_;
4285 lease->hostname_ = ctx.hostname_;
4291 if (ctx.callout_handle_ &&
4301 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.query_);
4305 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4311 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4312 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4315 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4318 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4321 ctx.callout_handle_->setArgument(
"lease4", lease);
4326 callout_status = ctx.callout_handle_->getStatus();
4338 ctx.callout_handle_->getArgument(
"lease4", lease);
4341 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4345 lease->fqdn_fwd_ =
false;
4346 lease->fqdn_rev_ =
false;
4349 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4350 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4352 lease->pool_id_ = pool->getID();
4361 "assigned-addresses"),
4362 static_cast<int64_t
>(1));
4366 "cumulative-assigned-addresses"),
4367 static_cast<int64_t
>(1));
4373 "assigned-addresses")),
4374 static_cast<int64_t
>(1));
4379 "cumulative-assigned-addresses")),
4380 static_cast<int64_t
>(1));
4384 static_cast<int64_t
>(1));
4403AllocEngine::renewLease4(
const Lease4Ptr& lease,
4413 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4418 lease->reuseable_valid_lft_ = 0;
4419 if (!updateLease4Information(lease, ctx)) {
4420 setLeaseReusable(lease, ctx);
4445 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4460 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4486 lease->pool_id_ = pool->getID();
4496 "assigned-addresses"),
4497 static_cast<int64_t
>(1));
4501 "cumulative-assigned-addresses"),
4502 static_cast<int64_t
>(1));
4508 "assigned-addresses")),
4509 static_cast<int64_t
>(1));
4514 "cumulative-assigned-addresses")),
4515 static_cast<int64_t
>(1));
4519 static_cast<int64_t
>(1));
4525 *lease = *old_values;
4532AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4551 expired->reuseable_valid_lft_ = 0;
4552 static_cast<void>(updateLease4Information(expired, ctx));
4556 .arg(ctx.
query_->getLabel())
4557 .arg(expired->toText());
4564 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(ctx.
query_);
4614 expired->pool_id_ = pool->getID();
4622 "assigned-addresses"),
4623 static_cast<int64_t
>(1));
4627 "cumulative-assigned-addresses"),
4628 static_cast<int64_t
>(1));
4634 "assigned-addresses")),
4635 static_cast<int64_t
>(1));
4640 "cumulative-assigned-addresses")),
4641 static_cast<int64_t
>(1));
4645 static_cast<int64_t
>(1));
4657AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4659 ctx.conflicting_lease_.reset();
4663 if (exist_lease->expired()) {
4668 ctx.old_lease_->hostname_.clear();
4669 ctx.old_lease_->fqdn_fwd_ =
false;
4670 ctx.old_lease_->fqdn_rev_ =
false;
4671 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4677 ctx.conflicting_lease_ = exist_lease;
4681 return (createLease4(ctx, candidate, callout_status));
4687AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4701 ctx.subnet_->getSharedNetwork(network);
4708 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4722 uint64_t subnets_with_unavail_leases = 0;
4725 uint64_t subnets_with_unavail_pools = 0;
4727 auto const& classes = ctx.query_->getClasses();
4731 if (subnet->getMatchClientId()) {
4732 client_id = ctx.clientid_;
4744 (attempts_ == 0 || possible_attempts < attempts_) ?
4748 if (max_attempts > 0) {
4751 ++subnets_with_unavail_leases;
4755 ++subnets_with_unavail_pools;
4758 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4763 for (
uint128_t i = 0; i < max_attempts; ++i) {
4768 IOAddress candidate = allocator->pickAddress(classes,
4770 ctx.requested_address_);
4773 if (candidate.isV4Zero()) {
4777 if (exclude_first_last_24) {
4779 auto const& bytes = candidate.
toBytes();
4780 if ((bytes.size() != 4) ||
4781 (bytes[3] == 0) || (bytes[3] == 255U)) {
4788 if (check_reservation_first && addressReserved(candidate, ctx)) {
4797 !resource_handler.tryLock4(candidate)) {
4806 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4808 new_lease = createLease4(ctx, candidate, callout_status);
4812 if (exist_lease->expired() &&
4813 (check_reservation_first || !addressReserved(candidate, ctx))) {
4815 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4833 subnet = subnet->getNextSubnet(original_subnet, classes);
4836 ctx.subnet_ = subnet;
4845 .arg(ctx.query_->getLabel())
4846 .arg(network->getName())
4847 .arg(subnets_with_unavail_leases)
4848 .arg(subnets_with_unavail_pools);
4850 static_cast<int64_t
>(1));
4853 "v4-allocation-fail-shared-network"),
4854 static_cast<int64_t
>(1));
4858 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4859 if (shared_network.empty()) {
4860 shared_network =
"(none)";
4863 .arg(ctx.query_->getLabel())
4864 .arg(ctx.subnet_->toText())
4865 .arg(ctx.subnet_->getID())
4866 .arg(shared_network);
4868 static_cast<int64_t
>(1));
4871 "v4-allocation-fail-subnet"),
4872 static_cast<int64_t
>(1));
4874 if (total_attempts == 0) {
4880 .arg(ctx.query_->getLabel());
4882 static_cast<int64_t
>(1));
4885 "v4-allocation-fail-no-pools"),
4886 static_cast<int64_t
>(1));
4893 .arg(ctx.query_->getLabel())
4894 .arg(total_attempts);
4896 static_cast<int64_t
>(1));
4899 "v4-allocation-fail"),
4900 static_cast<int64_t
>(1));
4903 if (!classes.empty()) {
4905 .arg(ctx.query_->getLabel())
4906 .arg(classes.toText());
4908 static_cast<int64_t
>(1));
4911 "v4-allocation-fail-classes"),
4912 static_cast<int64_t
>(1));
4919AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4921 bool changed =
false;
4922 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4924 lease->subnet_id_ = ctx.
subnet_->getID();
4926 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4928 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4933 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4937 }
else if (lease->client_id_) {
4941 lease->cltt_ = time(NULL);
4947 if (lease->valid_lft_ != lease->current_valid_lft_) {
4971 bool changed =
false;
4974 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4989 sao->boolValue() && ctx.
query_->inClass(
"STASH_AGENT_OPTIONS")) {
4998 extended_info->set(
"sub-options", relay_agent);
5002 std::vector<uint8_t> bytes = remote_id->toBinary();
5003 lease->remote_id_ = bytes;
5004 if (bytes.size() > 0) {
5005 extended_info->set(
"remote-id",
5012 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5013 lease->relay_id_ = bytes;
5014 if (bytes.size() > 0) {
5015 extended_info->set(
"relay-id",
5023 if (user_context && (user_context->getType() ==
Element::map)) {
5024 mutable_user_context =
copy(user_context, 0);
5039 ConstElementPtr old_extended_info = mutable_isc->get(
"relay-agent-info");
5040 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5042 mutable_isc->set(
"relay-agent-info", extended_info);
5043 mutable_user_context->set(
"ISC", mutable_isc);
5047 lease->setContext(mutable_user_context);
5059 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5064 if (ctx.
query_->relay_info_.empty()) {
5079 for (
auto const& relay : ctx.
query_->relay_info_) {
5088 if (!relay.options_.empty()) {
5092 if (buf.getLength() > 0) {
5093 const uint8_t* cp = buf.getData();
5094 std::vector<uint8_t> bytes;
5095 std::stringstream ss;
5097 bytes.assign(cp, cp + buf.getLength());
5103 if (remote_id_it != relay.options_.end()) {
5104 OptionPtr remote_id = remote_id_it->second;
5106 std::vector<uint8_t> bytes = remote_id->toBinary();
5107 if (bytes.size() > 0) {
5108 relay_elem->set(
"remote-id",
5115 if (relay_id_it != relay.options_.end()) {
5116 OptionPtr relay_id = relay_id_it->second;
5118 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5119 if (bytes.size() > 0) {
5120 relay_elem->set(
"relay-id",
5127 extended_info->add(relay_elem);
5133 if (user_context && (user_context->getType() ==
Element::map)) {
5134 mutable_user_context =
copy(user_context, 0);
5150 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5152 mutable_isc->set(
"relay-info", extended_info);
5153 mutable_user_context->set(
"ISC", mutable_isc);
5157 lease->setContext(mutable_user_context);
5161AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5162 const ClientContext4& ctx)
const {
5164 lease->reuseable_valid_lft_ = 0;
5180 if (lease->cltt_ < lease->current_cltt_) {
5184 uint32_t age = lease->cltt_ - lease->current_cltt_;
5186 if (age >= lease->current_valid_lft_) {
5191 uint32_t max_age = 0;
5192 if (!subnet->getCacheMaxAge().unspecified()) {
5193 max_age = subnet->getCacheMaxAge().get();
5194 if ((max_age == 0) || (age > max_age)) {
5200 if (!subnet->getCacheThreshold().unspecified()) {
5201 double threshold = subnet->getCacheThreshold().get();
5202 if ((threshold <= 0.) || (threshold > 1.)) {
5205 max_age = lease->valid_lft_ * threshold;
5206 if (age > max_age) {
5217 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5221AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5222 uint32_t current_preferred_lft,
5223 const ClientContext6& ctx)
const {
5225 lease->reuseable_valid_lft_ = 0;
5226 lease->reuseable_preferred_lft_ = 0;
5236 if (lease->cltt_ < lease->current_cltt_) {
5240 uint32_t age = lease->cltt_ - lease->current_cltt_;
5242 if (age >= lease->current_valid_lft_) {
5247 uint32_t max_age = 0;
5248 if (!subnet->getCacheMaxAge().unspecified()) {
5249 max_age = subnet->getCacheMaxAge().get();
5250 if ((max_age == 0) || (age > max_age)) {
5256 if (!subnet->getCacheThreshold().unspecified()) {
5257 double threshold = subnet->getCacheThreshold().get();
5258 if ((threshold <= 0.) || (threshold > 1.)) {
5261 max_age = lease->valid_lft_ * threshold;
5262 if (age > max_age) {
5274 (current_preferred_lft == 0)) {
5276 lease->reuseable_preferred_lft_ = current_preferred_lft;
5277 }
else if (current_preferred_lft > age) {
5278 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5286 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
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 std::string labelNetworkOrSubnet(SubnetPtr subnet)
Generates a label for subnet or shared-network from subnet.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
AllocEngine(isc::util::uint128_t const &attempts)
Constructor.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
void clearReclaimedExtendedInfo(const Lease4Ptr &lease) const
Clear extended info from a reclaimed V4 lease.
isc::util::ReadWriteMutex rw_mutex_
The read-write mutex.
static void getLifetimes6(ClientContext6 &ctx, uint32_t &preferred, uint32_t &valid)
Determines the preferred and valid v6 lease lifetimes.
static void findReservation(ClientContext6 &ctx)
void reclaimExpiredLeases4Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases4.
void deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
static uint32_t getValidLft(const ClientContext4 &ctx)
Returns the valid lifetime based on the v4 context.
void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv6 leases.
void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv4 leases.
Lease4Ptr allocateLease4(ClientContext4 &ctx)
Returns IPv4 lease.
void deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
Lease6Collection allocateLeases6(ClientContext6 &ctx)
Allocates IPv6 leases for a given IA container.
Lease6Collection renewLeases6(ClientContext6 &ctx)
Renews existing DHCPv6 leases for a given IA.
PrefixLenMatchType
Type of preferred PD-pool prefix length selection criteria.
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length.
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 Subnet4Ptr &first_subnet, const ClientClasses &client_classes)
Checks if the shared network includes a subnet with the match client ID flag set to true.
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_CONTINUE
continue normally
@ NEXT_STEP_SKIP
skip the next processing step
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static boost::shared_ptr< CalloutHandle > createCalloutHandle()
Return callout handle.
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Wrapper class around callout handle which automatically resets handle's state.
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
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_V6_HR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_HINT_RESERVED
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_OUT_OF_POOL
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ADDRESS_RESERVED
isc::log::Logger alloc_engine_logger("alloc-engine")
Logger for the AllocEngine.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_REQUESTED_LEASE
const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED
const int ALLOC_ENGINE_DBG_TRACE
Logging levels for the AllocEngine.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_COMPLETE
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ERROR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_HR
boost::shared_ptr< DUID > DuidPtr
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ALLOC_UNRESERVED
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_DECLINED_RECOVERED
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_TIMEOUT
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
boost::shared_ptr< DdnsParams > DdnsParamsPtr
Defines a pointer for DdnsParams instances.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_START
boost::shared_ptr< Option6IAPrefix > Option6IAPrefixPtr
Pointer to the Option6IAPrefix object.
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_HR
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_TIMEOUT
const isc::log::MessageID DHCPSRV_CFGMGR_IP_RESERVATIONS_UNIQUE_DUPLICATES_DETECTED
const isc::log::MessageID ALLOC_ENGINE_V6_HR_ADDR_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES
const isc::log::MessageID ALLOC_ENGINE_V6_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_EXPIRED_HINT_RESERVED
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
const int ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA
Records detailed results of various operations.
const int DHCPSRV_DBG_HOOKS
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_COMPLETE
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_PREFIX_LEASE
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
const isc::log::MessageID ALLOC_ENGINE_V4_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_PICK_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_NEW_LEASE
boost::shared_ptr< Option6IAAddr > Option6IAAddrPtr
A pointer to the isc::dhcp::Option6IAAddr object.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_CALCULATED_PREFERRED_LIFETIME
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_UNRESERVED
const isc::log::MessageID ALLOC_ENGINE_V6_DECLINED_RECOVERED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_START
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ALLOC_REQUESTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_NO_HR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SUBNET
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_ADDRESS_CONFLICT
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RENEW_SKIP
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_REMOVE_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET
const int ALLOC_ENGINE_DBG_TRACE_DETAIL
Record detailed traces.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_HR_PREFIX_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_CLASSES
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
boost::multiprecision::checked_uint128_t uint128_t
Defines the logger used by the top-level component of kea-lfc.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
Context information for the DHCPv4 lease allocation.
ClientIdPtr clientid_
Client identifier from the DHCP message.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
ConstHostPtr currentHost() const
Returns host for currently selected subnet.
ClientContext4()
Default constructor.
Pkt4Ptr query_
A pointer to the client's message.
Subnet4Ptr subnet_
Subnet selected for the client by the server.
Lease4Ptr new_lease_
A pointer to a newly allocated lease.
std::string hostname_
Hostname.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
bool rev_dns_update_
Perform reverse DNS update.
uint32_t offer_lft_
If not zero, then we will allocate on DISCOVER for this amount of time.
bool fake_allocation_
Indicates if this is a real or fake allocation.
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
bool unknown_requested_addr_
True when the address DHCPREQUEST'ed by client is not within a dynamic pool the server knows about.
Lease4Ptr old_lease_
A pointer to an old lease that the client had before update.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
bool fwd_dns_update_
Perform forward DNS update.
asiolink::IOAddress requested_address_
An address that the client desires.
Lease4Ptr conflicting_lease_
A pointer to the object representing a lease in conflict.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
HWAddrPtr hwaddr_
HW address from the DHCP message.
IAContext()
Default constructor.
Lease::Type type_
Lease type (IA or PD)
bool isNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was new.
void addHint(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128, const uint32_t preferred=0, const uint32_t valid=0)
Convenience method adding new hint.
void addNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding new prefix or address.
HintContainer hints_
Client's hints.
uint32_t iaid_
The IAID field from IA_NA or IA_PD that is being processed.
Context information for the DHCPv6 leases allocation.
IAContext & currentIA()
Returns IA specific context for the currently processed IA.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
ConstHostPtr currentHost() const
Returns host from the most preferred subnet.
ClientContext6()
Default constructor.
DuidPtr duid_
Client identifier.
void addAllocatedResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding allocated prefix or address.
Lease6Collection new_leases_
A collection of newly allocated leases.
bool isAllocated(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was allocated.
Subnet6Ptr subnet_
Subnet selected for the client by the server.
Subnet6Ptr host_subnet_
Subnet from which host reservations should be retrieved.
bool hasGlobalReservation(const IPv6Resrv &resv) const
Determines if a global reservation exists.
ResourceContainer allocated_resources_
Holds addresses and prefixes allocated for all IAs.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
Pkt6Ptr query_
A pointer to the client's message.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
Structure that holds a lease for IPv4 address.
Structure that holds a lease for IPv6 address and/or prefix.
@ 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