33#include <boost/foreach.hpp>
34#include <boost/make_shared.hpp>
52namespace ph = std::placeholders;
57struct AllocEngineHooks {
58 int hook_index_lease4_select_;
59 int hook_index_lease4_renew_;
60 int hook_index_lease4_expire_;
61 int hook_index_lease4_recover_;
62 int hook_index_lease6_select_;
63 int hook_index_lease6_renew_;
64 int hook_index_lease6_rebind_;
65 int hook_index_lease6_expire_;
66 int hook_index_lease6_recover_;
70 hook_index_lease4_select_ = HooksManager::registerHook(
"lease4_select");
71 hook_index_lease4_renew_ = HooksManager::registerHook(
"lease4_renew");
72 hook_index_lease4_expire_ = HooksManager::registerHook(
"lease4_expire");
73 hook_index_lease4_recover_= HooksManager::registerHook(
"lease4_recover");
74 hook_index_lease6_select_ = HooksManager::registerHook(
"lease6_select");
75 hook_index_lease6_renew_ = HooksManager::registerHook(
"lease6_renew");
76 hook_index_lease6_rebind_ = HooksManager::registerHook(
"lease6_rebind");
77 hook_index_lease6_expire_ = HooksManager::registerHook(
"lease6_expire");
78 hook_index_lease6_recover_= HooksManager::registerHook(
"lease6_recover");
86AllocEngineHooks
Hooks;
99 const uint8_t prefix_len) {
100 if (!prefix.
isV6()) {
102 "increase prefix " << prefix <<
")");
106 const std::vector<uint8_t>& vec = prefix.
toBytes();
108 if (prefix_len < 1 || prefix_len > 128) {
113 uint8_t n_bytes = (prefix_len - 1)/8;
114 uint8_t n_bits = 8 - (prefix_len - n_bytes*8);
115 uint8_t mask = 1 << n_bits;
124 uint8_t packed[V6ADDRESS_LEN];
127 std::memcpy(packed, &vec[0], V6ADDRESS_LEN);
130 if (packed[n_bytes] + uint16_t(mask) < 256u) {
131 packed[n_bytes] += mask;
136 packed[n_bytes] += mask;
139 for (
int i = n_bytes - 1; i >= 0; --i) {
142 if (packed[i] != 0) {
153 const uint8_t prefix_len) {
157 return (increasePrefix(address, prefix_len));
162AllocEngine::IterativeAllocator::pickAddressInternal(
const SubnetPtr& subnet,
168 uint8_t prefix_len = 0;
173 IOAddress last = subnet->getLastAllocated(pool_type_);
175 bool retrying =
false;
184 PoolCollection::const_iterator it;
185 PoolCollection::const_iterator first = pools.end();
187 for (it = pools.begin(); it != pools.end(); ++it) {
188 if (!(*it)->clientSupported(client_classes)) {
191 if (first == pools.end()) {
194 if ((*it)->inRange(last)) {
200 if (first == pools.end()) {
209 if (it == pools.end()) {
216 for (; it != pools.end(); ++it) {
217 if ((*it)->clientSupported(client_classes)) {
221 if (it == pools.end()) {
227 last = (*it)->getLastAllocated();
228 valid = (*it)->isLastAllocatedValid();
229 if (!valid && (last == (*it)->getFirstAddress())) {
231 (*it)->setLastAllocated(last);
232 subnet->setLastAllocated(pool_type_, last);
236 if (valid && !(*it)->inRange(last)) {
238 (*it)->resetLastAllocated();
239 (*it)->setLastAllocated((*it)->getFirstAddress());
245 Pool6Ptr pool6 = boost::dynamic_pointer_cast<Pool6>(*it);
249 isc_throw(Unexpected,
"Wrong type of pool: "
254 prefix_len = pool6->getLength();
257 IOAddress next = increaseAddress(last, prefix, prefix_len);
258 if ((*it)->inRange(next)) {
261 (*it)->setLastAllocated(next);
262 subnet->setLastAllocated(pool_type_, next);
267 (*it)->resetLastAllocated();
275 for (it = first; it != pools.end(); ++it) {
276 if ((*it)->clientSupported(client_classes)) {
277 (*it)->setLastAllocated((*it)->getFirstAddress());
278 (*it)->resetLastAllocated();
283 last = (*first)->getLastAllocated();
284 (*first)->setLastAllocated(last);
285 subnet->setLastAllocated(pool_type_, last);
295AllocEngine::HashedAllocator::pickAddressInternal(
const SubnetPtr&,
308AllocEngine::RandomAllocator::pickAddressInternal(
const SubnetPtr&,
317 : attempts_(attempts), incomplete_v4_reclamations_(0),
318 incomplete_v6_reclamations_(0) {
324 switch (engine_type) {
341 switch (engine_type) {
360 hook_index_lease4_select_ =
Hooks.hook_index_lease4_select_;
361 hook_index_lease6_select_ =
Hooks.hook_index_lease6_select_;
365 std::map<Lease::Type, AllocatorPtr>::const_iterator alloc = allocators_.find(type);
367 if (alloc == allocators_.end()) {
371 return (alloc->second);
398 if (CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
399 auto host = HostMgr::instance().get6(subnet_id, address);
401 reserved.push_back(host);
404 auto hosts = HostMgr::instance().getAll6(subnet_id, address);
405 reserved.insert(reserved.end(), hosts.begin(), hosts.end());
424 const IOAddress& address,
bool check_subnet) {
428 while (current_subnet) {
430 if (current_subnet->clientSupported(ctx.
query_->getClasses())) {
432 if (current_subnet->inPool(lease_type, address)) {
436 if (current_subnet->inPool(lease_type, address,
437 ctx.
query_->getClasses())) {
443 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_);
459 : query_(), fake_allocation_(false), subnet_(), host_subnet_(), duid_(),
460 hwaddr_(), host_identifiers_(), hosts_(), fwd_dns_update_(false),
461 rev_dns_update_(false), hostname_(), callout_handle_(), ias_(),
469 const std::string& hostname,
470 const bool fake_allocation,
473 : query_(query), fake_allocation_(fake_allocation), subnet_(subnet),
474 duid_(duid), hwaddr_(), host_identifiers_(), hosts_(),
475 fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname),
476 callout_handle_(callout_handle), allocated_resources_(), new_leases_(),
477 ias_(), ddns_params_() {
486 : iaid_(0), type_(
Lease::TYPE_NA), hints_(), old_leases_(),
487 changed_leases_(), new_resources_(), ia_rsp_() {
493 const uint8_t prefix_len,
494 const uint32_t preferred,
495 const uint32_t valid) {
496 hints_.push_back(
Resource(prefix, prefix_len, preferred, valid));
505 addHint(iaaddr->getAddress(), 128,
506 iaaddr->getPreferred(), iaaddr->getValid());
515 addHint(iaprefix->getAddress(), iaprefix->getLength(),
516 iaprefix->getPreferred(), iaprefix->getValid());
522 const uint8_t prefix_len) {
523 static_cast<void>(new_resources_.insert(
Resource(prefix, prefix_len)));
529 const uint8_t prefix_len)
const {
530 return (
static_cast<bool>(new_resources_.count(
Resource(prefix,
537 const uint8_t prefix_len) {
545 return (
static_cast<bool>
552 if (subnet && subnet->getReservationsInSubnet()) {
553 auto host =
hosts_.find(subnet->getID());
554 if (host !=
hosts_.cend()) {
555 return (host->second);
565 if (subnet &&
subnet_->getReservationsGlobal()) {
566 auto host =
hosts_.find(SUBNET_ID_GLOBAL);
567 if (host !=
hosts_.cend()) {
568 return (host->second);
578 return (ghost && ghost->hasReservation(resv));
584 if (ddns_params_ &&
subnet_ && (
subnet_->getID() == ddns_params_->getSubnetId())) {
585 return (ddns_params_);
591 return (ddns_params_);
610 std::map<SubnetID, ConstHostPtr> host_map;
612 subnet->getSharedNetwork(network);
615 if (subnet->getReservationsGlobal()) {
618 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
621 if (!subnet->getReservationsInSubnet()) {
634 const bool use_single_query = network &&
638 if (use_single_query) {
642 id_pair.second.size());
646 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
647 if ((*host)->getIPv6SubnetID() != SUBNET_ID_GLOBAL) {
648 host_map[(*host)->getIPv6SubnetID()] = *host;
659 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
660 subnet->getReservationsInSubnet()) {
663 if (use_single_query) {
664 if (host_map.count(subnet->getID()) > 0) {
665 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
673 id_pair.second.size());
676 ctx.
hosts_[subnet->getID()] = host;
686 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
696 &id_pair.second[0], id_pair.second.size());
730 for (
auto l : all_leases) {
731 if ((l)->subnet_id_ == subnet->getID()) {
736 subnet = subnet->getNextSubnet(ctx.
subnet_);
756 if (leases.empty() && !ctx.
hosts_.empty()) {
760 .arg(ctx.
query_->getLabel());
765 allocateReservedLeases6(ctx, leases);
767 leases = updateLeaseData(ctx, leases);
782 }
else if (!leases.empty() && ctx.
hosts_.empty()) {
786 .arg(ctx.
query_->getLabel());
790 removeNonmatchingReservedLeases6(ctx, leases);
792 leases = updateLeaseData(ctx, leases);
801 }
else if (!leases.empty() && !ctx.
hosts_.empty()) {
805 .arg(ctx.
query_->getLabel());
809 allocateReservedLeases6(ctx, leases);
821 removeNonmatchingReservedLeases6(ctx, leases);
830 removeNonreservedLeases6(ctx, leases);
835 leases = updateLeaseData(ctx, leases);
848 if (leases.empty()) {
862 .arg(ctx.
query_->getLabel());
864 leases = allocateUnreservedLeases6(ctx);
867 if (!leases.empty()) {
882 .arg(ctx.
query_->getLabel())
902 if (!ctx.currentIA().hints_.empty()) {
904 hint = ctx.currentIA().hints_[0].getAddress();
914 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
916 if (!subnet->clientSupported(ctx.query_->getClasses())) {
920 ctx.subnet_ = subnet;
924 pool = boost::dynamic_pointer_cast<Pool6>
925 (subnet->getPool(ctx.currentIA().type_, ctx.query_->getClasses(),
929 if (!pool || !pool->clientSupported(ctx.query_->getClasses())) {
933 bool in_subnet = subnet->getReservationsInSubnet();
950 (!subnet->getReservationsOutOfPool() ||
951 !subnet->inPool(ctx.currentIA().type_, hint))) {
952 hosts = getIPv6Resrv(subnet->getID(), hint);
961 lease = createLease6(ctx, hint, pool->getLength(), callout_status);
971 collection.push_back(lease);
977 .arg(ctx.query_->getLabel())
981 }
else if (lease->expired()) {
990 (!subnet->getReservationsOutOfPool() ||
991 !subnet->inPool(ctx.currentIA().type_, hint))) {
992 hosts = getIPv6Resrv(subnet->getID(), hint);
1001 ctx.currentIA().old_leases_.push_back(old_lease);
1004 lease = reuseExpiredLease(lease, ctx, pool->getLength(),
1008 leases.push_back(lease);
1014 .arg(ctx.query_->getLabel())
1023 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
1025 uint64_t total_attempts = 0;
1037 original_subnet->getSharedNetwork(network);
1044 original_subnet = network->getPreferredSubnet(original_subnet, ctx.currentIA().type_);
1047 ctx.subnet_ = subnet = original_subnet;
1051 uint64_t subnets_with_unavail_leases = 0;
1054 uint64_t subnets_with_unavail_pools = 0;
1056 for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) {
1058 if (!subnet->clientSupported(ctx.query_->getClasses())) {
1068 uint64_t possible_attempts =
1069 subnet->getPoolCapacity(ctx.currentIA().type_,
1070 ctx.query_->getClasses());
1077 uint64_t max_attempts = ((attempts_ == 0) || (possible_attempts < attempts_)) ? possible_attempts : attempts_;
1079 if (max_attempts > 0) {
1082 ++subnets_with_unavail_leases;
1086 ++subnets_with_unavail_pools;
1090 bool in_subnet = subnet->getReservationsInSubnet();
1091 bool out_of_pool = subnet->getReservationsOutOfPool();
1096 if (ctx.callout_handle_) {
1097 ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
1100 for (uint64_t i = 0; i < max_attempts; ++i) {
1104 IOAddress candidate = allocator->pickAddress(subnet,
1105 ctx.query_->getClasses(),
1110 uint8_t prefix_len = 128;
1112 pool = boost::dynamic_pointer_cast<Pool6>(
1113 subnet->getPool(ctx.currentIA().type_,
1114 ctx.query_->getClasses(),
1117 prefix_len = pool->getLength();
1122 if (check_reservation_first && in_subnet && !out_of_pool) {
1123 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1124 if (!hosts.empty()) {
1133 if (MultiThreadingMgr::instance().getMode() &&
1134 !resource_handler.
tryLock(ctx.currentIA().type_, candidate)) {
1147 if (!check_reservation_first && in_subnet && !out_of_pool) {
1148 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1149 if (!hosts.empty()) {
1158 ctx.subnet_ = subnet;
1159 Lease6Ptr lease = createLease6(ctx, candidate, prefix_len, callout_status);
1163 ctx.currentIA().old_leases_.clear();
1165 leases.push_back(lease);
1168 }
else if (ctx.callout_handle_ &&
1169 (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
1177 }
else if (existing->expired()) {
1179 if (!check_reservation_first && in_subnet && !out_of_pool) {
1180 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
1181 if (!hosts.empty()) {
1190 ctx.currentIA().old_leases_.push_back(old_lease);
1192 ctx.subnet_ = subnet;
1193 existing = reuseExpiredLease(existing, ctx, prefix_len,
1196 leases.push_back(existing);
1206 .arg(ctx.query_->getLabel())
1207 .arg(network->getName())
1208 .arg(subnets_with_unavail_leases)
1209 .arg(subnets_with_unavail_pools);
1215 .arg(ctx.query_->getLabel())
1216 .arg(ctx.subnet_->getID());
1218 if (total_attempts == 0) {
1224 .arg(ctx.query_->getLabel());
1231 .arg(ctx.query_->getLabel())
1232 .arg(total_attempts);
1244 if (ctx.hosts_.empty()) {
1247 .arg(ctx.query_->getLabel());
1258 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1259 if ((lease->valid_lft_ != 0)) {
1260 if ((ctx.hosts_.count(lease->subnet_id_) > 0) &&
1261 ctx.hosts_[lease->subnet_id_]->hasReservation(
makeIPv6Resrv(*lease))) {
1266 .arg(ctx.query_->getLabel())
1267 .arg(lease->typeToText(lease->type_))
1268 .arg(lease->addr_.toText());
1274 if (!ctx.host_subnet_) {
1276 ctx.subnet_->getSharedNetwork(network);
1281 ctx.host_subnet_ = network->getSubnet(lease->subnet_id_);
1289 if (host && !host->getHostname().empty()) {
1296 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1297 static_cast<bool>(fqdn));
1311 for (
Subnet6Ptr subnet = ctx.subnet_; subnet;
1312 subnet = subnet->getNextSubnet(ctx.subnet_)) {
1314 SubnetID subnet_id = subnet->getID();
1317 if (!subnet->clientSupported(ctx.query_->getClasses()) ||
1318 ctx.hosts_.count(subnet_id) == 0) {
1324 bool in_subnet = subnet->getReservationsInSubnet();
1330 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1331 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1335 if (ctx.isAllocated(addr, prefix_len)) {
1344 (subnet->getReservationsOutOfPool() &&
1345 subnet->inPool(ctx.currentIA().type_, addr))) {
1357 ctx.subnet_ = subnet;
1359 if (!ctx.host_subnet_) {
1360 ctx.host_subnet_ = subnet;
1361 if (!host->getHostname().empty()) {
1375 qualifyName(host->getHostname(), *ctx.getDdnsParams(),
1376 static_cast<bool>(fqdn));
1382 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1385 existing_leases.push_back(lease);
1390 .arg(ctx.query_->getLabel());
1394 .arg(
static_cast<int>(prefix_len))
1395 .arg(ctx.query_->getLabel());
1413 allocateGlobalReservedLeases6(ctx, existing_leases);
1428 BOOST_FOREACH(
const Lease6Ptr& lease, existing_leases) {
1429 if ((lease->valid_lft_ != 0) &&
1435 .arg(ctx.query_->getLabel())
1436 .arg(lease->typeToText(lease->type_))
1437 .arg(lease->addr_.toText());
1443 if (!ghost->getHostname().empty()) {
1450 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1451 static_cast<bool>(fqdn));
1466 const IPv6ResrvRange& reservs = ghost->getIPv6Reservations(type);
1469 const IOAddress& addr = type_lease_tuple.second.getPrefix();
1470 uint8_t prefix_len = type_lease_tuple.second.getPrefixLen();
1474 if (ctx.isAllocated(addr, prefix_len)) {
1482 if (!ghost->getHostname().empty()) {
1496 qualifyName(ghost->getHostname(), *ctx.getDdnsParams(),
1497 static_cast<bool>(fqdn));
1502 Lease6Ptr lease = createLease6(ctx, addr, prefix_len, callout_status);
1505 existing_leases.push_back(lease);
1510 .arg(ctx.query_->getLabel());
1514 .arg(
static_cast<int>(prefix_len))
1515 .arg(ctx.query_->getLabel());
1533AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1536 if (existing_leases.empty() || !ctx.subnet_) {
1541 if (!ctx.subnet_->getReservationsInSubnet() &&
1542 !ctx.subnet_->getReservationsGlobal()) {
1543 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1556 if ((ctx.hasGlobalReservation(resv)) ||
1557 ((ctx.hosts_.count(candidate->subnet_id_) > 0) &&
1558 (ctx.hosts_[candidate->subnet_id_]->hasReservation(resv)))) {
1567 auto hosts = getIPv6Resrv(ctx.subnet_->getID(), candidate->addr_);
1572 if (hosts.empty() && inAllowedPool(ctx, candidate->type_,
1573 candidate->addr_,
false)) {
1577 if (!hosts.empty()) {
1580 if (hosts.size() == 1) {
1583 .arg(candidate->addr_.toText())
1584 .arg(ctx.duid_->toText())
1585 .arg(hosts.front()->getIdentifierAsText());
1588 .arg(candidate->addr_.toText())
1589 .arg(
static_cast<int>(candidate->prefixlen_))
1590 .arg(ctx.duid_->toText())
1591 .arg(hosts.front()->getIdentifierAsText());
1596 .arg(candidate->addr_.toText())
1597 .arg(ctx.duid_->toText())
1601 .arg(candidate->addr_.toText())
1602 .arg(
static_cast<int>(candidate->prefixlen_))
1603 .arg(ctx.duid_->toText())
1621 StatsMgr::instance().addValue(
1622 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1624 "assigned-nas" :
"assigned-pds"),
1625 static_cast<int64_t
>(-1));
1633 ctx.currentIA().old_leases_.push_back(candidate);
1636 removeLeases(existing_leases, candidate->addr_);
1641AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1652 if (inAllowedPool(ctx, candidate->type_,
1653 candidate->addr_,
false)) {
1668 StatsMgr::instance().addValue(
1669 StatsMgr::generateName(
"subnet", candidate->subnet_id_,
1671 "assigned-nas" :
"assigned-pds"),
1672 static_cast<int64_t
>(-1));
1675 ctx.currentIA().old_leases_.push_back(candidate);
1678 removeLeases(existing_leases, candidate->addr_);
1683AllocEngine::removeLeases(
Lease6Collection& container,
const asiolink::IOAddress& addr) {
1685 bool removed =
false;
1686 for (Lease6Collection::iterator lease = container.begin();
1687 lease != container.end(); ++lease) {
1688 if ((*lease)->addr_ == addr) {
1695 container.erase(std::remove(container.begin(), container.end(),
Lease6Ptr()),
1706 int total = existing_leases.size();
1713 for (Lease6Collection::iterator lease = existing_leases.begin();
1714 lease != existing_leases.end(); ++lease) {
1718 if (ctx.hasGlobalReservation(resv) ||
1719 ((ctx.hosts_.count((*lease)->subnet_id_) > 0) &&
1720 (ctx.hosts_[(*lease)->subnet_id_]->hasReservation(resv)))) {
1739 StatsMgr::instance().addValue(
1740 StatsMgr::generateName(
"subnet", (*lease)->subnet_id_,
1742 "assigned-nas" :
"assigned-pds"),
1743 static_cast<int64_t
>(-1));
1748 ctx.currentIA().old_leases_.push_back(*lease);
1764 existing_leases.erase(std::remove(existing_leases.begin(),
1765 existing_leases.end(),
Lease6Ptr()), existing_leases.end());
1773 if (!expired->expired()) {
1774 isc_throw(BadValue,
"Attempt to recycle lease that is still valid");
1781 if (!ctx.fake_allocation_) {
1785 reclaimExpiredLease(expired, ctx.callout_handle_);
1789 expired->iaid_ = ctx.currentIA().iaid_;
1790 expired->duid_ = ctx.duid_;
1793 if (!ctx.currentIA().hints_.empty() &&
1794 ctx.currentIA().hints_[0].getPreferred()) {
1795 uint32_t preferred = ctx.currentIA().hints_[0].getPreferred();
1796 expired->preferred_lft_ = ctx.subnet_->getPreferred().get(preferred);
1798 expired->preferred_lft_ = ctx.subnet_->getPreferred();
1802 expired->reuseable_valid_lft_ = 0;
1803 if (!ctx.currentIA().hints_.empty() &&
1804 ctx.currentIA().hints_[0].getValid()) {
1805 uint32_t valid = ctx.currentIA().hints_[0].getValid();
1806 expired->valid_lft_ = ctx.subnet_->getValid().get(valid);
1808 expired->valid_lft_ = ctx.subnet_->getValid();
1810 expired->cltt_ = time(NULL);
1811 expired->subnet_id_ = ctx.subnet_->getID();
1812 expired->hostname_ = ctx.hostname_;
1813 expired->fqdn_fwd_ = ctx.fwd_dns_update_;
1814 expired->fqdn_rev_ = ctx.rev_dns_update_;
1815 expired->prefixlen_ = prefix_len;
1820 .arg(ctx.query_->getLabel())
1821 .arg(expired->toText());
1824 if (ctx.callout_handle_ &&
1825 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
1839 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1842 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1845 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1848 ctx.callout_handle_->setArgument(
"lease6", expired);
1851 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1853 callout_status = ctx.callout_handle_->getStatus();
1858 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1870 ctx.callout_handle_->getArgument(
"lease6", expired);
1873 if (!ctx.fake_allocation_) {
1882 if (ctx.subnet_->inPool(ctx.currentIA().type_, expired->addr_)) {
1883 StatsMgr::instance().addValue(
1884 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1886 "assigned-nas" :
"assigned-pds"),
1887 static_cast<int64_t
>(1));
1888 StatsMgr::instance().addValue(
1889 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1891 "cumulative-assigned-nas" :
1892 "cumulative-assigned-pds"),
1893 static_cast<int64_t
>(1));
1894 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
1895 "cumulative-assigned-nas" :
1896 "cumulative-assigned-pds",
1897 static_cast<int64_t
>(1));
1916 if (!classes.
empty()) {
1923 for (
auto name = classes.
cbegin();
1924 name != classes.
cend() && have_both < 2; ++name) {
1927 (cl && (!cl->getPreferred().unspecified()))) {
1928 candidate_preferred = cl->getPreferred();
1933 (cl && (!cl->getValid().unspecified()))) {
1934 candidate_valid = cl->getValid();
1941 if (!candidate_preferred) {
1942 candidate_preferred = ctx.
subnet_->getPreferred();
1946 if (!candidate_valid) {
1947 candidate_valid = ctx.
subnet_->getValid();
1951 preferred = candidate_preferred;
1952 valid = candidate_valid;
1976 uint32_t preferred = 0;
1981 ctx.currentIA().iaid_, preferred,
1982 valid, ctx.subnet_->getID(),
1983 ctx.hwaddr_, prefix_len));
1985 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1986 lease->fqdn_rev_ = ctx.rev_dns_update_;
1987 lease->hostname_ = ctx.hostname_;
1990 if (ctx.callout_handle_ &&
1991 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
2005 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
2008 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
2011 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
2014 ctx.callout_handle_->setArgument(
"lease6", lease);
2017 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
2019 callout_status = ctx.callout_handle_->getStatus();
2024 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
2031 ctx.callout_handle_->getArgument(
"lease6", lease);
2034 if (!ctx.fake_allocation_) {
2044 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
2045 StatsMgr::instance().addValue(
2046 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2048 "assigned-nas" :
"assigned-pds"),
2049 static_cast<int64_t
>(1));
2050 StatsMgr::instance().addValue(
2051 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2053 "cumulative-assigned-nas" :
2054 "cumulative-assigned-pds"),
2055 static_cast<int64_t
>(1));
2056 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2057 "cumulative-assigned-nas" :
2058 "cumulative-assigned-pds",
2059 static_cast<int64_t
>(1));
2063 ctx.currentIA().addNewResource(addr, prefix_len);
2102 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2104 subnet = subnet->getNextSubnet(ctx.
subnet_);
2107 if (!leases.empty()) {
2110 .arg(ctx.
query_->getLabel());
2114 removeNonmatchingReservedLeases6(ctx, leases);
2117 if (!ctx.
hosts_.empty()) {
2121 .arg(ctx.
query_->getLabel());
2124 allocateReservedLeases6(ctx, leases);
2130 removeNonreservedLeases6(ctx, leases);
2137 if (leases.empty()) {
2141 .arg(ctx.
query_->getLabel());
2143 leases = allocateUnreservedLeases6(ctx);
2147 for (Lease6Collection::iterator l = leases.begin(); l != leases.end(); ++l) {
2149 (*l)->prefixlen_)) {
2155 .arg(ctx.
query_->getLabel())
2156 .arg((*l)->typeToText((*l)->type_))
2158 extendLease6(ctx, *l);
2161 if (!leases.empty()) {
2165 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2177 .arg(ctx.
query_->getLabel())
2187 if (!lease || !ctx.subnet_) {
2193 if (ctx.subnet_->getID() != lease->subnet_id_) {
2195 ctx.subnet_->getSharedNetwork(network);
2201 ctx.subnet_ = subnet;
2209 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2210 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2224 StatsMgr::instance().addValue(
2225 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
"assigned-nas"),
2226 static_cast<int64_t
>(-1));
2229 ctx.currentIA().old_leases_.push_back(lease);
2236 .arg(ctx.query_->getLabel())
2237 .arg(lease->toText());
2242 bool changed =
false;
2243 uint32_t current_preferred_lft = lease->preferred_lft_;
2244 if (!ctx.currentIA().hints_.empty() &&
2245 ctx.currentIA().hints_[0].getPreferred()) {
2246 uint32_t preferred = ctx.currentIA().hints_[0].getPreferred();
2247 lease->preferred_lft_ = ctx.subnet_->getPreferred().get(preferred);
2249 lease->preferred_lft_ = ctx.subnet_->getPreferred();
2251 if (lease->preferred_lft_ < current_preferred_lft) {
2254 lease->reuseable_valid_lft_ = 0;
2255 if (!ctx.currentIA().hints_.empty() &&
2256 ctx.currentIA().hints_[0].getValid()) {
2257 uint32_t valid = ctx.currentIA().hints_[0].getValid();
2258 lease->valid_lft_ = ctx.subnet_->getValid().get(valid);
2260 lease->valid_lft_ = ctx.subnet_->getValid();
2262 if (lease->valid_lft_ < lease->current_valid_lft_) {
2266 lease->cltt_ = time(NULL);
2267 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2268 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2269 (lease->hostname_ != ctx.hostname_)) {
2271 lease->hostname_ = ctx.hostname_;
2272 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2273 lease->fqdn_rev_ = ctx.rev_dns_update_;
2275 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2277 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2279 lease->hwaddr_ = ctx.hwaddr_;
2287 .arg(ctx.query_->getLabel())
2288 .arg(lease->toText());
2292 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2293 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2294 if (HooksManager::calloutsPresent(hook_point)) {
2307 callout_handle->setArgument(
"query6", ctx.query_);
2310 callout_handle->setArgument(
"lease6", lease);
2314 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2316 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2320 HooksManager::callCallouts(hook_point, *callout_handle);
2325 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2329 .arg(ctx.query_->getName());
2336 bool update_stats =
false;
2340 if (old_data->expired()) {
2341 reclaimExpiredLease(old_data, ctx.callout_handle_);
2345 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2346 update_stats =
true;
2358 setLeaseReusable(lease, current_preferred_lft, ctx);
2364 if (lease->reuseable_valid_lft_ == 0) {
2369 StatsMgr::instance().addValue(
2370 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2372 "assigned-nas" :
"assigned-pds"),
2373 static_cast<int64_t
>(1));
2374 StatsMgr::instance().addValue(
2375 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2377 "cumulative-assigned-nas" :
2378 "cumulative-assigned-pds"),
2379 static_cast<int64_t
>(1));
2380 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2381 "cumulative-assigned-nas" :
2382 "cumulative-assigned-pds",
2383 static_cast<int64_t
>(1));
2396 ctx.currentIA().changed_leases_.push_back(old_data);
2402 for (Lease6Collection::const_iterator lease_it = leases.begin();
2403 lease_it != leases.end(); ++lease_it) {
2405 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2407 updated_leases.push_back(lease);
2411 lease->reuseable_valid_lft_ = 0;
2412 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2413 lease->fqdn_rev_ = ctx.rev_dns_update_;
2414 lease->hostname_ = ctx.hostname_;
2415 if (!ctx.fake_allocation_) {
2416 bool update_stats =
false;
2424 if (inAllowedPool(ctx, ctx.currentIA().type_,
2425 lease->addr_,
true)) {
2426 update_stats =
true;
2431 !(lease->hasIdenticalFqdn(**lease_it)));
2433 lease->cltt_ = time(NULL);
2434 if (!fqdn_changed) {
2435 uint32_t current_preferred_lft = lease->preferred_lft_;
2436 setLeaseReusable(lease, current_preferred_lft, ctx);
2438 if (lease->reuseable_valid_lft_ == 0) {
2439 ctx.currentIA().changed_leases_.push_back(*lease_it);
2444 StatsMgr::instance().addValue(
2445 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2447 "assigned-nas" :
"assigned-pds"),
2448 static_cast<int64_t
>(1));
2449 StatsMgr::instance().addValue(
2450 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2452 "cumulative-assigned-nas" :
2453 "cumulative-assigned-pds"),
2454 static_cast<int64_t
>(1));
2455 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2456 "cumulative-assigned-nas" :
2457 "cumulative-assigned-pds",
2458 static_cast<int64_t
>(1));
2462 updated_leases.push_back(lease);
2465 return (updated_leases);
2470 const bool remove_lease,
2471 const uint16_t max_unwarned_cycles) {
2486 bool incomplete_reclamation =
false;
2489 if (max_leases > 0) {
2498 if (leases.size() > max_leases) {
2500 incomplete_reclamation =
true;
2513 if (!leases.empty() &&
2514 HooksManager::calloutsPresent(
Hooks.hook_index_lease6_expire_)) {
2515 callout_handle = HooksManager::createCalloutHandle();
2518 size_t leases_processed = 0;
2519 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2523 if (MultiThreadingMgr::instance().getMode()) {
2527 reclaimExpiredLease(lease, remove_lease, callout_handle);
2530 reclaimExpiredLease(lease, remove_lease, callout_handle);
2534 }
catch (
const std::exception& ex) {
2536 .arg(lease->addr_.toText())
2547 if (!incomplete_reclamation) {
2548 if (leases_processed < leases.size()) {
2549 incomplete_reclamation =
true;
2566 .arg(leases_processed)
2571 if (incomplete_reclamation) {
2572 ++incomplete_v6_reclamations_;
2575 if ((max_unwarned_cycles > 0) &&
2576 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2578 .arg(max_unwarned_cycles);
2580 incomplete_v6_reclamations_ = 0;
2585 incomplete_v6_reclamations_ = 0;
2598 uint64_t deleted_leases = 0;
2604 }
catch (
const std::exception& ex) {
2611 .arg(deleted_leases);
2616 const bool remove_lease,
2617 const uint16_t max_unwarned_cycles) {
2632 bool incomplete_reclamation =
false;
2635 if (max_leases > 0) {
2644 if (leases.size() > max_leases) {
2646 incomplete_reclamation =
true;
2659 if (!leases.empty() &&
2660 HooksManager::calloutsPresent(
Hooks.hook_index_lease4_expire_)) {
2661 callout_handle = HooksManager::createCalloutHandle();
2664 size_t leases_processed = 0;
2665 BOOST_FOREACH(
Lease4Ptr lease, leases) {
2669 if (MultiThreadingMgr::instance().getMode()) {
2673 reclaimExpiredLease(lease, remove_lease, callout_handle);
2676 reclaimExpiredLease(lease, remove_lease, callout_handle);
2680 }
catch (
const std::exception& ex) {
2682 .arg(lease->addr_.toText())
2693 if (!incomplete_reclamation) {
2694 if (leases_processed < leases.size()) {
2695 incomplete_reclamation =
true;
2712 .arg(leases_processed)
2717 if (incomplete_reclamation) {
2718 ++incomplete_v4_reclamations_;
2721 if ((max_unwarned_cycles > 0) &&
2722 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2724 .arg(max_unwarned_cycles);
2726 incomplete_v4_reclamations_ = 0;
2731 incomplete_v4_reclamations_ = 0;
2738template<
typename LeasePtrType>
2740AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2742 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2746template<
typename LeasePtrType>
2748AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2753 if (!lease->stateExpiredReclaimed()) {
2754 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2759AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2760 const DbReclaimMode& reclaim_mode,
2766 .arg(lease->addr_.toText())
2767 .arg(
static_cast<int>(lease->prefixlen_));
2773 bool skipped =
false;
2774 if (callout_handle) {
2782 callout_handle->deleteAllArguments();
2783 callout_handle->setArgument(
"lease6", lease);
2784 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2786 HooksManager::callCallouts(
Hooks.hook_index_lease6_expire_,
2789 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2804 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2814 remove_lease = reclaimDeclined(lease);
2817 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2821 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2823 &lease_mgr, ph::_1));
2832 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2839 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2847 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2850 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2852 "reclaimed-leases"),
2857AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2858 const DbReclaimMode& reclaim_mode,
2864 .arg(lease->addr_.toText());
2870 bool skipped =
false;
2871 if (callout_handle) {
2879 callout_handle->setArgument(
"lease4", lease);
2880 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2882 HooksManager::callCallouts(
Hooks.hook_index_lease4_expire_,
2885 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2898 lease->hostname_.clear();
2899 lease->fqdn_fwd_ =
false;
2900 lease->fqdn_rev_ =
false;
2904 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2914 remove_lease = reclaimDeclined(lease);
2917 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2921 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
2923 &lease_mgr, ph::_1));
2930 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2932 "assigned-addresses"),
2936 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2939 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2941 "reclaimed-leases"),
2951 uint64_t deleted_leases = 0;
2957 }
catch (
const std::exception& ex) {
2964 .arg(deleted_leases);
2968AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
2973 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_recover_)) {
2983 callout_handle->setArgument(
"lease4", lease);
2986 HooksManager::callCallouts(
Hooks.hook_index_lease4_recover_, *callout_handle);
2991 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2993 .arg(lease->addr_.toText());
2999 .arg(lease->addr_.toText())
3000 .arg(lease->valid_lft_);
3002 StatsMgr& stats_mgr = StatsMgr::instance();
3005 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3006 "declined-addresses"),
static_cast<int64_t
>(-1));
3009 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3011 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3013 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3014 "reclaimed-declined-addresses"),
static_cast<int64_t
>(1));
3022AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
3027 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_recover_)) {
3037 callout_handle->setArgument(
"lease6", lease);
3040 HooksManager::callCallouts(
Hooks.hook_index_lease6_recover_, *callout_handle);
3045 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3047 .arg(lease->addr_.toText());
3053 .arg(lease->addr_.toText())
3054 .arg(lease->valid_lft_);
3056 StatsMgr& stats_mgr = StatsMgr::instance();
3059 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3060 "declined-addresses"),
static_cast<int64_t
>(-1));
3063 stats_mgr.
addValue(
"declined-addresses",
static_cast<int64_t
>(-1));
3065 stats_mgr.
addValue(
"reclaimed-declined-addresses",
static_cast<int64_t
>(1));
3067 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3068 "reclaimed-declined-addresses"),
static_cast<int64_t
>(1));
3076template<
typename LeasePtrType>
3077void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3078 const bool remove_lease,
3079 const std::function<
void (
const LeasePtrType&)>&
3080 lease_update_fun)
const {
3088 }
else if (lease_update_fun) {
3091 lease->reuseable_valid_lft_ = 0;
3092 lease->hostname_.clear();
3093 lease->fqdn_fwd_ =
false;
3094 lease->fqdn_rev_ =
false;
3096 lease_update_fun(lease);
3105 .arg(lease->addr_.toText());
3141 (!ctx.
subnet_->getReservationsOutOfPool() ||
3152 if (
CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->getIPReservationsUnique()) {
3156 hosts.push_back(host);
3163 for (
auto host : hosts) {
3167 if (id_pair.first == host->getIdentifierType() &&
3168 id_pair.second == host->getIdentifier()) {
3176 return (!hosts.empty());
3198 if (ctx.
hosts_.empty()) {
3203 bool search_global_done =
false;
3208 if (!search_global_done && subnet->getReservationsGlobal()) {
3209 auto host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3212 if (host != ctx.
hosts_.end() && host->second &&
3213 !host->second->getIPv4Reservation().isV4Zero()) {
3218 search_global_done =
true;
3221 if (subnet->getReservationsInSubnet()) {
3222 auto host = ctx.
hosts_.find(subnet->getID());
3227 if (host != ctx.
hosts_.end() && host->second) {
3228 auto reservation = host->second->getIPv4Reservation();
3229 if (!reservation.isV4Zero() &&
3230 (!subnet->getReservationsOutOfPool() ||
3240 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3268 bool try_clientid_lookup = (ctx.
clientid_ &&
3270 ctx.
query_->getClasses()));
3273 if (try_clientid_lookup) {
3281 for (
Subnet4Ptr subnet = original_subnet; subnet;
3282 subnet = subnet->getNextSubnet(original_subnet,
3283 ctx.
query_->getClasses())) {
3288 if (subnet->getMatchClientId()) {
3289 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
3290 if ((*l)->subnet_id_ == subnet->getID()) {
3292 client_lease = (*l);
3303 if (!client_lease && ctx.
hwaddr_) {
3308 for (
Subnet4Ptr subnet = original_subnet; subnet;
3309 subnet = subnet->getNextSubnet(original_subnet,
3310 ctx.
query_->getClasses())) {
3312 if (subnet->getMatchClientId()) {
3318 for (Lease4Collection::const_iterator client_lease_it = leases_hw_address.begin();
3319 client_lease_it != leases_hw_address.end(); ++client_lease_it) {
3320 Lease4Ptr existing_lease = *client_lease_it;
3321 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3322 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3324 client_lease = existing_lease;
3352 while (current_subnet) {
3355 ctx.
query_->getClasses())) {
3363 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_,
3364 ctx.
query_->getClasses());
3376 : subnet_(), clientid_(), hwaddr_(),
3377 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3378 fwd_dns_update_(false), rev_dns_update_(false),
3379 hostname_(
""), callout_handle_(), fake_allocation_(false),
3380 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3381 query_(), host_identifiers_(),
3389 const bool fwd_dns_update,
3390 const bool rev_dns_update,
3391 const std::string& hostname,
3392 const bool fake_allocation)
3393 : subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3394 requested_address_(requested_addr),
3395 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3396 hostname_(hostname), callout_handle_(),
3397 fake_allocation_(fake_allocation), old_lease_(), new_lease_(),
3398 hosts_(), host_identifiers_(),
3409 if (subnet_ && subnet_->getReservationsInSubnet()) {
3410 auto host = hosts_.find(subnet_->getID());
3411 if (host != hosts_.cend()) {
3412 return (host->second);
3416 return (globalHost());
3421 if (subnet_ && subnet_->getReservationsGlobal()) {
3422 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3423 if (host != hosts_.cend()) {
3424 return (host->second);
3434 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3435 return (ddns_params_);
3441 return (ddns_params_);
3463 if (subnet && !subnet->clientSupported(ctx.
query_->getClasses())) {
3464 ctx.
subnet_ = subnet->getNextSubnet(subnet, ctx.
query_->getClasses());
3477 return (discoverLease4(ctx));
3486 .arg(ctx.
query_->getLabel())
3504 std::map<SubnetID, ConstHostPtr> host_map;
3506 subnet->getSharedNetwork(network);
3509 if (subnet->getReservationsGlobal()) {
3512 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3515 if (!subnet->getReservationsInSubnet()) {
3528 const bool use_single_query = network &&
3532 if (use_single_query) {
3536 id_pair.second.size());
3540 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
3541 if ((*host)->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3542 host_map[(*host)->getIPv4SubnetID()] = *host;
3553 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
3554 subnet->getReservationsInSubnet()) {
3557 if (use_single_query) {
3558 if (host_map.count(subnet->getID()) > 0) {
3559 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3567 id_pair.second.size());
3570 ctx.
hosts_[subnet->getID()] = host;
3580 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3590 &id_pair.second[0], id_pair.second.size());
3607 findClientLease(ctx, client_lease);
3617 if (hasAddressReservation(ctx)) {
3621 .arg(ctx.
query_->getLabel())
3622 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3628 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3635 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3639 .arg(ctx.
query_->getLabel())
3640 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3646 new_lease = renewLease4(client_lease, ctx);
3659 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3660 !addressReserved(client_lease->addr_, ctx)) {
3664 .arg(ctx.
query_->getLabel());
3666 new_lease = renewLease4(client_lease, ctx);
3683 .arg(ctx.
query_->getLabel());
3696 .arg(ctx.
query_->getLabel());
3698 new_lease = allocateUnreservedLease4(ctx);
3718 findClientLease(ctx, client_lease);
3734 .arg(ctx.
query_->getLabel())
3740 }
else if (hasAddressReservation(ctx)) {
3749 .arg(ctx.
query_->getLabel())
3761 if (existing && !existing->expired() &&
3762 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
3767 .arg(ctx.
query_->getLabel())
3777 if (hasAddressReservation(ctx) &&
3785 if (!existing || existing->expired()) {
3789 .arg(ctx.
query_->getLabel())
3790 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3800 if ((!hasAddressReservation(ctx) ||
3806 .arg(ctx.
query_->getLabel())
3824 (hasAddressReservation(ctx) ||
3825 inAllowedPool(ctx, client_lease->addr_))) {
3829 .arg(ctx.
query_->getLabel())
3832 return (renewLease4(client_lease, ctx));
3846 .arg(ctx.
query_->getLabel())
3862 .arg(ctx.
query_->getLabel());
3867 new_lease = allocateUnreservedLease4(ctx);
3873 if (new_lease && client_lease) {
3878 .arg(ctx.
query_->getLabel())
3879 .arg(client_lease->addr_.toText());
3883 StatsMgr::instance().addValue(
3884 StatsMgr::generateName(
"subnet", client_lease->subnet_id_,
3885 "assigned-addresses"),
3886 static_cast<int64_t
>(-1));
3899 if (ctx.
query_->inClass(
"BOOTP")) {
3904 uint32_t requested_lft = 0;
3907 OptionUint32Ptr opt_lft = boost::dynamic_pointer_cast<OptionInt<uint32_t> >(opt);
3909 requested_lft = opt_lft->getValue();
3917 if (!classes.
empty()) {
3924 name != classes.
cend(); ++name) {
3926 if (cl && (!cl->getValid().unspecified())) {
3927 candidate_lft = cl->getValid();
3934 if (!candidate_lft) {
3935 candidate_lft = ctx.
subnet_->getValid();
3940 if (requested_lft > 0) {
3941 return (candidate_lft.
get(requested_lft));
3945 return (candidate_lft.
get());
3949AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
3961 time_t now = time(NULL);
3964 if (ctx.subnet_->getMatchClientId()) {
3965 client_id = ctx.clientid_;
3969 valid_lft, now, ctx.subnet_->getID()));
3972 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
3973 lease->fqdn_rev_ = ctx.rev_dns_update_;
3974 lease->hostname_ = ctx.hostname_;
3980 if (ctx.callout_handle_ &&
3981 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
3994 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
4000 Subnet4Ptr subnet4 = boost::dynamic_pointer_cast<Subnet4>(ctx.subnet_);
4001 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
4004 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
4007 ctx.callout_handle_->setArgument(
"lease4", lease);
4010 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.callout_handle_);
4012 callout_status = ctx.callout_handle_->getStatus();
4017 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4024 ctx.callout_handle_->getArgument(
"lease4", lease);
4027 if (!ctx.fake_allocation_) {
4033 StatsMgr::instance().addValue(
4034 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4035 "assigned-addresses"),
4036 static_cast<int64_t
>(1));
4037 StatsMgr::instance().addValue(
4038 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
4039 "cumulative-assigned-addresses"),
4040 static_cast<int64_t
>(1));
4041 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4042 static_cast<int64_t
>(1));
4062AllocEngine::renewLease4(
const Lease4Ptr& lease,
4065 isc_throw(BadValue,
"null lease specified for renewLease4");
4072 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4077 lease->reuseable_valid_lft_ = 0;
4078 if (!updateLease4Information(lease, ctx)) {
4079 setLeaseReusable(lease, ctx);
4095 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_renew_)) {
4119 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4127 HooksManager::callCallouts(
Hooks.hook_index_lease4_renew_,
4133 if (ctx.
callout_handle_->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
4142 if (!ctx.
fake_allocation_ && !skip && (lease->reuseable_valid_lft_ == 0)) {
4148 StatsMgr::instance().addValue(
4149 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4150 "assigned-addresses"),
4151 static_cast<int64_t
>(1));
4152 StatsMgr::instance().addValue(
4153 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4154 "cumulative-assigned-addresses"),
4155 static_cast<int64_t
>(1));
4156 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4157 static_cast<int64_t
>(1));
4163 *lease = *old_values;
4170AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4174 isc_throw(BadValue,
"null lease specified for reuseExpiredLease");
4178 isc_throw(BadValue,
"null subnet specified for the reuseExpiredLease");
4189 expired->reuseable_valid_lft_ = 0;
4190 static_cast<void>(updateLease4Information(expired, ctx));
4194 .arg(ctx.
query_->getLabel())
4195 .arg(expired->toText());
4199 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
4228 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.
callout_handle_);
4235 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4253 StatsMgr::instance().addValue(
4254 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4255 "assigned-addresses"),
4256 static_cast<int64_t
>(1));
4257 StatsMgr::instance().addValue(
4258 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4259 "cumulative-assigned-addresses"),
4260 static_cast<int64_t
>(1));
4261 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4262 static_cast<int64_t
>(1));
4274AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4276 ctx.conflicting_lease_.reset();
4280 if (exist_lease->expired()) {
4285 ctx.old_lease_->hostname_.clear();
4286 ctx.old_lease_->fqdn_fwd_ =
false;
4287 ctx.old_lease_->fqdn_rev_ =
false;
4288 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4294 ctx.conflicting_lease_ = exist_lease;
4298 return (createLease4(ctx, candidate, callout_status));
4304AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4319 ctx.subnet_->getSharedNetwork(network);
4326 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4332 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
4336 uint64_t total_attempts = 0;
4340 uint64_t subnets_with_unavail_leases = 0;
4343 uint64_t subnets_with_unavail_pools = 0;
4347 if (subnet->getMatchClientId()) {
4348 client_id = ctx.clientid_;
4351 uint64_t possible_attempts =
4353 ctx.query_->getClasses());
4360 uint64_t max_attempts = ((attempts_ == 0 || possible_attempts < attempts_) ? possible_attempts : attempts_);
4362 if (max_attempts > 0) {
4365 ++subnets_with_unavail_leases;
4369 ++subnets_with_unavail_pools;
4374 for (uint64_t i = 0; i < max_attempts; ++i) {
4378 IOAddress candidate = allocator->pickAddress(subnet,
4379 ctx.query_->getClasses(),
4381 ctx.requested_address_);
4383 if (check_reservation_first && addressReserved(candidate, ctx)) {
4391 if (MultiThreadingMgr::instance().getMode() &&
4392 !resource_handler.
tryLock4(candidate)) {
4401 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4403 new_lease = createLease4(ctx, candidate, callout_status);
4407 if (exist_lease->expired() &&
4408 (check_reservation_first || !addressReserved(candidate, ctx))) {
4410 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4419 if (ctx.callout_handle_ && (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
4428 subnet = subnet->getNextSubnet(original_subnet, ctx.query_->getClasses());
4431 ctx.subnet_ = subnet;
4440 .arg(ctx.query_->getLabel())
4441 .arg(network->getName())
4442 .arg(subnets_with_unavail_leases)
4443 .arg(subnets_with_unavail_pools);
4449 .arg(ctx.query_->getLabel())
4450 .arg(ctx.subnet_->toText())
4451 .arg(ctx.subnet_->getID())
4452 .arg(ctx.subnet_->getSharedNetworkName());
4454 if (total_attempts == 0) {
4460 .arg(ctx.query_->getLabel());
4467 .arg(ctx.query_->getLabel())
4468 .arg(total_attempts);
4472 if (!classes.
empty()) {
4474 .arg(ctx.query_->getLabel())
4482AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4484 bool changed =
false;
4485 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4487 lease->subnet_id_ = ctx.
subnet_->getID();
4489 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4491 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4496 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4500 }
else if (lease->client_id_) {
4504 lease->cltt_ = time(NULL);
4510 if (lease->valid_lft_ < lease->current_valid_lft_) {
4534 bool changed =
false;
4537 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4552 ElementPtr extended_info = Element::createMap();
4553 extended_info->set(
"relay-agent-info", relay_agent);
4557 if (lease->getContext()) {
4558 user_context = UserContext::toElement(lease->getContext());
4560 user_context = Element::createMap();
4565 if (!old_extended_info || (*old_extended_info != *extended_info)) {
4567 user_context->set(
"ISC", extended_info);
4571 lease->setContext(user_context);
4579 bool changed =
false;
4582 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4587 if (ctx.
query_->relay_info_.empty()) {
4601 ElementPtr relay_list = Element::createList();
4602 for (
auto relay : ctx.
query_->relay_info_) {
4603 ElementPtr relay_elem = Element::createMap();
4611 if (!relay.options_.empty()) {
4616 const uint8_t* cp =
static_cast<const uint8_t*
>(buf.
getData());
4617 std::vector<uint8_t>bytes;
4618 std::stringstream ss;
4626 relay_list->add(relay_elem);
4630 ElementPtr extended_info = Element::createMap();
4631 extended_info->set(
"relays", relay_list);
4635 if (lease->getContext()) {
4636 user_context = UserContext::toElement(lease->getContext());
4638 user_context = Element::createMap();
4643 if (!old_extended_info || (*old_extended_info != *extended_info)) {
4645 user_context->set(
"ISC", extended_info);
4649 lease->setContext(user_context);
4655AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
4656 const ClientContext4& ctx)
const {
4658 lease->reuseable_valid_lft_ = 0;
4674 if (lease->cltt_ < lease->current_cltt_) {
4678 uint32_t age = lease->cltt_ - lease->current_cltt_;
4680 if (age >= lease->current_valid_lft_) {
4685 uint32_t max_age = 0;
4686 if (!subnet->getCacheMaxAge().unspecified()) {
4687 max_age = subnet->getCacheMaxAge().get();
4688 if ((max_age == 0) || (age > max_age)) {
4694 if (!subnet->getCacheThreshold().unspecified()) {
4695 double threshold = subnet->getCacheThreshold().get();
4696 if ((threshold <= 0.) || (threshold > 1.)) {
4699 max_age = lease->valid_lft_ * threshold;
4700 if (age > max_age) {
4711 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
4715AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
4716 uint32_t current_preferred_lft,
4717 const ClientContext6& ctx)
const {
4719 lease->reuseable_valid_lft_ = 0;
4720 lease->reuseable_preferred_lft_ = 0;
4730 if (lease->cltt_ < lease->current_cltt_) {
4734 uint32_t age = lease->cltt_ - lease->current_cltt_;
4736 if (age >= lease->current_valid_lft_) {
4741 uint32_t max_age = 0;
4742 if (!subnet->getCacheMaxAge().unspecified()) {
4743 max_age = subnet->getCacheMaxAge().get();
4744 if ((max_age == 0) || (age > max_age)) {
4750 if (!subnet->getCacheThreshold().unspecified()) {
4751 double threshold = subnet->getCacheThreshold().get();
4752 if ((threshold <= 0.) || (threshold > 1.)) {
4755 max_age = lease->valid_lft_ * threshold;
4756 if (age > max_age) {
4768 (current_preferred_lft == 0)) {
4770 lease->reuseable_preferred_lft_ = current_preferred_lft;
4771 }
else if (current_preferred_lft > age) {
4772 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
4780 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when a function is not implemented.
The IOAddress class represents an IP addresses (version agnostic)
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
std::string toText() const
Convert the address to a string.
bool isV6() const
Convenience function to check for an IPv6 address.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
static IOAddress increase(const IOAddress &addr)
Returns an address increased by one.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
Notes: IntElement type is changed to int64_t.
Base class for all address/prefix allocation algorithms.
Address/prefix allocator that gets an address based on a hash.
HashedAllocator(Lease::Type type)
Default constructor (does nothing)
Address/prefix allocator that iterates over all addresses.
static isc::asiolink::IOAddress increasePrefix(const isc::asiolink::IOAddress &prefix, const uint8_t prefix_len)
Returns the next prefix.
static isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress &address, bool prefix, const uint8_t prefix_len)
Returns the next address or prefix.
IterativeAllocator(Lease::Type type)
Default constructor.
Random allocator that picks address randomly.
RandomAllocator(Lease::Type type)
Default constructor (does nothing)
bool updateLease6ExtendedInfo(const Lease6Ptr &lease, const ClientContext6 &ctx) const
Stores additional client query parameters on a V6 lease.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
bool updateLease4ExtendedInfo(const Lease4Ptr &lease, const ClientContext4 &ctx) const
Stores additional client query parameters on a V4 lease.
AllocType
Specifies allocation type.
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
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)
boost::shared_ptr< Allocator > AllocatorPtr
defines a pointer to allocator
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.
AllocEngine(AllocType engine_type, uint64_t attempts, bool ipv6=true)
Constructor.
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.
AllocatorPtr getAllocator(Lease::Type type)
Returns allocator for a given pool type.
An exception that is thrown when allocation module fails (e.g.
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.
std::list< ClientClass >::const_iterator const_iterator
Type of iterators.
bool empty() const
Check if classes is empty.
std::string toText(const std::string &separator=", ") const
Returns all class names as text.
const_iterator cbegin() const
Iterator to the first element.
const_iterator cend() const
Iterator to the past the end element.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) 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.
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv6 subnet.
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv4 subnet.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const
Return all hosts in a DHCPv4 subnet.
IPv6 reservation for a host.
Type
Type of the reservation.
static LeaseMgr & 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.
This template specifies a parameter value.
T get(T hint) const
Returns value with a hint.
CalloutNextStep
Specifies allowed next steps.
Wrapper class around callout handle which automatically resets handle's state.
Statistics Manager class.
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.
size_t getLength() const
Return the length of data written in the buffer.
const void * getData() const
Return a pointer to the head of the data stored 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.
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 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_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.
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
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 ALLOC_ENGINE_V6_HR_ADDR_GRANTED
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
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
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_RECLAIMED_LEASES_DELETE_COMPLETE
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
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_V6_ALLOC_UNRESERVED
std::pair< IPv6Resrv::Type, IPv6Resrv > IPv6ResrvTuple
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 ('hex') format.
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.
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.
bool fake_allocation_
Indicates if this is a real or fake allocation.
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
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.
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.
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_TA
the lease contains temporary IPv6 address
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
@ TYPE_NA
the lease contains non-temporary IPv6 address
static std::string typeToText(Type type)
returns text representation of a lease type