c network-programming ipv6 ipv4 getaddrinfo

c - getaddrinfo y IPv6



network-programming ipv4 (4)

@jwodder y @onteria_ cubrieron bien la parte de IPv6, así que solo abordaré la parte de los números :

ai_flags -> 40

Probablemente esta sea la suma de los dos siguientes en /usr/include/netdb.h :

# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ # define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose

Esta es la familia de protocolos , inet, inet6, apx, unix, etc .:

ai_family -> 2 bits/socket.h:78:#define PF_INET 2 /* IP protocol family. */ bits/socket.h:119:#define AF_INET PF_INET

Este es el tipo de socket , flujo, dgram, paquete, rdm, seqpacket:

ai_socktype -> 1 bits/socket.h:42: SOCK_STREAM = 1, /* Sequenced, reliable, connection-based

El protocolo de nivel superior , TCP, UDP, TCP6, UDP6, UDPlite, ospf, icmp, etc:

ai_protocol -> 6

Bastante divertido, en /etc/protocols :

tcp 6 TCP # transmission control protocol

El tamaño de la struct sockaddr . (Difiere en base a la familia de direcciones! Ugh.)

ai_addrlen -> 16

Esto se debe a que está recuperando una struct sockaddr_in , vea linux/in.h :

#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ struct sockaddr_in { sa_family_t sin_family; /* Address family */ __be16 sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr''. */ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)]; };

Y el último, desde /etc/hosts :)

ai_addr hostname -> 127.0.0.1

Estoy tratando de entender lo que devuelve la función getaddrinfo:

#include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/socket.h> #include <netdb.h> int main (int argc, char *argv[]) { struct addrinfo *res = 0 ; getaddrinfo("localhost", NULL ,NULL,&res); printf("ai_flags -> %i/n", res->ai_flags) ; printf("ai_family -> %i/n", res->ai_family) ; printf("ai_socktype -> %i/n", res->ai_socktype) ; printf("ai_protocol -> %i/n", res->ai_protocol) ; printf("ai_addrlen -> %i/n", res->ai_addrlen) ; struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr; printf("ai_addr hostname -> %s/n", inet_ntoa(saddr->sin_addr)); freeaddrinfo(res); return 0 ; }

resultados:

ai_flags -> 40 ai_family -> 2 ai_socktype -> 1 ai_protocol -> 6 ai_addrlen -> 16 ai_addr hostname -> 127.0.0.1

En / etc / hosts, tengo:

127.0.0.1 localhost ::1 localhost

Getaddrinfo devuelve solo 127.0.0.1 y no :: 1? No entiendo porque

La segunda pregunta es ¿dónde puedo encontrar el significado de esos ints (40,2,1,6, etc.)? He leído al hombre pero no hay nada de eso.

También quería saber si es posible dar una dirección IPv6 (por ejemplo: 1) y la función devuelve el nombre: ¿localhost?

Muchas gracias !!


Se han dado otras respuestas a la mayoría de las partes, pero para responder a esta parte final:

También quería saber si es posible dar una dirección IPv6 (por ejemplo: 1) y la función devuelve el nombre: ¿localhost?

La función que desea es getnameinfo() ; dada una dirección de socket, devuelve un nombre de cadena.


res también contiene una struct addrinfo *ai_next; campo struct addrinfo *ai_next; , que es un puntero a las entradas adicionales encontradas por getaddrinfo , o NULL si no hubo otras entradas. Si examinas res->ai_next , deberías encontrar la entrada de IPv6.

En cuanto a los campos de enteros en una struct addrinfo , corresponden a constantes predefinidas con valores definidos por la implementación, y los valores enteros en sí mismos no son de interés general. Si desea saber qué significa un campo determinado, compárelo con las constantes que se pueden asignar a ese campo ( SOCK_STREAM , SOCK_DGRAM , etc. para ai_socktype ; IPPROTO_TCP , IPPROTO_UDP , etc. para ai_protocol ; y así sucesivamente) o, para ai_flags , pruebe cada bit correspondiente a una constante predefinida (por ejemplo, if (res->ai_flags & AI_NUMERICHOST) {printf("ai_flags has AI_NUMERICHOST/n"); } ).


extern struct sockaddr_in6 create_socket6(int port, const char * address) { struct addrinfo hints, *res, *resalloc; struct sockaddr_in6 input_socket6; int errcode; /* 0 out our structs to be on the safe side */ memset (&hints, 0, sizeof (hints)); memset (&input_socket6, 0, sizeof(struct sockaddr_in6)); /* We only care about IPV6 results */ hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_DEFAULT; errcode = getaddrinfo (address, NULL, &hints, &res); if (errcode != 0) { perror ("[ERROR] getaddrinfo "); return input_socket6; } resalloc = res; while (res) { /* Check to make sure we have a valid AF_INET6 address */ if(res->ai_family == AF_INET6) { /* Use memcpy since we''re going to free the res variable later */ memcpy (&input_socket6, res->ai_addr, res->ai_addrlen); /* Here we convert the port to network byte order */ input_socket6.sin6_port = htons (port); input_socket6.sin6_family = AF_INET6; break; } res = res->ai_next; } freeaddrinfo(resalloc); return input_socket6; }

Aquí hay un código que lo explica. Básicamente, a menos que le dé a getaddrinfo algunos consejos para que funcione solo con IPV6, también le dará los resultados de IPV4. Es por eso que tiene que recorrer los resultados como se muestra.