2011-08-23 8 views
9

ipv6ネットワークとホスト側の計算について質問したいと思います。bitwiseと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はありますか?または配列を使用する必要がありますか?

+1

あなたは/ 24として255.255.255.0を記述する場合、ビットいじるがほぼ同じです。 – Flexo

+6

IPv4にも 'unsigned int'を使うべきではないことに注意してください。あなたは 'uint32_t'(またはそれのtypedef)を使用するべきです。 –

答えて

1

みんなiは、ソースコードは、それを使用してコーディングに行く以下である私の問題を解決しました。機能は、IPv6アドレスが有効であると仮定警告、 私のタイプは次のとおりです。

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

インデントが必要です! –

+0

ok!私は良いと思う – iyasar

+0

多く! :D良い1つ。 –

1

inet_ptonを使用して、アドレスをネットワークバイトオーダーでバイナリに変換できます。次に、ビットを1バイトずつセット/クリアします。 「

0

16のバイトアレイLIK脅威IPを、次のバイトに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++; 
} 

に他のものを設定するには、右ここでコードを書いたので、それはhasn tはテストされていますが、私はあなたがプレフィックス長からこの

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から導き出されました。 D:

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

メモリ破損アラート!ヒント:prefixLengthが3の場合、ループは何回繰り返されますか? – JdeBP

+0

@JdeBP 8の倍数(tm)でテストされました:-) –

1

OK私はC++ではなくC言語でこれを行いましたが、うまくいくはずです。また、GNU拡張のAFAIKであるbswap_64を使用しているため、すべてで動作しない可能性があります。

非常に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; 
} 
+0

ちょうどi686バーチャルボックスで試してみましたが、これもかなり速いです。 – benofbrown

関連する問題