CMSG_DATA.3 revision 1.6
$NetBSD: CMSG_DATA.3,v 1.6 2025/03/26 14:12:16 riastradh Exp $
$OpenBSD: CMSG_DATA.3,v 1.5 2008/03/24 16:11:07 deraadt Exp $
Written by Jared Yanovich <jaredy@openbsd.org>
Public domain, July 3, 2005
.Dd January 24, 2015 .Dt CMSG_DATA 3 .Os .Sh NAME .Nm CMSG_DATA , .Nm CMSG_FIRSTHDR , .Nm CMSG_LEN , .Nm CMSG_NXTHDR , .Nm CMSG_SPACE .Nd socket control message routines .Sh SYNOPSIS n sys/socket.h .Ft unsigned char * .Fn CMSG_DATA "struct cmsghdr *" .Ft const unsigned char * .Fn CCMSG_DATA "struct cmsghdr *" .Ft struct cmsghdr * .Fn CMSG_FIRSTHDR "struct msghdr *" .Ft size_t .Fn CMSG_LEN "size_t" .Ft struct cmsghdr * .Fn CMSG_NXTHDR "struct msghdr *" "struct cmsghdr *" .Ft size_t .Fn CMSG_SPACE "size_t" .Sh DESCRIPTION The control message API is used to construct ancillary data objects for use in control messages sent and received across sockets.

p Control messages are passed around by the .Xr recvmsg 2 and .Xr sendmsg 2 system calls. The .Vt cmsghdr structure, described in .Xr recvmsg 2 , is used to specify a chain of control messages.

p 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.

p The following routines are provided: l -tag -width Ds t Fn CMSG_DATA cmsg This routine accesses the data portion of the control message header .Fa cmsg . It ensures proper alignment constraints on the beginning of ancillary data are met. t Fn CMSG_FIRSTHDR mhdr This routine accesses the first control message attached to the message .Fa msg . If no control messages are attached to the message, this routine returns .Dv NULL . t Fn CMSG_LEN len This routine determines the size in bytes of a control message, which includes the control message header. .Fa len specifies the length of the data held by the control message.

p This value is what is normally stored in the .Fa cmsg_len of each control message.

p This routine accounts for any alignment constraints on the beginning of ancillary data.

p If .Fa len is an integer constant expression, then .Fn CMSG_LEN len is an integer constant expression. t Fn CMSG_NXTHDR mhdr cmsg This routine returns the location of the control message following .Fa cmsg in the message .Fa mhdr . If .Fa cmsg is the last control message in the chain, this routine returns .Dv NULL . t Fn CMSG_SPACE len This routine determines the size in bytes needed to hold a control message and its contents of length .Fa len , which includes the control message header.

p This value is what is normally stored in .Fa msg_msgcontrollen .

p This routine accounts for any alignment constraints on the beginning of ancillary data as well as any needed to pad the next control message.

p If .Fa len is an integer constant expression, then .Fn CMSG_SPACE len is an integer constant expression. .El .Sh EXAMPLES The following example constructs a control message containing a file descriptor and passes it over a socket: d -literal -offset indent 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; (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"); .Ed

p And an example that receives the control message and handles all the file descriptors it receives: d -literal -offset indent struct msghdr msg; struct cmsghdr *cmsg; union { struct cmsghdr hdr; unsigned char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; (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_CTRUNC) warnx("control message truncated"); for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int *fdp = (int *)CMSG_DATA(cmsg); socklen_t nbytes = cmsg->cmsg_len - CMSG_LEN(0); socklen_t nfds = nbytes/sizeof(fdp[0]); assert(nbytes % sizeof(fdp[0]) == 0); while (nfds --> 0) { int fd = *fdp++; /* Do something with the descriptor. */ } } } .Ed

p Note that even if the receiver .Em intends to size its control buffer for .Em one file descriptor with .Li CMSG_SPACE(sizeof(int)) , this size may be rounded up for alignment to enough space for more than one file descriptor. So if the sender may send more than one file descriptor at a time, the receiver cannot restrict itself to receiving at most one at a time, and must be prepared to handle all of them \(em otherwise they will simply leak on the receiver side. .Sh SEE ALSO .Xr recvmsg 2 , .Xr sendmsg 2 , .Xr socket 2 .Sh HISTORY The control message API first appeared in x 4.2 .