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