システムプログラム(第6回): ライブラリ関数 getaddrinfo()

                                       筑波大学 システム情報系 情報工学域
                                       新城 靖
                                       <yas@cs.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2022/2022-06-29/getaddrinfo.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2022/
http://www.coins.tsukuba.ac.jp/~yas/

ライブラリ関数getaddrinfo()

GETADDRINFO(3)           BSD Library Functions Manual           GETADDRINFO(3)

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

     struct addrinfo {
             int ai_flags;           /* input flags */
             int ai_family;          /* protocol family for socket */
             int ai_socktype;        /* socket type */
             int ai_protocol;        /* protocol for socket */
             socklen_t ai_addrlen;   /* length of socket-address */
             struct sockaddr *ai_addr; /* socket-address for socket */
             char *ai_canonname;     /* canonical name for service location */
             struct addrinfo *ai_next; /* pointer to next in list */
     };
ライブラリ関数 getaddrinfo() は、第一引数として、ホスト名、第2引数とし てポート番号に関連した(/etc/services に含まれている)、第3引数として、 調べたいアドレスの制約に関するヒントを与える。重要なヒントとしては、以 下のものがある。
ai_family
IPv4 専用にするには、PF_INET、IPv6 専用にするには、PF_INET6 と指定する。 PF_UNSPE (0) を指定すると、任意のものが返される。 (普通は、IPv4 か IPv6 の意味だが、他のプロトコルのアドレスが 返されることも考えられる。)
ai_socktype
TCP の場合、SOCK_STREAM, UDP の場合、SOCK_DGRAM と指定す ることがよいとgetaddrinfo() の設計者は考えている。

ライブラリ関数 getaddrinfo() は、与えられた引数から、IP アドレス(やポー ト番号)を調べ、結果を構造体 struct addrinfo に格納して返す。その構造体 は、ヒープ(malloc() されたメモリ)に置かれている。関数 getaddrinfo() は、構造体へのポインタを第4引数で示された番地に保存する(第4引数は、 ポインタを保存するための番地)。 この構造体の中の ai_addr に目的の IP アドレスを含んだ struct sockaddr が含まれている。

1つのホストに複数の IP アドレスが割り当てられている場合もある。その場 合は、ai_next を手繰ればわかる。

getaddrinfo() の設計者は、こうして得られたstruct sockaddr をそのまま利 用して、socket() システム・コールやconnect() システム・コールを呼ぶこと を想定している。

     s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
     connect(s, res->ai_addr, res->ai_addrlen);
便利といえば便利だが、想定外の利用方法で利用するときに使いにくい。たと えば、TCP か UDP を後で決めたい時や、複数のアドレスのうちどれを使うかを 後で決めたい時などである。

ライブラリ関数 getaddrinfo() の内部的では、/etc/hosts というファイル や, NIS の hosts マップ, DNSの名前サーバなどが調べられる。どれがどの順 番で調べられるかは、システムに依存する。


Last updated: 2022/06/07 17:02:30
Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>