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