Index: lib/libc/sys/recv.2 =================================================================== --- lib/libc/sys/recv.2 +++ lib/libc/sys/recv.2 @@ -366,6 +366,7 @@ .Xr read 2 , .Xr select 2 , .Xr socket 2 , +.Xr CMSG_DATA 3 , .Xr unix 4 .Sh HISTORY The Index: lib/libc/sys/send.2 =================================================================== --- lib/libc/sys/send.2 +++ lib/libc/sys/send.2 @@ -242,7 +242,8 @@ .Xr recv 2 , .Xr select 2 , .Xr socket 2 , -.Xr write 2 +.Xr write 2 , +.Xr CMSG_DATA 3 .Sh HISTORY The .Fn send Index: lib/libc/sys/socket.2 =================================================================== --- lib/libc/sys/socket.2 +++ lib/libc/sys/socket.2 @@ -299,6 +299,7 @@ .Xr shutdown 2 , .Xr socketpair 2 , .Xr write 2 , +.Xr CMSG_DATA 3 , .Xr getprotoent 3 , .Xr netgraph 4 , .Xr protocols 5 Index: share/man/man3/CMSG_DATA.3 =================================================================== --- /dev/null +++ share/man/man3/CMSG_DATA.3 @@ -0,0 +1,212 @@ +.\" Written by Jared Yanovich +.\" Public domain, July 3, 2005 +.Dd April 26, 2017 +.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 for ancillary data access +.Sh SYNOPSIS +.In sys/socket.h +.Ft unsigned char * +.Fn CMSG_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. +.Pp +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. +.Pp +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. +.Pp +The following routines are provided: +.Bl -tag -width Ds +.It 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. +.It 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 . +.It 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. +This value is what is normally stored in the +.Fa cmsg_len +of each control message. +This routine accounts for any alignment constraints on the beginning of +ancillary data. +.It 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 . +.It 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. +This value is what is normally stored in +.Fa 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. +.El +.Sh EXAMPLES +The following example constructs a control message containing a file descriptor +in the parent process and passes it over a pre-shared socket over the child +process. +Then the child process sends a "hello" string to the parent process using the +received file descriptor. +.Bd -literal +#include + +#include +#include +#include +#include +#include + +#define HELLOLEN sizeof("hello") + +int +main() +{ + struct msghdr msg; + union { + struct cmsghdr hdr; + unsigned char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; + char buf[HELLOLEN]; + int hellofd[2]; + int presharedfd[2]; + struct cmsghdr *cmsg; + + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, presharedfd) == -1) + err(EX_OSERR, "failed to create a pre-shared socket pair"); + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = &cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + + switch (fork()) { + case -1: + err(EX_OSERR, "fork"); + case 0: + close(presharedfd[0]); + strlcpy(buf, "hello", HELLOLEN); + + if (recvmsg(presharedfd[1], &msg, 0) == -1) + err(EX_IOERR, "failed to receive a message"); + if (msg.msg_flags & (MSG_CTRUNC | MSG_TRUNC)) + errx(EX_IOERR, "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) { + hellofd[1] = *(int *)CMSG_DATA(cmsg); + printf("child: sending '%s'\n", buf); + if (write(hellofd[1], buf, HELLOLEN) == -1) + err(EX_IOERR, "failed to send 'hello'"); + } + } + break; + default: + close(presharedfd[1]); + + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, hellofd) == -1) + err(EX_OSERR, "failed to create a 'hello' socket pair"); + + 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) = hellofd[1]; + + if (sendmsg(presharedfd[0], &msg, 0) == -1) + err(EX_IOERR, "sendmsg"); + close(hellofd[1]); + + if (read(hellofd[0], buf, HELLOLEN) == -1) + err(EX_IOERR, "faild to receive 'hello'"); + printf("parent: received '%s'\n", buf); + break; + } + + return (0); +} +.Ed +.Sh SEE ALSO +.Xr recvmsg 2 , +.Xr sendmsg 2 , +.Xr socket 2 , +.Xr ip 4 , +.Xr ip6 4 , +.Xr unix 4 +.Sh STANDARDS +.Bl -item +.It +.Rs +.%A W. Stevens +.%A M. Thomas +.%T "Advanced Sockets API for IPv6" +.%R RFC 2292 +.%D February 1998 +.Re +.It +.Rs +.%A W. Stevens +.%A M. Thomas +.%A E. Nordmark +.%A T. Jinmei +.%T "Advanced Sockets Application Program Interface (API) for IPv6" +.%R RFC 3542 +.%D May 2003 +.Re +.El +.Sh HISTORY +The control message API first appeared in +.Bx 4.2 . +This manual page was originally written by +.An Jared Yanovich Aq Mt jaredy@OpenBSD.org +for +.Ox 3.8 +and eventually brought to +.Fx 12.0 +by +.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . Index: share/man/man3/Makefile =================================================================== --- share/man/man3/Makefile +++ share/man/man3/Makefile @@ -8,6 +8,7 @@ MAN= assert.3 \ ATOMIC_VAR_INIT.3 \ bitstring.3 \ + CMSG_DATA.3 \ end.3 \ fpgetround.3 \ intro.3 \ @@ -57,6 +58,10 @@ bitstring.3 bit_set.3 \ bitstring.3 bitstr_size.3 \ bitstring.3 bit_test.3 +MLINKS+= CMSG_DATA.3 CMSG_FIRSTHDR.3 \ + CMSG_DATA.3 CMSG_LEN.3 \ + CMSG_DATA.3 CMSG_NEXTHDR.3 \ + CMSG_DATA.3 CMSG_SPACE.3 MLINKS+= end.3 edata.3 \ end.3 etext.3 MLINKS+= fpgetround.3 fpgetmask.3 \ Index: share/man/man4/ip.4 =================================================================== --- share/man/man4/ip.4 +++ share/man/man4/ip.4 @@ -888,6 +888,7 @@ .Xr recv 2 , .Xr send 2 , .Xr byteorder 3 , +.Xr CMSG_DATA 3 , .Xr sourcefilter 3 , .Xr icmp 4 , .Xr igmp 4 , Index: share/man/man4/ip6.4 =================================================================== --- share/man/man4/ip6.4 +++ share/man/man4/ip6.4 @@ -651,6 +651,7 @@ .Xr send 2 , .Xr setsockopt 2 , .Xr socket 2 , +.Xr CMSG_DATA 3 , .\" .Xr inet6_option_space 3 , .\" .Xr inet6_rthdr_space 3 , .Xr if_nametoindex 3 , Index: share/man/man4/unix.4 =================================================================== --- share/man/man4/unix.4 +++ share/man/man4/unix.4 @@ -350,6 +350,7 @@ .Xr sendto 2 , .Xr setsockopt 2 , .Xr socket 2 , +.Xr CMSG_DATA 3 , .Xr intro 4 .Rs .%T "An Introductory 4.3 BSD Interprocess Communication Tutorial"