2011-08-23 10 views
9

Voglio chiedere informazioni sul calcolo della rete IPv6 e del lato host.esiste un codice per indirizzo bitwise e ipv6 e maschera di rete (prefisso)?

Ad esempio, ho l'indirizzo IPv6 2001:470:1f15:1bcd:34::41 e il prefisso 96.

Conoscete un modo semplice per eseguire il bit a bit and tra indirizzo IPv6 e prefisso?

Secondo IPv4:

192.168.1.2 255.255.255.0 network : 192.168.1.0 

così semplice.

Voglio fare la stessa cosa per l'indirizzo IPv6. Ma l'indirizzo IPv6 è di 16 byte, quindi non è possibile utilizzare unsigned int per quello.

C'è qualche API per fare questo? O dovrei usare gli array?

+1

Se si scrive 255.255.255.0 come/24 allora la giocherellare bit è quasi identico. – Flexo

+6

Nota che non dovresti usare anche 'unsigned int' per IPv4; dovresti usare 'uint32_t' (o un typedef di esso). –

risposta

1

ragazzi ho risolto il mio problema il codice sorgente è inferiore a usarlo e andare sulla codifica: D:. Attenzione la funzione di assumere l'indirizzo IPv6 è valido, il mio tipo è:

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

Rientro necessario! –

+0

ok.! penso meglio – iyasar

+0

Molto! : D Bella. –

1

È possibile convertire l'indirizzo in binario nell'ordine dei byte di rete con inet_pton. Quindi imposta/cancella i bit un byte alla volta.

0

minacce PI lik una matrice di 16 byte, saltare i masked/8 byte nel byte successivo mascherare i masked%8 bit superiori, impostare gli altri per 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++; 
} 

giallo il codice proprio qui, così hasn' t stato testato, ma sto pensando si potrebbe usare qualcosa di simile

2

Calcolare maschera dal prefisso di lunghezza:

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

Applicare la maschera di rete all'indirizzo, l'ho derivato da 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

Avviso di corruzione della memoria! Suggerimento: quante volte il ciclo si itera se prefissoLength è, per esempio, 3? – JdeBP

+0

@JdeBP Testato in multipli di 8 solo (tm) :-) –

1

OK , L'ho fatto in C piuttosto che in C++, ma dovrebbe funzionare. Inoltre, usa bswap_64, che è AFAIK un'estensione GNU, quindi potrebbe non funzionare su tutto.

Sembra di essere molto veloce su amd64, e più veloce rispetto alla soluzione attuale Yasar ha messo a punto:

#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

L'ho appena provato su una virtual box i686 ed è anche molto più veloce. – benofbrown

Problemi correlati