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);
struct cmsghdr { socklen_t cmsg_len; /* data byte count, including header */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by unsigned char cmsg_data[]; */ };
補助データは struct cmsghdr 構造体のシーケンスに追加データが付加されたものである。 このシーケンスにはこのマニュアルページに書かれている マクロを使ってアクセスすべきで、直接アクセスすべきではない。 使用可能な制御メッセージのタイプについては、 それぞれのプロトコルのマニュアルページを参照のこと。 接続毎の最大補助用バッファサイズは net.core.optmem_max sysctl を使って設定できる。 socket(7) を参照。
CMSG_FIRSTHDR() は、渡した msghdr に関連した補助データバッファ中の、最初の cmsghdr へのポインタを返す。
CMSG_NXTHDR() は、渡した cmsghdr の次にくる (有効な) cmsghdr を返す。 バッファに十分な空きが無い場合、NULL を返す。
CMSG_ALIGN() に長さを与えると、必要なアラインメントを加味した長さを返してくる。 これは定数式である。
CMSG_SPACE() は、与えたデータ長が占めるのに必要な補助要素 (ancillary element) の バイト数を返す。これは定数式である。
CMSG_DATA() は、 cmsghdr のデータ部分へのポインタを返す。
CMSG_LEN() は、 cmsghdr 構造体の cmsg_len メンバにデータを格納する際に必要な値を返す。アラインメントも考慮に入れ られる。 引数としてデータ長をとる。これは定数式である。
補助データを作るためには最初に msghdr のメンバー msg_controllen を、制御メッセージバッファの長さで初期化する。 CMSG_FIRSTHDR() を msghdr に用いると最初の制御メッセージが得られ、 CMSG_NEXTHDR を使うと次の制御メッセージが得られる。 それぞれの制御メッセージでは、 cmsg_len を初期化する (CMSG_LEN() を使う)。 その他の cmsghdr ヘッダーフィールド、そしてデータ部分に対しても CMSG_DATA() を使って初期化をする。 最後に msghdr の msg_controllen フィールドに、バッファ中の制御メッセージの長さの CMSG_SPACE() の合計がセットされる。 msghdr についての詳細は recvmsg(2) を参照。
制御メッセージバッファが全てのメッセージを納めるのには短すぎる場合、 msghdr の msg_flags メンバーに MSG_CTRUNC フラグがセットされる。
Linux では CMSG_LEN(), CMSG_DATA(), CMSG_ALIGN() は定数式である (それらの引数が定数とみなされる)。 このことは、大域変数のサイズを宣言するのに使える。 しかし移植性はなくなるだろう。
struct msghdr msgh; struct cmsghdr *cmsg; int *ttlptr; 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) { ttlptr = (int *) CMSG_DATA(cmsg); received_ttl = *ttlptr; 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 buf[CMSG_SPACE(sizeof myfds)]; /* ancillary data buffer */ int *fdptr; msg.msg_control = buf; msg.msg_controllen = sizeof buf; cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD); /* Initialize the payload: */ fdptr = (int *) CMSG_DATA(cmsg); memcpy(fdptr, myfds, NUM_FD * sizeof(int)); /* Sum of the length of all control messages in the buffer: */ msg.msg_controllen = cmsg->cmsg_len;
RFC 2292