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