CMSG(3) Linux Programmer's Manual CMSG(3)

名前

CMSG_ALIGN, CMSG_SPACE, CMSG_NXTHDR, CMSG_FIRSTHDR - 補助データにアクセスする。

書式

#include <sys/socket.h>
struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh);
struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh,
                            struct cmsghdr *cmsg);
size_t CMSG_ALIGN(size_t length);
size_t CMSG_SPACE(size_t length);
size_t CMSG_LEN(size_t length);
unsigned char *CMSG_DATA(struct cmsghdr *cmsg);

説明

これらのマクロは制御メッセージ (補助データ (ancillary data) とも呼ばれる) を作り、 それにアクセスするために使われる。 制御メッセージはソケットにのるデータではない。 この制御情報は、到着したパケットへのインターフェイス、様々なあまり 使われないヘッダーフィールド、エラー記述の拡張、ファイルデスクリ プタの集合や、UNIXにおける信頼情報 (credential) を含んでいる。 制御メッセージは、例えば IP オプションのような追加ヘッダーフィールドを 送るのに使う事ができる。 補助データは、 sendmsg(2) を呼び出して送り、 recvmsg(2) を呼び出して受け取る。 詳細はそれらのマニュアルページを参照。

補助データは cmsghdr 構造体のシーケンスに追加データが付加されたものである。使用可能な制御メッセージのタイプについては、 それぞれのプロトコルのマニュアルページを参照のこと。接続毎の最大補助用バッファーサイズは /proc/sys/net/core/optmem_max を使って設定できる。 socket(7) を参照。

cmsghdr 構造体は以下のように定義されている。


struct cmsghdr {
    size_t cmsg_len;    /* Data byte count, including header
                           (type is socklen_t in POSIX) */
    int    cmsg_level;  /* Originating protocol */
    int    cmsg_type;   /* Protocol-specific type */
/* followed by
   unsigned char cmsg_data[]; */
};

The sequence of cmsghdr structures should never be accessed directly. Instead, use only the following macros:

When initializing a buffer that will contain a series of cmsghdr structures (e.g., to be sent with sendmsg(2)), that buffer should first be zero-initialized to ensure the correct operation of CMSG_NXTHDR().

補助データを作るためには最初に msghdr のメンバー msg_controllen を、制御メッセージバッファーの長さで初期化する。 CMSG_FIRSTHDR() を msghdr に用いると最初の制御メッセージが得られ、 CMSG_NXTHDR() を使うと次の制御メッセージが得られる。 それぞれの制御メッセージでは、 cmsg_len を初期化する (CMSG_LEN() を使う)。 その他の cmsghdr ヘッダーフィールド、そしてデータ部分に対しても CMSG_DATA() を使って初期化をする。 最後に msghdrmsg_controllen フィールドに、バッファー中の制御メッセージの長さの CMSG_SPACE() の合計がセットされる。 msghdr についての詳細は recvmsg(2) を参照。

準拠

This ancillary data model conforms to the POSIX.1g draft, 4.4BSD-Lite, the IPv6 advanced API described in RFC 2292 and SUSv2. CMSG_FIRSTHDR(), CMSG_NXTHDR(), and CMSG_DATA() are specified in POSIX.1-2008. CMSG_SPACE() and CMSG_LEN() will be included in the next POSIX release (Issue 8).

CMSG_ALIGN() is a Linux extension.

注意

移植性のために、補助データへのアクセスには、 ここで述べられているマクロだけを使うべきである。 CMSG_ALIGN() は Linux での拡張であり、移植性を考えたプログラムでは使うべきではない。

In Linux, CMSG_LEN(), CMSG_DATA(), and CMSG_ALIGN() are constant expressions (assuming their argument is constant), meaning that these values can be used to declare the size of global variables. This may not be portable, however.

次のコードは、受け取った補助バッファーから IP_TTL オプションを探すものである。


struct msghdr msgh;
struct cmsghdr *cmsg;
int received_ttl;
/* Receive auxiliary data in msgh */
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
        cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
    if (cmsg->cmsg_level == IPPROTO_IP
            && cmsg->cmsg_type == IP_TTL) {
        memcpy(&receive_ttl, CMSG_DATA(cmsg), sizeof(received_ttl));
        break;
    }
}
if (cmsg == NULL) {
    /* Error: IP_TTL not enabled or small buffer or I/O error */
}

以下のコードは、 SCM_RIGHTS を使い、ファイルディスクリプターの配列を UNIX ドメインソケットを通して送るものである。


struct msghdr msg = { 0 };
struct cmsghdr *cmsg;
int myfds[NUM_FD];  /* Contains the file descriptors to pass */
char iobuf[1];
struct iovec io = {
    .iov_base = iobuf,
    .iov_len = sizeof(iobuf)
};
union {         /* Ancillary data buffer, wrapped in a union
                   in order to ensure it is suitably aligned */
    char buf[CMSG_SPACE(sizeof(myfds))];
    struct cmsghdr align;
} u;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = u.buf;
msg.msg_controllen = sizeof(u.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(myfds));
memcpy(CMSG_DATA(cmsg), myfds, sizeof(myfds));

関連項目

recvmsg(2), sendmsg(2)

RFC 2292

この文書について

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

2020-11-01 Linux