我想问一下ipv6网络和主机端的计算。
例如,我有IPv6地址2001:470:1f15:1bcd:34::41
和前缀96
。
您是否知道在IPv6地址和前缀之间执行按位and
的简单方法?
根据IPv4:
192.168.1.2 255.255.255.0 network : 192.168.1.0
这么简单。
我想对IPv6地址做同样的事情。但IPv6地址为16字节,因此您无法使用unsigned int
。
有没有API可以做到这一点?或者我应该使用数组吗?
答案 0 :(得分:2)
从前缀长度计算掩码:
struct sockaddr_in6 netmask;
for (long i = prefixLength, j = 0; i > 0; i -= 8, ++j)
netmask.sin6_addr.s6_addr[ j ] = i >= 8 ? 0xff
: (ULONG)(( 0xffU << ( 8 - i ) ) & 0xffU );
将netmask应用于地址,我是从inet_lnaof
派生的。
bool
inet6_lnaof (
struct in6_addr* restrict dst,
const struct in6_addr* restrict src,
const struct in6_addr* restrict netmask
)
{
bool has_lna = FALSE;
assert (NULL != dst);
assert (NULL != src);
assert (NULL != netmask);
for (unsigned i = 0; i < 16; i++) {
dst->s6_addr[i] = src->s6_addr[i] & netmask->s6_addr[i];
has_lna |= (0 != (src->s6_addr[i] & !netmask->s6_addr[i]));
}
return has_lna;
}
答案 1 :(得分:1)
您可以使用inet_pton以网络字节顺序将地址转换为二进制。然后一次设置/清除一个字节。
答案 2 :(得分:1)
typedef uint16_t ip6_addr[8];
void ipv6_app_mask(const char *ip6addr, unsigned int mask, ip6_addr ip6){
ip6_addr in_ip6;
inet_pton(PF_INET6, ip6addr, ip6);
for(int i = 0; i < 8; i++){
in_ip6[i] = ntohs(ip6[i]);
}
int index = (int) (mask / 16);
int remain_mask = mask % 16;
if(remain_mask == 0 && index == 8)
return;
switch(remain_mask){
case 0:in_ip6[index++] = 0; break;
case 1:in_ip6[index++]&=0x8000; break;
case 2:in_ip6[index++]&=0xc000; break;
case 3:in_ip6[index++]&=0xe000; break;
case 4:in_ip6[index++]&=0xf000; break;
case 5:in_ip6[index++]&=0xf800; break;
case 6:in_ip6[index++]&=0xfc00; break;
case 7:in_ip6[index++]&=0xfe00; break;
case 8:in_ip6[index++]&=0xff00; break;
case 9:in_ip6[index++]&=0xff80; break;
case 10:in_ip6[index++]&=0xffc0; break;
case 11:in_ip6[index++]&=0xffe0; break;
case 12:in_ip6[index++]&=0xfff0; break;
case 13:in_ip6[index++]&=0xfff8; break;
case 14:in_ip6[index++]&=0xfffc; break;
case 15:in_ip6[index++]&=0xfffe; break;
}
for (int i = index; i < 8; i++){
in_ip6[i] = 0;
}
for(int i = 0; i < 8; i++){
ip6[i] = htons(in_ip6[i]);
}
return;
}
答案 3 :(得分:1)
好吧,我是用C而不是C ++做的,但它应该有效。此外,它使用bswap_64,它是AFAIK的GNU扩展,因此可能不适用于所有内容。
amd64似乎非常快,并且比Yasar提出的当前解决方案更快:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>
#if defined __GNUC__ && __GNUC__ >= 2
#include <byteswap.h>
#else
#error "Sorry, you need GNU for this"
#endif
struct split
{
uint64_t start;
uint64_t end;
};
void ipv6_prefix (unsigned char *masked, unsigned char *packed, int prefix)
{
struct split parts;
uint64_t mask = 0;
unsigned char *p = masked;
memset(masked, 0, sizeof(struct in6_addr));
memcpy(&parts, packed, sizeof(parts));
if (prefix <= 64)
{
mask = bswap_64(bswap_64(parts.start) & ((uint64_t) (~0) << (64 - prefix)));
memcpy(masked, &mask, sizeof(uint64_t));
return;
}
prefix -= 64;
memcpy(masked, &(parts.start), sizeof(uint64_t));
p += sizeof(uint64_t);
mask = bswap_64(bswap_64(parts.end) & (uint64_t) (~0) << (64 - prefix));
memcpy(p, &mask, sizeof(uint64_t));
}
int main (int argc, char **argv)
{
unsigned char packed[sizeof(struct in6_addr)];
unsigned char masked[sizeof(struct in6_addr)];
char buf[INET6_ADDRSTRLEN], *p;
int prefix = 56;
if (argc < 2)
return 1;
if ((p = strchr(argv[1], '/')))
{
*p++ = '\0';
prefix = atoi(p);
}
inet_pton(AF_INET6, argv[1], packed);
ipv6_prefix(masked, packed, prefix);
inet_ntop(AF_INET6, masked, buf, INET6_ADDRSTRLEN);
printf("prefix = %s/%d\n", buf, prefix);
return 0;
}
答案 4 :(得分:0)
威胁IP一个16字节的数组,跳过下一个字节掩码中的masked/8
字节更高的masked%8
位,将其他字节设置为0
int offset=masked/8;
char remmask=0;
int rem = masked%8;
while(rem)
{
rem--;
remmask|= 0x80>>rem; //0x80 is the highest bit in a byte set
}
offset++;
(((char*)ipv6)+offset) &= remmask;
while(offset<16)
{
(((char*)ipv6)+offset=0;
offset++;
}
在这里编写代码,所以它还没有经过测试,但我想你可以使用这样的东西
答案 5 :(得分:0)
这是一个简单的计时器:
bool timer_check()
{
static int count = 0;
time_t seconds1;
if(val)
{
time(&seconds);
val = false;
printf("In the first if loop\n");
}
time(&seconds1);
if( (seconds1 - seconds) <= 10 && count < 10 )
{
count ++;
}
if ((seconds1 - seconds) >= 10)
{
count = 0;
seconds = seconds1;
}
if (count < 10)
return true;
return false;
}