-// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
}
}
+IOAddress offsetAddress(const IOAddress& addr, uint64_t offset) {
+ // There is nothing to do if the offset is 0.
+ if (offset == 0) {
+ return (addr);
+ }
+
+ // If this is IPv4 addrss we utilize the conversion to uint32_t.
+ if (addr.isV4()) {
+ return (IOAddress(addr.toUint32() + offset));
+ }
+
+ // This is IPv6 address. Let's first convert the offset value to network
+ // byte order and store within the vector.
+ std::vector<uint8_t> offset_bytes(8);
+ int offset_idx = 0;
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0xff00000000000000) >> 56);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x00ff000000000000) >> 48);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x0000ff0000000000) >> 40);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x000000ff00000000) >> 32);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x00000000ff000000) >> 24);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x0000000000ff0000) >> 16);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x000000000000ff00) >> 8);
+ offset_bytes[offset_idx++] = static_cast<uint8_t>(offset & 0x00000000000000ff);
+
+ // Convert the IPv6 address to vector.
+ auto addr_bytes = addr.toBytes();
+
+ // Sum up the bytes.
+
+ uint16_t carry = 0;
+ for (int i = offset_bytes.size() - 1; (i >= 0) || (carry > 0); --i) {
+ // Sum the bytes of the address, offset and the carry.
+ uint16_t sum = static_cast<uint16_t>(addr_bytes[i+8]) + carry;
+
+ // Protect against the case when we went beyond the offset vector and
+ // we have only carry to add.
+ if (i >= 0 ) {
+ sum += static_cast<uint16_t>(offset_bytes[i]);
+ }
+
+ // Update the address byte.
+ addr_bytes[i+8] = sum % 256;
+
+ // Calculate the carry value.
+ carry = sum / 256;
+ }
+
+ // Reconstruct IPv6 address from the vector.
+ return (IOAddress::fromBytes(AF_INET6, &addr_bytes[0]));
+}
+
+
};
};
-// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// @param delegated_len length of the prefixes to be delegated from the pool
/// @return number of prefixes in range
uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len);
+
+/// @brief Finds the address increased by offset.
+///
+/// Adds offset to the IPv4 or iPv6 address and finds the resulting address.
+/// Note that the current limitation is the maximum value of the offset,
+/// i.e. max uint64_t.
+///
+/// @param addr input address
+/// @param offset distance of the returned address from the input address.
+/// @return address being offset greater than the input address
+IOAddress offsetAddress(const IOAddress& addr, uint64_t offset);
+
};
};
-// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
}
+// Checks the function which finds an IPv4 address from input address and offset.
+TEST(AddrUtilitiesTest, offsetIPv4Address) {
+ EXPECT_EQ("10.1.2.46", offsetAddress(IOAddress("10.1.1.45"), 257).toText());
+ EXPECT_EQ("10.1.7.9", offsetAddress(IOAddress("10.1.1.45"), 1500).toText());
+}
+
+// Checks the function which finds an IPv6 address from input address and offset.
+TEST(AddrUtilitiesTest, offsetIPv6Address) {
+ EXPECT_EQ("2001:db8:1::4", offsetAddress(IOAddress("2001:db8:1::4"), 0).toText());
+ EXPECT_EQ("2001:db8:1::10:3", offsetAddress(IOAddress("2001:db8:1::4"), 0xFFFFF).toText());
+ EXPECT_EQ("2001:db8:2::", offsetAddress(IOAddress("2001:db8:1:FFFF::1"), 0xFFFFFFFFFFFFFFFF).toText());
+ EXPECT_EQ("3000::1c", offsetAddress(IOAddress("3000::15"), 7).toText());
+}
+
}; // end of anonymous namespace