2011-08-23 11 views
9

Deseo preguntar sobre el cálculo de la red ipv6 y del lado del host.¿hay algún código para la dirección bitwise e ipv6 y la máscara de red (prefijo)?

Por ejemplo, tengo la dirección IPv6 2001:470:1f15:1bcd:34::41 y el prefijo 96.

¿Conoces una manera fácil de hacer bitwise and entre la dirección IPv6 y el prefijo?

De acuerdo con IPv4:

192.168.1.2 255.255.255.0 network : 192.168.1.0 

tan simple.

Quiero hacer lo mismo con la dirección IPv6. Pero la dirección IPv6 es de 16 bytes, por lo que no puede usar unsigned int para eso.

¿Hay alguna API para hacer esto? ¿O debería usar matrices?

+1

Si se escribe como 255.255.255.0/24 entonces el trasteo de bits es casi idéntica. – Flexo

+6

Tenga en cuenta que tampoco debe usar 'unsigned int' para IPv4; deberías estar usando 'uint32_t' (o un typedef de él). –

Respuesta

1

i chicos resuelven mi problema el código fuente está por debajo de utilizarlo e ir en la codificación: D:. Warning la función asume la dirección IPv6 es válida, mi tipo es:

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

¡Necesita sangría! –

+0

ok.! pienso mejor – iyasar

+0

¡Mucho! : D Niza. –

1

Puede convertir la dirección a binario en orden de bytes de red con inet_pton. Luego configure/borre los bits un byte a la vez.

0

amenaza la IP lik una matriz de 16 bytes, no tome la masked/8 bytes en el siguiente byte enmascarar los más altos masked%8 los bits, establezca los otros a 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++; 
} 

escribió el código aquí, por lo que hasn' t sido probado pero estoy pensando que podría utilizar algo como esto

2

Calcular máscara de longitud de prefijo:

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

Aplicar máscara de red a la dirección, esto se deriva de 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

¡Alerta de corrupción de memoria! Sugerencia: ¿Cuántas veces itera su ciclo si prefixLength es, por ejemplo, 3? – JdeBP

+0

@JdeBP Probado en múltiplos de 8 solamente (tm) :-) –

1

OK , Hice esto en C en lugar de C++, pero debería funcionar. Además, usa bswap_64, que es AFAIK una extensión de GNU, por lo que puede no funcionar en todo.

Parece que ser muy rápido en AMD64, y más rápido que la solución actual Yasar ha llegado con:

#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

Acabo de probarlo en una i686 virtualbox y es mucho más rápido en eso también. – benofbrown

Cuestiones relacionadas