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) {
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);
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) {
1398 ctx.subnet_ = subnet;
1401 if (!ghost->getHostname().empty()) {
1415 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1416 static_cast<bool>(fqdn));
1421 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1424 existing_leases.push_back(lease);
1429 .arg(ctx.query_->getLabel());
1433 .arg(
static_cast<int>(prefix_len))
1434 .arg(ctx.query_->getLabel());
1452AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1455 if (existing_leases.empty() || !ctx.subnet_) {
1460 if (!ctx.subnet_->getReservationsInSubnet() &&
1461 !ctx.subnet_->getReservationsGlobal()) {
1462 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1471 for (
auto const& candidate :
copy) {
1475 if ((ctx.hasGlobalReservation(resv)) ||
1476 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1477 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1486 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1491 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1492 candidate->addr_,
false)) {
1496 if (!hosts.empty()) {
1499 if (hosts.size() == 1) {
1502 .arg(candidate->addr_.
toText())
1503 .arg(ctx.duid_->toText())
1504 .arg(hosts.front()->getIdentifierAsText());
1507 .arg(candidate->addr_.
toText())
1508 .arg(
static_cast<int>(candidate->prefixlen_))
1509 .arg(ctx.duid_->toText())
1510 .arg(hosts.front()->getIdentifierAsText());
1515 .arg(candidate->addr_.
toText())
1516 .arg(ctx.duid_->toText())
1520 .arg(candidate->addr_.
toText())
1521 .arg(
static_cast<int>(candidate->prefixlen_))
1522 .arg(ctx.duid_->toText())
1543 "assigned-nas" :
"assigned-pds"),
1544 static_cast<int64_t
>(-1));
1548 auto const& pool = subnet->getPool(ctx.currentIA().type_, candidate->addr_,
false);
1553 ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1554 static_cast<int64_t
>(-1));
1564 ctx.currentIA().old_leases_.push_back(candidate);
1567 removeLeases(existing_leases, candidate->addr_);
1572AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1579 for (
auto const& candidate :
copy) {
1583 if (inAllowedPool(ctx, candidate->type_,
1584 candidate->addr_,
false)) {
1602 "assigned-nas" :
"assigned-pds"),
1603 static_cast<int64_t
>(-1));
1607 auto const& pool = subnet->getPool(candidate->type_, candidate->addr_,
false);
1612 candidate->type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1613 static_cast<int64_t
>(-1));
1618 ctx.currentIA().old_leases_.push_back(candidate);
1621 removeLeases(existing_leases, candidate->addr_);
1628 bool removed =
false;
1629 for (Lease6Collection::iterator lease = container.begin();
1630 lease != container.end(); ++lease) {
1631 if ((*lease)->addr_ == addr) {
1638 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1649 int total = existing_leases.size();
1656 for (Lease6Collection::iterator lease = existing_leases.begin();
1657 lease != existing_leases.end(); ++lease) {
1661 if (ctx.hasGlobalReservation(resv) ||
1662 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1663 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1685 "assigned-nas" :
"assigned-pds"),
1686 static_cast<int64_t
>(-1));
1690 auto const& pool = subnet->getPool(ctx.currentIA().type_, (*lease)->addr_,
false);
1695 ctx.currentIA().type_ ==
Lease::TYPE_NA ?
"assigned-nas" :
"assigned-pds")),
1696 static_cast<int64_t
>(-1));
1703 ctx.currentIA().old_leases_.push_back(*lease);
1718 existing_leases.erase(std::remove(existing_leases.begin(),
1719 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1727 if (!expired->expired()) {
1735 if (!ctx.fake_allocation_) {
1739 reclaimExpiredLease(expired, ctx.callout_handle_);
1743 expired->iaid_ = ctx.currentIA().iaid_;
1744 expired->duid_ = ctx.duid_;
1747 getLifetimes6(ctx, expired->preferred_lft_, expired->valid_lft_);
1748 expired->reuseable_valid_lft_ = 0;
1750 expired->cltt_ = time(NULL);
1751 expired->subnet_id_ = ctx.subnet_->getID();
1752 expired->hostname_ = ctx.hostname_;
1753 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1754 expired->fqdn_rev_ = ctx.rev_dns_update_;
1755 expired->prefixlen_ = prefix_len;
1760 .arg(ctx.query_->getLabel())
1761 .arg(expired->toText());
1764 if (ctx.callout_handle_ &&
1779 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1782 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1785 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1788 ctx.callout_handle_->setArgument(
"lease6", expired);
1793 callout_status = ctx.callout_handle_->getStatus();
1810 ctx.callout_handle_->getArgument(
"lease6", expired);
1813 if (!ctx.fake_allocation_) {
1817 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, expired->addr_,
false);
1819 expired->pool_id_ = pool->getID();
1827 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1831 "assigned-nas" :
"assigned-pds"),
1832 static_cast<int64_t
>(1));
1837 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
1838 static_cast<int64_t
>(1));
1844 "pool" :
"pd-pool", pool->getID(),
1846 "assigned-nas" :
"assigned-pds")),
1847 static_cast<int64_t
>(1));
1852 "pool" :
"pd-pool", pool->getID(),
1854 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
1855 static_cast<int64_t
>(1));
1859 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
1860 static_cast<int64_t
>(1));
1879 if (!classes.
empty()) {
1886 for (
auto const& name : classes) {
1889 (cl && (!cl->getPreferred().unspecified()))) {
1890 candidate_preferred = cl->getPreferred();
1895 (cl && (!cl->getValid().unspecified()))) {
1896 candidate_valid = cl->getValid();
1899 if (have_both == 2) {
1906 if (!candidate_preferred) {
1907 candidate_preferred = ctx.
subnet_->getPreferred();
1911 if (!candidate_valid) {
1912 candidate_valid = ctx.
subnet_->getValid();
1916 preferred = candidate_preferred;
1917 valid = candidate_valid;
1932 if (!preferred || preferred > valid) {
1933 preferred = ((valid * 5)/8);
1936 .arg(ctx.
query_->getLabel())
1950 uint32_t preferred = 0;
1955 ctx.currentIA().iaid_, preferred,
1956 valid, ctx.subnet_->getID(),
1957 ctx.hwaddr_, prefix_len));
1959 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1960 lease->fqdn_rev_ = ctx.rev_dns_update_;
1961 lease->hostname_ = ctx.hostname_;
1964 if (ctx.callout_handle_ &&
1979 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1982 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1985 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1988 ctx.callout_handle_->setArgument(
"lease6", lease);
1993 callout_status = ctx.callout_handle_->getStatus();
2005 ctx.callout_handle_->getArgument(
"lease6", lease);
2008 if (!ctx.fake_allocation_) {
2012 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2014 lease->pool_id_ = pool->getID();
2023 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2027 "assigned-nas" :
"assigned-pds"),
2028 static_cast<int64_t
>(1));
2033 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2034 static_cast<int64_t
>(1));
2040 "pool" :
"pd-pool", pool->getID(),
2042 "assigned-nas" :
"assigned-pds")),
2043 static_cast<int64_t
>(1));
2048 "pool" :
"pd-pool", pool->getID(),
2050 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2051 static_cast<int64_t
>(1));
2055 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2056 static_cast<int64_t
>(1));
2060 ctx.currentIA().addNewResource(addr, prefix_len);
2099 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2101 subnet = subnet->getNextSubnet(ctx.
subnet_);
2104 if (!leases.empty()) {
2107 .arg(ctx.
query_->getLabel());
2111 removeNonmatchingReservedLeases6(ctx, leases);
2114 if (!ctx.
hosts_.empty()) {
2118 .arg(ctx.
query_->getLabel());
2121 allocateReservedLeases6(ctx, leases);
2127 removeNonreservedLeases6(ctx, leases);
2134 if (leases.empty()) {
2138 .arg(ctx.
query_->getLabel());
2140 leases = allocateUnreservedLeases6(ctx);
2144 for (
auto const& l : leases) {
2152 .arg(ctx.
query_->getLabel())
2153 .arg(l->typeToText(l->type_))
2155 extendLease6(ctx, l);
2158 if (!leases.empty()) {
2162 for (
auto const& lease : leases) {
2174 .arg(ctx.
query_->getLabel())
2184 if (!lease || !ctx.subnet_) {
2190 if (ctx.subnet_->getID() != lease->subnet_id_) {
2192 ctx.subnet_->getSharedNetwork(network);
2198 ctx.subnet_ = subnet;
2206 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2207 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2224 "assigned-nas" :
"assigned-pds"),
2225 static_cast<int64_t
>(-1));
2227 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2232 "pool" :
"pd-pool", pool->getID(),
2234 "assigned-nas" :
"assigned-pds")),
2235 static_cast<int64_t
>(-1));
2239 ctx.currentIA().old_leases_.push_back(lease);
2246 .arg(ctx.query_->getLabel())
2247 .arg(lease->toText());
2252 bool changed =
false;
2255 uint32_t current_preferred_lft = lease->preferred_lft_;
2256 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2259 if ((lease->preferred_lft_ != current_preferred_lft) ||
2260 (lease->valid_lft_ != lease->current_valid_lft_)) {
2264 lease->cltt_ = time(NULL);
2265 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2266 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2267 (lease->hostname_ != ctx.hostname_)) {
2269 lease->hostname_ = ctx.hostname_;
2270 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2271 lease->fqdn_rev_ = ctx.rev_dns_update_;
2273 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2275 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2277 lease->hwaddr_ = ctx.hwaddr_;
2285 .arg(ctx.query_->getLabel())
2286 .arg(lease->toText());
2290 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2291 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2305 callout_handle->setArgument(
"query6", ctx.query_);
2308 callout_handle->setArgument(
"lease6", lease);
2312 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2314 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2327 .arg(ctx.query_->getName());
2334 bool update_stats =
false;
2338 if (old_data->expired()) {
2339 reclaimExpiredLease(old_data, ctx.callout_handle_);
2343 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2344 update_stats =
true;
2357 setLeaseReusable(lease, current_preferred_lft, ctx);
2362 if (lease->reuseable_valid_lft_ == 0) {
2363 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2365 lease->pool_id_ = pool->getID();
2374 "assigned-nas" :
"assigned-pds"),
2375 static_cast<int64_t
>(1));
2380 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2381 static_cast<int64_t
>(1));
2383 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2388 "pool" :
"pd-pool", pool->getID(),
2390 "assigned-nas" :
"assigned-pds")),
2391 static_cast<int64_t
>(1));
2396 "pool" :
"pd-pool", pool->getID(),
2398 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2399 static_cast<int64_t
>(1));
2403 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2404 static_cast<int64_t
>(1));
2417 ctx.currentIA().changed_leases_.push_back(old_data);
2423 for (
auto const& lease_it : leases) {
2425 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2427 updated_leases.push_back(lease);
2431 lease->reuseable_valid_lft_ = 0;
2432 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2433 lease->fqdn_rev_ = ctx.rev_dns_update_;
2434 lease->hostname_ = ctx.hostname_;
2435 uint32_t current_preferred_lft = lease->preferred_lft_;
2436 if (lease->valid_lft_ == 0) {
2438 getLifetimes6(ctx, lease->preferred_lft_, lease->valid_lft_);
2440 if (!ctx.fake_allocation_) {
2441 bool update_stats =
false;
2449 if (inAllowedPool(ctx, ctx.currentIA().type_,
2450 lease->addr_,
true)) {
2451 update_stats =
true;
2456 !(lease->hasIdenticalFqdn(*lease_it)));
2458 lease->cltt_ = time(NULL);
2459 if (!fqdn_changed) {
2460 setLeaseReusable(lease, current_preferred_lft, ctx);
2462 if (lease->reuseable_valid_lft_ == 0) {
2463 ctx.currentIA().changed_leases_.push_back(lease_it);
2471 "assigned-nas" :
"assigned-pds"),
2472 static_cast<int64_t
>(1));
2477 "cumulative-assigned-nas" :
"cumulative-assigned-pds"),
2478 static_cast<int64_t
>(1));
2480 auto const& pool = ctx.subnet_->getPool(ctx.currentIA().type_, lease->addr_,
false);
2485 "pool" :
"pd-pool", pool->getID(),
2487 "assigned-nas" :
"assigned-pds")),
2488 static_cast<int64_t
>(1));
2493 "pool" :
"pd-pool", pool->getID(),
2495 "cumulative-assigned-nas" :
"cumulative-assigned-pds")),
2496 static_cast<int64_t
>(1));
2500 "cumulative-assigned-nas" :
"cumulative-assigned-pds",
2501 static_cast<int64_t
>(1));
2505 updated_leases.push_back(lease);
2508 return (updated_leases);
2513 const uint16_t timeout,
2514 const bool remove_lease,
2515 const uint16_t max_unwarned_cycles) {
2524 max_unwarned_cycles);
2525 }
catch (
const std::exception& ex) {
2534 const uint16_t timeout,
2535 const bool remove_lease,
2536 const uint16_t max_unwarned_cycles) {
2546 bool incomplete_reclamation =
false;
2549 if (max_leases > 0) {
2558 if (leases.size() > max_leases) {
2560 incomplete_reclamation =
true;
2573 if (!leases.empty() &&
2578 size_t leases_processed = 0;
2579 for (
auto const& lease : leases) {
2587 reclaimExpiredLease(lease, remove_lease, callout_handle);
2590 reclaimExpiredLease(lease, remove_lease, callout_handle);
2594 }
catch (
const std::exception& ex) {
2596 .arg(lease->addr_.toText())
2607 if (!incomplete_reclamation) {
2608 if (leases_processed < leases.size()) {
2609 incomplete_reclamation =
true;
2626 .arg(leases_processed)
2631 if (incomplete_reclamation) {
2632 ++incomplete_v6_reclamations_;
2635 if ((max_unwarned_cycles > 0) &&
2636 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2638 .arg(max_unwarned_cycles);
2640 incomplete_v6_reclamations_ = 0;
2645 incomplete_v6_reclamations_ = 0;
2658 uint64_t deleted_leases = 0;
2664 }
catch (
const std::exception& ex) {
2671 .arg(deleted_leases);
2676 const uint16_t timeout,
2677 const bool remove_lease,
2678 const uint16_t max_unwarned_cycles) {
2687 max_unwarned_cycles);
2688 }
catch (
const std::exception& ex) {
2697 const uint16_t timeout,
2698 const bool remove_lease,
2699 const uint16_t max_unwarned_cycles) {
2709 bool incomplete_reclamation =
false;
2712 if (max_leases > 0) {
2721 if (leases.size() > max_leases) {
2723 incomplete_reclamation =
true;
2736 if (!leases.empty() &&
2741 size_t leases_processed = 0;
2742 for (
auto const& lease : leases) {
2750 reclaimExpiredLease(lease, remove_lease, callout_handle);
2753 reclaimExpiredLease(lease, remove_lease, callout_handle);
2757 }
catch (
const std::exception& ex) {
2759 .arg(lease->addr_.toText())
2770 if (!incomplete_reclamation) {
2771 if (leases_processed < leases.size()) {
2772 incomplete_reclamation =
true;
2789 .arg(leases_processed)
2794 if (incomplete_reclamation) {
2795 ++incomplete_v4_reclamations_;
2798 if ((max_unwarned_cycles > 0) &&
2799 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2801 .arg(max_unwarned_cycles);
2803 incomplete_v4_reclamations_ = 0;
2808 incomplete_v4_reclamations_ = 0;
2815template<
typename LeasePtrType>
2817AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2819 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2823template<
typename LeasePtrType>
2825AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2830 if (!lease->stateExpiredReclaimed()) {
2831 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2836AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2837 const DbReclaimMode& reclaim_mode,
2843 .arg(lease->addr_.toText())
2844 .arg(
static_cast<int>(lease->prefixlen_));
2850 bool skipped =
false;
2851 if (callout_handle) {
2859 callout_handle->deleteAllArguments();
2860 callout_handle->setArgument(
"lease6", lease);
2861 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2881 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2891 remove_lease = reclaimDeclined(lease);
2894 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2898 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2900 &lease_mgr, ph::_1));
2912 static_cast<int64_t
>(-1));
2916 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2922 static_cast<int64_t
>(-1));
2927 "reclaimed-leases")),
2928 static_cast<int64_t
>(1));
2937 static_cast<int64_t
>(-1));
2941 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
2947 static_cast<int64_t
>(-1));
2952 "reclaimed-leases")),
2953 static_cast<int64_t
>(1));
2961 "reclaimed-leases"),
2962 static_cast<int64_t
>(1));
2969AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2970 const DbReclaimMode& reclaim_mode,
2976 .arg(lease->addr_.toText());
2982 bool skipped =
false;
2983 if (callout_handle) {
2991 callout_handle->setArgument(
"lease4", lease);
2992 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
3010 lease->hostname_.clear();
3011 lease->fqdn_fwd_ =
false;
3012 lease->fqdn_rev_ =
false;
3016 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
3026 remove_lease = reclaimDeclined(lease);
3029 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
3033 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
3035 &lease_mgr, ph::_1));
3044 "assigned-addresses"),
3045 static_cast<int64_t
>(-1));
3050 "reclaimed-leases"),
3051 static_cast<int64_t
>(1));
3055 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3060 "assigned-addresses")),
3061 static_cast<int64_t
>(-1));
3066 "reclaimed-leases")),
3067 static_cast<int64_t
>(1));
3081 uint64_t deleted_leases = 0;
3087 }
catch (
const std::exception& ex) {
3094 .arg(deleted_leases);
3098AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
3113 callout_handle->setArgument(
"lease4", lease);
3123 .arg(lease->addr_.toText());
3129 .arg(lease->addr_.toText())
3130 .arg(lease->valid_lft_);
3136 "declined-addresses"),
3137 static_cast<int64_t
>(-1));
3140 "reclaimed-declined-addresses"),
3141 static_cast<int64_t
>(1));
3145 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
3149 "declined-addresses")),
3150 static_cast<int64_t
>(-1));
3154 "reclaimed-declined-addresses")),
3155 static_cast<int64_t
>(1));
3160 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3162 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3170AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3185 callout_handle->setArgument(
"lease6", lease);
3195 .arg(lease->addr_.toText());
3201 .arg(lease->addr_.toText())
3202 .arg(lease->valid_lft_);
3208 "declined-addresses"),
3209 static_cast<int64_t
>(-1));
3212 "reclaimed-declined-addresses"),
3213 static_cast<int64_t
>(1));
3217 auto const& pool = subnet->getPool(lease->type_, lease->addr_,
false);
3221 "declined-addresses")),
3222 static_cast<int64_t
>(-1));
3226 "reclaimed-declined-addresses")),
3227 static_cast<int64_t
>(1));
3232 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3234 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3244 lease->relay_id_.clear();
3245 lease->remote_id_.clear();
3246 if (lease->getContext()) {
3253 if (lease->getContext()) {
3259template<
typename LeasePtrType>
3260void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3261 const bool remove_lease,
3262 const std::function<
void (
const LeasePtrType&)>&
3263 lease_update_fun)
const {
3271 }
else if (lease_update_fun) {
3274 lease->reuseable_valid_lft_ = 0;
3275 lease->hostname_.clear();
3276 lease->fqdn_fwd_ =
false;
3277 lease->fqdn_rev_ =
false;
3280 lease_update_fun(lease);
3289 .arg(lease->addr_.toText());
3295 return(
"<empty subnet>");
3299 subnet->getSharedNetwork(network);
3300 std::ostringstream ss;
3302 ss <<
"shared-network: " << network->getName();
3304 ss <<
"subnet id: " << subnet->getID();
3343 (!ctx.
subnet_->getReservationsOutOfPool() ||
3354 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3359 hosts.push_back(host);
3373 for (
auto const& host : hosts) {
3377 if (id_pair.first == host->getIdentifierType() &&
3378 id_pair.second == host->getIdentifier()) {
3386 return (!hosts.empty());
3408 if (ctx.
hosts_.empty()) {
3413 auto global_host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3414 auto global_host_address = ((global_host != ctx.
hosts_.end() && global_host->second) ?
3415 global_host->second->getIPv4Reservation() :
3424 if (subnet->getReservationsGlobal() &&
3426 (subnet->inRange(global_host_address))) {
3431 if (subnet->getReservationsInSubnet()) {
3432 auto host = ctx.
hosts_.find(subnet->getID());
3437 if (host != ctx.
hosts_.end() && host->second) {
3438 auto reservation = host->second->getIPv4Reservation();
3439 if (!reservation.isV4Zero() &&
3440 (!subnet->getReservationsOutOfPool() ||
3450 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3456 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3483 auto const& classes = ctx.
query_->getClasses();
3487 bool try_clientid_lookup = (ctx.
clientid_ &&
3491 if (try_clientid_lookup) {
3499 for (
Subnet4Ptr subnet = original_subnet; subnet;
3500 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3505 if (subnet->getMatchClientId()) {
3506 for (
auto const& l : leases_client_id) {
3507 if (l->subnet_id_ == subnet->getID()) {
3520 if (!client_lease && ctx.
hwaddr_) {
3525 for (
Subnet4Ptr subnet = original_subnet; subnet;
3526 subnet = subnet->getNextSubnet(original_subnet, classes)) {
3528 if (subnet->getMatchClientId()) {
3534 for (
auto const& client_lease_it : leases_hw_address) {
3535 Lease4Ptr existing_lease = client_lease_it;
3536 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3537 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3539 client_lease = existing_lease;
3567 auto const& classes = ctx.
query_->getClasses();
3569 while (current_subnet) {
3578 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_, classes);
3590 : early_global_reservations_lookup_(false),
3591 subnet_(), clientid_(), hwaddr_(),
3592 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3593 fwd_dns_update_(false), rev_dns_update_(false),
3594 hostname_(
""), callout_handle_(), fake_allocation_(false), offer_lft_(0),
3595 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3596 query_(), host_identifiers_(), unknown_requested_addr_(false),
3605 const bool fwd_dns_update,
3606 const bool rev_dns_update,
3607 const std::string& hostname,
3608 const bool fake_allocation,
3609 const uint32_t offer_lft)
3610 : early_global_reservations_lookup_(false),
3611 subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3612 requested_address_(requested_addr),
3613 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3614 hostname_(hostname), callout_handle_(),
3615 fake_allocation_(fake_allocation), offer_lft_(offer_lft), old_lease_(), new_lease_(),
3616 hosts_(), host_identifiers_(), unknown_requested_addr_(false),
3627 if (subnet_ && subnet_->getReservationsInSubnet()) {
3628 auto host = hosts_.find(subnet_->getID());
3629 if (host != hosts_.cend()) {
3630 return (host->second);
3634 return (globalHost());
3639 if (subnet_ && subnet_->getReservationsGlobal()) {
3640 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3641 if (host != hosts_.cend()) {
3642 return (host->second);
3652 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3653 return (ddns_params_);
3659 return (ddns_params_);
3681 auto const& classes = ctx.
query_->getClasses();
3682 if (subnet && !subnet->clientSupported(classes)) {
3683 ctx.
subnet_ = subnet->getNextSubnet(subnet, classes);
3704 .arg(ctx.
query_->getLabel())
3722 !subnet->getReservationsInSubnet()) {
3728 subnet->getReservationsGlobal()) {
3731 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3734 if (!subnet->getReservationsInSubnet()) {
3740 std::map<SubnetID, ConstHostPtr> host_map;
3742 subnet->getSharedNetwork(network);
3751 const bool use_single_query = network &&
3755 if (use_single_query) {
3759 id_pair.second.size());
3763 for (
auto const& host : hosts) {
3764 if (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3765 host_map[host->getIPv4SubnetID()] = host;
3771 auto const& classes = ctx.
query_->getClasses();
3777 if (subnet->clientSupported(classes) && subnet->getReservationsInSubnet()) {
3780 if (use_single_query) {
3781 if (host_map.count(subnet->getID()) > 0) {
3782 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3790 id_pair.second.size());
3793 ctx.
hosts_[subnet->getID()] = host;
3803 subnet = subnet->getNextSubnet(ctx.
subnet_, classes);
3809 for (
auto const& host : ctx.
hosts_) {
3810 host.second->encapsulateOptions();
3820 &id_pair.second[0], id_pair.second.size());
3837 findClientLease(ctx, client_lease);
3850 if (hasAddressReservation(ctx)) {
3854 .arg(ctx.
query_->getLabel())
3855 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3861 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3868 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3872 .arg(ctx.
query_->getLabel())
3873 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3878 "v4-reservation-conflicts"),
3879 static_cast<int64_t
>(1));
3881 static_cast<int64_t
>(1));
3885 new_lease = renewLease4(client_lease, ctx);
3898 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3899 !addressReserved(client_lease->addr_, ctx)) {
3903 .arg(ctx.
query_->getLabel());
3909 (time(NULL) + ctx.
offer_lft_ < client_lease->getExpirationTime())) {
3913 new_lease = renewLease4(client_lease, ctx);
3930 .arg(ctx.
query_->getLabel());
3943 .arg(ctx.
query_->getLabel());
3945 new_lease = allocateUnreservedLease4(ctx);
3965 findClientLease(ctx, client_lease);
3981 .arg(ctx.
query_->getLabel())
3987 }
else if (hasAddressReservation(ctx)) {
3996 .arg(ctx.
query_->getLabel())
4008 if (existing && !existing->expired() &&
4009 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
4014 .arg(ctx.
query_->getLabel())
4024 if (hasAddressReservation(ctx) &&
4032 if (!existing || existing->expired()) {
4036 .arg(ctx.
query_->getLabel())
4037 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
4047 if ((!hasAddressReservation(ctx) ||
4053 .arg(ctx.
query_->getLabel())
4073 ((hasAddressReservation(ctx) &&
4075 inAllowedPool(ctx, client_lease->addr_))) {
4079 .arg(ctx.
query_->getLabel())
4082 return (renewLease4(client_lease, ctx));
4096 .arg(ctx.
query_->getLabel())
4112 .arg(ctx.
query_->getLabel());
4117 new_lease = allocateUnreservedLease4(ctx);
4123 if (new_lease && client_lease) {
4128 .arg(ctx.
query_->getLabel())
4129 .arg(client_lease->addr_.toText());
4135 "assigned-addresses"),
4136 static_cast<int64_t
>(-1));
4140 auto const& pool = subnet->getPool(
Lease::TYPE_V4, client_lease->addr_,
false);
4145 "assigned-addresses")),
4146 static_cast<int64_t
>(-1));
4169 if (!classes.
empty()) {
4175 for (
auto const& name : classes) {
4177 if (cl && (!cl->getOfferLft().unspecified())) {
4178 offer_lft = cl->getOfferLft();
4186 offer_lft = ctx.
subnet_->getOfferLft();
4195 if (ctx.
query_->inClass(
"BOOTP")) {
4200 uint32_t requested_lft = 0;
4203 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
4205 requested_lft = opt_lft->getValue();
4213 if (!classes.
empty()) {
4219 for (
auto const& name : classes) {
4221 if (cl && (!cl->getValid().unspecified())) {
4222 candidate_lft = cl->getValid();
4229 if (!candidate_lft) {
4230 candidate_lft = ctx.
subnet_->getValid();
4235 if (requested_lft > 0) {
4236 return (candidate_lft.
get(requested_lft));
4240 return (candidate_lft.
get());
4244AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
4254 uint32_t valid_lft = (ctx.offer_lft_ ? ctx.offer_lft_ :
getValidLft(ctx));
4256 time_t now = time(NULL);
4259 if (ctx.subnet_->getMatchClientId()) {
4260 client_id = ctx.clientid_;
4264 valid_lft, now, ctx.subnet_->getID()));
4267 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
4268 lease->fqdn_rev_ = ctx.rev_dns_update_;
4269 lease->hostname_ = ctx.hostname_;
4275 if (ctx.callout_handle_ &&
4289 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4295 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4296 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4299 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4302 ctx.callout_handle_->setArgument(
"offer_lft", ctx.offer_lft_);
4305 ctx.callout_handle_->setArgument(
"lease4", lease);
4310 callout_status = ctx.callout_handle_->getStatus();
4322 ctx.callout_handle_->getArgument(
"lease4", lease);
4325 if (ctx.fake_allocation_ && ctx.offer_lft_) {
4329 lease->fqdn_fwd_ =
false;
4330 lease->fqdn_rev_ =
false;
4333 if (!ctx.fake_allocation_ || ctx.offer_lft_) {
4334 auto const& pool = ctx.subnet_->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4336 lease->pool_id_ = pool->getID();
4345 "assigned-addresses"),
4346 static_cast<int64_t
>(1));
4350 "cumulative-assigned-addresses"),
4351 static_cast<int64_t
>(1));
4357 "assigned-addresses")),
4358 static_cast<int64_t
>(1));
4363 "cumulative-assigned-addresses")),
4364 static_cast<int64_t
>(1));
4368 static_cast<int64_t
>(1));
4387AllocEngine::renewLease4(
const Lease4Ptr& lease,
4397 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4402 lease->reuseable_valid_lft_ = 0;
4403 if (!updateLease4Information(lease, ctx)) {
4404 setLeaseReusable(lease, ctx);
4444 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4470 lease->pool_id_ = pool->getID();
4480 "assigned-addresses"),
4481 static_cast<int64_t
>(1));
4485 "cumulative-assigned-addresses"),
4486 static_cast<int64_t
>(1));
4492 "assigned-addresses")),
4493 static_cast<int64_t
>(1));
4498 "cumulative-assigned-addresses")),
4499 static_cast<int64_t
>(1));
4503 static_cast<int64_t
>(1));
4509 *lease = *old_values;
4516AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4535 expired->reuseable_valid_lft_ = 0;
4536 static_cast<void>(updateLease4Information(expired, ctx));
4540 .arg(ctx.
query_->getLabel())
4541 .arg(expired->toText());
4598 expired->pool_id_ = pool->getID();
4606 "assigned-addresses"),
4607 static_cast<int64_t
>(1));
4611 "cumulative-assigned-addresses"),
4612 static_cast<int64_t
>(1));
4618 "assigned-addresses")),
4619 static_cast<int64_t
>(1));
4624 "cumulative-assigned-addresses")),
4625 static_cast<int64_t
>(1));
4629 static_cast<int64_t
>(1));
4641AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4643 ctx.conflicting_lease_.reset();
4647 if (exist_lease->expired()) {
4652 ctx.old_lease_->hostname_.clear();
4653 ctx.old_lease_->fqdn_fwd_ =
false;
4654 ctx.old_lease_->fqdn_rev_ =
false;
4655 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4661 ctx.conflicting_lease_ = exist_lease;
4665 return (createLease4(ctx, candidate, callout_status));
4671AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4685 ctx.subnet_->getSharedNetwork(network);
4692 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4706 uint64_t subnets_with_unavail_leases = 0;
4709 uint64_t subnets_with_unavail_pools = 0;
4711 auto const& classes = ctx.query_->getClasses();
4715 if (subnet->getMatchClientId()) {
4716 client_id = ctx.clientid_;
4728 (attempts_ == 0 || possible_attempts < attempts_) ?
4732 if (max_attempts > 0) {
4735 ++subnets_with_unavail_leases;
4739 ++subnets_with_unavail_pools;
4742 bool exclude_first_last_24 = ((subnet->get().second <= 24) &&
4747 for (
uint128_t i = 0; i < max_attempts; ++i) {
4752 IOAddress candidate = allocator->pickAddress(classes,
4754 ctx.requested_address_);
4761 if (exclude_first_last_24) {
4763 auto const& bytes = candidate.
toBytes();
4764 if ((bytes.size() != 4) ||
4765 (bytes[3] == 0) || (bytes[3] == 255U)) {
4772 if (check_reservation_first && addressReserved(candidate, ctx)) {
4781 !resource_handler.
tryLock4(candidate)) {
4790 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4792 new_lease = createLease4(ctx, candidate, callout_status);
4796 if (exist_lease->expired() &&
4797 (check_reservation_first || !addressReserved(candidate, ctx))) {
4799 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4817 subnet = subnet->getNextSubnet(original_subnet, classes);
4820 ctx.subnet_ = subnet;
4829 .arg(ctx.query_->getLabel())
4830 .arg(network->getName())
4831 .arg(subnets_with_unavail_leases)
4832 .arg(subnets_with_unavail_pools);
4834 static_cast<int64_t
>(1));
4837 "v4-allocation-fail-shared-network"),
4838 static_cast<int64_t
>(1));
4842 std::string shared_network = ctx.subnet_->getSharedNetworkName();
4843 if (shared_network.empty()) {
4844 shared_network =
"(none)";
4847 .arg(ctx.query_->getLabel())
4848 .arg(ctx.subnet_->toText())
4849 .arg(ctx.subnet_->getID())
4850 .arg(shared_network);
4852 static_cast<int64_t
>(1));
4855 "v4-allocation-fail-subnet"),
4856 static_cast<int64_t
>(1));
4858 if (total_attempts == 0) {
4864 .arg(ctx.query_->getLabel());
4866 static_cast<int64_t
>(1));
4869 "v4-allocation-fail-no-pools"),
4870 static_cast<int64_t
>(1));
4877 .arg(ctx.query_->getLabel())
4878 .arg(total_attempts);
4880 static_cast<int64_t
>(1));
4883 "v4-allocation-fail"),
4884 static_cast<int64_t
>(1));
4887 if (!classes.empty()) {
4889 .arg(ctx.query_->getLabel())
4890 .arg(classes.toText());
4892 static_cast<int64_t
>(1));
4895 "v4-allocation-fail-classes"),
4896 static_cast<int64_t
>(1));
4903AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4905 bool changed =
false;
4906 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4908 lease->subnet_id_ = ctx.
subnet_->getID();
4910 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4912 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4917 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4921 }
else if (lease->client_id_) {
4925 lease->cltt_ = time(NULL);
4931 if (lease->valid_lft_ != lease->current_valid_lft_) {
4955 bool changed =
false;
4958 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4974 extended_info->set(
"sub-options", relay_agent);
4978 std::vector<uint8_t> bytes = remote_id->toBinary();
4979 lease->remote_id_ = bytes;
4980 if (bytes.size() > 0) {
4981 extended_info->set(
"remote-id",
4988 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
4989 lease->relay_id_ = bytes;
4990 if (bytes.size() > 0) {
4991 extended_info->set(
"relay-id",
4999 if (user_context && (user_context->getType() ==
Element::map)) {
5000 mutable_user_context =
copy(user_context, 0);
5015 ConstElementPtr old_extended_info = mutable_isc->get(
"relay-agent-info");
5016 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5018 mutable_isc->set(
"relay-agent-info", extended_info);
5019 mutable_user_context->set(
"ISC", mutable_isc);
5023 lease->setContext(mutable_user_context);
5035 if (!ctx.
subnet_->getStoreExtendedInfo()) {
5040 if (ctx.
query_->relay_info_.empty()) {
5055 for (
auto const& relay : ctx.
query_->relay_info_) {
5064 if (!relay.options_.empty()) {
5069 const uint8_t* cp = buf.
getData();
5070 std::vector<uint8_t> bytes;
5071 std::stringstream ss;
5079 if (remote_id_it != relay.options_.end()) {
5080 OptionPtr remote_id = remote_id_it->second;
5082 std::vector<uint8_t> bytes = remote_id->toBinary();
5083 if (bytes.size() > 0) {
5084 relay_elem->set(
"remote-id",
5091 if (relay_id_it != relay.options_.end()) {
5092 OptionPtr relay_id = relay_id_it->second;
5094 std::vector<uint8_t> bytes = relay_id->toBinary(
false);
5095 if (bytes.size() > 0) {
5096 relay_elem->set(
"relay-id",
5103 extended_info->add(relay_elem);
5109 if (user_context && (user_context->getType() ==
Element::map)) {
5110 mutable_user_context =
copy(user_context, 0);
5126 if (!old_extended_info || (*old_extended_info != *extended_info)) {
5128 mutable_isc->set(
"relay-info", extended_info);
5129 mutable_user_context->set(
"ISC", mutable_isc);
5133 lease->setContext(mutable_user_context);
5137AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
5138 const ClientContext4& ctx)
const {
5140 lease->reuseable_valid_lft_ = 0;
5156 if (lease->cltt_ < lease->current_cltt_) {
5160 uint32_t age = lease->cltt_ - lease->current_cltt_;
5162 if (age >= lease->current_valid_lft_) {
5167 uint32_t max_age = 0;
5168 if (!subnet->getCacheMaxAge().unspecified()) {
5169 max_age = subnet->getCacheMaxAge().get();
5170 if ((max_age == 0) || (age > max_age)) {
5176 if (!subnet->getCacheThreshold().unspecified()) {
5177 double threshold = subnet->getCacheThreshold().get();
5178 if ((threshold <= 0.) || (threshold > 1.)) {
5181 max_age = lease->valid_lft_ * threshold;
5182 if (age > max_age) {
5193 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
5197AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
5198 uint32_t current_preferred_lft,
5199 const ClientContext6& ctx)
const {
5201 lease->reuseable_valid_lft_ = 0;
5202 lease->reuseable_preferred_lft_ = 0;
5212 if (lease->cltt_ < lease->current_cltt_) {
5216 uint32_t age = lease->cltt_ - lease->current_cltt_;
5218 if (age >= lease->current_valid_lft_) {
5223 uint32_t max_age = 0;
5224 if (!subnet->getCacheMaxAge().unspecified()) {
5225 max_age = subnet->getCacheMaxAge().get();
5226 if ((max_age == 0) || (age > max_age)) {
5232 if (!subnet->getCacheThreshold().unspecified()) {
5233 double threshold = subnet->getCacheThreshold().get();
5234 if ((threshold <= 0.) || (threshold > 1.)) {
5237 max_age = lease->valid_lft_ * threshold;
5238 if (age > max_age) {
5250 (current_preferred_lft == 0)) {
5252 lease->reuseable_preferred_lft_ = current_preferred_lft;
5253 }
else if (current_preferred_lft > age) {
5254 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
5262 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
std::string toText() const
Convert the address to a string.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
bool isV6Zero() const
Convenience function to check if it is an IPv4 zero address.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
static ElementPtr create(const Position &pos=ZERO_POSITION())
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Notes: IntElement type is changed to int64_t.
Multiple lease records found where one expected.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
void updateLease6ExtendedInfo(const Lease6Ptr &lease, const ClientContext6 &ctx) const
Stores additional client query parameters on a V6 lease.
void reclaimExpiredLeases6Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases6.
bool updateLease4ExtendedInfo(const Lease4Ptr &lease, const ClientContext4 &ctx) const
Stores additional client query parameters on a V4 lease.
static uint32_t getOfferLft(const ClientContext4 &ctx)
Returns the offer lifetime based on the v4 context.
static std::string labelNetworkOrSubnet(SubnetPtr subnet)
Generates a label for subnet or shared-network from subnet.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
AllocEngine(isc::util::uint128_t const &attempts)
Constructor.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
void clearReclaimedExtendedInfo(const Lease4Ptr &lease) const
Clear extended info from a reclaimed V4 lease.
isc::util::ReadWriteMutex rw_mutex_
The read-write mutex.
static void getLifetimes6(ClientContext6 &ctx, uint32_t &preferred, uint32_t &valid)
Determines the preferred and valid v6 lease lifetimes.
static void findReservation(ClientContext6 &ctx)
void reclaimExpiredLeases4Internal(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Body of reclaimExpiredLeases4.
void deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
static uint32_t getValidLft(const ClientContext4 &ctx)
Returns the valid lifetime based on the v4 context.
void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv6 leases.
void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout, const bool remove_lease, const uint16_t max_unwarned_cycles=0)
Reclaims expired IPv4 leases.
Lease4Ptr allocateLease4(ClientContext4 &ctx)
Returns IPv4 lease.
void deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
Lease6Collection allocateLeases6(ClientContext6 &ctx)
Allocates IPv6 leases for a given IA container.
Lease6Collection renewLeases6(ClientContext6 &ctx)
Renews existing DHCPv6 leases for a given IA.
PrefixLenMatchType
Type of preferred PD-pool prefix length selection criteria.
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Container for storing client class names.
bool empty() const
Check if classes is empty.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
ConstHostCollection getAll6(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv6 subnet.
ConstHostCollection getAll4(const SubnetID &subnet_id, const HostMgrOperationTarget target) const
Return all hosts in a DHCPv4 subnet.
ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
bool getDisableSingleQuery() const
Returns the disable single query flag.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv4 subnet.
ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns a host connected to the IPv6 subnet.
IPv6 reservation for a host.
Type
Type of the reservation.
static TrackingLeaseMgr & instance()
Return current lease manager.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv6 leases.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv6 leases.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv4 leases.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv4 leases.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
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 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.
bool getMode() const
Get the multi-threading mode.
A template representing an optional value.
T get() const
Retrieves the encapsulated value.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
size_t getLength() const
Return the length of data written in the buffer.
Utility class to measure code execution times.
long getTotalMilliseconds() const
Retrieves the total measured duration in milliseconds.
void stop()
Stops the stopwatch.
std::string logFormatTotalDuration() const
Returns the total measured duration in the format directly usable in the log messages.
This template specifies a parameter value.
T get(T hint) const
Returns value with a hint.
Write mutex RAII handler.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_LEASES_HR
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_INVALID
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS6
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_EXTEND_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_IN_USE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_HR_LEASE_EXISTS
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_HR
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
const isc::log::MessageID ALLOC_ENGINE_V6_REUSE_EXPIRED_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_V6_HR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_HINT_RESERVED
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_OUT_OF_POOL
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ADDRESS_RESERVED
isc::log::Logger alloc_engine_logger("alloc-engine")
Logger for the AllocEngine.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_REQUESTED_LEASE
const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED
const int ALLOC_ENGINE_DBG_TRACE
Logging levels for the AllocEngine.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_IGNORING_UNSUITABLE_GLOBAL_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_COMPLETE
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ERROR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_HR
boost::shared_ptr< DUID > DuidPtr
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ALLOC_UNRESERVED
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_DECLINED_RECOVERED
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_SLOW
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_TIMEOUT
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
boost::shared_ptr< DdnsParams > DdnsParamsPtr
Defines a pointer for DdnsParams instances.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_START
boost::shared_ptr< Option6IAPrefix > Option6IAPrefixPtr
Pointer to the Option6IAPrefix object.
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_HR
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_TIMEOUT
const isc::log::MessageID DHCPSRV_CFGMGR_IP_RESERVATIONS_UNIQUE_DUPLICATES_DETECTED
const isc::log::MessageID ALLOC_ENGINE_V6_HR_ADDR_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_CLASSES
const isc::log::MessageID ALLOC_ENGINE_V6_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_EXPIRED_HINT_RESERVED
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
const int ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA
Records detailed results of various operations.
const int DHCPSRV_DBG_HOOKS
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_COMPLETE
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_PREFIX_LEASE
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
const isc::log::MessageID ALLOC_ENGINE_V4_NO_MORE_EXPIRED_LEASES
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_PICK_ADDRESS
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_NEW_LEASE
boost::shared_ptr< Option6IAAddr > Option6IAAddrPtr
A pointer to the isc::dhcp::Option6IAAddr object.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_CALCULATED_PREFERRED_LIFETIME
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_UNRESERVED
const isc::log::MessageID ALLOC_ENGINE_V6_DECLINED_RECOVERED
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_START
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ALLOC_REQUESTED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_NO_HR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SUBNET
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_ADDRESS_CONFLICT
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RENEW_SKIP
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_REMOVE_LEASE
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET
const int ALLOC_ENGINE_DBG_TRACE_DETAIL
Record detailed traces.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_HR_PREFIX_GRANTED
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_CLASSES
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
boost::multiprecision::checked_uint128_t uint128_t
Defines the logger used by the top-level component of kea-lfc.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
Context information for the DHCPv4 lease allocation.
ClientIdPtr clientid_
Client identifier from the DHCP message.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
bool early_global_reservations_lookup_
Indicates if early global reservation is enabled.
ConstHostPtr currentHost() const
Returns host for currently selected subnet.
ClientContext4()
Default constructor.
Pkt4Ptr query_
A pointer to the client's message.
Subnet4Ptr subnet_
Subnet selected for the client by the server.
Lease4Ptr new_lease_
A pointer to a newly allocated lease.
std::string hostname_
Hostname.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
bool rev_dns_update_
Perform reverse DNS update.
uint32_t offer_lft_
If not zero, then we will allocate on DISCOVER for this amount of time.
bool fake_allocation_
Indicates if this is a real or fake allocation.
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
bool unknown_requested_addr_
True when the address DHCPREQUEST'ed by client is not within a dynamic pool the server knows about.
Lease4Ptr old_lease_
A pointer to an old lease that the client had before update.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
bool fwd_dns_update_
Perform forward DNS update.
asiolink::IOAddress requested_address_
An address that the client desires.
Lease4Ptr conflicting_lease_
A pointer to the object representing a lease in conflict.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
HWAddrPtr hwaddr_
HW address from the DHCP message.
IAContext()
Default constructor.
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_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