我需要在in_addr / in6_addr结构中存储IP地址/网络掩码。 对于IPv4,我使用以下代码来测试网络掩码是否连续:
((((~netmask + 1) & (~netmask)) != 0) && (netmask != 0))
我想知道是否有一种聪明的方法可以为IPv6做同样的事情。
答案 0 :(得分:1)
有些编译器有128位整数。我在代码中使用了__uint128_t,这是在AMD64架构上使用gcc编译的。
如果您使用的是128位整数的编译器,则可以简单地重用现有代码,因为它不会对字大小做出任何假设。
如果你需要用较小的字大小进行计算,它自然会变得更复杂,但并不多。首先运行一个指针,通过掩码的字来找到第一个带有零位的字(例如):
for (i = 0; i < 4 && netmask[i] != 0xffffffff; ++i)
接下来,您可以将原始测试应用于netmask[i]
,最后您需要测试任何剩余的单词是否为零。
另一种方法是将原始测试应用于每个单词,并测试每对单词的第一个是全部的,或者第二个是全零:
int contiguous(uint32_t **netmask)
{
int i;
for (i = 0; i < 4; ++i) {
if ((~netmask[i] + 1) & (~netmask[i])) return 0;
}
for (i = 0; i < 3; ++i) {
if ((netmask[i] != 0xffffffff) && (netmask[i+1] != 0)) return 0;
}
return 1;
}
您也可以采用更常见的方法,不要将掩码作为输入,而是将前缀长度指定为0到128范围内的整数作为输入。然后你可以自己构造位掩码并知道它是连续的。
答案 1 :(得分:1)
我遇到了以下解决方案:
将IPV6字节拆分为四个32位的块,并按以下方式创建三个部分:
uint64_t netmask1, netmask2, netmask3;
netmask1 = (netmask.s6_addr32[0] << 32) + in6_netmask.s6_addr32[1];
netmask2 = (netmask.s6_addr32[1] << 32) + in6_netmask.s6_addr32[2];
netmask3 = (netmask.s6_addr32[2] << 32) + in6_netmask.s6_addr32[3];
如果其中一个部分不连续,则网络掩码不是连续的。
if ((((~address1 + 1) & (~address1)) != 0) ||
(((~address2 + 1) & (~address2)) != 0) ||
((~address3 + 1) & (~address3)) != 0))) {
// Netmask is not valid!
}