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