From: Marcin Siodelski Date: Wed, 16 Sep 2020 10:26:34 +0000 (+0200) Subject: [#1415] Improved offsetAddres X-Git-Tag: Kea-1.9.0~109 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5cfc8f929a34ebb0dc752c896101ffa85a71c2df;p=thirdparty%2Fkea.git [#1415] Improved offsetAddres According to the review comments, the conversion of the offset to a vector was simplified. In addition, when the offset address exceeds the maximum value for IPv4 address the max value is returned. --- diff --git a/src/lib/asiolink/addr_utilities.cc b/src/lib/asiolink/addr_utilities.cc index a23780c54d..b31e3ea8d2 100644 --- a/src/lib/asiolink/addr_utilities.cc +++ b/src/lib/asiolink/addr_utilities.cc @@ -381,21 +381,23 @@ IOAddress offsetAddress(const IOAddress& addr, uint64_t offset) { // If this is IPv4 addrss we utilize the conversion to uint32_t. if (addr.isV4()) { - return (IOAddress(addr.toUint32() + offset)); + auto addr_uint32 = static_cast(addr.toUint32()); + // If the result would exceed the maximum possible IPv4 address, let's return + // the maximum IPv4 address. + if (static_cast(std::numeric_limits::max() - addr_uint32) < offset) { + return (IOAddress(std::numeric_limits::max())); + } + return (IOAddress(static_cast(addr_uint32 + 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); + for (int offset_idx = offset_bytes.size() - 1; offset_idx >= 0; --offset_idx) { + offset_bytes[offset_idx] = static_cast(offset & 0x00000000000000ff); + offset = offset >> 8; + } // Convert the IPv6 address to vector. auto addr_bytes = addr.toBytes(); diff --git a/src/lib/asiolink/addr_utilities.h b/src/lib/asiolink/addr_utilities.h index 3ad96a64c2..bd78deec4c 100644 --- a/src/lib/asiolink/addr_utilities.h +++ b/src/lib/asiolink/addr_utilities.h @@ -84,7 +84,8 @@ uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len); /// /// 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. +/// i.e. max uint64_t. If the sum of the IPv4 address and the offset exceeds +/// the maximum value of uint32_t type, the 255.255.255.255 is returned. /// /// @param addr input address /// @param offset distance of the returned address from the input address. diff --git a/src/lib/asiolink/tests/addr_utilities_unittest.cc b/src/lib/asiolink/tests/addr_utilities_unittest.cc index b6121029d3..69aca84f2c 100644 --- a/src/lib/asiolink/tests/addr_utilities_unittest.cc +++ b/src/lib/asiolink/tests/addr_utilities_unittest.cc @@ -371,6 +371,8 @@ TEST(AddrUtilitiesTest, prefixesInRange) { 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()); + // Using very large offset. The maximum IPv4 address should be returned. + EXPECT_EQ("255.255.255.255", offsetAddress(IOAddress("255.255.254.254"), 0xFFFFFFFFFFFFFFFA).toText()); } // Checks the function which finds an IPv6 address from input address and offset.