2009-09-10 7 views
6

getaddrinfo 호출에는 많은 흥미로운 플래그가 있습니다. AI_V4MAPPED 플래그의 목적이 무엇인지 궁금합니다. 어떤 시스템에서도 getaddrinfo를 생성하여 :: ffff : n.n.n.n 양식 주소를 얻을 수있는 것처럼 보이지 않습니다.이 플래그를 설정할 때 기대할 수 있습니다. 나는 잘못된 것을 기대하고 있나? 나는 벌레를보고 있니?getaddrinfo에서 AI_V4MAPPED 플래그의 목적은 무엇입니까?

특히 AF_INET6 제품군 주소를 요청하고 AI_V4MAPPED를 지정하면 DNS A (IPv4 주소) 레코드 만있는 호스트에 대해 :: ffff : n.n.n.n 주소를 볼 것으로 예상됩니다. 또한 일반적으로 AI_ALL을 지정하여 호스트의 DNS AAAA (IPv6 주소) 레코드와 DNS A 레코드를 :: ffff : n.n.n.n 형식으로 얻을 수 있다고 생각합니다.

다시 여기에 잘못된 모든 것을 기대합니까?

나는 이것을 Fedora 11 - glibc 2.10.1 및 OS X 10.4에서 테스트했습니다. 한 가지 예외 - -

답변

6

난 당신이 데비안 레니 (2.7 glibc가)에 얻을 것으로 예상하고 정확하게 얻을 내가 AI_ALL없이 AI_V4MAPPED를 지정하면, 내가 찾아 호스트 이름은 CNAME이가 A 레코드 가리키는했다, 나는 '돈 돌려받는 사람을 얻지 마라. AI_ALL도 지정되거나 호스트 이름이 A 레코드와 직접 연관되어 있으면 정상적으로 작동합니다.

이유를 모르겠다. 아마도 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; 
} 
+1

나는 이것에 대해 더 많은 연구를 해왔다. getaddrinfo는 AAAA 요청을 처리하지 못하게하는 이상한 경우가 많기 때문에 버그가 많은 것으로 보입니다. – Omnifarious

+0

답변은 실제 답변에 가장 근접하므로 답변 크레딧을받습니다. – Omnifarious

+0

AI_ALL이없는 AI_V4MAPPED는 glibc 버그입니다. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=503912를 참조하십시오. – unixman83

4

, AI_V4MAPPED 맥 OS X 10.6에서 작동하지 않습니다 :

여기 내 테스트 프로그램입니다. hints.ai_family = AF_INET6hints.ai_flags = AI_V4MAPPED을 입력하면 항상 EAI_NONAME을 반환하고 gai_strerror()은 "노드 이름이나 서비스 이름을 제공하거나 알 수 없음"을 출력합니다.

OS X 10.7에서 제대로 작동합니다.

페도라를 사용 중이더라도 누군가에게 도움이 될 경우를 대비하여 여기에 게시하십시오.

관련 문제