AF_LOCAL(7) ローカルな

Other Alias

unix, AF_UNIX

書式

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

unix_socket = socket(AF_UNIX, type, 0);
error = socketpair(AF_UNIX, type, 0, int *sv);

説明

AF_UNIX (AF_LOCAL とも言われる) ソケットファミリーは、同じマシン上でプロセス同士が 効率的に通信するために用いられる。 伝統的に、Unix ソケットは、名前なしにもできるし、 (ソケット型であると印のついた) ファイルシステムのパス名に 結び付けることもできる。 さらに Linux では、ファイルシステムに依存しない 抽象名前空間 (abstract namespace) もサポートしている。

有効なタイプは以下の通りである:

SOCK_STREAM
ストリーム指向のソケット
SOCK_DGRAM
メッセージ境界を保存するデータグラム指向のソケット (ほとんどの Unix の実装では、Unix ドメイン・データグラム・ソケットは 常に信頼でき、データグラムの並び替えは行わない)
SOCK_SEQPACKET
(Linux 2.6.4 以降で利用できる) メッセージ境界を保存し、送信された順序でメッセージを届ける接続指向ソケット

Unix ソケットでは、補助データを使って ファイルディスクリプタやプロセスの信任状 (credential) を 送受信することもできる。

アドレスのフォーマット

Unix ドメインソケットのアドレスは以下の構造体で表現される。
#define UNIX_PATH_MAX    108
struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[UNIX_PATH_MAX];  /* pathname */
};

sun_family には必ず AF_UNIX が入っている。

この構造体では 3 種類のアドレスが区別される。

*
pathname (パス名): bind(2) を使って、Unix ドメインソケットを NULL 終端されたファイルシステム上の パス名に結び付けることができる。 getsockname(2), getpeername(2), accept(2) がソケットのアドレスを返す際には、 その長さは sizeof(sa_family_t) + strlen(sun_path) + 1 であり、 sun_path に NULL 終端されたパス名が格納される。
*
unnamed (名前なし): bind(2) を使ってパス名に結び付けることができないストリーム型のソケットは 名前を持たない。同様に、 socketpair(2) で作成される 2 つのソケットも名前を持たない。 getsockname(2), getpeername(2), accept(2) が名前なしのソケットのアドレスを返す際には、 その長さは sizeof(sa_family_t) であり、 sun_path は検査すべきではない。
*
abstract (抽象): 抽象ソケットアドレスは、 sun_path[0] がヌルバイト ('\0') であることから区別できる。 sun_path の残りの全バイトによりソケットの「名前」が定義される (名前中のヌルバイトには特別な意味はない)。 この名前はファイルシステムのパス名とは何の関係もない。 この名前空間におけるソケットのアドレスは、 sun_path の残りのバイトで表される。 getsockname(2), getpeername(2), accept(2) が抽象ソケットのアドレスを返す際には、その長さは sizeof(struct sockaddr_un) であり、 sun_path に抽象名前空間の名前が格納される。 ソケットの抽象名前空間は Linux による拡張であり、移植性はない。

ソケットオプション

歴史的な理由により、これらのオプションは たとえ AF_UNIX 固有のオプションであっても SOL_SOCKET 型で指定する。 ソケットファミリーとして SOL_SOCKET を指定すると、 setsockopt(2) でオプションが設定でき、 getsockopt(2) で取得ができる。
SO_PASSCRED
送信プロセスの補助メッセージとして信任状を受信できるようにする。 このオプションがセットされていて、まだソケットが接続されていないと、 抽象名前空間に他と重ならない名前が自動的に生成される。 ブール整数値のフラグを取る。

ソケット API

この節では、Linux の Unix ドメイン・ソケットでの、 ドメイン固有の詳細仕様とソケット API でサポートされていない機能に ついて説明する。

Unix ドメイン・ソケットでは、帯域外データ (out-of-band data) の 送信 (send(2) と recv(2) の MSG_OOB フラグ) はサポートされていない。

send(2) MSG_MORE フラグは Unix ドメイン・ソケットではサポートされていない。

recv(2) の flags 引き数での MSG_TRUNC の使用は Unix ドメイン・ソケットではサポートされていない。

SO_SNDBUF ソケットオプションは Unix ドメイン・ソケットで効果を持つが、 SO_RCVBUF は効果がない。 データグラム・ソケットでは、 SO_SNDBUF の値が出力データグラムの上限サイズとなる。 実際の上限値は、 SO_SNDBUF オプションとして設定された値の 2倍 (socket(7) 参照) からオーバヘッドとして使用される 32 バイトを引いた値となる。

補助メッセージ

補助データを送受するには、 sendmsg(2) や recvmsg(2) を使用する。 歴史的な理由により、以下に示す補助メッセージの型は たとえ AF_UNIX 固有のものであっても SOL_SOCKET 型で指定する。 これらを送るには、構造体 cmsghdrcmsg_level フィールドに SOL_SOCKET をセットし、 cmsg_type フィールドにタイプをセットする。 詳細は cmsg(3) を見よ。
SCM_RIGHTS
他のプロセスでオープンされたファイルディスクリプタのセットを送受信する。 データ部分にファイルディスクリプタの整数配列が入っている。 渡されたファイルディスクリプタは、あたかも dup(2) で生成されたかのように振る舞う。
SCM_CREDENTIALS
Unix 信任状を送受信する。これは認証に用いることができる。 信任状は、 struct ucred の補助メッセージとして渡される。 この構造体は <sys/socket.h> で以下のように定義されている。

