EN JA
GETADDRINFO(3)
GETADDRINFO(3) FreeBSD Library Functions Manual GETADDRINFO(3)

名称

getaddrinfo, freeaddrinfoホストとサービス名へのソケットアドレス構造体

書式

#include < sys/types.h>
#include < sys/socket.h>
#include < netdb.h>

int
getaddrinfo( const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res);

void
freeaddrinfo( struct addrinfo *ai);

解説

getaddrinfo() 関数は、ホスト hostname とサービス servname のために IP アドレスとポート番号のリストを得るために使用されます。それは、 gethostbyname(3)getservbyname(3) 関数を置換し、より多くの柔軟性を提供します。

hostnameservname 引数は、ヌル文字で終了する文字列へのポインタか NULL ポインタのいずれかです。 hostname のための受け入れできる値は、有効なホスト名またはドット付きの数値 IPv4 アドレスまたは IPv6 アドレスから成る数値ホストアドレス文字列のいずれかです。 servname は、 services(5) でリストされた 10 進数のポート番号かサービス名のいずれかです。少なくとも hostnameservname の 1 つは、非 NULL でなければなりません。

hints は、 struct addrinfo へのオプションのポインタで、< netdb.h>で定義されています:

struct addrinfo { 
 int ai_flags;  /* 入力フラグ */ 
 int ai_family;  /* ソケットのためのプロトコルファミリ */ 
 int ai_socktype; /* ソケットタイプ */ 
 int ai_protocol; /* ソケットのためのプロトコル */ 
 socklen_t ai_addrlen; /* ソケットアドレスの長さ */ 
 struct sockaddr *ai_addr; /* ソケットのためのソケットアドレス */ 
 char *ai_canonname; /* サービス位置のための標準名 */ 
 struct addrinfo *ai_next; /* リストの中の次のポインタ */ 
};

この構造体は、呼び出し側サポートか使用したいソケットのタイプに関してヒント (hints) を提供するために使用することができます。呼び出し側は、 hints で次の構造体要素を供給することができます:

ai_family
使用されるべきであるプロトコルファミリです。 ai_familyPF_UNSPEC に設定されるとき、呼び出し側がオペレーティングシステムによってサポートされたどんなプロトコルファミリも受け付けることを意味します。
ai_socktype
必要とするソケットのタイプを示します: SOCK_STREAM, SOCK_DGRAM, または SOCK_RAW です。 ai_socktype が 0 であるときに、呼び出し側は、どんなソケットタイプも受け付けます。
ai_protocol
IPPROTO_UDP または IPPROTO_TCP の望まれている転送プロトコルを示します。 ai_protocol が 0 であるなら、呼び出し側は、どんなプロトコルも受け付けます。
ai_flags
hints パラメータが指す ai_flags フィールドは、0 に設定されるか、または値 AI_ADDRCONFIG, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERVAI_PASSIVE の 1 つ以上のビット単位の論理和 (OR) となります。
AI_ADDRCONFIG
AI_ADDRCONFIG ビットが設定されるなら、IPv4 アドレスは、ローカルシステムで設定される場合のみ、返されるべきであり、IPv6 アドレスは、IPv6 アドレスがローカルシステムで設定される場合にだけ、返されます。
AI_CANONNAME
AI_CANONNAME ビットが設定されているなら、 getaddrinfo() への呼び出しが成功すれば、返された最初の addrinfo 構造体の ai_canonname 要素で指定されたホスト名の標準の名前を含むヌル文字で終了した文字列を返します。
AI_NUMERICHOST
AI_NUMERICHOST ビットが設定されているなら、 hostname は、IPv4 または IPv6 を定義する数値文字列として扱われるべきである、またはどんな名前解決も試みられるべきでないことを示します。
AI_NUMERICSERV
AI_NUMERICSERV ビットが設定されるなら、供給された NULL でない servname 文字列は、数値ポート文字列となります。そうでなければ、 EAI_NONAME エラーが返されます。このビットは、呼び出される任意のタイプの名前解決サービス (例えば、NIS+) を抑制します。
AI_PASSIVE
AI_PASSIVE ビットが設定されているなら、返されたソケットアドレス構造体は、 bind(2) への呼び出しで使用するためのもであることを示します。この場合、 hostname 引数が NULL ポインタであるなら、ソケットアドレス構造体の IP アドレスの部分は、IPv4 アドレスのための INADDR_ANY か IPv6 アドレスのための IN6ADDR_ANY_INIT に設定されます。

AI_PASSIVE ビットが設定されていないなら、返されたソケットアドレス構造体は、接続指向のプロトコルのためには、 connect(2) への呼び出しが、コネクションレスのプロトコルが選ばれるなら、 connect(2), sendto(2), または sendmsg(2) への呼び出しが使える状態です。ソケットアドレス構造体の IP アドレスの部分の hostname が NULL ポインタで AI_PASSIVE が設定されていないなら、ループバックアドレスに設定されます。

hints を通して渡された addrinfo 構造体の他のすべての要素は、0 か NULL ポインタでなければなりません。

hints が NULL ポインタであるなら、 getaddrinfo() は、まるで呼び出し側が PF_UNSPEC に設定された ai_family と他のすべての要素が 0 か NULL に設定された struct addrinfo を提供したかのように振る舞います。

