25const uint32_t bitMask4[] = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
26 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
27 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
28 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
29 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
30 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
31 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
32 0x0000000f, 0x00000007, 0x00000003, 0x00000001,
36const uint8_t bitMask6[]= { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
39const uint8_t revMask6[]= { 0xff, 0x7f, 0x3f, 0x1f, 0xf, 0x7, 0x3, 0x1 };
51 "Too large netmask. 0..128 is allowed in IPv6");
58 uint8_t packed[V6ADDRESS_LEN];
59 memcpy(packed, &prefix.toBytes()[0], V6ADDRESS_LEN);
68 uint8_t mask = bitMask6[len % 8];
71 packed[len / 8] = packed[len / 8] & mask;
75 len = (len / 8 + 1) * 8;
79 for (
int i = len / 8; i <
sizeof(packed); ++i) {
102 uint32_t addr = prefix.toUint32();
103 return (
IOAddress(addr & (~bitMask4[len])));
118 uint32_t addr = prefix.toUint32();
119 return (
IOAddress(addr | bitMask4[len]));
132 "Too large netmask. 0..128 is allowed in IPv6");
136 uint8_t packed[V6ADDRESS_LEN];
137 memcpy(packed, &prefix.toBytes()[0], 16);
145 uint8_t mask = bitMask6[len % 8];
151 packed[len / 8] = packed[len / 8] | ~mask;
155 len = (len / 8 + 1) * 8;
159 for (
int i = len / 8; i <
sizeof(packed); ++i) {
174 return (firstAddrInPrefix4(prefix, len));
177 return (firstAddrInPrefix6(prefix, len));
184 return (lastAddrInPrefix4(prefix, len));
187 return (lastAddrInPrefix6(prefix, len));
195 <<
static_cast<unsigned>(len) <<
", allowed range is 0..32");
197 uint32_t x = ~bitMask4[len];
204 if (min.getFamily() != max.getFamily()) {
217 uint64_t max_numeric =
static_cast<uint64_t
>(max.toUint32());
218 uint64_t min_numeric =
static_cast<uint64_t
>(min.toUint32());
223 return (max_numeric - min_numeric + 1);
239 static IOAddress max6(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
241 return (std::numeric_limits<uint64_t>::max());
250 const std::vector<uint8_t>& bin(count.
toBytes());
254 for (
int i = 0 ; i < 8; i++) {
256 return (std::numeric_limits<uint64_t>::max());
262 uint64_t numeric = 0;
263 for (
int i = 8; i < 16; i++) {
274 if (min.getFamily() != max.getFamily()) {
285 uint32_t max_numeric = max.toUint32();
286 uint32_t min_numeric = min.toUint32();
291 uint32_t xor_numeric = max_numeric ^ min_numeric;
292 if ((min_numeric & ~xor_numeric) != min_numeric) {
295 for (uint8_t prefix_len = 0; prefix_len <= 32; ++prefix_len) {
296 if (xor_numeric == bitMask4[prefix_len]) {
298 return (
static_cast<int>(prefix_len));
306 uint8_t min_packed[V6ADDRESS_LEN];
307 memcpy(min_packed, &min.toBytes()[0], 16);
308 uint8_t max_packed[V6ADDRESS_LEN];
309 memcpy(max_packed, &max.toBytes()[0], 16);
314 for (uint8_t i = 0; i < 16; ++i) {
315 uint8_t xor_byte = min_packed[i] ^ max_packed[i];
318 if ((min_packed[i] & ~xor_byte) != min_packed[i]) {
329 for (uint8_t j = 0; j < 8; ++j) {
330 if (xor_byte == revMask6[j]) {
332 candidate =
static_cast<int>((i * 8) + j);
335 if (candidate == 128) {
341 if (xor_byte == 0xff) {
353 if (delegated_len < pool_len) {
357 uint8_t
const count(delegated_len - pool_len);
362 return std::numeric_limits<uint128_t>::max();
376 auto addr_uint32 =
static_cast<uint64_t
>(addr.
toUint32());
379 if (
static_cast<uint64_t
>(std::numeric_limits<uint32_t>::max() - addr_uint32) < offset) {
380 return (
IOAddress(std::numeric_limits<uint32_t>::max()));
382 return (
IOAddress(
static_cast<uint32_t
>(addr_uint32 + offset)));
387 std::vector<uint8_t> offset_bytes(16);
388 for (
int offset_idx = offset_bytes.size() - 1; offset_idx >= 0; --offset_idx) {
389 offset_bytes[offset_idx] =
static_cast<uint8_t
>(offset & 0xff);
390 offset = offset >> 8;
394 auto addr_bytes = addr.
toBytes();
398 for (
int i = offset_bytes.size() - 1; (i >= 0); --i) {
400 uint16_t sum =
static_cast<uint16_t
>(addr_bytes[i]) + carry;
401 sum +=
static_cast<uint16_t
>(offset_bytes[i]);
404 addr_bytes[i] = sum % 256;
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
The IOAddress class represents an IP addresses (version agnostic)
static IOAddress subtract(const IOAddress &a, const IOAddress &b)
Subtracts one address from another (a - b)
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
bool isV4() const
Convenience function to check for an IPv4 address.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
static IOAddress increase(const IOAddress &addr)
Returns an address increased by one.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A wrapper interface for the ASIO library.
IOAddress firstAddrInPrefix(const IOAddress &prefix, uint8_t len)
This code is based on similar code from the Dibbler project.
uint128_t addrsInRange(const IOAddress &min, const IOAddress &max)
Returns number of available addresses in the specified range (min - max).
uint128_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len)
Returns number of available IPv6 prefixes in the specified prefix.
IOAddress lastAddrInPrefix(const IOAddress &prefix, uint8_t len)
returns a last address in a given prefix
IOAddress getNetmask4(uint8_t len)
Generates an IPv4 netmask of specified length.
IOAddress offsetAddress(const IOAddress &addr, uint128_t offset)
Finds the address increased by offset.
int prefixLengthFromRange(const IOAddress &min, const IOAddress &max)
Returns prefix length from the specified range (min - max).
boost::multiprecision::checked_uint128_t uint128_t
Defines the logger used by the top-level component of kea-lfc.