2010-09-17 18 views
7

Tengo un programa donde un componente externo me pasa una cadena que contiene una dirección IP. Entonces necesito convertirlo en un URI. Para IPv4 esto es fácil; Prefijo http: // y anexar /. Sin embargo, para IPv6 también necesito rodearlo entre corchetes [].Indica si una cadena de texto es una dirección IPv6 o una dirección IPv4 usando sockets C estándar API

¿Hay una llamada API de sockets estándar para determinar la familia de direcciones de la dirección?

+0

Sé que no es parte de la API de sockets, pero si IP4 e IP6 son las únicas posibilidades, ¿no puedes hacer esto con 'strlen'? ;-) –

+0

@Steve Jessop considere, p. ff02 :: 2 y 8.8.8.8 – nos

+0

@nos: bastante justo, no se dio cuenta de que el primero era una dirección válida. De manera más general, ¿hay alguna manera de examinar las cadenas, es un código más simple que usar la API de sockets? En este caso, la estructura que contiene la dirección analizada no es necesaria. –

Respuesta

13

Utilice getaddrinfo() y establezca la bandera de sugerencia AI_NUMERICHOST, familia en AF_UNSPEC, al devolver exitosamente desde getaddrinfo, el miembro struct addrinfo .ai_family resultante será AF_INET o AF_INET6.

EDITAR, pequeño ejemplo

#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

tipo de. Puede usar inet_pton() para intentar analizar la cadena primero como IPv4 (AF_INET) y luego como IPv6 (AF_INET6). El código de retorno le permitirá saber si la función tuvo éxito, y la cadena contiene una dirección del tipo de intento.

Por ejemplo:

#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() tiene un montón de gastos generales, pero básicamente también llamadas inet_pton(). inet_pton() es realmente todo lo que necesitas y en mi humilde opinión la mejor respuesta a esta pregunta. Tampoco requiere una función de limpieza. – rockdaboot

Cuestiones relacionadas