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