2010-09-16 3 views
9

Я использую getifaddrs() и inet_ntop(), чтобы получить IP-адреса в системе. Когда система настроена на IPv6, возвращаемый адрес находится в сокращенной версии (используя :: для нулей). Есть ли способ расширить этот адрес до полного?развернуть адрес IPv6, чтобы я мог его распечатать на stdout

Это код, я использую:

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

код очень ценится.

EDIT:
Так как это, по-видимому очень трудно понять, я дам вам пример:

Если я получаю ABCD: 12 :: 3 Мне нужно, чтобы развернуть его на ABCD: 0012: 0000: 0000: 0000: 0000: 0000: 0003
Причина? потому что это часть требований. Просто как тот.

+1

сокращенный вариант является действительным ipv6 адрес - так почему вы хотите, чтобы развернуть его? – Femaref

+0

, потому что мне нужно его полностью сохранить в нашей базе данных. это требование. – Jessica

+1

@Jessica: Вы храните его как 128-битное целое, правильно? Поскольку сохранение его в виде текстового представления несколько бессмысленно - есть IPv6-адреса, которые могут быть представлены многими способами именно из-за синтаксиса '::' сокращенного. – Piskvor

ответ

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

фантастический. первый% 02x% 02: должен быть% 02x% 02x: кстати – Jessica

+0

@Jessica: fixed – 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

Используйте этот код. это расширит адрес ipv6 –