1.\" Written by Jared Yanovich <jaredy@openbsd.org> 2.\" Public domain, July 3, 2005 3.\" 4.\" $FreeBSD$ 5.Dd August 19, 2018 6.Dt CMSG_DATA 3 7.Os 8.Sh NAME 9.Nm CMSG_DATA , 10.Nm CMSG_FIRSTHDR , 11.Nm CMSG_LEN , 12.Nm CMSG_NXTHDR , 13.Nm CMSG_SPACE 14.Nd socket control message routines for ancillary data access 15.Sh SYNOPSIS 16.In sys/socket.h 17.Ft unsigned char * 18.Fn CMSG_DATA "struct cmsghdr *" 19.Ft struct cmsghdr * 20.Fn CMSG_FIRSTHDR "struct msghdr *" 21.Ft size_t 22.Fn CMSG_LEN "size_t" 23.Ft struct cmsghdr * 24.Fn CMSG_NXTHDR "struct msghdr *" "struct cmsghdr *" 25.Ft size_t 26.Fn CMSG_SPACE "size_t" 27.Sh DESCRIPTION 28The control message API is used to construct ancillary data objects for 29use in control messages sent and received across sockets. 30.Pp 31Control messages are passed around by the 32.Xr recvmsg 2 33and 34.Xr sendmsg 2 35system calls. 36The 37.Vt cmsghdr 38structure, described in 39.Xr recvmsg 2 , 40is used to specify a chain of control messages. 41.Pp 42These routines should be used instead of directly accessing the control 43message header members and data buffers as they ensure that necessary 44alignment constraints are met. 45.Pp 46The following routines are provided: 47.Bl -tag -width Ds 48.It Fn CMSG_DATA cmsg 49This routine accesses the data portion of the control message header 50.Fa cmsg . 51It ensures proper alignment constraints on the beginning of ancillary 52data are met. 53.It Fn CMSG_FIRSTHDR mhdr 54This routine accesses the first control message attached to the 55message 56.Fa msg . 57If no control messages are attached to the message, this routine 58returns 59.Dv NULL . 60.It Fn CMSG_LEN len 61This routine determines the size in bytes of a control message, 62which includes the control message header. 63.Fa len 64specifies the length of the data held by the control message. 65This value is what is normally stored in the 66.Fa cmsg_len 67of each control message. 68This routine accounts for any alignment constraints on the beginning of 69ancillary data. 70.It Fn CMSG_NXTHDR mhdr cmsg 71This routine returns the location of the control message following 72.Fa cmsg 73in the message 74.Fa mhdr . 75If 76.Fa cmsg 77is the last control message in the chain, this routine returns 78.Dv NULL . 79.It Fn CMSG_SPACE len 80This routine determines the size in bytes needed to hold a control 81message and its contents of length 82.Fa len , 83which includes the control message header. 84This value is what is normally stored in 85.Fa msg_msgcontrollen . 86This routine accounts for any alignment constraints on the beginning of 87ancillary data as well as any needed to pad the next control message. 88.El 89.Sh EXAMPLES 90The following example constructs a control message containing a file descriptor 91in the parent process and passes it over a pre-shared socket over the child 92process. 93Then the child process sends a "hello" string to the parent process using the 94received file descriptor. 95.Bd -literal 96#include <sys/socket.h> 97 98#include <err.h> 99#include <stdio.h> 100#include <string.h> 101#include <sysexits.h> 102#include <unistd.h> 103 104#define HELLOLEN sizeof("hello") 105 106int 107main() 108{ 109 struct msghdr msg; 110 union { 111 struct cmsghdr hdr; 112 unsigned char buf[CMSG_SPACE(sizeof(int))]; 113 } cmsgbuf; 114 char buf[HELLOLEN]; 115 int hellofd[2]; 116 int presharedfd[2]; 117 struct cmsghdr *cmsg; 118 119 if (socketpair(PF_LOCAL, SOCK_STREAM, 0, presharedfd) == -1) 120 err(EX_OSERR, "failed to create a pre-shared socket pair"); 121 122 memset(&msg, 0, sizeof(msg)); 123 msg.msg_control = &cmsgbuf.buf; 124 msg.msg_controllen = sizeof(cmsgbuf.buf); 125 msg.msg_iov = NULL; 126 msg.msg_iovlen = 0; 127 128 switch (fork()) { 129 case -1: 130 err(EX_OSERR, "fork"); 131 case 0: 132 close(presharedfd[0]); 133 strlcpy(buf, "hello", HELLOLEN); 134 135 if (recvmsg(presharedfd[1], &msg, 0) == -1) 136 err(EX_IOERR, "failed to receive a message"); 137 if (msg.msg_flags & (MSG_CTRUNC | MSG_TRUNC)) 138 errx(EX_IOERR, "control message truncated"); 139 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 140 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 141 if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && 142 cmsg->cmsg_level == SOL_SOCKET && 143 cmsg->cmsg_type == SCM_RIGHTS) { 144 hellofd[1] = *(int *)CMSG_DATA(cmsg); 145 printf("child: sending '%s'\n", buf); 146 if (write(hellofd[1], buf, HELLOLEN) == -1) 147 err(EX_IOERR, "failed to send 'hello'"); 148 } 149 } 150 break; 151 default: 152 close(presharedfd[1]); 153 154 if (socketpair(PF_LOCAL, SOCK_STREAM, 0, hellofd) == -1) 155 err(EX_OSERR, "failed to create a 'hello' socket pair"); 156 157 cmsg = CMSG_FIRSTHDR(&msg); 158 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 159 cmsg->cmsg_level = SOL_SOCKET; 160 cmsg->cmsg_type = SCM_RIGHTS; 161 *(int *)CMSG_DATA(cmsg) = hellofd[1]; 162 163 if (sendmsg(presharedfd[0], &msg, 0) == -1) 164 err(EX_IOERR, "sendmsg"); 165 close(hellofd[1]); 166 167 if (read(hellofd[0], buf, HELLOLEN) == -1) 168 err(EX_IOERR, "faild to receive 'hello'"); 169 printf("parent: received '%s'\n", buf); 170 break; 171 } 172 173 return (0); 174} 175.Ed 176.Sh SEE ALSO 177.Xr recvmsg 2 , 178.Xr sendmsg 2 , 179.Xr socket 2 , 180.Xr ip 4 , 181.Xr ip6 4 , 182.Xr unix 4 183.Sh STANDARDS 184.Bl -item 185.It 186.Rs 187.%A W. Stevens 188.%A M. Thomas 189.%T "Advanced Sockets API for IPv6" 190.%R RFC 2292 191.%D February 1998 192.Re 193.It 194.Rs 195.%A W. Stevens 196.%A M. Thomas 197.%A E. Nordmark 198.%A T. Jinmei 199.%T "Advanced Sockets Application Program Interface (API) for IPv6" 200.%R RFC 3542 201.%D May 2003 202.Re 203.El 204.Sh HISTORY 205The control message API first appeared in 206.Bx 4.2 . 207This manual page was originally written by 208.An Jared Yanovich Aq Mt jaredy@OpenBSD.org 209for 210.Ox 3.8 211and eventually brought to 212.Fx 12.0 213by 214.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org . 215