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