Skip to content

Commit 978ab54

Browse files
committed
[#1415] Added utility to find offset address
1 parent 639e0e6 commit 978ab54

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

src/lib/asiolink/addr_utilities.cc

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
1+
// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
22
//
33
// This Source Code Form is subject to the terms of the Mozilla Public
44
// 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) {
373373
}
374374
}
375375

376+
IOAddress offsetAddress(const IOAddress& addr, uint64_t offset) {
377+
// There is nothing to do if the offset is 0.
378+
if (offset == 0) {
379+
return (addr);
380+
}
381+
382+
// If this is IPv4 addrss we utilize the conversion to uint32_t.
383+
if (addr.isV4()) {
384+
return (IOAddress(addr.toUint32() + offset));
385+
}
386+
387+
// This is IPv6 address. Let's first convert the offset value to network
388+
// byte order and store within the vector.
389+
std::vector<uint8_t> offset_bytes(8);
390+
int offset_idx = 0;
391+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0xff00000000000000) >> 56);
392+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x00ff000000000000) >> 48);
393+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x0000ff0000000000) >> 40);
394+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x000000ff00000000) >> 32);
395+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x00000000ff000000) >> 24);
396+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x0000000000ff0000) >> 16);
397+
offset_bytes[offset_idx++] = static_cast<uint8_t>((offset & 0x000000000000ff00) >> 8);
398+
offset_bytes[offset_idx++] = static_cast<uint8_t>(offset & 0x00000000000000ff);
399+
400+
// Convert the IPv6 address to vector.
401+
auto addr_bytes = addr.toBytes();
402+
403+
// Sum up the bytes.
404+
405+
uint16_t carry = 0;
406+
for (int i = offset_bytes.size() - 1; (i >= 0) || (carry > 0); --i) {
407+
// Sum the bytes of the address, offset and the carry.
408+
uint16_t sum = static_cast<uint16_t>(addr_bytes[i+8]) + carry;
409+
410+
// Protect against the case when we went beyond the offset vector and
411+
// we have only carry to add.
412+
if (i >= 0 ) {
413+
sum += static_cast<uint16_t>(offset_bytes[i]);
414+
}
415+
416+
// Update the address byte.
417+
addr_bytes[i+8] = sum % 256;
418+
419+
// Calculate the carry value.
420+
carry = sum / 256;
421+
}
422+
423+
// Reconstruct IPv6 address from the vector.
424+
return (IOAddress::fromBytes(AF_INET6, &addr_bytes[0]));
425+
}
426+
427+
376428
};
377429
};

src/lib/asiolink/addr_utilities.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
1+
// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
22
//
33
// This Source Code Form is subject to the terms of the Mozilla Public
44
// 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);
7979
/// @param delegated_len length of the prefixes to be delegated from the pool
8080
/// @return number of prefixes in range
8181
uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len);
82+
83+
/// @brief Finds the address increased by offset.
84+
///
85+
/// Adds offset to the IPv4 or iPv6 address and finds the resulting address.
86+
/// Note that the current limitation is the maximum value of the offset,
87+
/// i.e. max uint64_t.
88+
///
89+
/// @param addr input address
90+
/// @param offset distance of the returned address from the input address.
91+
/// @return address being offset greater than the input address
92+
IOAddress offsetAddress(const IOAddress& addr, uint64_t offset);
93+
8294
};
8395
};
8496

src/lib/asiolink/tests/addr_utilities_unittest.cc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
1+
// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
22
//
33
// This Source Code Form is subject to the terms of the Mozilla Public
44
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -367,4 +367,18 @@ TEST(AddrUtilitiesTest, prefixesInRange) {
367367

368368
}
369369

370+
// Checks the function which finds an IPv4 address from input address and offset.
371+
TEST(AddrUtilitiesTest, offsetIPv4Address) {
372+
EXPECT_EQ("10.1.2.46", offsetAddress(IOAddress("10.1.1.45"), 257).toText());
373+
EXPECT_EQ("10.1.7.9", offsetAddress(IOAddress("10.1.1.45"), 1500).toText());
374+
}
375+
376+
// Checks the function which finds an IPv6 address from input address and offset.
377+
TEST(AddrUtilitiesTest, offsetIPv6Address) {
378+
EXPECT_EQ("2001:db8:1::4", offsetAddress(IOAddress("2001:db8:1::4"), 0).toText());
379+
EXPECT_EQ("2001:db8:1::10:3", offsetAddress(IOAddress("2001:db8:1::4"), 0xFFFFF).toText());
380+
EXPECT_EQ("2001:db8:2::", offsetAddress(IOAddress("2001:db8:1:FFFF::1"), 0xFFFFFFFFFFFFFFFF).toText());
381+
EXPECT_EQ("3000::1c", offsetAddress(IOAddress("3000::15"), 7).toText());
382+
}
383+
370384
}; // end of anonymous namespace

0 commit comments

Comments
 (0)