xref: /freebsd/share/man/man3/CMSG_DATA.3 (revision c8b8b38e5f605f3c85bd7c8723b147734905565a)
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