From: Marcin Siodelski Date: Fri, 11 Sep 2020 10:45:17 +0000 (+0200) Subject: [#1415] Added utility to find offset address X-Git-Tag: Kea-1.9.0~118 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=978ab5497d10e046cd3e7c0efc4e7f7348390092;p=thirdparty%2Fkea.git [#1415] Added utility to find offset address --- diff --git a/src/lib/asiolink/addr_utilities.cc b/src/lib/asiolink/addr_utilities.cc index f580782313..a23780c54d 100644 --- a/src/lib/asiolink/addr_utilities.cc +++ b/src/lib/asiolink/addr_utilities.cc @@ -1,4 +1,4 @@ -// 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 @@ -373,5 +373,57 @@ uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len) { } } +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 offset_bytes(8); + int offset_idx = 0; + offset_bytes[offset_idx++] = static_cast((offset & 0xff00000000000000) >> 56); + offset_bytes[offset_idx++] = static_cast((offset & 0x00ff000000000000) >> 48); + offset_bytes[offset_idx++] = static_cast((offset & 0x0000ff0000000000) >> 40); + offset_bytes[offset_idx++] = static_cast((offset & 0x000000ff00000000) >> 32); + offset_bytes[offset_idx++] = static_cast((offset & 0x00000000ff000000) >> 24); + offset_bytes[offset_idx++] = static_cast((offset & 0x0000000000ff0000) >> 16); + offset_bytes[offset_idx++] = static_cast((offset & 0x000000000000ff00) >> 8); + offset_bytes[offset_idx++] = static_cast(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(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(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])); +} + + }; }; diff --git a/src/lib/asiolink/addr_utilities.h b/src/lib/asiolink/addr_utilities.h index a461bd119a..3ad96a64c2 100644 --- a/src/lib/asiolink/addr_utilities.h +++ b/src/lib/asiolink/addr_utilities.h @@ -1,4 +1,4 @@ -// 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 @@ -79,6 +79,18 @@ int prefixLengthFromRange(const IOAddress& min, const IOAddress& max); /// @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); + }; }; diff --git a/src/lib/asiolink/tests/addr_utilities_unittest.cc b/src/lib/asiolink/tests/addr_utilities_unittest.cc index 4c6461fc83..b6121029d3 100644 --- a/src/lib/asiolink/tests/addr_utilities_unittest.cc +++ b/src/lib/asiolink/tests/addr_utilities_unittest.cc @@ -1,4 +1,4 @@ -// 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 @@ -367,4 +367,18 @@ TEST(AddrUtilitiesTest, prefixesInRange) { } +// 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