2010-09-17 12 views
7

Mam program, w którym składnik zewnętrzny przekazuje mi ciąg znaków zawierający adres IP. Następnie muszę przekształcić go w URI. Dla IPv4 jest to łatwe; Dodaję przedrostek http: // i dołączam /. Jednak w przypadku IPv6 muszę również otoczyć go w nawiasach kwadratowych [].Poinformuj, czy ciąg tekstowy jest adresem IPv6 lub adresem IPv4 za pomocą standardowego interfejsu API gniazd C

Czy istnieje standardowe wywołanie API gniazd w celu ustalenia rodziny adresu adresu?

+0

Wiem, że to nie jest część API gniazd, ale jeśli IP4 i IP6 są jedynymi możliwościami, nie możesz tego zrobić za pomocą 'strlen'? ;-) –

+0

@Steve Jessop rozważyć np. ff02 :: 2 i 8.8.8.8 – nos

+0

@nos: wystarczająco fair, nie zdawałem sobie sprawy, że ten pierwszy był prawidłowym adresem. Mówiąc bardziej ogólnie, czy istnieje sposób na zbadanie łańcuchów, to prostszy kod niż użycie API gniazd? W takim przypadku struktura zawierająca przeanalizowany adres nie jest potrzebna. –

Odpowiedz

13

Użyj getaddrinfo() i ustaw flagę podpowiedzi AI_NUMERICHOST, rodzina na AF_UNSPEC, po pomyślnym powrocie z getaddrinfo, wynikowym członkiem struct addrinfo .ai_family będzie albo AF_INET, albo AF_INET6.

EDIT mały przykład

#include <sys/types.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <netdb.h> 

int main(int argc, char *argv[]) 
{ 
    struct addrinfo hint, *res = NULL; 
    int ret; 

    memset(&hint, '\0', sizeof hint); 

    hint.ai_family = PF_UNSPEC; 
    hint.ai_flags = AI_NUMERICHOST; 

    ret = getaddrinfo(argv[1], NULL, &hint, &res); 
    if (ret) { 
     puts("Invalid address"); 
     puts(gai_strerror(ret)); 
     return 1; 
    } 
    if(res->ai_family == AF_INET) { 
     printf("%s is an ipv4 address\n",argv[1]); 
    } else if (res->ai_family == AF_INET6) { 
     printf("%s is an ipv6 address\n",argv[1]); 
    } else { 
     printf("%s is an is unknown address format %d\n",argv[1],res->ai_family); 
    } 

    freeaddrinfo(res); 
    return 0; 
} 

$ ./a.out 127.0.0.1 
127.0.0.1 is an ipv4 address 
$ ./a.out ff01::01 
ff01::01 is an ipv6 address 
16

Rodzaj. Możesz użyć inet_pton(), aby przetworzyć łańcuch najpierw jako IPv4 (AF_INET), a następnie IPv6 (AF_INET6). Kod powrotu poinformuje Cię, czy funkcja się powiodła, a ciąg zawiera w sobie adres podanego typu.

Na przykład:

#include <arpa/inet.h> 
#include <stdio.h> 

static int 
ip_version(const char *src) { 
    char buf[16]; 
    if (inet_pton(AF_INET, src, buf)) { 
     return 4; 
    } else if (inet_pton(AF_INET6, src, buf)) { 
     return 6; 
    } 
    return -1; 
} 

int 
main(int argc, char *argv[]) { 
    for (int i = 1; i < argc; ++i) { 
     printf("%s\t%d\n", argv[i], ip_version(argv[i])); 
    } 

    return 0; 
} 
+1

getaddrinfo() ma pęczek overhead ale w zasadzie również wywołuje inet_pton(). inet_pton() jest naprawdę wszystkim czego potrzebujesz i IMHO najlepszą odpowiedzią na to pytanie. Nie wymaga również funkcji czyszczenia. – rockdaboot

Powiązane problemy