|
1 | | -// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC") |
| 1 | +// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") |
2 | 2 | // |
3 | 3 | // This Source Code Form is subject to the terms of the Mozilla Public |
4 | 4 | // 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) { |
373 | 373 | } |
374 | 374 | } |
375 | 375 |
|
| 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 | + |
376 | 428 | }; |
377 | 429 | }; |
0 commit comments