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