| CMSG_DATA(3) | Library Functions Manual | CMSG_DATA(3) | 
CMSG_DATA, CMSG_FIRSTHDR,
  CMSG_LEN, CMSG_NXTHDR,
  CMSG_SPACE —
#include <sys/socket.h>
unsigned char *
  
  CMSG_DATA(struct
    cmsghdr *);
const unsigned char *
  
  CCMSG_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:
CMSG_DATA(cmsg)CMSG_FIRSTHDR(mhdr)NULL.CMSG_LEN(len)CMSG_NXTHDR(mhdr,
    cmsg)NULL.CMSG_SPACE(len)
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);
| January 24, 2015 | NetBSD 9.4 |