getaddrinfoのAI_V4MAPPEDフラグの目的は何ですか?
-
05-07-2019 - |
質問
getaddrinfo呼び出しには、多くの興味深いフラグがあります。 AI_V4MAPPEDフラグの目的は何だろうと思っています。どのシステムでも、このフラグを設定すると予想されるように、getaddrinfoを取得して:: ffff:n.n.n.n形式のアドレスを生成できるようには見えません。間違ったことを期待していますか?バグがありますか?
特に、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でこれをテストしました
解決
Debian Lenny(glibc 2.7)で、期待どおりの結果が得られます-1つの例外があります- AI_ALL
とホスト名なしで AI_V4MAPPED
を指定した場合検索すると、Aレコードを指しているCNAMEがありますが、返されません。 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;
}
他のヒント
私の経験では、 AI_V4MAPPED
はMac OS X 10.6では動作しません。 hints.ai_family = AF_INET6
および hints.ai_flags = AI_V4MAPPED
を指定すると、常に EAI_NONAME
および gai_strerror()が返されますcode>は、&quot;ノード名もservnameも指定された、または不明です&quot;を出力します。
OS X 10.7で正常に動作します。
Fedoraを使用している場合でも、誰かを助けるためにここに投稿します。