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