2019-06-15 14:20:32 +00:00
|
|
|
#include "IPv6ToBinary.h"
|
|
|
|
#include <Poco/Net/IPAddress.h>
|
2020-11-08 16:01:12 +00:00
|
|
|
#include <Poco/ByteOrder.h>
|
|
|
|
|
2020-11-29 17:54:46 +00:00
|
|
|
#include <Common/formatIPv6.h>
|
|
|
|
|
2019-06-19 17:31:46 +00:00
|
|
|
#include <cstring>
|
2019-06-15 14:20:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2020-12-01 19:12:11 +00:00
|
|
|
/// Result array could be indexed with all possible uint8 values without extra check.
|
|
|
|
/// For values greater than 128 we will store same value as for 128 (all bits set).
|
2020-11-29 17:54:46 +00:00
|
|
|
constexpr size_t IPV6_MASKS_COUNT = 256;
|
|
|
|
|
|
|
|
using RawMaskArray = std::array<uint8_t, IPV6_BINARY_LENGTH>;
|
|
|
|
|
2020-11-21 14:56:58 +00:00
|
|
|
void IPv6ToRawBinary(const Poco::Net::IPAddress & address, char * res)
|
2019-06-15 14:20:32 +00:00
|
|
|
{
|
|
|
|
if (Poco::Net::IPAddress::IPv6 == address.family())
|
|
|
|
{
|
2020-11-21 14:56:58 +00:00
|
|
|
memcpy(res, address.addr(), 16);
|
2019-06-15 14:20:32 +00:00
|
|
|
}
|
|
|
|
else if (Poco::Net::IPAddress::IPv4 == address.family())
|
|
|
|
{
|
|
|
|
/// Convert to IPv6-mapped address.
|
2020-11-21 14:56:58 +00:00
|
|
|
memset(res, 0, 10);
|
2019-06-15 14:20:32 +00:00
|
|
|
res[10] = '\xFF';
|
|
|
|
res[11] = '\xFF';
|
|
|
|
memcpy(&res[12], address.addr(), 4);
|
|
|
|
}
|
|
|
|
else
|
2020-11-21 14:56:58 +00:00
|
|
|
memset(res, 0, 16);
|
|
|
|
}
|
2019-06-15 14:20:32 +00:00
|
|
|
|
2020-11-21 14:56:58 +00:00
|
|
|
std::array<char, 16> IPv6ToBinary(const Poco::Net::IPAddress & address)
|
|
|
|
{
|
|
|
|
std::array<char, 16> res;
|
|
|
|
IPv6ToRawBinary(address, res.data());
|
2019-06-15 14:20:32 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-12-01 17:38:49 +00:00
|
|
|
static constexpr RawMaskArray generateBitMask(size_t prefix)
|
|
|
|
{
|
2020-11-29 17:54:46 +00:00
|
|
|
if (prefix >= 128)
|
|
|
|
prefix = 128;
|
|
|
|
RawMaskArray arr{0};
|
|
|
|
size_t i = 0;
|
|
|
|
for (; prefix >= 8; ++i, prefix -= 8)
|
|
|
|
arr[i] = 0xff;
|
|
|
|
if (prefix > 0)
|
|
|
|
arr[i++] = ~(0xff >> prefix);
|
|
|
|
while (i < 16)
|
|
|
|
arr[i++] = 0x00;
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
2020-12-01 17:38:49 +00:00
|
|
|
static constexpr std::array<RawMaskArray, IPV6_MASKS_COUNT> generateBitMasks()
|
|
|
|
{
|
2020-11-29 17:54:46 +00:00
|
|
|
std::array<RawMaskArray, IPV6_MASKS_COUNT> arr{};
|
|
|
|
for (size_t i = 0; i < IPV6_MASKS_COUNT; ++i)
|
|
|
|
arr[i] = generateBitMask(i);
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t * getCIDRMaskIPv6(UInt8 prefix_len)
|
|
|
|
{
|
|
|
|
static constexpr std::array<RawMaskArray, IPV6_MASKS_COUNT> IPV6_RAW_MASK_ARRAY = generateBitMasks();
|
|
|
|
return IPV6_RAW_MASK_ARRAY[prefix_len].data();
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:20:32 +00:00
|
|
|
}
|