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