CMSG_DATA(3) | Library Functions Manual | CMSG_DATA(3) |
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 cmsghdr 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:
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);
June 20, 2008 | NetBSD 6.1 |