是否有按位和ipv6地址以及网络掩码(前缀)的代码?

问题描述 投票:9回答:6

我想问一下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可以做到这一点?还是应该使用数组?

c++ c networking ipv6
6个回答
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 );

将网络掩码应用于地址,这是我从inet_lnaof派生的。

inet_lnaof

1
投票

您可以使用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
投票

[好,我是用C而不是C ++做到的,但是应该可以。另外,它使用bswap_64,这是AFAIK的GNU扩展,因此可能无法在所有情况下使用。

在amd64上似乎非常快,并且比Yasar提出的当前解决方案要快:

inet_pton

0
投票

将IP设置为16个字节的数组,在下一个字节掩码中跳过#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; } 个字节,将较高的masked/8位设置为高,将其他的设置为masked%8

0

在此处编写代码,因此尚未经过测试,但我认为您可以使用类似的代码


0
投票

家伙,我解决了我的问题,下面的源代码使用它并继续进行编码:D:警告该函数假定IPv6地址有效。我的类型是:

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++;
}

0
投票
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;
}
© www.soinside.com 2019 - 2024. All rights reserved.