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