2011-08-23 35 views
9

Tôi muốn hỏi về tính toán mạng ipv6 và phía máy chủ. Ví dụ: Tôi có địa chỉ IPv6 2001:470:1f15:1bcd:34::41 và tiền tố 96.có mã nào cho địa chỉ bitwise và ipv6 và mặt nạ mạng (tiền tố) không?

Bạn có biết cách dễ dàng để thực hiện bitwise and giữa địa chỉ IPv6 và tiền tố không?

Theo IPv4:

192.168.1.2 255.255.255.0 network : 192.168.1.0 

Vì vậy, đơn giản.

Tôi muốn làm điều tương tự với địa chỉ IPv6. Nhưng địa chỉ IPv6 là 16 byte, vì vậy bạn không thể sử dụng unsigned int cho điều đó.

Có API nào để làm điều này không? Hoặc tôi nên sử dụng mảng?

+1

Nếu bạn viết 255.255.255.0 như/24 sau đó các bit không quan trọng là gần như giống hệt nhau. – Flexo

+6

Lưu ý rằng bạn không nên sử dụng 'unsigned int' cho IPv4; bạn nên sử dụng 'uint32_t' (hoặc typedef của nó). –

Trả lời

1

guys tôi giải quyết vấn đề của tôi mã nguồn dưới sử dụng nó và đi về mật mã: D:. Cảnh báo chức năng đảm nhận địa chỉ IPv6 là hợp lệ, loại của tôi là:

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

Cần thụt lề! –

+0

ok.! tôi nghĩ rằng tốt hơn – iyasar

+0

Nhiều! : D Đẹp nhất. –

1

Bạn có thể chuyển đổi địa chỉ thành nhị phân theo thứ tự byte mạng với inet_pton. Sau đó thiết lập/xóa bit một byte tại một thời điểm.

0

Threat IP Lik một mảng 16 byte, bỏ qua masked/8 byte trong byte tiếp theo mặt nạ các masked%8 bit cao hơn, thiết lập những cái khác để 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++; 
} 

Wrote mã ngay tại đây, vì vậy nó hasn' t được thử nghiệm nhưng tôi nghĩ bạn có thể sử dụng giống như mặt nạ

2

Tính từ tiền tố chiều dài:

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); 

Áp dụng mặt nạ mạng để xử lý, tôi lấy được từ 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

Cảnh báo tham nhũng bộ nhớ! Gợi ý: Vòng lặp của bạn lặp đi lặp lại bao nhiêu lần nếu prefixLength là 3? – JdeBP

+0

@JdeBP Thử nghiệm trong bội số của 8 chỉ (tm) :-) –

1

OK , Tôi đã làm điều này trong C chứ không phải là C++, nhưng nó sẽ làm việc. Ngoài ra, nó sử dụng bswap_64 mà là AFAIK một phần mở rộng GNU vì vậy có thể không hoạt động trên tất cả mọi thứ.

Nó có vẻ là rất nhanh chóng trên amd64, và nhanh hơn so với giải pháp hiện tại Yasar đã đưa ra:

#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

Chỉ cần thử nó trên một virtualbox i686 và nó nhanh hơn đáng kể trên đó quá. – benofbrown

Các vấn đề liên quan