我将 IPv6 地址存储在std::pair<in6_addr, uint8_t>
. 那是网络和 CIDR 位的一对。
在检查白名单时,我只需迭代关联的网络,并进行 CIDR 匹配:
bool cidr6_match(const in6_addr &address, const in6_addr &network, uint8_t bits) {
#ifdef LINUX
const uint32_t *a = address.s6_addr32;
const uint32_t *n = network.s6_addr32;
#else
const uint32_t *a = address.__u6_addr.__u6_addr32;
const uint32_t *n = network.__u6_addr.__u6_addr32;
#endif
int bits_whole, bits_incomplete;
bits_whole = bits >> 5; // number of whole u32
bits_incomplete = bits & 0x1F; // number of bits in incomplete u32
if (bits_whole) {
if (memcmp(a, n, bits_whole << 2)) {
return false;
}
}
if (bits_incomplete) {
uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete));
if ((a[bits_whole] ^ n[bits_whole]) & mask) {
return false;
}
}
return true;
}
改编自 xfrm 的addr_match。
更多关于与 CIDR 匹配的信息:IP cidr 匹配功能
我很高兴听到其他人可以提出更多奇特的数据类型。对于我自己的用例,我有一堆左右的 IP 可以针对每个帐户进行验证,所以一个简单的列表对我来说就足够了。