getnameinfo(3) アドレスから名前への変換をプロトコルに依存しないかたちで行う

書式

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


int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags);

glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

getnameinfo(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

説明

getnameinfo() 関数は、 getaddrinfo(3) の逆の動作を行う。つまり、プロトコルに依存しないかたちで ソケットアドレスから対応するホスト名とサービスへの変換を行う。 この関数は gethostbyaddr(3) と getservbyport(3) の機能を一つにしたものだが、 これらの関数と違い、 getnameinfo(3) はリエントラントであり、IPv4 と IPv6 の差分に依存しないかたちで プログラムを書くことができる。

sa 引き数は、 IP アドレスとポート番号の情報を保持している 汎用的なソケットアドレス構造体 (sockaddr_in 型または sockaddr_in6 型) へのポインタである。 salensa のサイズである。 hostserv 引き数は、(それぞれサイズが hostlenservlen の) 呼び出し側で確保されたバッファへのポインタであり、 ホスト名とサービス名を含むヌル終端された文字列が それぞれのバッファに格納される。

ホスト名が不要であることをこの関数に伝えるには、 host に NULL を指定するか、 hostlen に 0 を指定する。同様に、サービス名が不要な場合は、 serv に NULL を指定するか、 servlen に 0 を指定する。 しかし、ホスト名とサービス名の両方を不要だと指定することはできない (いずれか一方は要求すること)。

flags 引き数で getnameinfo() の動作を変えることができる。指定できる値は以下の通り:

NI_NAMEREQD
指定すると、ホスト名が決定できなかった場合にエラーを返す。
NI_DGRAM
指定すると、ストリームベース (TCP) でなくデータグラムベース (UDP) のサービスを対象にする。数は少ないが、 UDP と TCP で違うサービスを提供しているポート (512-514) に対して必要となる。
NI_NOFQDN
指定すると、ローカルなホストには fully qualified domain name (FQDN) の ホスト名の部分のみを返す。
NI_NUMERICHOST
指定すると、数値形式のホスト名が返される。 (指定しなくても、ノードの名前が決定できない場合は数値形式が返ることがある)。
NI_NUMERICSERV
指定すると、数値形式のサービス名 (例えばポート番号) が返される (指定しなくても、サービス名が決定できない場合は数値形式が返ることがある)。

国際化ドメイン名のための getnameinfo() の拡張

glibc 2.3.4 から、 getnameinfo() に拡張が行われ、ホスト名と 国際化ドメイン名 (Internationalized Domain Name; IDN) 形式との間で 透過的な変換ができるようになっている (IDN 形式については RFC 3490 の Internationalizing Domain Names in Applications (IDNA) を参照)。3つのフラグが新たに定義されている:

NI_IDN
このフラグを指定すると、必要であれば、検索処理で見つかった名前は IDN 形式からロケールに応じた符号化形式に変換される。 ASCII 文字だけの名前はこの変換では影響を受けない。このため、 既存のプログラムや環境でこのフラグを使うことができる。
NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES
これらのフラグをセットすると、IDNA 処理で使用されるフラグ IDNA_ALLOW_UNASSIGNED (未割り当ての Unicode のコードポイントを許容) と IDNA_USE_STD3_ASCII_RULES (出力が STD3 準拠のホスト名かをチェックする) がそれぞれ有効になる。

返り値

成功すると 0 が返り、(要求されていれば) ノードとサービスの名前がヌル終端された文字列の形式でそれぞれの指定バッファに返される (バッファの長さにあうように縮められるかもしれない)。 エラーの場合は、以下の 0 以外のエラー・コードが返される:
EAI_AGAIN
指定された名前が現時点では解決できなかった。 後で再試行してみること。
EAI_BADFLAGS
flags 引き数に不正な値が与えられた。
EAI_FAIL
回復できないエラーが発生した。
EAI_FAMILY
指定したアドレスファミリーが認識できなかった。 あるいはアドレスの長さが指定されたファミリーに合うものでなかった。
EAI_MEMORY
メモリが足りない。
EAI_NONAME
与えられたパラメータでは名前が解決できない。 NI_NAMEREQD が設定されていたがホスト名が決定できなかったか、 ホスト名もサービス名も要求されなかった。
EAI_OVERFLOW
host または serv が指しているバッファが小さすぎた。
EAI_SYSTEM
システムエラーが起った。 エラーコードは errno に設定される。

gai_strerror(3) 関数を使うと、これらのエラー・コードを、エラー・レポートに適した 人間が読みやすい文字列に翻訳してくれる。

ファイル

/etc/hosts
/etc/nsswitch.conf
/etc/resolv.conf

バージョン

getnameinfo() は、glibc バージョン 2.1 以降で提供されている。

準拠

RFC 2553, POSIX.1-2001.

注意

適切なバッファサイズを選択できるように、 <netdb.h> に以下の定数が定義されている。
#define NI_MAXHOST      1025
#define NI_MAXSERV      32

glibc 2.8 以降では、機能検査マクロ _BSD_SOURCE, _SVID_SOURCE, _GNU_SOURCE のいずれかが定義された場合にのみ、これらの定義が公開される。

前者は、最近のバージョンの BIND のヘッダファイル <arpa/nameser.h> 中の定数 MAXDNAME と同じ値である。 後者は、割り当て済の数値について記した現在の RFC に 列挙されてサービスから推量した値である。

以下のコードは、指定されたソケットアドレスに対する ホストとサービスの数値表式を取得しようと試みる。 特定のアドレスファミリーに対する参照情報は 一切ハードコードされていないことに着目してほしい。

struct sockaddr *sa;    /* input */
socklen_t len;          /* input */
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
if (getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf,
            sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
    printf("host=%s, serv=%s\n", hbuf, sbuf);

以下ではソケットアドレスに 逆向きのアドレスマッピングが存在するかをチェックしている。

struct sockaddr *sa;    /* input */
socklen_t len;          /* input */
char hbuf[NI_MAXHOST];
if (getnameinfo(sa, len, hbuf, sizeof(hbuf),
            NULL, 0, NI_NAMEREQD))
    printf("could not resolve hostname");
else
    printf("host=%s\n", hbuf);

getnameinfo() を使ったプログラム例が getaddrinfo(3) に記載されている。

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。