void
*
CMSG_DATA(
struct cmsghdr *
)
struct
cmsghdr
*
CMSG_FIRSTHDR(
struct msghdr *
)
size_t
CMSG_LEN(
size_t
)
struct
cmsghdr
*
CMSG_NXTHDR(
struct msghdr *
, struct cmsghdr *
)
size_t
CMSG_SPACE(
size_t
)
Control messages are passed around by the recvmsg(2) and sendmsg(2) system calls. The structure, described in recvmsg(2), is used to specify a chain of control messages.
These routines should be used instead of directly accessing the control message header members and data buffers as they ensure that necessary alignment constraints are met.
The following routines are provided:
cmsg
)
cmsg
.
It ensures proper alignment constraints on the beginning of ancillary
data are met.
mhdr
)
msg
.
If no control messages are attached to the message, this routine
returns
NULL
.
len
)
len
specifies the length of the data held by the control message.
This value is what is normally stored in the
cmsg_len
of each control message.
This routine accounts for any alignment constraints on the beginning of
ancillary data.
This macro might not evaluate to a compile-time constant.
mhdr
, cmsg
)
cmsg
in the message
mhdr
.
If
cmsg
is the last control message in the chain, this routine returns
NULL
.
len
)
len
,
which includes the control message header.
This value is what is normally stored in
msg_msgcontrollen
.
This routine accounts for any alignment constraints on the beginning of
ancillary data as well as any needed to pad the next control message.
This macro might not evaluate to a compile-time constant.
struct msghdr msg;
struct cmsghdr *cmsg;
/* We use a union to make sure hdr is aligned */
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} *cmsgbuf;
/*
* We allocate in the heap instead of the stack to avoid C99
* variable stack allocation, which breaks gcc -fstack-protector.
*/
if ((cmsgbuf = malloc(sizeof(*cmsgbuf))) == NULL)
err(1, "malloc");
(void)memset(&msg, 0, sizeof(msg));
msg.msg_control = cmsgbuf->buf;
msg.msg_controllen = sizeof(cmsgbuf->buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
if (sendmsg(s, &msg, 0) == -1)
err(1, "sendmsg");
free(cmsgbuf);
And an example that receives and decomposes the control message:
struct msghdr msg;
struct cmsghdr *cmsg;
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} *cmsgbuf;
if ((cmsgbuf = malloc(sizeof(*cmsgbuf))) == NULL)
err(1, "malloc");
(void)memset(&msg, 0, sizeof(msg));
msg.msg_control = cmsgbuf->buf;
msg.msg_controllen = sizeof(cmsgbuf->buf);
if (recvmsg(s, &msg, 0) == -1)
err(1, "recvmsg");
if ((msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC))
errx(1, "control message truncated");
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
fd = *(int *)CMSG_DATA(cmsg);
/* Do something with the descriptor. */
}
}
free(cmsgbuf);