getaddrinfo() 呼び出しが成功した後で、 *res は、1 つ以上の addrinfo 構造体のリンクリストへのポインタです。リストは、NULL ポインタが遭遇するまでそれぞれの addrinfo 構造体で ai_next ポインタに従って横断することができます。それぞれ返された addrinfo 構造体の ai_family, ai_socktype,ai_protocol の 3 つのメンバは、 socket(2) への呼び出しに適しています。リストの中の addrinfo 構造体ごとに、 ai_addr メンバは、長さ ai_addrlen の書き込まれたソケットアドレス構造体を指します。

getaddrinfo() の、この実装は、RFC 4007 の第 11 章で文書化されているようにスコープ識別子がある数値 IPv6 アドレス記法を許します。パーセント文字とスコープ識別子をアドレスに追加することによって、アドレスのための sin6_scope_id フィールドを満たすことができます。これは、スコープアドレスの管理をより簡単にして、スコープアドレスのカットアンドペースト入力を許します。

現時点では、コードは、形式付きリンクローカルのアドレスだけをサポートします。スコープ識別子は、リンク ( ne0 のような) に関連しているハードウェアインタフェースの名前に決め打ちされます。例として、“ fe80::1%ne0”は、“ ne0 インタフェースに関連するリンク上の fe80::1”を意味します。

現在の実装は、インタフェースとリンクと 1 対 1 の関係を仮定していますが、必ずしも仕様として本当ではありません。

すべての情報は、 getaddrinfo() によって動的に割り付けられて返されます: それは、ソケットアドレス構造体と同様に addrinfo 構造体自体と addrinfo 構造体に含まれる標準のホスト名の文字列です。

getaddrinfo() への呼び出しが成功することによって作成された動的に割り付けられた構造体に割り付けられたメモリは、 freeaddrinfo() 関数によって解放されます。 ai ポインタは、 getaddrinfo() への呼び出しによって作成された addrinfo 構造体を指すべきです。

戻り値

getaddrinfo() は、成功すれば 0 を、エラーが発生するなら gai_strerror(3) に記載されたエラーコードの 1 つを返します。

使用例

次のコードは、ストリームソケットを通して“ www.kame.net”サービス“ http”に接続しようと試みます。それは、アドレスファミリにかかわらず利用可能なすべてのアドレスを通ってループします。宛先 (終点) が IPv4 アドレスとして解決するなら、 AF_INET ソケットを使用します。同様に、IPv6 として解決するなら AF_INET6 ソケットが使用されます。特定のアドレスファミリに決めうちされた参照がないことに注意してください。 getaddrinfo() が IPv4/v6 でないアドレスを返しても、コードは、動作します。

struct addrinfo hints, *res, *res0; 
int error; 
int s; 
const char *cause = NULL; 
 
memset(&hints, 0, sizeof(hints)); 
hints.ai_family = PF_UNSPEC; 
hints.ai_socktype = SOCK_STREAM; 
error = getaddrinfo("www.kame.net", "http", &hints, &res0); 
if (error) { 
 errx(1, "%s", gai_strerror(error)); 
 /* NOTREACHED */ 
} 
s = -1; 
for (res = res0; res; res = res->ai_next) { 
 s = socket(res->ai_family, res->ai_socktype, 
     res->ai_protocol); 
 if (s < 0) { 
  cause = "socket"; 
  continue; 
 } 
 
 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { 
  cause = "connect"; 
  close(s); 
  s = -1; 
  continue; 
 } 
 
 break; /* オーケ、1 つを取得 */ 
} 
if (s < 0) { 
 err(1, "%s", cause); 
 /* NOTREACHED */ 
} 
freeaddrinfo(res0);

次の例は、利用可能なすべてのアドレスファミリのためにサービス“ http”でワイルドカードリッスンソケットをオープンしようと試みています。

struct addrinfo hints, *res, *res0; 
int error; 
int s[MAXSOCK]; 
int nsock; 
const char *cause = NULL; 
 
memset(&hints, 0, sizeof(hints)); 
hints.ai_family = PF_UNSPEC; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_flags = AI_PASSIVE; 
error = getaddrinfo(NULL, "http", &hints, &res0); 
if (error) { 
 errx(1, "%s", gai_strerror(error)); 
 /* NOTREACHED */ 
} 
nsock = 0; 
for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { 
 s[nsock] = socket(res->ai_family, res->ai_socktype, 
     res->ai_protocol); 
 if (s[nsock] < 0) { 
  cause = "socket"; 
  continue; 
 } 
 
 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) { 
  cause = "bind"; 
  close(s[nsock]); 
  continue; 
 } 
 (void) listen(s[nsock], 5); 
 
 nsock++; 
} 
if (nsock == 0) { 
 err(1, "%s", cause); 
 /* NOTREACHED */ 
} 
freeaddrinfo(res0);

関連項目

bind(2), connect(2), send(2), socket(2), gai_strerror(3), gethostbyname(3), getnameinfo(3), getservbyname(3), resolver(3), hosts(5), resolv.conf(5), services(5), hostname(7), named(8) R. Gilligan, S. Thomson, J. Bound, J. McCann, and W. Stevens, Basic Socket Interface Extensions for IPv6, RFC 3493, February 2003. S. Deering, B. Haberman, T. Jinmei, E. Nordmark, and B. Zill, IPv6 Scoped Address Architecture, RFC 4007, March 2005. Craig Metz, Protocol Independence Using the Sockets API, Proceedings of the freenix track: 2000 USENIX annual technical conference, June 2000.

規格

getaddrinfo() 関数は、 IEEE Std 1003.1-2004 (“POSIX.1”) 仕様で定義され、 RFC 3493, “Basic Socket Interface Extensions for IPv6”で文書化されました。
February 14, 2013 FreeBSD