プログラミングインタフェース

inetd デーモン

inetd(1M) デーモンは起動時に呼び出され、待機するサービスを /etc/inet/inetd.conf ファイルから取得します。デーモンは /etc/inet/inetd.conf ファイルに記述されている各サービスごとに 1 つのソケットを作成し、各ソケットに適切なポート番号の割り当てを行います。inetd(1M) についての詳細は、マニュアルページを参照してください。

inetd(1M) デーモンは各ソケットをポーリングして、そのソケットに対応するサービスへのコネクション要求を待機します。SOCK_STREAM タイプのソケットの場合、inetd(1M) は待機ソケット上で受け入れ (accept(3SOCKET))、フォークし (fork(2))、新しいソケットをファイル記述子 0 および 1 (stdin および stdout) に複製し (dup(2)) 、ほかの開いているファイル記述子を閉じて、適切なサーバーを実行します (exec(2))。

inetd(1M) を使用する主な利点は、使用していないサービスがシステムのリソースを消費しない点にあります。また、コネクションの確立に関する処理の大部分を inetd(1M) が行う点も大きな利点の 1 つです。inetd(1M) によって起動されたサーバーのソケットはファイル記述子 01 上のクライアントに接続されます。したがって、サーバーはすぐに、読み取り、書き込み、送信、または受信を行うことができます。fflush(3C) を適宜使用する限り、サーバーはバッファリングされた入出力を stdio の規約に従って使用できます。

getpeername(3SOCKET) ルーチンはソケットに接続されたピア (プロセス) のアドレスを返します。このルーチンは、inetd(1M) によって起動されたサーバーで使用すると便利です。たとえば、このルーチンを使用すると、クライアントの IPv6 アドレスを表現するときに使用される fec0::56:a00:20ff:fe7d:3dd2 のようなインターネットアドレスを記録できます。次に、inetd(1M) サーバーが使用するコードの例を示します。

    struct sockaddr_storage name;
    int namelen = sizeof (name);
    char abuf[INET6_ADDRSTRLEN];
    struct in6_addr addr6;
    struct in_addr addr;

    if (getpeername(fd, (struct sockaddr *)&name, &namelen) == -1) {
        perror("getpeername");
        exit(1);
    } else {
        addr = ((struct sockaddr_in *)&name)->sin_addr;
        addr6 = ((struct sockaddr_in6 *)&name)->sin6_addr;
        if (name.ss_family == AF_INET) {
                (void) inet_ntop(AF_INET, &addr, abuf, sizeof (abuf));
        } else if (name.ss_family == AF_INET6 &&
                   IN6_IS_ADDR_V4MAPPED(&addr6)) {
                /* これは IPv4 でマップされた IPv6 アドレス */
                IN6_MAPPED_TO_IN(&addr6, &addr);
                (void) inet_ntop(AF_INET, &addr, abuf, sizeof (abuf));
        } else if (name.ss_family == AF_INET6) {
                (void) inet_ntop(AF_INET6, &addr6, abuf, sizeof (abuf));

        }
        syslog("Connection from %s\n", abuf);
    }