2011-08-23 7 views
9

मैं आईपीवी 6 नेटवर्क और मेजबान पक्ष की गणना के बारे में पूछना चाहता हूं।क्या bitwise और ipv6 पता और नेटवर्क मास्क (उपसर्ग) के लिए कोई कोड है?

उदाहरण के लिए, मेरे पास आईपीवी 6 पता 2001:470:1f15:1bcd:34::41 और उपसर्ग 96 है।

क्या आप आईपीवी 6 पता और उपसर्ग के बीच bitwise and करने का एक आसान तरीका जानते हैं?

आईपीवी 4 के अनुसार:

192.168.1.2 255.255.255.0 network : 192.168.1.0 

तो सरल।

मैं आईपीवी 6 पते पर एक ही काम करना चाहता हूं। लेकिन आईपीवी 6 पता 16 बाइट्स है, इसलिए आप इसके लिए unsigned int का उपयोग नहीं कर सकते हैं।

क्या ऐसा करने के लिए कोई एपीआई है? या मुझे सरणी का उपयोग करना चाहिए?

+1

आप के रूप में/24 255.255.255.0 बारे में तो थोड़ा नगण्य लगभग समान है। – Flexo

+6

ध्यान दें कि आपको आईपीवी 4 के लिए 'हस्ताक्षरित int' का उपयोग नहीं करना चाहिए; आपको 'uint32_t' (या इसका टाइपिफ़) का उपयोग करना चाहिए। –

उत्तर

1

लोग मैं मेरी समस्या हल स्रोत कोड के नीचे है इसका इस्तेमाल और पर कोडिंग जाना: डी:। चेतावनी समारोह मान 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

ठीक है! मुझे लगता है कि बेहतर – iyasar

+0

बहुत कुछ! : डी अच्छा है। –

1

आप inet_pton के साथ नेटवर्क बाइट ऑर्डर में बाइनरी में पता बदल सकते हैं। फिर एक समय में एक बाइट बिट्स सेट/साफ़ करें।

0

खतरा आईपी एक 16 बाइट्स सरणी lik, अगले बाइट में 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 टी परीक्षण किया गया लेकिन मैं आपको उपसर्ग लंबाई से इस

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 से लिया है।

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

स्मृति भ्रष्टाचार चेतावनी! संकेत: उपसर्ग लम्बाई है, कहें, 3, आपके लूप को कितनी बार फिर से चालू करता है? – JdeBP

+0

@JdeBP 8 के गुणकों में परीक्षण किया गया (टीएम) :-) –

1

ठीक , मैंने सी ++ की बजाय सी में यह किया, लेकिन इसे काम करना चाहिए। साथ ही, यह bswap_64 का उपयोग करता है जो AFAIK एक जीएनयू एक्सटेंशन है, इसलिए सब कुछ पर काम नहीं कर सकता है।

यह 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

संबंधित मुद्दे