2010-09-17 12 views
7

Ho un programma in cui un componente esterno mi passa una stringa che contiene un indirizzo IP. Quindi ho bisogno di trasformarlo in un URI. Per IPv4 questo è facile; Mi affido http: // e append /. Tuttavia, per IPv6 ho bisogno di circondarlo anche tra parentesi [].Indicare se una stringa di testo è un indirizzo IPv6 o un indirizzo IPv4 utilizzando l'API C socket standard

Esiste una chiamata API socket standard per determinare la famiglia di indirizzi dell'indirizzo?

+0

So che non fa parte dell'API socket, ma se IP4 e IP6 sono le uniche possibilità, non è possibile farlo con 'strlen'? ;-) –

+0

@Steve Jessop considera per es. ff02 :: 2 e 8.8.8.8 – nos

+0

@nos: abbastanza giusto, non si è reso conto che il primo era un indirizzo valido. Più in generale, c'è un modo per esaminare le stringhe, è un codice più semplice rispetto all'utilizzo dell'API socket? In questo caso, la struttura contenente l'indirizzo analizzato non è necessaria. –

risposta

13

Utilizzare getaddrinfo() e impostare il flag di suggerimento AI_NUMERICHOST, famiglia su AF_UNSPEC, in caso di esito positivo da getaddrinfo, la struttura risultante addrinfo .ai_family sarà AF_INET o AF_INET6.

EDIT, piccolo esempio

#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

Una specie. È possibile utilizzare inet_pton() per provare l'analisi della stringa prima come IPv4 (AF_INET) quindi IPv6 (AF_INET6). Il codice di ritorno consente di sapere se la funzione è riuscita e la stringa contiene quindi un indirizzo del tipo tentato.

Ad esempio:

#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() ha un mucchio di overhead ma in pratica chiama anche inet_pton(). inet_pton() è davvero tutto ciò di cui hai bisogno e IMHO è la migliore risposta a questa domanda. Inoltre non richiede una funzione di pulizia. – rockdaboot

Problemi correlati