networking network-programming ipv6

networking - ¿Cuál es el propósito de la bandera AI_V4MAPPED en getaddrinfo?



network-programming ipv6 (2)

En mi experiencia, AI_V4MAPPED no funciona en Mac OS X 10.6. Si proporciona hints.ai_family = AF_INET6 y hints.ai_flags = AI_V4MAPPED , siempre devolverá EAI_NONAME , y gai_strerror() imprimirá "nodename o servname provided, o no known".

Funciona correctamente en OS X 10.7.

Publicando esto aquí en caso de que ayude a alguien, incluso si estás en Fedora.

La llamada getaddrinfo tiene muchas banderas interesantes. Me pregunto cuál es el propósito de la bandera AI_V4MAPPED. En ningún sistema, parece que soy capaz de hacer que getaddrinfo produzca :: ffff: nnnn las direcciones de formulario que esperaría cuando configuro este indicador. ¿Estoy esperando lo equivocado? ¿Estoy viendo errores?

En particular, si solicito direcciones de familia AF_INET6 y especifico AI_V4MAPPED esperaría ver direcciones :: ffff: nnnn para hosts que solo tienen registros DNS A (dirección IPv4). Y generalmente también esperaría que si especificara AI_ALL obtendría los registros DNS AAAA (dirección IPv6) de un host y los registros DNS A en formato :: ffff: nnnn.

Nuevamente, ¿estoy esperando todas las cosas equivocadas aquí?

He probado esto en Fedora 11 - glibc 2.10.1 y OS X 10.4.


Obtuve exactamente lo que esperaba obtener en Debian Lenny (glibc 2.7) - con una excepción - si especifico AI_V4MAPPED sin AI_ALL , y el nombre de host que busco tiene CNAME apuntando a los registros A, no los devuelvo . Funciona bien si también se especifica AI_ALL o si el nombre de host está directamente asociado con los registros A.

No sé por qué, quizás sea un error glibc.

Aquí está mi programa de prueba:

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct addrinfo hints = { 0 }; struct addrinfo *res, *res_c; int err; char name[INET6_ADDRSTRLEN]; if (argc < 2) { return 1; } hints.ai_family = AF_INET6; hints.ai_flags = AI_V4MAPPED | AI_ALL; err = getaddrinfo(argv[1], NULL, &hints, &res); if (err) { printf("getaddrinfo: %s/n", gai_strerror(err)); return 1; } for (res_c = res; res_c; res_c = res_c->ai_next) { const void *addr; int port; struct protoent *proto; switch (res_c->ai_family) { case AF_INET6: addr = &((struct sockaddr_in6 *)(res_c->ai_addr))->sin6_addr; port = ((struct sockaddr_in6 *)(res_c->ai_addr))->sin6_port; printf("AF_INET6/t"); break; case AF_INET: addr = &((struct sockaddr_in *)(res_c->ai_addr))->sin_addr; port = ((struct sockaddr_in *)(res_c->ai_addr))->sin_port; printf("AF_INET/t"); break; default: addr = NULL; printf("(%d)/t", res_c->ai_family); } proto = getprotobynumber(res_c->ai_protocol); if (proto) { printf("%s/t", proto->p_name); } else { printf("(%d)/t", res_c->ai_protocol); } switch (res_c->ai_socktype) { case SOCK_STREAM: printf("SOCK_STREAM/t"); break; case SOCK_DGRAM: printf("SOCK_DGRAM/t"); break; default: printf("(?socktype?)/t"); break; } if (addr && inet_ntop(res_c->ai_family, addr, name, sizeof name)) printf("addr = %s", name); if (addr) printf(",%d", port); printf("/n"); } return 0; }