2010-09-16 17 views
9

Estoy usando getifaddrs() y inet_ntop() para obtener las direcciones IP en el sistema. Cuando el sistema está configurado en IPv6, la dirección devuelta se encuentra en la versión abreviada (utilizando :: para ceros). ¿Hay alguna forma de expandir esa dirección a una completa?expandir una dirección IPv6 para que pueda imprimirlo en stdout

Este es el código que estoy utilizando:

struct ifaddrs *myaddrs, *ifa; 
void *in_addr; 
char buf[64]; 

if(getifaddrs(&myaddrs) != 0) 
{ 
    perror("getifaddrs"); 
    exit(1); 
} 

for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) 
{ 
    if (ifa->ifa_addr == NULL) 
     continue; 
    if (!(ifa->ifa_flags & IFF_UP)) 
     continue; 

    switch (ifa->ifa_addr->sa_family) 
    { 
     case AF_INET: 
     { 
      struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr; 
      in_addr = &s4->sin_addr; 
      break; 
     } 

     case AF_INET6: 
     { 
      struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr; 
      in_addr = &s6->sin6_addr; 
      break; 
     } 

     default: 
      continue; 
    } 

    if (!inet_ntop(ifa->ifa_addr->sa_family, in_addr, buf, sizeof(buf))) 
    { 
     printf("%s: inet_ntop failed!\n", ifa->ifa_name); 
    } 
    else 
    { 
     printf("IP address: %s\n", buf); 
    } 
} 

freeifaddrs(myaddrs); 

Código es muy apreciada.

EDIT:
Dado que este es aparentemente muy difícil de comprender le daré un ejemplo:

Si consigo ABCD: 12 :: 3 necesito para expandirlo a ABCD: 0012: 0000: 0000: 0000: 0000: 0000: 0003
¿El motivo? porque es parte de los requisitos. Simple como eso.

+1

la versión abreviada es una dirección IPv6 válida - ¿por qué querrías para expandirlo? – Femaref

+0

porque necesito almacenarlo en su totalidad en nuestra base de datos. ese es el requisito – Jessica

+1

@Jessica: Lo está almacenando como un entero de 128 bits, ¿correcto? Debido a que almacenarlo como una representación textual es un poco inútil, existen direcciones IPv6 que se pueden representar de muchas maneras, precisamente debido a la sintaxis '::' acortada. – Piskvor

Respuesta

11
void ipv6_to_str_unexpanded(char * str, const struct in6_addr * addr) { 
    sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
       (int)addr->s6_addr[0], (int)addr->s6_addr[1], 
       (int)addr->s6_addr[2], (int)addr->s6_addr[3], 
       (int)addr->s6_addr[4], (int)addr->s6_addr[5], 
       (int)addr->s6_addr[6], (int)addr->s6_addr[7], 
       (int)addr->s6_addr[8], (int)addr->s6_addr[9], 
       (int)addr->s6_addr[10], (int)addr->s6_addr[11], 
       (int)addr->s6_addr[12], (int)addr->s6_addr[13], 
       (int)addr->s6_addr[14], (int)addr->s6_addr[15]); 
} 
+2

fantástico. el primer% 02x% 02: debe ser% 02x% 02x: por cierto – Jessica

+0

@Jessica: fijo – nategoose

0
  #include<stdio.h> 
      #include <netinet/in.h> 
      #include <arpa/inet.h> 

      struct in6_addrr 
      { 
       unsigned char addr[16]; 
      }; 

      void ipv6_expander(const struct in6_addr * addr) 
      { 
       char str[40]; 
       sprintf(str,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", 
       (int)addr->s6_addr[0], (int)addr->s6_addr[1], 
       (int)addr->s6_addr[2], (int)addr->s6_addr[3], 
       (int)addr->s6_addr[4], (int)addr->s6_addr[5], 
       (int)addr->s6_addr[6], (int)addr->s6_addr[7], 
       (int)addr->s6_addr[8], (int)addr->s6_addr[9], 
       (int)addr->s6_addr[10], (int)addr->s6_addr[11], 
       (int)addr->s6_addr[12], (int)addr->s6_addr[13], 
       (int)addr->s6_addr[14], (int)addr->s6_addr[15]); 
       printf("\nExpanded ipv6 Addr %s\n",str); 
      } 

      int main(int argc,char *argv[]) 
      { 
       struct in6_addrr ipv6; 
       printf("\nGiven IPv6 Addr %s\n",argv[1]); 
       if(inet_pton(AF_INET6,argv[1],&ipv6.addr)) 
       { 
        ipv6_expander(&ipv6.addr); 
       } 
       else 
       { 
        printf("\n error\n"); 
       } 
       return; 
      } 
+0

Utilice este código. Esto expandirá la dirección IPv6 –

Cuestiones relacionadas