]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1415] Added utility to find offset address
authorMarcin Siodelski <marcin@isc.org>
Fri, 11 Sep 2020 10:45:17 +0000 (12:45 +0200)
committerMarcin Siodelski <marcin@isc.org>
Wed, 16 Sep 2020 14:39:12 +0000 (14:39 +0000)
src/lib/asiolink/addr_utilities.cc
src/lib/asiolink/addr_utilities.h
src/lib/asiolink/tests/addr_utilities_unittest.cc

index f580782313cb331e6214865131938e23024c6c56..a23780c54df04548be3782b0553703c07a80fbbb 100644 (file)
@@ -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<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]));
+}
+
+
 };
 };
index a461bd119acdbc210fcbdb4576127d9cbcccf444..3ad96a64c26bd30fe60a1337d71d7dccf9caa3bf 100644 (file)
@@ -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);
+
 };
 };
 
index 4c6461fc8352a1096a9db70aa1203d02552d5a9c..b6121029d3fdfb03a79f0d659a197b84b45be05f 100644 (file)
@@ -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