Kea  2.3.5-git
subnet.cc
Go to the documentation of this file.
1 // Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <asiolink/io_address.h>
11 #include <dhcp/option_space.h>
13 #include <dhcpsrv/shared_network.h>
14 #include <dhcpsrv/subnet.h>
16 
17 #include <boost/lexical_cast.hpp>
18 #include <boost/make_shared.hpp>
19 
20 #include <algorithm>
21 #include <sstream>
22 
23 using namespace isc::asiolink;
24 using namespace isc::data;
25 using namespace isc::dhcp;
26 using namespace isc::util;
27 
28 namespace {
29 
34 bool
35 prefixLessThanFirstAddress(const IOAddress& prefix, const PoolPtr& pool) {
36  return (prefix < pool->getFirstAddress());
37 }
38 
47 bool
48 comparePoolFirstAddress(const PoolPtr& pool1, const PoolPtr& pool2) {
49  return (pool1->getFirstAddress() < pool2->getFirstAddress());
50 };
51 
52 }
53 
54 namespace isc {
55 namespace dhcp {
56 
57 // This is an initial value of subnet-id. See comments in subnet.h for details.
58 SubnetID Subnet::static_id_ = 1;
59 
60 Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
61  const SubnetID id)
62  : id_(id == 0 ? generateNextID() : id), prefix_(prefix),
63  prefix_len_(len),
64  shared_network_name_() {
65  if ((prefix.isV6() && len > 128) ||
66  (prefix.isV4() && len > 32)) {
68  "Invalid prefix length specified for subnet: " << len);
69  }
70 }
71 
72 bool
76 
77  return ((first <= addr) && (addr <= last));
78 }
79 
80 std::string
81 Subnet::toText() const {
82  std::stringstream tmp;
83  tmp << prefix_ << "/" << static_cast<unsigned int>(prefix_len_);
84  return (tmp.str());
85 }
86 
87 uint64_t
89  switch (type) {
90  case Lease::TYPE_V4:
91  case Lease::TYPE_NA:
92  return sumPoolCapacity(pools_);
93  case Lease::TYPE_TA:
94  return sumPoolCapacity(pools_ta_);
95  case Lease::TYPE_PD:
96  return sumPoolCapacity(pools_pd_);
97  default:
98  isc_throw(BadValue, "Unsupported pool type: "
99  << static_cast<int>(type));
100  }
101 }
102 
103 uint64_t
105  const ClientClasses& client_classes) const {
106  switch (type) {
107  case Lease::TYPE_V4:
108  case Lease::TYPE_NA:
109  return sumPoolCapacity(pools_, client_classes);
110  case Lease::TYPE_TA:
111  return sumPoolCapacity(pools_ta_, client_classes);
112  case Lease::TYPE_PD:
113  return sumPoolCapacity(pools_pd_, client_classes);
114  default:
115  isc_throw(BadValue, "Unsupported pool type: "
116  << static_cast<int>(type));
117  }
118 }
119 
120 uint64_t
122  const ClientClasses& client_classes,
123  Allocator::PrefixLenMatchType prefix_length_match,
124  uint8_t hint_prefix_length) const {
125  switch (type) {
126  case Lease::TYPE_V4:
127  case Lease::TYPE_NA:
128  return sumPoolCapacity(pools_, client_classes);
129  case Lease::TYPE_TA:
130  return sumPoolCapacity(pools_ta_, client_classes);
131  case Lease::TYPE_PD:
132  return sumPoolCapacity(pools_pd_, client_classes, prefix_length_match,
133  hint_prefix_length);
134  default:
135  isc_throw(BadValue, "Unsupported pool type: "
136  << static_cast<int>(type));
137  }
138 }
139 
140 uint64_t
142  uint64_t sum = 0;
143  for (auto const& p : pools) {
144  uint64_t x = p->getCapacity();
145 
146  // Check if we can add it. If sum + x > uint64::max, then we would have
147  // overflown if we tried to add it.
148  if (x > std::numeric_limits<uint64_t>::max() - sum) {
149  return (std::numeric_limits<uint64_t>::max());
150  }
151 
152  sum += x;
153  }
154 
155  return (sum);
156 }
157 
158 uint64_t
160  const ClientClasses& client_classes) const {
161  uint64_t sum = 0;
162  for (auto const& p : pools) {
163  if (!p->clientSupported(client_classes)) {
164  continue;
165  }
166  uint64_t x = p->getCapacity();
167 
168  // Check if we can add it. If sum + x > uint64::max, then we would have
169  // overflown if we tried to add it.
170  if (x > std::numeric_limits<uint64_t>::max() - sum) {
171  return (std::numeric_limits<uint64_t>::max());
172  }
173 
174  sum += x;
175  }
176 
177  return (sum);
178 }
179 
180 uint64_t
182  const ClientClasses& client_classes,
183  Allocator::PrefixLenMatchType prefix_length_match,
184  uint8_t hint_prefix_length) const {
185  uint64_t sum = 0;
186  for (auto const& p : pools) {
187  if (!p->clientSupported(client_classes)) {
188  continue;
189  }
190 
191  if (!Allocator::isValidPrefixPool(prefix_length_match, p,
192  hint_prefix_length)) {
193  continue;
194  }
195 
196  uint64_t x = p->getCapacity();
197 
198  // Check if we can add it. If sum + x > uint64::max, then we would have
199  // overflown if we tried to add it.
200  if (x > std::numeric_limits<uint64_t>::max() - sum) {
201  return (std::numeric_limits<uint64_t>::max());
202  }
203 
204  sum += x;
205  }
206 
207  return (sum);
208 }
209 
210 std::pair<IOAddress, uint8_t>
211 Subnet::parsePrefixCommon(const std::string& prefix) {
212  auto pos = prefix.find('/');
213  if ((pos == std::string::npos) ||
214  (pos == prefix.size() - 1) ||
215  (pos == 0)) {
216  isc_throw(BadValue, "unable to parse invalid prefix " << prefix);
217  }
218 
219  try {
220  IOAddress address(prefix.substr(0, pos));
221  int length = boost::lexical_cast<int>(prefix.substr(pos + 1));
222  return (std::make_pair(address, static_cast<int>(length)));
223 
224  } catch (...) {
225  isc_throw(BadValue, "unable to parse invalid prefix " << prefix);
226  }
227 }
228 
229 
230 void Subnet4::checkType(Lease::Type type) const {
231  if (type != Lease::TYPE_V4) {
232  isc_throw(BadValue, "Only TYPE_V4 is allowed for Subnet4");
233  }
234 }
235 
236 Subnet4::Subnet4(const IOAddress& prefix, uint8_t length,
237  const Triplet<uint32_t>& t1,
238  const Triplet<uint32_t>& t2,
239  const Triplet<uint32_t>& valid_lifetime,
240  const SubnetID id)
241  : Subnet(prefix, length, id), Network4() {
242  if (!prefix.isV4()) {
243  isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
244  << " specified in subnet4");
245  }
246  // Timers.
247  setT1(t1);
248  setT2(t2);
249  setValid(valid_lifetime);
250 }
251 
253 Subnet4::create(const IOAddress& prefix, uint8_t length,
254  const Triplet<uint32_t>& t1,
255  const Triplet<uint32_t>& t2,
256  const Triplet<uint32_t>& valid_lifetime,
257  const SubnetID id) {
258  Subnet4Ptr subnet = boost::make_shared<Subnet4>
259  (prefix, length, t1, t2, valid_lifetime, id);
260  subnet->setAllocator(Lease::TYPE_V4,
261  boost::make_shared<IterativeAllocator>
262  (Lease::TYPE_V4, subnet));
263  subnet->setAllocationState(Lease::TYPE_V4,
265 
266  return (subnet);
267 }
268 
270 Subnet4::getNextSubnet(const Subnet4Ptr& first_subnet) const {
271  SharedNetwork4Ptr network;
272  getSharedNetwork(network);
273  if (network) {
274  return (network->getNextSubnet(first_subnet, getID()));
275  }
276 
277  return (Subnet4Ptr());
278 }
279 
281 Subnet4::getNextSubnet(const Subnet4Ptr& first_subnet,
282  const ClientClasses& client_classes) const {
283  SharedNetwork4Ptr network;
284  getSharedNetwork(network);
285  // We can only get next subnet if shared network has been defined for
286  // the current subnet.
287  if (network) {
288  Subnet4Ptr subnet;
289  do {
290  // Use subnet identifier of this subnet if this is the first
291  // time we're calling getNextSubnet. Otherwise, use the
292  // subnet id of the previously returned subnet.
293  SubnetID subnet_id = subnet ? subnet->getID() : getID();
294  subnet = network->getNextSubnet(first_subnet, subnet_id);
295  // If client classes match the subnet, return it. Otherwise,
296  // try another subnet.
297  if (subnet && subnet->clientSupported(client_classes)) {
298  return (subnet);
299  }
300  } while (subnet);
301  }
302 
303  // No subnet found.
304  return (Subnet4Ptr());
305 }
306 
307 
308 bool
310  NetworkPtr network;
311  getSharedNetwork(network);
312  if (network && !network->clientSupported(client_classes)) {
313  return (false);
314  }
315 
316  return (Network4::clientSupported(client_classes));
317 }
318 
320  // check if the type is valid (and throw if it isn't)
321  checkType(type);
322 
323  switch (type) {
324  case Lease::TYPE_V4:
325  case Lease::TYPE_NA:
326  return (pools_);
327  case Lease::TYPE_TA:
328  return (pools_ta_);
329  case Lease::TYPE_PD:
330  return (pools_pd_);
331  default:
332  isc_throw(BadValue, "Unsupported pool type: "
333  << static_cast<int>(type));
334  }
335 }
336 
338  // check if the type is valid (and throw if it isn't)
339  checkType(type);
340 
341  switch (type) {
342  case Lease::TYPE_V4:
343  case Lease::TYPE_NA:
344  return (pools_);
345  case Lease::TYPE_TA:
346  return (pools_ta_);
347  case Lease::TYPE_PD:
348  return (pools_pd_);
349  default:
350  isc_throw(BadValue, "Invalid pool type specified: "
351  << static_cast<int>(type));
352  }
353 }
354 
357  auto alloc = allocators_.find(type);
358 
359  if (alloc == allocators_.end()) {
360  isc_throw(BadValue, "no allocator initialized for pool type "
361  << Lease::typeToText(type));
362  }
363  return (alloc->second);
364 }
365 
366 void
368  allocators_[type] = allocator;
369 }
370 
373  auto state = allocation_states_.find(type);
374 
375  if (state == allocation_states_.end()) {
376  isc_throw(BadValue, "no allocation state initialized for pool type "
377  << Lease::typeToText(type));
378  }
379  return (state->second);
380 }
381 
382 void
384  allocation_states_[type] = allocation_state;
385 }
386 
388  bool anypool /* true */) const {
389  // check if the type is valid (and throw if it isn't)
390  checkType(type);
391 
392  const PoolCollection& pools = getPools(type);
393 
394  PoolPtr candidate;
395 
396  if (!pools.empty()) {
397  // Pools are sorted by their first prefixes. For example: 2001::,
398  // 2001::db8::, 3000:: etc. If our hint is 2001:db8:5:: we want to
399  // find the pool with the longest matching prefix, so: 2001:db8::,
400  // rather than 2001::. upper_bound returns the first pool with a prefix
401  // that is greater than 2001:db8:5::, i.e. 3000::. To find the longest
402  // matching prefix we use decrement operator to go back by one item.
403  // If returned iterator points to begin it means that prefixes in all
404  // pools are greater than out prefix, and thus there is no match.
405  PoolCollection::const_iterator ub =
406  std::upper_bound(pools.begin(), pools.end(), hint,
407  prefixLessThanFirstAddress);
408 
409  if (ub != pools.begin()) {
410  --ub;
411  if ((*ub)->inRange(hint)) {
412  candidate = *ub;
413  }
414  }
415 
416  // If we don't find anything better, then let's just use the first pool
417  if (!candidate && anypool) {
418  candidate = *pools.begin();
419  }
420  }
421 
422  // Return a pool or NULL if no match found.
423  return (candidate);
424 }
425 
427  const ClientClasses& client_classes,
428  const isc::asiolink::IOAddress& hint) const {
429  // check if the type is valid (and throw if it isn't)
430  checkType(type);
431 
432  const PoolCollection& pools = getPools(type);
433 
434  PoolPtr candidate;
435 
436  if (!pools.empty()) {
437  PoolCollection::const_iterator ub =
438  std::upper_bound(pools.begin(), pools.end(), hint,
439  prefixLessThanFirstAddress);
440 
441  if (ub != pools.begin()) {
442  --ub;
443  if ((*ub)->inRange(hint) &&
444  (*ub)->clientSupported(client_classes)) {
445  candidate = *ub;
446  }
447  }
448  }
449 
450  // Return a pool or NULL if no match found.
451  return (candidate);
452 }
453 
454 void
455 Subnet::addPool(const PoolPtr& pool) {
456  // check if the type is valid (and throw if it isn't)
457  checkType(pool->getType());
458 
459  // Check that the pool is in range with a subnet only if this is
460  // not a pool of IPv6 prefixes. The IPv6 prefixes delegated for
461  // the particular subnet don't need to match the prefix of the
462  // subnet.
463  if (pool->getType() != Lease::TYPE_PD) {
464  if (!inRange(pool->getFirstAddress()) || !inRange(pool->getLastAddress())) {
465  isc_throw(BadValue, "a pool of type "
466  << Lease::typeToText(pool->getType())
467  << ", with the following address range: "
468  << pool->getFirstAddress() << "-"
469  << pool->getLastAddress() << " does not match"
470  << " the prefix of a subnet: "
471  << prefix_ << "/" << static_cast<int>(prefix_len_)
472  << " to which it is being added");
473 
474  }
475  }
476 
477  bool overlaps = false;
478  if (pool->getType() == Lease::TYPE_V4) {
479  overlaps = poolOverlaps(Lease::TYPE_V4, pool);
480 
481  } else {
482  overlaps =
483  poolOverlaps(Lease::TYPE_NA, pool) ||
484  poolOverlaps(Lease::TYPE_PD, pool) ||
486  }
487 
488  if (overlaps) {
489  isc_throw(BadValue,"a pool of type "
490  << Lease::typeToText(pool->getType())
491  << ", with the following address range: "
492  << pool->getFirstAddress() << "-"
493  << pool->getLastAddress() << " overlaps with "
494  "an existing pool in the subnet: "
495  << prefix_ << "/" << static_cast<int>(prefix_len_)
496  << " to which it is being added");
497  }
498 
499  PoolCollection& pools_writable = getPoolsWritable(pool->getType());
500 
501  // Add the pool to the appropriate pools collection
502  pools_writable.push_back(pool);
503 
504  // Sort pools by first address.
505  std::sort(pools_writable.begin(), pools_writable.end(),
506  comparePoolFirstAddress);
507 }
508 
509 void
511  getPoolsWritable(type).clear();
512 }
513 
514 bool
516 
517  // Let's start with checking if it even belongs to that subnet.
518  if ((type != Lease::TYPE_PD) && !inRange(addr)) {
519  return (false);
520  }
521 
522  const PoolCollection& pools = getPools(type);
523 
524  for (auto const& pool : pools) {
525  if (pool->inRange(addr)) {
526  return (true);
527  }
528  }
529  // There's no pool that address belongs to
530  return (false);
531 }
532 
533 bool
535  const isc::asiolink::IOAddress& addr,
536  const ClientClasses& client_classes) const {
537 
538  // Let's start with checking if it even belongs to that subnet.
539  if ((type != Lease::TYPE_PD) && !inRange(addr)) {
540  return (false);
541  }
542 
543  const PoolCollection& pools = getPools(type);
544 
545  for (auto const& pool : pools) {
546  if (!pool->clientSupported(client_classes)) {
547  continue;
548  }
549  if (pool->inRange(addr)) {
550  return (true);
551  }
552  }
553  // There's no pool that address belongs to
554  return (false);
555 }
556 
557 bool
558 Subnet::poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const {
559  const PoolCollection& pools = getPools(pool_type);
560 
561  // If no pools, we don't overlap. Nothing to do.
562  if (pools.empty()) {
563  return (false);
564  }
565 
566  // We're going to insert a new pool, likely between two existing pools.
567  // So we're going to end up with the following case:
568  // |<---- pool1 ---->| |<-------- pool2 ------>| |<-- pool3 -->|
569  // F1 L1 F2 L2 F3 L3
570  // where pool1 and pool3 are existing pools, pool2 is a pool being
571  // inserted and "F"/"L" mark first and last address in the pools
572  // respectively. So the following conditions must be fulfilled:
573  // F2 > L1 and L2 < F3. Obviously, for any pool: F < L.
574 
575  // Search for pool3. We use F2 and upper_bound to find the F3 (upper_bound
576  // returns first pool in the sorted container which first address is
577  // greater than F2). prefixLessThanPoolAddress with the first argument
578  // set to "true" is the custom comparison function for upper_bound, which
579  // compares F2 with the first addresses of the existing pools.
580  PoolCollection::const_iterator pool3_it =
581  std::upper_bound(pools.begin(), pools.end(), pool->getFirstAddress(),
582  prefixLessThanFirstAddress);
583 
584  // The upper_bound function returns a first pool which first address is
585  // greater than the address F2. However, it is also possible that there is a
586  // pool which first address is equal to F2. Such pool is also in conflict
587  // with a new pool. If the returned value is pools.begin() it means that all
588  // pools have greater first address than F2, thus none of the pools can have
589  // first address equal to F2. Otherwise, we'd need to check them for
590  // equality. However any pool has first address <= last address, so checking
591  // that the new pool first address is greater than the pool before pool3
592  // last address is enough. We now have to find the pool1. This pool should
593  // be right before the pool3 if there is any pool before pool3.
594  if (pool3_it != pools.begin()) {
595  PoolPtr pool1 = *(pool3_it - 1);
596  // F2 must be greater than L1, otherwise pools will overlap.
597  if (pool->getFirstAddress() <= pool1->getLastAddress()) {
598  return (true);
599  }
600  }
601 
602  // If returned value is unequal pools.end() it means that there is a pool3,
603  // with F3 > F2.
604  if (pool3_it != pools.end()) {
605  // Let's store the pointer to this pool.
606  PoolPtr pool3 = *pool3_it;
607  // F3 must be greater than L2, otherwise pools will overlap.
608  if (pool3->getFirstAddress() <= pool->getLastAddress()) {
609  return (true);
610  }
611  }
612 
613  return (false);
614 }
615 
616 Subnet6::Subnet6(const IOAddress& prefix, uint8_t length,
617  const Triplet<uint32_t>& t1,
618  const Triplet<uint32_t>& t2,
619  const Triplet<uint32_t>& preferred_lifetime,
620  const Triplet<uint32_t>& valid_lifetime,
621  const SubnetID id)
622  : Subnet(prefix, length, id), Network6() {
623  if (!prefix.isV6()) {
624  isc_throw(BadValue, "Non IPv6 prefix " << prefix
625  << " specified in subnet6");
626  }
627 
628  // Timers.
629  setT1(t1);
630  setT2(t2);
631  setPreferred(preferred_lifetime);
632  setValid(valid_lifetime);
633 }
634 
636 Subnet6::create(const IOAddress& prefix, uint8_t length,
637  const Triplet<uint32_t>& t1,
638  const Triplet<uint32_t>& t2,
639  const Triplet<uint32_t>& preferred_lifetime,
640  const Triplet<uint32_t>& valid_lifetime,
641  const SubnetID id) {
642  Subnet6Ptr subnet = boost::make_shared<Subnet6>
643  (prefix, length, t1, t2, preferred_lifetime, valid_lifetime, id);
644  // IA_NA
645  subnet->setAllocator(Lease::TYPE_NA,
646  boost::make_shared<IterativeAllocator>
647  (Lease::TYPE_NA, subnet));
648  subnet->setAllocationState(Lease::TYPE_NA,
650  // IA_TA
651  subnet->setAllocator(Lease::TYPE_TA,
652  boost::make_shared<IterativeAllocator>
653  (Lease::TYPE_TA, subnet));
654  subnet->setAllocationState(Lease::TYPE_TA,
656  // IA_PD
657  subnet->setAllocator(Lease::TYPE_PD,
658  boost::make_shared<IterativeAllocator>
659  (Lease::TYPE_PD, subnet));
660  subnet->setAllocationState(Lease::TYPE_PD,
662  return (subnet);
663 }
664 
665 void Subnet6::checkType(Lease::Type type) const {
666  if ((type != Lease::TYPE_NA) && (type != Lease::TYPE_TA) && (type != Lease::TYPE_PD)) {
667  isc_throw(BadValue, "Invalid Pool type: " << Lease::typeToText(type)
668  << "(" << static_cast<int>(type)
669  << "), must be TYPE_NA, TYPE_TA or TYPE_PD for Subnet6");
670  }
671 }
672 
674 Subnet6::getNextSubnet(const Subnet6Ptr& first_subnet) const {
675  SharedNetwork6Ptr network;
676  getSharedNetwork(network);
677  if (network) {
678  return (network->getNextSubnet(first_subnet, getID()));
679  }
680 
681  return (Subnet6Ptr());
682 }
683 
685 Subnet6::getNextSubnet(const Subnet6Ptr& first_subnet,
686  const ClientClasses& client_classes) const {
687  SharedNetwork6Ptr network;
688  getSharedNetwork(network);
689  // We can only get next subnet if shared network has been defined for
690  // the current subnet.
691  if (network) {
692  Subnet6Ptr subnet;
693  do {
694  // Use subnet identifier of this subnet if this is the first
695  // time we're calling getNextSubnet. Otherwise, use the
696  // subnet id of the previously returned subnet.
697  SubnetID subnet_id = subnet ? subnet->getID() : getID();
698  subnet = network->getNextSubnet(first_subnet, subnet_id);
699  // If client classes match the subnet, return it. Otherwise,
700  // try another subnet.
701  if (subnet && subnet->clientSupported(client_classes)) {
702  return (subnet);
703  }
704  } while (subnet);
705  }
706 
707  // No subnet found.
708  return (Subnet6Ptr());
709 }
710 
711 bool
713  NetworkPtr network;
714  getSharedNetwork(network);
715  if (network && !network->clientSupported(client_classes)) {
716  return (false);
717  }
718 
719  return (Network6::clientSupported(client_classes));
720 }
721 
725 
726  // Add user-context
727  contextToElement(map);
728 
729  // Set subnet id
730  SubnetID id = getID();
731  map->set("id", Element::create(static_cast<long long>(id)));
732 
733  // Set subnet
734  map->set("subnet", Element::create(toText()));
735 
736  return (map);
737 }
738 
741  // Prepare the map
743  ElementPtr network_map = Network4::toElement();
744 
745  merge(map, network_map);
746 
747  // Set DHCP4o6
748  const Cfg4o6& d4o6 = get4o6();
749  isc::data::merge(map, d4o6.toElement());
750 
751  // Set pools
752  const PoolCollection& pools = getPools(Lease::TYPE_V4);
753  ElementPtr pool_list = Element::createList();
754  for (auto const& pool : pools) {
755  // Add the formated pool to the list
756  pool_list->add(pool->toElement());
757  }
758  map->set("pools", pool_list);
759 
760  return (map);
761 }
762 
763 std::pair<IOAddress, uint8_t>
764 Subnet4::parsePrefix(const std::string& prefix) {
765  std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix);
766  if (!parsed.first.isV4() || parsed.first.isV4Zero() ||
767  (parsed.second > 32) || (parsed.second == 0)) {
768  isc_throw(BadValue, "unable to parse invalid IPv4 prefix " << prefix);
769  }
770  return (parsed);
771 }
772 
775  // Prepare the map
777  ElementPtr network_map = Network6::toElement();
778 
779  merge(map, network_map);
780 
781  // Set pools
782  const PoolCollection& pools = getPools(Lease::TYPE_NA);
783  ElementPtr pool_list = Element::createList();
784  for (auto const& pool : pools) {
785  // Add the formated pool to the list
786  pool_list->add(pool->toElement());
787  }
788  map->set("pools", pool_list);
789 
790  // Set pd-pools
791  const PoolCollection& pdpools = getPools(Lease::TYPE_PD);
792  ElementPtr pdpool_list = Element::createList();
793  for (auto const& pool : pdpools) {
794  // Add the formated pool to the list
795  pdpool_list->add(pool->toElement());
796  }
797  map->set("pd-pools", pdpool_list);
798 
799  return (map);
800 }
801 
802 std::pair<IOAddress, uint8_t>
803 Subnet6::parsePrefix(const std::string& prefix) {
804  std::pair<IOAddress, uint8_t> parsed = Subnet::parsePrefixCommon(prefix);
805  if (!parsed.first.isV6() || parsed.first.isV6Zero() ||
806  (parsed.second > 128) || (parsed.second == 0)) {
807  isc_throw(BadValue, "unable to parse invalid IPv6 prefix " << prefix);
808  }
809  return (parsed);
810 }
811 
812 } // namespace dhcp
813 } // namespace isc
static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match, PoolPtr pool, uint8_t hint_prefix_length)
Check if the pool matches the selection criteria relative to the provided hint prefix length...
Definition: allocator.cc:15
Subnet4Ptr getNextSubnet(const Subnet4Ptr &first_subnet) const
Returns next subnet within shared network.
Definition: subnet.cc:270
SubnetAllocationStatePtr getAllocationState(Lease::Type type) const
Returns subnet-specific allocation state.
Definition: subnet.cc:372
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition: network.h:70
bool inRange(const isc::asiolink::IOAddress &addr) const
checks if specified address is in range.
Definition: subnet.cc:73
static Subnet4Ptr create(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id=0)
Factory function creating an instance of the Subnet4.
Definition: subnet.cc:253
static std::string typeToText(Type type)
returns text representation of a lease type
Definition: lease.cc:53
Subnet4(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id=0)
Constructor with all parameters.
Definition: subnet.cc:236
void setAllocator(Lease::Type type, const AllocatorPtr &allocator)
Sets new allocator instance.
Definition: subnet.cc:367
static SubnetIterativeAllocationStatePtr create(const SubnetPtr &subnet)
Factory function creating the state instance from subnet.
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition: subnet.h:477
void addPool(const PoolPtr &pool)
Adds a new pool for the subnet.
Definition: subnet.cc:455
void setT1(const isc::util::Triplet< uint32_t > &t1)
Sets new renew timer for a network.
Definition: network.h:400
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
std::vector< PoolPtr > PoolCollection
a container for either IPv4 or IPv6 Pools
Definition: pool.h:494
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: cfg_4o6.cc:22
std::map< Lease::Type, AllocatorPtr > allocators_
Lease allocators used by the subnet.
Definition: subnet.h:461
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
Definition: pool.h:491
bool inPool(Lease::Type type, const isc::asiolink::IOAddress &addr) const
checks if the specified address is in pools.
Definition: subnet.cc:515
void setAllocationState(Lease::Type type, const SubnetAllocationStatePtr &allocation_state)
Sets subnet-specific allocation state.
Definition: subnet.cc:383
uint8_t prefix_len_
a prefix length of the subnet.
Definition: subnet.h:455
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:291
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:286
static std::pair< asiolink::IOAddress, uint8_t > parsePrefix(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition: subnet.cc:764
virtual data::ElementPtr toElement() const
Unparse a subnet object.
Definition: subnet.cc:774
Specialization of the Network object for DHCPv6 case.
Definition: network.h:1342
SubnetID getID() const
Returns unique ID for that subnet.
Definition: subnet.h:82
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
AllocatorPtr getAllocator(Lease::Type type) const
Returns lease allocator instance.
Definition: subnet.cc:356
PrefixLenMatchType
Type of preferred PD-pool prefix length selection criteria.
Definition: allocator.h:60
Definition: edns.h:19
This structure contains information about DHCP4o6 (RFC7341)
Definition: cfg_4o6.h:22
Subnet6Ptr getNextSubnet(const Subnet6Ptr &first_subnet) const
Returns next subnet within shared network.
Definition: subnet.cc:674
void getSharedNetwork(SharedNetworkPtrType &shared_network) const
Retrieves pointer to a shared network associated with a subnet.
Definition: subnet.h:237
IPv4 lease.
Definition: lease.h:50
const PoolCollection & getPools(Lease::Type type) const
Returns all pools (const variant).
Definition: subnet.cc:319
boost::shared_ptr< SubnetAllocationState > SubnetAllocationStatePtr
static Subnet6Ptr create(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &preferred_lifetime, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id=0)
Factory function creating an instance of the Subnet4.
Definition: subnet.cc:636
virtual data::ElementPtr toElement() const
Unparse a subnet object.
Definition: subnet.cc:740
uint64_t sumPoolCapacity(const PoolCollection &pools) const
Returns a sum of possible leases in all pools.
Definition: subnet.cc:141
static std::pair< asiolink::IOAddress, uint8_t > parsePrefixCommon(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition: subnet.cc:211
uint64_t getPoolCapacity(Lease::Type type) const
Returns the number of possible leases for specified lease type.
Definition: subnet.cc:88
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition: user_context.cc:15
isc::asiolink::IOAddress prefix_
a prefix of the subnet.
Definition: subnet.h:452
PoolCollection pools_
collection of IPv4 or non-temporary IPv6 pools in that subnet.
Definition: subnet.h:443
the lease contains temporary IPv6 address
Definition: lease.h:48
virtual bool clientSupported(const isc::dhcp::ClientClasses &client_classes) const
Checks whether this network supports client that belongs to specified classes.
Definition: network.cc:69
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
bool poolOverlaps(const Lease::Type &pool_type, const PoolPtr &pool) const
Checks if the specified pool overlaps with an existing pool.
Definition: subnet.cc:558
the lease contains non-temporary IPv6 address
Definition: lease.h:47
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
virtual data::ElementPtr toElement() const
Unparse a subnet object.
Definition: subnet.cc:723
void setPreferred(const isc::util::Triplet< uint32_t > &preferred)
Sets new preferred lifetime for a network.
Definition: network.h:1366
Defines the logger used by the top-level component of kea-lfc.
virtual data::ElementPtr toElement() const
Unparses network object.
Definition: network.cc:342
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element.
Definition: data.cc:1139
PoolCollection & getPoolsWritable(Lease::Type type)
Returns all pools (non-const variant).
Definition: subnet.cc:337
const PoolPtr getPool(Lease::Type type, const isc::asiolink::IOAddress &addr, bool anypool=true) const
Returns a pool that specified address belongs to.
Definition: subnet.cc:387
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:241
Type
Type of lease or pool.
Definition: lease.h:46
static std::pair< asiolink::IOAddress, uint8_t > parsePrefix(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition: subnet.cc:803
Specialization of the Network object for DHCPv4 case.
Definition: network.h:1205
virtual bool clientSupported(const isc::dhcp::ClientClasses &client_classes) const
Checks whether this subnet and parent shared network supports the client that belongs to specified cl...
Definition: subnet.cc:712
void delPools(Lease::Type type)
Deletes all pools of specified type.
Definition: subnet.cc:510
void setValid(const isc::util::Triplet< uint32_t > &valid)
Sets new valid lifetime for a network.
Definition: network.h:385
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition: subnet.h:635
PoolCollection pools_ta_
collection of IPv6 temporary address pools in that subnet.
Definition: subnet.h:446
void setT2(const isc::util::Triplet< uint32_t > &t2)
Sets new rebind timer for a network.
Definition: network.h:415
boost::shared_ptr< Allocator > AllocatorPtr
Defines a pointer to an allocator.
Definition: allocator.h:209
PoolCollection pools_pd_
collection of IPv6 prefix pools in that subnet.
Definition: subnet.h:449
Container for storing client class names.
Definition: classify.h:108
virtual bool clientSupported(const isc::dhcp::ClientClasses &client_classes) const
Checks whether this subnet and parent shared network supports the client that belongs to specified cl...
Definition: subnet.cc:309
virtual data::ElementPtr toElement() const
Unparses network object.
Definition: network.cc:295
virtual std::string toText() const
Returns textual representation of the subnet (e.g.
Definition: subnet.cc:81
std::map< Lease::Type, SubnetAllocationStatePtr > allocation_states_
Holds subnet-specific allocation state.
Definition: subnet.h:464
Subnet6(const isc::asiolink::IOAddress &prefix, uint8_t length, const util::Triplet< uint32_t > &t1, const util::Triplet< uint32_t > &t2, const util::Triplet< uint32_t > &preferred_lifetime, const util::Triplet< uint32_t > &valid_lifetime, const SubnetID id=0)
Constructor with all parameters.
Definition: subnet.cc:616
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25