struct ucred {
    pid_t pid;    /* process ID of the sending process */
    uid_t uid;    /* user ID of the sending process */
    gid_t gid;    /* group ID of the sending process */
};

glibc 2.8 以降では、この構造体の定義を得るためには機能検査マクロ _GNU_SOURCE を定義しなければならない。

送信側が指定した信任状は、カーネルがチェックする。 実効ユーザー ID が 0 のプロセスには、 自分自身以外の値を指定する事が許される。 送信側は以下の 3 つを指定しなければならない。 1) 自分自身のプロセス ID (CAP_SYS_ADMIN 権限を持っていない場合)、 2) 自分自身のユーザー ID あるいは実効ユーザー ID か保存 set-user-ID (CAP_SETUID 権限を持っていない場合)、 3) 自分自身のグループ ID あるいは実行グループ ID か保存 set-group-ID (CAP_SETGID を持っていない場合)。 struct ucred メッセージを受信するためには、ソケットに対し SO_PASSCRED オプションを有効にしなくてはならない。

エラー

EADDRINUSE
選択したソケットが既に用いられていた。または、 ファイルシステムのソケットオブジェクトが既に存在していた。
ECONNREFUSED
listen 状態にないソケットオブジェクトに対して connect(2) が呼ばれた。リモートソケットが存在していなかった、 ファイル名がソケットではなかった、などのときに起こる。
ECONNRESET
リモートソケットが予期しないかたちでクローズされた。
EFAULT
ユーザーメモリアドレスが不正。
EINVAL
渡した引数が不正。よくある原因は、 渡したアドレスの sun_type フィールドに AF_UNIX を設定しなかった、 行おうとした操作に対してソケットの状態が有効ではなかった、など。
EISCONN
既に接続されているソケットに対して connect(2) が呼ばれた。または、指定したターゲットアドレスが 既に接続済みのソケットだった。
ENOMEM
メモリが足りない。
ENOTCONN
ソケット操作にターゲットアドレスが必要だが、 このソケットは接続されていない。
EOPNOTSUPP
ストリーム指向でないソケットに対してストリーム操作が呼び出された。 または帯域外データオプションを用いようとした。
EPERM
送信者が struct ucred に不正な信任状を渡した。
EPIPE
リモートソケットがストリームソケット上でクローズされた。 可能な場合は SIGPIPE も同時に送られる。これを避けるには MSG_NOSIGNAL フラグを sendmsg(2) や recvmsg(2) に渡す。
EPROTONOSUPPORT
渡されたプロトコルが AF_UNIX でない。
EPROTOTYPE
リモートソケットとローカルソケットのタイプが一致していなかった (SOCK_DGRAMSOCK_STREAM)。
ESOCKTNOSUPPORT
未知のソケットタイプ。

他にも汎用のソケット層でエラーが起こったり、 ファイルシステム上にソケットオブジェクトを作ろうとした場合に ファイルシステムのエラーが起こることがある。 それぞれの詳細は適切な man ページを参照すること。

バージョン

SCM_CREDENTIALS と抽象名前空間は、Linux 2.2 で導入された。 移植性が必要なプログラムでは使うべきではない。 (BSD 由来のシステムの中にも信任状の送受信をサポートしているものがあるが、 その実装の詳細はシステムによって異なる)

注意

Linux の実装では、ファイルシステム上から見えるソケットは、 それらが置かれているディレクトリのパーミッションに従う。 ソケットの所有者、グループ、パーミッションは変更できる。 新しいソケットを作るとき、作ろうとするディレクトリに対して プロセスが書き込みと検索 (実行) 権限を持っていなければ、作成に失敗する。 ソケットオブジェクトに接続するには、 read/write 権限が必要である。 この動作は、多くの BSD 由来のシステムとは異なっている (BSD では Unix ソケットに対してはパーミッションを無視する)。 移植性の必要なプログラムでは、 セキュリティをこの仕様に依存してはならない。

ファイル名を指定してソケットにバインドすると、 ファイルシステムにソケットが生成される。 これは必要なくなったときに呼びだしたユーザーが削除しなければならない (unlink(2) を用いる)。 Unix で通常使われる「背後で閉じる方式」が適用される。 ソケットはいつでも unlink することができ、最後の参照が クローズされたときにファイルシステムから削除される。

SOCK_STREAM 上でファイルディスクリプタや信任状を渡すためには、同じ sendmsg(2) や recvmsg(2) コールで補助データ以外のデータを少なくとも 1 バイト送信/受信する必要がある。

Unix ドメインのストリーム・ソケットでは、 帯域外データの概念はサポートされない。

bind(2) 参照。