getAddrinfo에서 AI_V4MAPPED 플래그의 목적은 무엇입니까?
-
05-07-2019 - |
문제
getAddrinfo 호출에는 많은 흥미로운 깃발이 있습니다. AI_V4MAPPED 플래그의 목적이 무엇인지 궁금합니다. 시스템이 없음 시스템에서는이 플래그를 설정할 때 예상대로 :: ffff : nnnn 양식 주소를 생산할 수있는 getAddrinfo를 얻을 수있는 것 같습니다. 내가 잘못된 것을 기대하고 있습니까? 나는 버그를보고 있습니까?
Particlar에서 AF_INET6 제품군 주소를 요청하고 AI_V4MAPPE를 지정하면 DNS A (IPv4 주소) 레코드 만있는 호스트의 경우 :: FFFF : NNNN 주소를 확인할 것으로 예상됩니다. 또한 AI_ALL을 지정하면 호스트의 DNS AAAA (IPv6 주소) 레코드와 DNS A Records :: FFFF : NNNN Form을 모두 얻을 것으로 기대합니다.
다시, 나는 여기서 모든 잘못된 것을 기대하고 있습니까?
Fedora 11 -GLIBC 2.10.1 및 OS X 10.4에서 이것을 테스트했습니다.
해결책
나는 당신이 기대하는 것을 정확하게 얻습니다. 데비안 레니 (Glibc 2.7) - 한 가지 예외로 - 내가 지정하면 AI_V4MAPPED
없이 AI_ALL
, 그리고 내가 찾는 호스트 이름에는 레코드를 가리키는 cname이 있습니다. 만약 잘 작동합니다 AI_ALL
또한 지정되거나 호스트 이름이 레코드와 직접 연관되어 있는지 여부.
왜 그런지 모르겠습니다 - 아마도 그게 glibc 버그일까요?
내 테스트 프로그램은 다음과 같습니다.
#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;
}
다른 팁
내 경험상 AI_V4MAPPED
Mac OS X 10.6에서는 작동하지 않습니다. 당신이 제공하는 경우 hints.ai_family = AF_INET6
그리고 hints.ai_flags = AI_V4MAPPED
항상 돌아올 것입니다 EAI_NONAME
, 그리고 gai_strerror()
"Nodename 또는 Servname 제공 또는 알려지지 않은"인쇄.
OS X 10.7에서 제대로 작동합니다.
페도라에도 불구하고 누군가를 돕는 경우에 여기에 이것을 게시합니다.