Kea  1.9.9-git
ip_range_permutation.cc
Go to the documentation of this file.
1 // Copyright (C) 2020 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>
10 
11 #include <iostream>
12 
13 using namespace isc::asiolink;
14 
15 namespace isc {
16 namespace dhcp {
17 
18 IPRangePermutation::IPRangePermutation(const AddressRange& range)
19  : range_start_(range.start_), step_(1), cursor_(addrsInRange(range_start_, range.end_) - 1),
20  state_(), done_(false), generator_() {
21  std::random_device rd;
22  generator_.seed(rd());
23 }
24 
26  : range_start_(range.start_), step_(static_cast<uint64_t>(1) << (128 - range.delegated_length_)),
27  cursor_(prefixesInRange(range.prefix_length_, range.delegated_length_) - 1),
28  state_(), done_(false), generator_() {
29 }
30 
33  // If we're done iterating over the pool let's return zero address and
34  // set the user supplied done flag to true.
35  if (done_) {
36  done = true;
37  return (range_start_.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() : IOAddress::IPV6_ZERO_ADDRESS());
38  }
39 
40  // If there is one address left, return this address.
41  if (cursor_ == 0) {
42  done = done_ = true;
43  return (state_.at(0));
44  }
45 
46  // We're not done.
47  done = false;
48 
49  // The cursor indicates where we're in the range starting from its end. The
50  // addresses between the cursor and the end of the range have been already
51  // returned by this function. Therefore we focus on the remaining cursor-1
52  // addresses. Let's get random address from this sub-range.
53  std::uniform_int_distribution<int> dist(0, cursor_ - 1);
54  auto next_loc = dist(generator_);
55 
56  IOAddress next_loc_address = IOAddress::IPV4_ZERO_ADDRESS();
57 
58  // Check whether this address exists in our map or not. If it exists
59  // it means it was swapped with some other address in previous calls to
60  // this function.
61  auto next_loc_existing = state_.find(next_loc);
62  if (next_loc_existing != state_.end()) {
63  // Address exists, so let's record it.
64  next_loc_address = next_loc_existing->second;
65  } else {
66  // Address does not exist on this position. We infer this address from
67  // its position by advancing the range start by position. For example,
68  // if the range is 192.0.2.1-192.0.2.10 and the picked random position is
69  // 5, the address we get is 192.0.2.6. This random address will be later
70  // returned to the caller.
71  next_loc_address = offsetAddress(range_start_, next_loc * step_);
72  }
73 
74  // Let's get the address at cursor position in the same way.
75  IOAddress cursor_address = IOAddress::IPV4_ZERO_ADDRESS();
76  auto cursor_existing = state_.find(cursor_);
77  if (cursor_existing != state_.end()) {
78  cursor_address = cursor_existing->second;
79  } else {
80  cursor_address = offsetAddress(range_start_, cursor_ * step_);
81  }
82 
83  // Now we swap them.... in fact we don't swap because as an optimization
84  // we don't record the addresses we returned by this function. We merely
85  // replace the address at random position with the address from cursor
86  // position. This address will be returned in the future if we get back
87  // to this position as a result of randomization.
88  if (next_loc_existing == state_.end()) {
89  state_.insert(std::make_pair(next_loc, cursor_address));
90  } else {
91  state_.at(next_loc) = cursor_address;
92  }
93  // Move the cursor one position backwards.
94  --cursor_;
95 
96  // Return the address from the random position.
97  return (next_loc_address);
98 }
99 
100 } // end of namespace isc::dhcp
101 } // end of namespace isc
Structure representing delegated prefix range.
Definition: ip_range.h:32
IPRangePermutation(const AddressRange &range)
Constructor for address ranges.
asiolink::IOAddress next(bool &done)
Returns next random address or prefix from the permutation.
Defines the logger used by the top-level component of kea-dhcp-ddns.
Structure representing IP address range.
Definition: ip_range.h:16