メインコンテンツへジャンプする

JPNICはインターネットの円滑な運営を支えるための組織です

ロゴ:JPNIC

WHOIS 検索 サイト内検索 WHOISとは? JPNIC WHOIS Gateway
WHOIS検索 サイト内検索

runidn の仕様書


概要

runidn は、名前解決に gethostbyname() などの標準的な関数 を使用している UNIX アプリケーションを、再コンパイルなしに国際化ドメイン名 を扱えるようにするためのコマンドです。

ここでは、runidn の仕様について解説します。 使用方法については、 runidn のガイド のほうをご覧ください。


実装

runidn は共有ライブラリのプリロード機構を用いて、標準的な名前解決用の 関数を、国際化ドメイン名の処理機能を持つ別のバージョンのものに動的に 置き換えることで、クライアントでの国際化ドメイン名の処理を実現します。

多くのシステムでは、共有ライブラリのプリロードは 環境変数LD_PRELOADを用いて実現されています。 この環境変数にプリロードしたい共有ライブラリファイルのパス名を指定すると、 アプリケーションの実行時にアプリケーションに標準の共有ライブラリがリンク される前に指定したライブラリがリンクされます。 これによって標準のライブラリ関数を置換えることができます。

runidnの実体はこの環境変数LD_PRELOADを設定して引数で 指定されたコマンドを起動するだけのシェルスクリプトであり、実際に 国際化ドメイン名の処理を行うのはアプリケーションにリンクされる 共有ライブラリ libidnkitres です。


置き換える関数

libidnkitres が置き換える対象としている関数は、次の通り です。

  • gethostbyname()
  • gethostbyname_r()
  • gethostbyname2()
  • gethostbyname2_r()
  • gethostbyaddr()
  • gethostbyaddr_r()
  • getipnodebyname()
  • getipnodebyaddr()
  • getaddrinfo()
  • getnameinfo()
  • freehostent()
  • freeaddrinfo()

freehostent()freeaddrinfo() はそれ自体が 名前解決を行うわけではありませんが、関連する名前解決関数のメモリ管理等 の都合により置き換わります。

なお、runidn が置き換えるこれらの関数には、システムによって引数の型、 引数の個数、戻り値の型などが微妙に異なるものがあります。

gethostbyaddr() 関数については、以下の 3 通りの 形式を認識できるようになっています。

struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
struct hostent *gethostbyaddr(const char *addr, size_t len, int type);
struct hostent *gethostbyaddr(const char *addr, int len, int type);

getnameinfo() 関数については、以下の 4 通りの 形式を認識できるようになっています。

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

gethostbyname_r() 関数については、以下の 2 通りの 形式を認識できるようになっています。

struct hostent *gethostbyname_r(const char *name,
                                struct hostent *result,
                                char *buffer, int buflen,
                                int *h_errnop);

int gethostbyname_r(const char *restrict name,
                    struct hostent *restrict result_buf,
                    char *restrict buffer, size_t buflen,
                    struct hostent **restrict result,
                    int *restrict h_errnop);

gethostbyaddr_r() 関数については、 以下の 2 通りの形式を認識できるようになっています。

int gethostbyaddr_r(const char *addr, int length, int format,
                    struct hostent *restrict result_buf,
                    char *restrict buf, size_t buflen,
                    struct hostent **restrict result,
                    int *restrict h_errnop);
struct hostent *gethostbyaddr_r(const char *addr, int length,
                                int type, struct hostent *result,
                                char *buffer, int buflen,
                                int *h_errnop);

その他の関数については、それぞれ下記のような形式を認識できるように なっています。

struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyname2(const char *name, int af);
struct hostent *getipnodebyname(const char *name, int af, int flags,
                                int *error_num);
struct hostent *getipnodebyaddr(const void *src, size_t len, int af,
                                int *error_num);
void freehostent(struct hostent *ptr);
int getaddrinfo(const char *nodename, const char *servname,
                const struct addrinfo *hints, struct addrinfo **res);
void freeaddrinfo(struct addrinfo *ai);
int gethostbyname2_r(const char *name, int af,
                     struct hostent *restrict result_buf,
                     char *restrict buf, size_t buflen,
                     struct hostent **restrict result,
                     int *restrict h_errnop);

システムに用意されている名前解決関数が runidn の想定外の形式であった場合、 最悪 runidn のコンパイル中にエラーが起きることもあります。


処理の詳細

アプリケーションが runidn によって置き変わった名前解決関数を呼び出すと、 置き変わった関数の内部では次のような処理を行います。

  1. 関数への引数として渡されたドメイン名を、ローカルエンコーディング から IDN エンコーディングにエンコードします。
  2. libidnkitres によって置き換わる前の、同名の元の関数を呼び出します。 このとき、関数に渡す引数は、置き換えた関数に渡されたものとほぼ同じ ものを用いますが、ドメイン名だけは先ほど IDN エンコーディングに エンコードしたものを渡します。
  3. 元の関数から問い合わせ結果のデータを受け取ったら、データに含まれる ドメイン名を IDN エンコーディングからローカルエンコーディングに デコードします。
  4. 置き換えた関数の処理を終え、関数の呼び出し元へ戻ります。 先ほどローカルエンコーディングにデコードした問い合わせ結果を、 アプリケーションへ返します。

ドメイン名のエンコードやデコードの処理はすべて idnkit ライブラリ (libidnkit) の高レベル API (api モジュール) を使用しています。 現在の実装では libidnkitres は idnkit ライブラリ (libidnkit) を 呼び出すのではなく、libidnkit 自体を内部に抱え込むような形態になっています。

このページを評価してください

このWebページは役に立ちましたか?
ページの改良点等がございましたら自由にご記入ください。

このフォームをご利用した場合、ご連絡先の記入がないと、 回答を差し上げられません。 回答が必要な場合は、お問い合わせ先をご利用ください。

ロゴ:JPNIC

Copyright© 1996-2020 Japan Network Information Center. All Rights Reserved.