33 #include <boost/foreach.hpp>
34 #include <boost/make_shared.hpp>
52 namespace ph = std::placeholders;
57 struct 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");
86 AllocEngineHooks
Hooks;
93 AllocEngine::IterativeAllocator::IterativeAllocator(
Lease::Type lease_type)
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));
162 AllocEngine::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());
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);
295 AllocEngine::HashedAllocator::pickAddressInternal(
const SubnetPtr&,
308 AllocEngine::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());
1533 AllocEngine::removeNonmatchingReservedLeases6(
ClientContext6& ctx,
1536 if (existing_leases.empty() || !ctx.subnet_) {
1541 if (!ctx.subnet_->getReservationsInSubnet() &&
1542 !ctx.subnet_->getReservationsGlobal()) {
1543 removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
1552 BOOST_FOREACH(
const Lease6Ptr& candidate, copy) {
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_);
1641 AllocEngine::removeNonmatchingReservedNoHostLeases6(
ClientContext6& ctx,
1648 BOOST_FOREACH(
const Lease6Ptr& candidate, copy) {
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_);
1683 AllocEngine::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));
1918 uint32_t preferred = ctx.subnet_->getPreferred();
1919 if (!ctx.currentIA().hints_.empty() &&
1920 ctx.currentIA().hints_[0].getPreferred()) {
1921 preferred = ctx.currentIA().hints_[0].getPreferred();
1922 preferred = ctx.subnet_->getPreferred().get(preferred);
1924 uint32_t valid = ctx.subnet_->getValid();
1925 if (!ctx.currentIA().hints_.empty() &&
1926 ctx.currentIA().hints_[0].getValid()) {
1927 valid = ctx.currentIA().hints_[0].getValid();
1928 valid = ctx.subnet_->getValid().get(valid);
1931 ctx.currentIA().iaid_, preferred,
1932 valid, ctx.subnet_->getID(),
1933 ctx.hwaddr_, prefix_len));
1935 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
1936 lease->fqdn_rev_ = ctx.rev_dns_update_;
1937 lease->hostname_ = ctx.hostname_;
1940 if (ctx.callout_handle_ &&
1941 HooksManager::calloutsPresent(hook_index_lease6_select_)) {
1955 ctx.callout_handle_->setArgument(
"query6", ctx.query_);
1958 ctx.callout_handle_->setArgument(
"subnet6", ctx.subnet_);
1961 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
1964 ctx.callout_handle_->setArgument(
"lease6", lease);
1967 HooksManager::callCallouts(hook_index_lease6_select_, *ctx.callout_handle_);
1969 callout_status = ctx.callout_handle_->getStatus();
1974 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
1981 ctx.callout_handle_->getArgument(
"lease6", lease);
1984 if (!ctx.fake_allocation_) {
1994 if (ctx.subnet_->inPool(ctx.currentIA().type_, addr)) {
1995 StatsMgr::instance().addValue(
1996 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
1998 "assigned-nas" :
"assigned-pds"),
1999 static_cast<int64_t>(1));
2000 StatsMgr::instance().addValue(
2001 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2003 "cumulative-assigned-nas" :
2004 "cumulative-assigned-pds"),
2005 static_cast<int64_t>(1));
2006 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2007 "cumulative-assigned-nas" :
2008 "cumulative-assigned-pds",
2009 static_cast<int64_t
>(1));
2013 ctx.currentIA().addNewResource(addr, prefix_len);
2052 leases.insert(leases.end(), leases_subnet.begin(), leases_subnet.end());
2054 subnet = subnet->getNextSubnet(ctx.
subnet_);
2057 if (!leases.empty()) {
2060 .arg(ctx.
query_->getLabel());
2064 removeNonmatchingReservedLeases6(ctx, leases);
2067 if (!ctx.
hosts_.empty()) {
2071 .arg(ctx.
query_->getLabel());
2074 allocateReservedLeases6(ctx, leases);
2080 removeNonreservedLeases6(ctx, leases);
2087 if (leases.empty()) {
2091 .arg(ctx.
query_->getLabel());
2093 leases = allocateUnreservedLeases6(ctx);
2097 for (Lease6Collection::iterator l = leases.begin(); l != leases.end(); ++l) {
2099 (*l)->prefixlen_)) {
2105 .arg(ctx.
query_->getLabel())
2106 .arg((*l)->typeToText((*l)->type_))
2108 extendLease6(ctx, *l);
2111 if (!leases.empty()) {
2115 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2127 .arg(ctx.
query_->getLabel())
2137 if (!lease || !ctx.subnet_) {
2143 if (ctx.subnet_->getID() != lease->subnet_id_) {
2145 ctx.subnet_->getSharedNetwork(network);
2151 ctx.subnet_ = subnet;
2159 (((lease->type_ !=
Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) ||
2160 !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) {
2174 StatsMgr::instance().addValue(
2175 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
"assigned-nas"),
2176 static_cast<int64_t>(-1));
2179 ctx.currentIA().old_leases_.push_back(lease);
2186 .arg(ctx.query_->getLabel())
2187 .arg(lease->toText());
2192 bool changed =
false;
2193 uint32_t current_preferred_lft = lease->preferred_lft_;
2194 if (!ctx.currentIA().hints_.empty() &&
2195 ctx.currentIA().hints_[0].getPreferred()) {
2196 uint32_t preferred = ctx.currentIA().hints_[0].getPreferred();
2197 lease->preferred_lft_ = ctx.subnet_->getPreferred().get(preferred);
2199 lease->preferred_lft_ = ctx.subnet_->getPreferred();
2201 if (lease->preferred_lft_ < current_preferred_lft) {
2204 lease->reuseable_valid_lft_ = 0;
2205 if (!ctx.currentIA().hints_.empty() &&
2206 ctx.currentIA().hints_[0].getValid()) {
2207 uint32_t valid = ctx.currentIA().hints_[0].getValid();
2208 lease->valid_lft_ = ctx.subnet_->getValid().get(valid);
2210 lease->valid_lft_ = ctx.subnet_->getValid();
2212 if (lease->valid_lft_ < lease->current_valid_lft_) {
2216 lease->cltt_ = time(NULL);
2217 if ((lease->fqdn_fwd_ != ctx.fwd_dns_update_) ||
2218 (lease->fqdn_rev_ != ctx.rev_dns_update_) ||
2219 (lease->hostname_ != ctx.hostname_)) {
2221 lease->hostname_ = ctx.hostname_;
2222 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2223 lease->fqdn_rev_ = ctx.rev_dns_update_;
2225 if ((!ctx.hwaddr_ && lease->hwaddr_) ||
2227 (!lease->hwaddr_ || (*ctx.hwaddr_ != *lease->hwaddr_)))) {
2229 lease->hwaddr_ = ctx.hwaddr_;
2237 .arg(ctx.query_->getLabel())
2238 .arg(lease->toText());
2242 int hook_point = ctx.query_->getType() ==
DHCPV6_RENEW ?
2243 Hooks.hook_index_lease6_renew_ :
Hooks.hook_index_lease6_rebind_;
2244 if (HooksManager::calloutsPresent(hook_point)) {
2257 callout_handle->setArgument(
"query6", ctx.query_);
2260 callout_handle->setArgument(
"lease6", lease);
2264 callout_handle->setArgument(
"ia_na", ctx.currentIA().ia_rsp_);
2266 callout_handle->setArgument(
"ia_pd", ctx.currentIA().ia_rsp_);
2270 HooksManager::callCallouts(hook_point, *callout_handle);
2275 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2279 .arg(ctx.query_->getName());
2286 bool update_stats =
false;
2290 if (old_data->expired()) {
2291 reclaimExpiredLease(old_data, ctx.callout_handle_);
2295 if (ctx.subnet_->inPool(ctx.currentIA().type_, old_data->addr_)) {
2296 update_stats =
true;
2308 setLeaseReusable(lease, current_preferred_lft, ctx);
2314 if (lease->reuseable_valid_lft_ == 0) {
2319 StatsMgr::instance().addValue(
2320 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2322 "assigned-nas" :
"assigned-pds"),
2323 static_cast<int64_t>(1));
2324 StatsMgr::instance().addValue(
2325 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
2327 "cumulative-assigned-nas" :
2328 "cumulative-assigned-pds"),
2329 static_cast<int64_t>(1));
2330 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2331 "cumulative-assigned-nas" :
2332 "cumulative-assigned-pds",
2333 static_cast<int64_t
>(1));
2346 ctx.currentIA().changed_leases_.push_back(old_data);
2352 for (Lease6Collection::const_iterator lease_it = leases.begin();
2353 lease_it != leases.end(); ++lease_it) {
2355 if (ctx.currentIA().isNewResource(lease->addr_, lease->prefixlen_)) {
2357 updated_leases.push_back(lease);
2361 lease->reuseable_valid_lft_ = 0;
2362 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
2363 lease->fqdn_rev_ = ctx.rev_dns_update_;
2364 lease->hostname_ = ctx.hostname_;
2365 if (!ctx.fake_allocation_) {
2366 bool update_stats =
false;
2374 if (inAllowedPool(ctx, ctx.currentIA().type_,
2375 lease->addr_,
true)) {
2376 update_stats =
true;
2381 !(lease->hasIdenticalFqdn(**lease_it)));
2383 lease->cltt_ = time(NULL);
2384 if (!fqdn_changed) {
2385 uint32_t current_preferred_lft = lease->preferred_lft_;
2386 setLeaseReusable(lease, current_preferred_lft, ctx);
2388 if (lease->reuseable_valid_lft_ == 0) {
2389 ctx.currentIA().changed_leases_.push_back(*lease_it);
2394 StatsMgr::instance().addValue(
2395 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2397 "assigned-nas" :
"assigned-pds"),
2398 static_cast<int64_t>(1));
2399 StatsMgr::instance().addValue(
2400 StatsMgr::generateName(
"subnet", lease->subnet_id_,
2402 "cumulative-assigned-nas" :
2403 "cumulative-assigned-pds"),
2404 static_cast<int64_t>(1));
2405 StatsMgr::instance().addValue(ctx.currentIA().type_ ==
Lease::TYPE_NA ?
2406 "cumulative-assigned-nas" :
2407 "cumulative-assigned-pds",
2408 static_cast<int64_t
>(1));
2412 updated_leases.push_back(lease);
2415 return (updated_leases);
2420 const bool remove_lease,
2421 const uint16_t max_unwarned_cycles) {
2436 bool incomplete_reclamation =
false;
2439 if (max_leases > 0) {
2448 if (leases.size() > max_leases) {
2450 incomplete_reclamation =
true;
2463 if (!leases.empty() &&
2464 HooksManager::calloutsPresent(
Hooks.hook_index_lease6_expire_)) {
2465 callout_handle = HooksManager::createCalloutHandle();
2468 size_t leases_processed = 0;
2469 BOOST_FOREACH(
Lease6Ptr lease, leases) {
2473 if (MultiThreadingMgr::instance().getMode()) {
2477 reclaimExpiredLease(lease, remove_lease, callout_handle);
2480 reclaimExpiredLease(lease, remove_lease, callout_handle);
2484 }
catch (
const std::exception& ex) {
2486 .arg(lease->addr_.toText())
2497 if (!incomplete_reclamation) {
2498 if (leases_processed < leases.size()) {
2499 incomplete_reclamation =
true;
2516 .arg(leases_processed)
2521 if (incomplete_reclamation) {
2522 ++incomplete_v6_reclamations_;
2525 if ((max_unwarned_cycles > 0) &&
2526 (incomplete_v6_reclamations_ > max_unwarned_cycles)) {
2528 .arg(max_unwarned_cycles);
2530 incomplete_v6_reclamations_ = 0;
2535 incomplete_v6_reclamations_ = 0;
2548 uint64_t deleted_leases = 0;
2554 }
catch (
const std::exception& ex) {
2561 .arg(deleted_leases);
2566 const bool remove_lease,
2567 const uint16_t max_unwarned_cycles) {
2582 bool incomplete_reclamation =
false;
2585 if (max_leases > 0) {
2594 if (leases.size() > max_leases) {
2596 incomplete_reclamation =
true;
2609 if (!leases.empty() &&
2610 HooksManager::calloutsPresent(
Hooks.hook_index_lease4_expire_)) {
2611 callout_handle = HooksManager::createCalloutHandle();
2614 size_t leases_processed = 0;
2615 BOOST_FOREACH(
Lease4Ptr lease, leases) {
2619 if (MultiThreadingMgr::instance().getMode()) {
2623 reclaimExpiredLease(lease, remove_lease, callout_handle);
2626 reclaimExpiredLease(lease, remove_lease, callout_handle);
2630 }
catch (
const std::exception& ex) {
2632 .arg(lease->addr_.toText())
2643 if (!incomplete_reclamation) {
2644 if (leases_processed < leases.size()) {
2645 incomplete_reclamation =
true;
2662 .arg(leases_processed)
2667 if (incomplete_reclamation) {
2668 ++incomplete_v4_reclamations_;
2671 if ((max_unwarned_cycles > 0) &&
2672 (incomplete_v4_reclamations_ > max_unwarned_cycles)) {
2674 .arg(max_unwarned_cycles);
2676 incomplete_v4_reclamations_ = 0;
2681 incomplete_v4_reclamations_ = 0;
2688 template<
typename LeasePtrType>
2690 AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
const bool remove_lease,
2692 reclaimExpiredLease(lease, remove_lease ? DB_RECLAIM_REMOVE : DB_RECLAIM_UPDATE,
2696 template<
typename LeasePtrType>
2698 AllocEngine::reclaimExpiredLease(
const LeasePtrType& lease,
2703 if (!lease->stateExpiredReclaimed()) {
2704 reclaimExpiredLease(lease, DB_RECLAIM_LEAVE_UNCHANGED, callout_handle);
2709 AllocEngine::reclaimExpiredLease(
const Lease6Ptr& lease,
2710 const DbReclaimMode& reclaim_mode,
2716 .arg(lease->addr_.toText())
2717 .arg(static_cast<int>(lease->prefixlen_));
2723 bool skipped =
false;
2724 if (callout_handle) {
2732 callout_handle->deleteAllArguments();
2733 callout_handle->setArgument(
"lease6", lease);
2734 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2736 HooksManager::callCallouts(
Hooks.hook_index_lease6_expire_,
2739 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2754 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2764 remove_lease = reclaimDeclined(lease);
2767 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2771 reclaimLeaseInDatabase<Lease6Ptr>(lease, remove_lease,
2773 &lease_mgr, ph::_1));
2782 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2789 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2797 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2800 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2802 "reclaimed-leases"),
2807 AllocEngine::reclaimExpiredLease(
const Lease4Ptr& lease,
2808 const DbReclaimMode& reclaim_mode,
2814 .arg(lease->addr_.toText());
2820 bool skipped =
false;
2821 if (callout_handle) {
2829 callout_handle->setArgument(
"lease4", lease);
2830 callout_handle->setArgument(
"remove_lease", reclaim_mode == DB_RECLAIM_REMOVE);
2832 HooksManager::callCallouts(
Hooks.hook_index_lease4_expire_,
2835 skipped = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2848 lease->hostname_.clear();
2849 lease->fqdn_fwd_ =
false;
2850 lease->fqdn_rev_ =
false;
2854 bool remove_lease = (reclaim_mode == DB_RECLAIM_REMOVE);
2864 remove_lease = reclaimDeclined(lease);
2867 if (reclaim_mode != DB_RECLAIM_LEAVE_UNCHANGED) {
2871 reclaimLeaseInDatabase<Lease4Ptr>(lease, remove_lease,
2873 &lease_mgr, ph::_1));
2880 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2882 "assigned-addresses"),
2886 StatsMgr::instance().addValue(
"reclaimed-leases", int64_t(1));
2889 StatsMgr::instance().addValue(StatsMgr::generateName(
"subnet",
2891 "reclaimed-leases"),
2901 uint64_t deleted_leases = 0;
2907 }
catch (
const std::exception& ex) {
2914 .arg(deleted_leases);
2918 AllocEngine::reclaimDeclined(
const Lease4Ptr& lease) {
2923 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_recover_)) {
2933 callout_handle->setArgument(
"lease4", lease);
2936 HooksManager::callCallouts(
Hooks.hook_index_lease4_recover_, *callout_handle);
2941 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2943 .arg(lease->addr_.toText());
2949 .arg(lease->addr_.toText())
2950 .arg(lease->valid_lft_);
2952 StatsMgr& stats_mgr = StatsMgr::instance();
2955 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
2956 "declined-addresses"), static_cast<int64_t>(-1));
2959 stats_mgr.
addValue(
"declined-addresses", static_cast<int64_t>(-1));
2961 stats_mgr.
addValue(
"reclaimed-declined-addresses", static_cast<int64_t>(1));
2963 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
2964 "reclaimed-declined-addresses"), static_cast<int64_t>(1));
2972 AllocEngine::reclaimDeclined(
const Lease6Ptr& lease) {
2977 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_recover_)) {
2987 callout_handle->setArgument(
"lease6", lease);
2990 HooksManager::callCallouts(
Hooks.hook_index_lease6_recover_, *callout_handle);
2995 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
2997 .arg(lease->addr_.toText());
3003 .arg(lease->addr_.toText())
3004 .arg(lease->valid_lft_);
3006 StatsMgr& stats_mgr = StatsMgr::instance();
3009 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3010 "declined-addresses"), static_cast<int64_t>(-1));
3013 stats_mgr.
addValue(
"declined-addresses", static_cast<int64_t>(-1));
3015 stats_mgr.
addValue(
"reclaimed-declined-addresses", static_cast<int64_t>(1));
3017 stats_mgr.
addValue(StatsMgr::generateName(
"subnet", lease->subnet_id_,
3018 "reclaimed-declined-addresses"), static_cast<int64_t>(1));
3026 template<
typename LeasePtrType>
3027 void AllocEngine::reclaimLeaseInDatabase(
const LeasePtrType& lease,
3028 const bool remove_lease,
3029 const std::function<
void (
const LeasePtrType&)>&
3030 lease_update_fun)
const {
3038 }
else if (lease_update_fun) {
3041 lease->reuseable_valid_lft_ = 0;
3042 lease->hostname_.clear();
3043 lease->fqdn_fwd_ =
false;
3044 lease->fqdn_rev_ =
false;
3046 lease_update_fun(lease);
3055 .arg(lease->addr_.toText());
3091 (!ctx.
subnet_->getReservationsOutOfPool() ||
3106 hosts.push_back(host);
3113 for (
auto host : hosts) {
3117 if (id_pair.first == host->getIdentifierType() &&
3118 id_pair.second == host->getIdentifier()) {
3126 return (!hosts.empty());
3148 if (ctx.
hosts_.empty()) {
3153 bool search_global_done =
false;
3158 if (!search_global_done && subnet->getReservationsGlobal()) {
3159 auto host = ctx.
hosts_.find(SUBNET_ID_GLOBAL);
3162 if (host != ctx.
hosts_.end() && host->second &&
3163 !host->second->getIPv4Reservation().isV4Zero()) {
3168 search_global_done =
true;
3171 if (subnet->getReservationsInSubnet()) {
3172 auto host = ctx.
hosts_.find(subnet->getID());
3177 if (host != ctx.
hosts_.end() && host->second) {
3178 auto reservation = host->second->getIPv4Reservation();
3179 if (!reservation.isV4Zero() &&
3180 (!subnet->getReservationsOutOfPool() ||
3190 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3218 bool try_clientid_lookup = (ctx.
clientid_ &&
3220 ctx.
query_->getClasses()));
3223 if (try_clientid_lookup) {
3231 for (
Subnet4Ptr subnet = original_subnet; subnet;
3232 subnet = subnet->getNextSubnet(original_subnet,
3233 ctx.
query_->getClasses())) {
3238 if (subnet->getMatchClientId()) {
3239 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
3240 if ((*l)->subnet_id_ == subnet->getID()) {
3242 client_lease = (*l);
3253 if (!client_lease && ctx.
hwaddr_) {
3258 for (
Subnet4Ptr subnet = original_subnet; subnet;
3259 subnet = subnet->getNextSubnet(original_subnet,
3260 ctx.
query_->getClasses())) {
3262 if (subnet->getMatchClientId()) {
3268 for (Lease4Collection::const_iterator client_lease_it = leases_hw_address.begin();
3269 client_lease_it != leases_hw_address.end(); ++client_lease_it) {
3270 Lease4Ptr existing_lease = *client_lease_it;
3271 if ((existing_lease->subnet_id_ == subnet->getID()) &&
3272 existing_lease->belongsToClient(ctx.
hwaddr_, client_id)) {
3274 client_lease = existing_lease;
3302 while (current_subnet) {
3305 ctx.
query_->getClasses())) {
3313 current_subnet = current_subnet->getNextSubnet(ctx.
subnet_,
3314 ctx.
query_->getClasses());
3326 : subnet_(), clientid_(), hwaddr_(),
3327 requested_address_(
IOAddress::IPV4_ZERO_ADDRESS()),
3328 fwd_dns_update_(false), rev_dns_update_(false),
3329 hostname_(
""), callout_handle_(), fake_allocation_(false),
3330 old_lease_(), new_lease_(), hosts_(), conflicting_lease_(),
3331 query_(), host_identifiers_(),
3339 const bool fwd_dns_update,
3340 const bool rev_dns_update,
3341 const std::string& hostname,
3342 const bool fake_allocation)
3343 : subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
3344 requested_address_(requested_addr),
3345 fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
3346 hostname_(hostname), callout_handle_(),
3347 fake_allocation_(fake_allocation), old_lease_(), new_lease_(),
3348 hosts_(), host_identifiers_(),
3359 if (subnet_ && subnet_->getReservationsInSubnet()) {
3360 auto host = hosts_.find(subnet_->getID());
3361 if (host != hosts_.cend()) {
3362 return (host->second);
3366 return (globalHost());
3371 if (subnet_ && subnet_->getReservationsGlobal()) {
3372 auto host = hosts_.find(SUBNET_ID_GLOBAL);
3373 if (host != hosts_.cend()) {
3374 return (host->second);
3384 if (ddns_params_ && subnet_ && (subnet_->getID() == ddns_params_->getSubnetId())) {
3385 return (ddns_params_);
3391 return (ddns_params_);
3413 if (subnet && !subnet->clientSupported(ctx.
query_->getClasses())) {
3414 ctx.
subnet_ = subnet->getNextSubnet(subnet, ctx.
query_->getClasses());
3427 return (discoverLease4(ctx));
3436 .arg(ctx.
query_->getLabel())
3454 std::map<SubnetID, ConstHostPtr> host_map;
3456 subnet->getSharedNetwork(network);
3459 if (subnet->getReservationsGlobal()) {
3462 ctx.
hosts_[SUBNET_ID_GLOBAL] = ghost;
3465 if (!subnet->getReservationsInSubnet()) {
3478 const bool use_single_query = network &&
3482 if (use_single_query) {
3486 id_pair.second.size());
3490 for (
auto host = hosts.begin(); host != hosts.end(); ++host) {
3491 if ((*host)->getIPv4SubnetID() != SUBNET_ID_GLOBAL) {
3492 host_map[(*host)->getIPv4SubnetID()] = *host;
3503 if (subnet->clientSupported(ctx.
query_->getClasses()) &&
3504 subnet->getReservationsInSubnet()) {
3507 if (use_single_query) {
3508 if (host_map.count(subnet->getID()) > 0) {
3509 ctx.
hosts_[subnet->getID()] = host_map[subnet->getID()];
3517 id_pair.second.size());
3520 ctx.
hosts_[subnet->getID()] = host;
3530 subnet = subnet->getNextSubnet(ctx.
subnet_, ctx.
query_->getClasses());
3540 &id_pair.second[0], id_pair.second.size());
3557 findClientLease(ctx, client_lease);
3567 if (hasAddressReservation(ctx)) {
3571 .arg(ctx.
query_->getLabel())
3572 .arg(ctx.
currentHost()->getIPv4Reservation().toText());
3578 if (!client_lease || (client_lease->addr_ != ctx.
currentHost()->getIPv4Reservation())) {
3585 new_lease = allocateOrReuseLease4(ctx.
currentHost()->getIPv4Reservation(), ctx,
3589 .arg(ctx.
query_->getLabel())
3590 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3596 new_lease = renewLease4(client_lease, ctx);
3609 if (!new_lease && client_lease && inAllowedPool(ctx, client_lease->addr_) &&
3610 !addressReserved(client_lease->addr_, ctx)) {
3614 .arg(ctx.
query_->getLabel());
3616 new_lease = renewLease4(client_lease, ctx);
3633 .arg(ctx.
query_->getLabel());
3646 .arg(ctx.
query_->getLabel());
3648 new_lease = allocateUnreservedLease4(ctx);
3668 findClientLease(ctx, client_lease);
3684 .arg(ctx.
query_->getLabel())
3690 }
else if (hasAddressReservation(ctx)) {
3699 .arg(ctx.
query_->getLabel())
3711 if (existing && !existing->expired() &&
3712 !existing->belongsToClient(ctx.
hwaddr_, ctx.
subnet_->getMatchClientId() ?
3717 .arg(ctx.
query_->getLabel())
3727 if (hasAddressReservation(ctx) &&
3735 if (!existing || existing->expired()) {
3739 .arg(ctx.
query_->getLabel())
3740 .arg(ctx.
currentHost()->getIPv4Reservation().toText())
3750 if ((!hasAddressReservation(ctx) ||
3756 .arg(ctx.
query_->getLabel())
3774 (hasAddressReservation(ctx) ||
3775 inAllowedPool(ctx, client_lease->addr_))) {
3779 .arg(ctx.
query_->getLabel())
3782 return (renewLease4(client_lease, ctx));
3796 .arg(ctx.
query_->getLabel())
3812 .arg(ctx.
query_->getLabel());
3817 new_lease = allocateUnreservedLease4(ctx);
3823 if (new_lease && client_lease) {
3828 .arg(ctx.
query_->getLabel())
3829 .arg(client_lease->addr_.toText());
3833 StatsMgr::instance().addValue(
3834 StatsMgr::generateName(
"subnet", client_lease->subnet_id_,
3835 "assigned-addresses"),
3836 static_cast<int64_t>(-1));
3849 if (ctx.
query_->inClass(
"BOOTP")) {
3854 uint32_t requested_lft = 0;
3859 requested_lft = opt_lft->
getValue();
3867 if (!classes.
empty()) {
3874 name != classes.
cend(); ++name) {
3876 if (cl && (!cl->getValid().unspecified())) {
3877 candidate_lft = cl->getValid();
3884 if (!candidate_lft) {
3885 candidate_lft = ctx.
subnet_->getValid();
3890 if (requested_lft > 0) {
3891 return (candidate_lft.
get(requested_lft));
3895 return (candidate_lft.
get());
3899 AllocEngine::createLease4(
const ClientContext4& ctx,
const IOAddress& addr,
3911 time_t now = time(NULL);
3914 if (ctx.subnet_->getMatchClientId()) {
3915 client_id = ctx.clientid_;
3919 valid_lft, now, ctx.subnet_->getID()));
3922 lease->fqdn_fwd_ = ctx.fwd_dns_update_;
3923 lease->fqdn_rev_ = ctx.rev_dns_update_;
3924 lease->hostname_ = ctx.hostname_;
3930 if (ctx.callout_handle_ &&
3931 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
3944 ctx.callout_handle_->setArgument(
"query4", ctx.query_);
3951 ctx.callout_handle_->setArgument(
"subnet4", subnet4);
3954 ctx.callout_handle_->setArgument(
"fake_allocation", ctx.fake_allocation_);
3957 ctx.callout_handle_->setArgument(
"lease4", lease);
3960 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.callout_handle_);
3962 callout_status = ctx.callout_handle_->getStatus();
3967 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
3974 ctx.callout_handle_->getArgument(
"lease4", lease);
3977 if (!ctx.fake_allocation_) {
3983 StatsMgr::instance().addValue(
3984 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
3985 "assigned-addresses"),
3986 static_cast<int64_t>(1));
3987 StatsMgr::instance().addValue(
3988 StatsMgr::generateName(
"subnet", ctx.subnet_->getID(),
3989 "cumulative-assigned-addresses"),
3990 static_cast<int64_t>(1));
3991 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
3992 static_cast<int64_t>(1));
4012 AllocEngine::renewLease4(
const Lease4Ptr& lease,
4015 isc_throw(BadValue,
"null lease specified for renewLease4");
4022 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4027 lease->reuseable_valid_lft_ = 0;
4028 if (!updateLease4Information(lease, ctx)) {
4029 setLeaseReusable(lease, ctx);
4045 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_renew_)) {
4069 ctx.
callout_handle_->setArgument(
"clientid", subnet4->getMatchClientId() ?
4077 HooksManager::callCallouts(
Hooks.hook_index_lease4_renew_,
4083 if (ctx.
callout_handle_->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
4092 if (!ctx.
fake_allocation_ && !skip && (lease->reuseable_valid_lft_ == 0)) {
4098 StatsMgr::instance().addValue(
4099 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4100 "assigned-addresses"),
4101 static_cast<int64_t>(1));
4102 StatsMgr::instance().addValue(
4103 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4104 "cumulative-assigned-addresses"),
4105 static_cast<int64_t>(1));
4106 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4107 static_cast<int64_t>(1));
4113 *lease = *old_values;
4120 AllocEngine::reuseExpiredLease4(
Lease4Ptr& expired,
4124 isc_throw(BadValue,
"null lease specified for reuseExpiredLease");
4128 isc_throw(BadValue,
"null subnet specified for the reuseExpiredLease");
4139 expired->reuseable_valid_lft_ = 0;
4140 static_cast<void>(updateLease4Information(expired, ctx));
4144 .arg(ctx.
query_->getLabel())
4145 .arg(expired->toText());
4149 HooksManager::calloutsPresent(hook_index_lease4_select_)) {
4178 HooksManager::callCallouts(hook_index_lease4_select_, *ctx.
callout_handle_);
4185 if (callout_status == CalloutHandle::NEXT_STEP_SKIP) {
4203 StatsMgr::instance().addValue(
4204 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4205 "assigned-addresses"),
4206 static_cast<int64_t>(1));
4207 StatsMgr::instance().addValue(
4208 StatsMgr::generateName(
"subnet", ctx.
subnet_->getID(),
4209 "cumulative-assigned-addresses"),
4210 static_cast<int64_t>(1));
4211 StatsMgr::instance().addValue(
"cumulative-assigned-addresses",
4212 static_cast<int64_t>(1));
4224 AllocEngine::allocateOrReuseLease4(
const IOAddress& candidate, ClientContext4& ctx,
4226 ctx.conflicting_lease_.reset();
4230 if (exist_lease->expired()) {
4235 ctx.old_lease_->hostname_.clear();
4236 ctx.old_lease_->fqdn_fwd_ =
false;
4237 ctx.old_lease_->fqdn_rev_ =
false;
4238 return (reuseExpiredLease4(exist_lease, ctx, callout_status));
4244 ctx.conflicting_lease_ = exist_lease;
4248 return (createLease4(ctx, candidate, callout_status));
4254 AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) {
4269 ctx.subnet_->getSharedNetwork(network);
4276 ctx.subnet_ = subnet = network->getPreferredSubnet(ctx.subnet_);
4282 bool check_reservation_first = MultiThreadingMgr::instance().getMode();
4286 uint64_t total_attempts = 0;
4290 uint64_t subnets_with_unavail_leases = 0;
4293 uint64_t subnets_with_unavail_pools = 0;
4297 if (subnet->getMatchClientId()) {
4298 client_id = ctx.clientid_;
4301 uint64_t possible_attempts =
4303 ctx.query_->getClasses());
4310 uint64_t max_attempts = ((attempts_ == 0 || possible_attempts < attempts_) ? possible_attempts : attempts_);
4312 if (max_attempts > 0) {
4315 ++subnets_with_unavail_leases;
4319 ++subnets_with_unavail_pools;
4324 for (uint64_t i = 0; i < max_attempts; ++i) {
4328 IOAddress candidate = allocator->pickAddress(subnet,
4329 ctx.query_->getClasses(),
4331 ctx.requested_address_);
4333 if (check_reservation_first && addressReserved(candidate, ctx)) {
4341 if (MultiThreadingMgr::instance().getMode() &&
4342 !resource_handler.
tryLock4(candidate)) {
4351 if (check_reservation_first || !addressReserved(candidate, ctx)) {
4353 new_lease = createLease4(ctx, candidate, callout_status);
4357 if (exist_lease->expired() &&
4358 (check_reservation_first || !addressReserved(candidate, ctx))) {
4360 new_lease = reuseExpiredLease4(exist_lease, ctx, callout_status);
4369 if (ctx.callout_handle_ && (callout_status != CalloutHandle::NEXT_STEP_CONTINUE)) {
4378 subnet = subnet->getNextSubnet(original_subnet, ctx.query_->getClasses());
4381 ctx.subnet_ = subnet;
4390 .arg(ctx.query_->getLabel())
4391 .arg(network->getName())
4392 .arg(subnets_with_unavail_leases)
4393 .arg(subnets_with_unavail_pools);
4399 .arg(ctx.query_->getLabel())
4400 .arg(ctx.subnet_->getID());
4402 if (total_attempts == 0) {
4408 .arg(ctx.query_->getLabel());
4415 .arg(ctx.query_->getLabel())
4416 .arg(total_attempts);
4420 if (!classes.
empty()) {
4422 .arg(ctx.query_->getLabel())
4430 AllocEngine::updateLease4Information(
const Lease4Ptr& lease,
4432 bool changed =
false;
4433 if (lease->subnet_id_ != ctx.
subnet_->getID()) {
4435 lease->subnet_id_ = ctx.
subnet_->getID();
4437 if ((!ctx.
hwaddr_ && lease->hwaddr_) ||
4439 (!lease->hwaddr_ || (*ctx.
hwaddr_ != *lease->hwaddr_)))) {
4444 if (!lease->client_id_ || (*ctx.
clientid_ != *lease->client_id_)) {
4448 }
else if (lease->client_id_) {
4452 lease->cltt_ = time(NULL);
4458 if (lease->valid_lft_ < lease->current_valid_lft_) {
4482 bool changed =
false;
4485 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4500 ElementPtr extended_info = Element::createMap();
4501 extended_info->set(
"relay-agent-info", relay_agent);
4505 if (lease->getContext()) {
4506 user_context = UserContext::toElement(lease->getContext());
4508 user_context = Element::createMap();
4513 if (!old_extended_info || (*old_extended_info != *extended_info)) {
4515 user_context->set(
"ISC", extended_info);
4519 lease->setContext(user_context);
4527 bool changed =
false;
4530 if (!ctx.
subnet_->getStoreExtendedInfo()) {
4535 if (ctx.
query_->relay_info_.empty()) {
4549 ElementPtr relay_list = Element::createList();
4550 for (
auto relay : ctx.
query_->relay_info_) {
4551 ElementPtr relay_elem = Element::createMap();
4559 if (!relay.options_.empty()) {
4564 const uint8_t* cp =
static_cast<const uint8_t*
>(buf.
getData());
4565 std::vector<uint8_t>bytes;
4566 std::stringstream ss;
4574 relay_list->add(relay_elem);
4578 ElementPtr extended_info = Element::createMap();
4579 extended_info->set(
"relays", relay_list);
4583 if (lease->getContext()) {
4584 user_context = UserContext::toElement(lease->getContext());
4586 user_context = Element::createMap();
4591 if (!old_extended_info || (*old_extended_info != *extended_info)) {
4593 user_context->set(
"ISC", extended_info);
4597 lease->setContext(user_context);
4603 AllocEngine::setLeaseReusable(
const Lease4Ptr& lease,
4604 const ClientContext4& ctx)
const {
4606 lease->reuseable_valid_lft_ = 0;
4622 if (lease->cltt_ < lease->current_cltt_) {
4626 uint32_t age = lease->cltt_ - lease->current_cltt_;
4628 if (age >= lease->current_valid_lft_) {
4633 uint32_t max_age = 0;
4634 if (!subnet->getCacheMaxAge().unspecified()) {
4635 max_age = subnet->getCacheMaxAge().get();
4636 if ((max_age == 0) || (age > max_age)) {
4642 if (!subnet->getCacheThreshold().unspecified()) {
4643 double threshold = subnet->getCacheThreshold().get();
4644 if ((threshold <= 0.) || (threshold > 1.)) {
4647 max_age = lease->valid_lft_ * threshold;
4648 if (age > max_age) {
4659 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
4663 AllocEngine::setLeaseReusable(
const Lease6Ptr& lease,
4664 uint32_t current_preferred_lft,
4665 const ClientContext6& ctx)
const {
4667 lease->reuseable_valid_lft_ = 0;
4668 lease->reuseable_preferred_lft_ = 0;
4678 if (lease->cltt_ < lease->current_cltt_) {
4682 uint32_t age = lease->cltt_ - lease->current_cltt_;
4684 if (age >= lease->current_valid_lft_) {
4689 uint32_t max_age = 0;
4690 if (!subnet->getCacheMaxAge().unspecified()) {
4691 max_age = subnet->getCacheMaxAge().get();
4692 if ((max_age == 0) || (age > max_age)) {
4698 if (!subnet->getCacheThreshold().unspecified()) {
4699 double threshold = subnet->getCacheThreshold().get();
4700 if ((threshold <= 0.) || (threshold > 1.)) {
4703 max_age = lease->valid_lft_ * threshold;
4704 if (age > max_age) {
4716 (current_preferred_lft == 0)) {
4718 lease->reuseable_preferred_lft_ = current_preferred_lft;
4719 }
else if (current_preferred_lft > age) {
4720 lease->reuseable_preferred_lft_ = current_preferred_lft - age;
4728 lease->reuseable_valid_lft_ = lease->current_valid_lft_ - age;
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_SELECT_SKIP
static HostMgr & instance()
Returns a sole instance of the HostMgr.
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_COMPLETE
bool fake_allocation_
Indicates if this is a real or fake allocation.
boost::shared_ptr< DUID > DuidPtr
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_EXTEND_LEASE
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
bool updateLease4ExtendedInfo(const Lease4Ptr &lease, const ClientContext4 &ctx) const
Stores additional client query parameters on a V4 lease.
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_COMPLETE
const int ALLOC_ENGINE_DBG_TRACE
Logging levels for the AllocEngine.
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...
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
A generic exception that is thrown when a function is not implemented.
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
static const uint32_t STATE_EXPIRED_RECLAIMED
Expired and reclaimed lease.
Structure that holds a lease for IPv4 address.
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const
Return all hosts in a DHCPv4 subnet.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_IN_USE
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
ConstHostPtr currentHost() const
Returns host from the most preferred subnet.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
static void findReservation(ClientContext6 &ctx)
Attempts to find appropriate host reservation.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
isc::util::ReadWriteMutex rw_mutex_
The read-write mutex.
boost::shared_ptr< Pool6 > Pool6Ptr
a pointer an IPv6 Pool
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_START
static std::string typeToText(Type type)
returns text representation of a lease type
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_TIMEOUT
void addAllocatedResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding allocated prefix or address.
static IPv6Resrv makeIPv6Resrv(const Lease6 &lease)
Creates an IPv6Resrv instance from a Lease6.
static isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress &address, bool prefix, const uint8_t prefix_len)
Returns the next address or prefix.
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_REMOVE_RESERVED
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_SLOW
long getTotalMilliseconds() const
Retrieves the total measured duration in milliseconds.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RENEW_SKIP
static ConstHostPtr findGlobalReservation(ClientContext6 &ctx)
Attempts to find the host reservation for the client.
static CfgMgr & instance()
returns a single instance of Configuration Manager
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL
Write mutex RAII handler.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_HR_ADDR_GRANTED
const int DHCPSRV_DBG_HOOKS
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_UNRESERVED
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_HR
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID ALLOC_ENGINE_V4_NO_MORE_EXPIRED_LEASES
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_HR
Resource race avoidance RAII handler for DHCPv4.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
the lease contains IPv6 prefix (for prefix delegation)
boost::shared_ptr< Element > ElementPtr
const int ALLOC_ENGINE_DBG_TRACE_DETAIL
Record detailed traces.
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv4 leases.
DuidPtr duid_
Client identifier.
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
Lease4Ptr allocateLease4(ClientContext4 &ctx)
Returns IPv4 lease.
A configuration holder for IPv4 subnet.
Forward declaration to OptionInt.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_TIMEOUT
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ADDRESS_RESERVED
IPv6 reservation for a host.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ERROR
AllocEngine(AllocType engine_type, uint64_t attempts, bool ipv6=true)
Constructor.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
hooks::CalloutHandlePtr callout_handle_
Callout handle associated with the client's message.
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
RAII object enabling copying options retrieved from the packet.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SHARED_NETWORK
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_LEASES_NO_HR
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...
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_NEW_LEASE
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
An exception that is thrown when allocation module fails (e.g.
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_RECOVER_SKIP
virtual void getExpiredLeases6(Lease6Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv6 leases.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
Statistics Manager class.
boost::shared_ptr< DdnsParams > DdnsParamsPtr
Defines a pointer for DdnsParams instances.
asiolink::IOAddress requested_address_
An address that the client desires.
Resource race avoidance RAII handler.
void deleteExpiredReclaimedLeases4(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
const isc::log::MessageID ALLOC_ENGINE_V6_HR_PREFIX_GRANTED
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
void addNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128)
Convenience method adding new prefix or address.
AllocType
Specifies allocation type.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SHARED_NETWORK
bool updateLease6ExtendedInfo(const Lease6Ptr &lease, const ClientContext6 &ctx) const
Stores additional client query parameters on a V6 lease.
bool tryLock(Lease::Type type, const asiolink::IOAddress &addr)
Tries to acquires a resource.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
void stop()
Stops the stopwatch.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
Subnet6Ptr subnet_
Subnet selected for the client by the server.
ResourceContainer allocated_resources_
Holds addresses and prefixes allocated for all IAs.
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
Pool information for IPv6 addresses and prefixes.
std::list< ClientClass >::const_iterator const_iterator
Type of iterators.
const int ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA
Records detailed results of various operations.
Lease4Ptr conflicting_lease_
A pointer to the object representing a lease in conflict.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_RECOVER_SKIP
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
boost::shared_ptr< Option6IAPrefix > Option6IAPrefixPtr
Pointer to the Option6IAPrefix object.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL
const isc::log::MessageID ALLOC_ENGINE_V6_HINT_RESERVED
const_iterator cend() const
Iterator to the past the end element.
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Lease4Ptr old_lease_
A pointer to an old lease that the client had before update.
ConstHostPtr currentHost() const
Returns host for currently selected subnet.
Utility class to measure code execution times.
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE_DATA
std::map< SubnetID, ConstHostPtr > hosts_
Holds a map of hosts belonging to the client within different subnets.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_PREFIX_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_OUT_OF_POOL
Random allocator that picks address randomly.
Context information for the DHCPv6 leases allocation.
const isc::log::MessageID ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA
Subnet6Ptr host_subnet_
Subnet from which host reservations should be retrieved.
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
Notes: IntElement type is changed to int64_t.
Lease6Collection renewLeases6(ClientContext6 &ctx)
Renews existing DHCPv6 leases for a given IA.
Wrapper class around callout handle which automatically resets handle's state.
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.
Subnet4Ptr subnet_
Subnet selected for the client by the server.
Pkt4Ptr query_
A pointer to the client's message.
const isc::log::MessageID ALLOC_ENGINE_V4_LEASE_RECLAIM
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_START
CalloutNextStep
Specifies allowed next steps.
ClientContext4()
Default constructor.
boost::shared_ptr< const Element > ConstElementPtr
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.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
bool hasGlobalReservation(const IPv6Resrv &resv) const
Determines if a global reservation exists.
Structure that holds a lease for IPv6 address and/or prefix.
bool getDisableSingleQuery() const
Returns the disable single query flag.
Address/prefix allocator that iterates over all addresses.
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.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_NO_POOLS
const isc::log::MessageID ALLOC_ENGINE_V6_LEASES_RECLAMATION_SLOW
std::vector< Lease6Ptr > Lease6Collection
A collection of IPv6 leases.
virtual Lease6Ptr getLease6(Lease::Type type, const isc::asiolink::IOAddress &addr) const =0
Returns existing IPv6 lease for a given IPv6 address.
const isc::log::MessageID ALLOC_ENGINE_V6_REUSE_EXPIRED_LEASE_DATA
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Type
Type of the reservation.
virtual void getExpiredLeases4(Lease4Collection &expired_leases, const size_t max_leases) const =0
Returns a collection of expired DHCPv4 leases.
the lease contains temporary IPv6 address
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE_FAILED
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
void addHostIdentifier(const Host::IdentifierType &id_type, const std::vector< uint8_t > &identifier)
Convenience function adding host identifier into host_identifiers_ list.
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
the lease contains non-temporary IPv6 address
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_FAIL_SUBNET
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_EXISTING_LEASE
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
const isc::log::MessageID ALLOC_ENGINE_V6_RENEW_HR
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_CLASSES
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
const isc::log::MessageID ALLOC_ENGINE_V6_EXPIRED_HINT_RESERVED
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
Lease6Collection new_leases_
A collection of newly allocated leases.
T get(T hint) const
Returns value with a hint.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
ClientIdPtr clientid_
Client identifier from the DHCP message.
uint32_t iaid_
The IAID field from IA_NA or IA_PD that is being processed.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_V6_HR
const isc::log::MessageID ALLOC_ENGINE_V6_LEASE_RECLAIM
Lease::Type type_
Lease type (IA or PD)
boost::shared_ptr< Allocator > AllocatorPtr
defines a pointer to allocator
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_COMPLETE
Address/prefix allocator that gets an address based on a hash.
Pkt6Ptr query_
A pointer to the client's message.
std::string logFormatTotalDuration() const
Returns the total measured duration in the format directly usable in the log messages.
bool isNewResource(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was new.
Lease6Collection allocateLeases6(ClientContext6 &ctx)
Allocates IPv6 leases for a given IA container.
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_NO_POOLS
Lease4Ptr new_lease_
A pointer to a newly allocated lease.
static const uint32_t INFINITY_LFT
Infinity (means static, i.e. never expire)
const isc::log::MessageID ALLOC_ENGINE_V4_LEASES_RECLAMATION_COMPLETE
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_NEW_LEASE_DATA
HashedAllocator(Lease::Type type)
Default constructor (does nothing)
a common structure for IPv4 and IPv6 leases
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_ALLOC_UNRESERVED
Type
Type of lease or pool.
const isc::log::MessageID DHCPSRV_HOOK_LEASE4_SELECT_SKIP
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_REMOVE_LEASE
IAContext()
Default constructor.
bool fwd_dns_update_
Perform forward DNS update.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_FAIL_SUBNET
isc::log::Logger alloc_engine_logger("alloc-engine")
Logger for the AllocEngine.
const isc::log::MessageID DHCPSRV_HOOK_LEASE6_EXTEND_SKIP
Base class for all address/prefix allocation algorithms.
A generic exception that is thrown if a function is called in a prohibited way.
static uint32_t getValidLft(const ClientContext4 &ctx)
Returns the valid lifetime based on the v4 context.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_SHARED_ADDR_LEASE
const isc::log::MessageID ALLOC_ENGINE_V4_OFFER_REQUESTED_LEASE
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
void deleteExpiredReclaimedLeases6(const uint32_t secs)
Deletes reclaimed leases expired more than specified amount of time ago.
std::string toText() const
Convert the address to a string.
const isc::log::MessageID ALLOC_ENGINE_V6_RECLAIMED_LEASES_DELETE
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
IAContext & currentIA()
Returns IA specific context for the currently processed IA.
static const uint32_t STATE_DEFAULT
A lease in the default state.
ConstHostPtr globalHost() const
Returns global host reservation if there is one.
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.
const isc::log::MessageID ALLOC_ENGINE_V4_DECLINED_RECOVERED
bool isV6() const
Convenience function to check for an IPv6 address.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
std::string hostname_
Hostname.
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
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.
const isc::log::MessageID ALLOC_ENGINE_LEASE_RECLAIMED
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
static const uint32_t STATE_DECLINED
Declined lease.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_PICK_ADDRESS
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V4_ALLOC_ERROR
const isc::log::MessageID ALLOC_ENGINE_V4_RECLAIMED_LEASES_DELETE_FAILED
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_PREFIX_LEASE
bool empty() const
Check if classes is empty.
static isc::asiolink::IOAddress increasePrefix(const isc::asiolink::IOAddress &prefix, const uint8_t prefix_len)
Returns the next prefix.
std::pair< IPv6Resrv::Type, IPv6Resrv > IPv6ResrvTuple
HWAddrPtr hwaddr_
HW address from the DHCP message.
bool isAllocated(const asiolink::IOAddress &prefix, const uint8_t prefix_len=128) const
Checks if specified address or prefix was allocated.
The IOAddress class represents an IP addresses (version agnostic)
static LeaseMgr & instance()
Return current lease manager.
T getValue() const
Return option value.
virtual Lease6Collection getLeases6(Lease::Type type, const DUID &duid, uint32_t iaid) const =0
Returns existing IPv6 leases for a given DUID+IA combination.
RandomAllocator(Lease::Type type)
Default constructor (does nothing)
Context information for the DHCPv4 lease allocation.
const isc::log::MessageID ALLOC_ENGINE_V6_REVOKED_ADDR_LEASE
size_t getLength() const
Return the length of data written in the buffer.
const_iterator cbegin() const
Iterator to the first element.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_INVALID
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs)=0
Deletes all expired and reclaimed DHCPv6 leases.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
std::pair< Host::IdentifierType, std::vector< uint8_t > > IdentifierPair
A tuple holding host identifier type and value.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_ALLOC_REQUESTED
Container for storing client class names.
static IOAddress increase(const IOAddress &addr)
Returns an address increased by one.
boost::shared_ptr< Option6IAAddr > Option6IAAddrPtr
A pointer to the isc::dhcp::Option6IAAddr object.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_HR_LEASE_EXISTS
bool rev_dns_update_
Perform reverse DNS update.
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
const isc::log::MessageID ALLOC_ENGINE_V4_REQUEST_USE_HR
const isc::log::MessageID ALLOC_ENGINE_V6_EXTEND_LEASE
virtual void updateLease6(const Lease6Ptr &lease6)=0
Updates IPv6 lease.
const isc::log::MessageID ALLOC_ENGINE_V6_NO_MORE_EXPIRED_LEASES
DdnsParamsPtr getDdnsParams()
Returns the set of DDNS behavioral parameters based on the selected subnet.
const isc::log::MessageID ALLOC_ENGINE_V6_ALLOC_NO_LEASES_HR
AllocatorPtr getAllocator(Lease::Type type)
Returns allocator for a given pool type.
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
IdentifierList host_identifiers_
A list holding host identifiers extracted from a message received by the server.
const isc::log::MessageID ALLOC_ENGINE_V4_DISCOVER_ADDRESS_CONFLICT
ClientContext6()
Default constructor.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
std::string toText(const std::string &separator=", ") const
Returns all class names as text.
const isc::log::MessageID ALLOC_ENGINE_V6_DECLINED_RECOVERED