xref: /freebsd/lib/libopenbsd/imsg_init.3 (revision 90aad5d3e44d137ce80d2ec257de07c7c1367bd3)
1.\" $OpenBSD: imsg_init.3,v 1.13 2015/07/11 16:23:59 deraadt Exp $
2.\"
3.\" Copyright (c) 2010 Nicholas Marriott <nicm@openbsd.org>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
14.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
15.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: July 11 2015 $
18.Dt IMSG_INIT 3
19.Os
20.Sh NAME
21.Nm imsg_init ,
22.Nm imsg_read ,
23.Nm imsg_get ,
24.Nm imsg_compose ,
25.Nm imsg_composev ,
26.Nm imsg_create ,
27.Nm imsg_add ,
28.Nm imsg_close ,
29.Nm imsg_free ,
30.Nm imsg_flush ,
31.Nm imsg_clear ,
32.Nm ibuf_open ,
33.Nm ibuf_dynamic ,
34.Nm ibuf_add ,
35.Nm ibuf_reserve ,
36.Nm ibuf_seek ,
37.Nm ibuf_size ,
38.Nm ibuf_left ,
39.Nm ibuf_close ,
40.Nm ibuf_write ,
41.Nm ibuf_free ,
42.Nm msgbuf_init ,
43.Nm msgbuf_clear ,
44.Nm msgbuf_write ,
45.Nm msgbuf_drain
46.Nd IPC messaging functions
47.Sh SYNOPSIS
48.In sys/types.h
49.In sys/queue.h
50.In sys/uio.h
51.In imsg.h
52.Ft void
53.Fn imsg_init "struct imsgbuf *ibuf" "int fd"
54.Ft ssize_t
55.Fn imsg_read "struct imsgbuf *ibuf"
56.Ft ssize_t
57.Fn imsg_get "struct imsgbuf *ibuf" "struct imsg *imsg"
58.Ft int
59.Fn imsg_compose "struct imsgbuf *ibuf" "u_int32_t type" "uint32_t peerid" \
60    "pid_t pid" "int fd" "const void *data" "u_int16_t datalen"
61.Ft int
62.Fn imsg_composev "struct imsgbuf *ibuf" "u_int32_t type" "u_int32_t peerid" \
63    "pid_t pid" "int fd" "const struct iovec *iov" "int iovcnt"
64.Ft "struct ibuf *"
65.Fn imsg_create "struct imsgbuf *ibuf" "u_int32_t type" "u_int32_t peerid" \
66    "pid_t pid" "u_int16_t datalen"
67.Ft int
68.Fn imsg_add "struct ibuf *buf" "const void *data" "u_int16_t datalen"
69.Ft void
70.Fn imsg_close "struct imsgbuf *ibuf" "struct ibuf *msg"
71.Ft void
72.Fn imsg_free "struct imsg *imsg"
73.Ft int
74.Fn imsg_flush "struct imsgbuf *ibuf"
75.Ft void
76.Fn imsg_clear "struct imsgbuf *ibuf"
77.Ft "struct ibuf *"
78.Fn ibuf_open "size_t len"
79.Ft "struct ibuf *"
80.Fn ibuf_dynamic "size_t len" "size_t max"
81.Ft int
82.Fn ibuf_add "struct ibuf *buf" "const void *data" "size_t len"
83.Ft "void *"
84.Fn ibuf_reserve "struct ibuf *buf" "size_t len"
85.Ft "void *"
86.Fn ibuf_seek "struct ibuf *buf" "size_t pos" "size_t len"
87.Ft size_t
88.Fn ibuf_size "struct ibuf *buf"
89.Ft size_t
90.Fn ibuf_left "struct ibuf *buf"
91.Ft void
92.Fn ibuf_close "struct msgbuf *msgbuf" "struct ibuf *buf"
93.Ft int
94.Fn ibuf_write "struct msgbuf *msgbuf"
95.Ft void
96.Fn ibuf_free "struct ibuf *buf"
97.Ft void
98.Fn msgbuf_init "struct msgbuf *msgbuf"
99.Ft void
100.Fn msgbuf_clear "struct msgbuf *msgbuf"
101.Ft int
102.Fn msgbuf_write "struct msgbuf *msgbuf"
103.Ft void
104.Fn msgbuf_drain "struct msgbuf *msgbuf" "size_t n"
105.Sh DESCRIPTION
106The
107.Nm imsg
108functions provide a simple mechanism for communication between processes
109using sockets.
110Each transmitted message is guaranteed to be presented to the receiving program
111whole.
112They are commonly used in privilege separated processes, where processes with
113different rights are required to cooperate.
114.Pp
115A program using these functions should be linked with
116.Em -lutil .
117.Pp
118The basic
119.Nm
120structure is the
121.Em imsgbuf ,
122which wraps a file descriptor and represents one side of a channel on which
123messages are sent and received:
124.Bd -literal -offset indent
125struct imsgbuf {
126	TAILQ_HEAD(, imsg_fd)	fds;
127	struct ibuf_read	r;
128	struct msgbuf		w;
129	int			fd;
130	pid_t			pid;
131};
132.Ed
133.Pp
134.Fn imsg_init
135is a routine which initializes
136.Fa ibuf
137as one side of a channel associated with
138.Fa fd .
139The file descriptor is used to send and receive messages,
140but is not closed by any of the imsg functions.
141An imsgbuf is initialized with the
142.Em w
143member as the output buffer queue,
144.Em fd
145with the file descriptor passed to
146.Fn imsg_init
147and the other members for internal use only.
148.Pp
149The
150.Fn imsg_clear
151function frees any data allocated as part of an imsgbuf.
152.Pp
153.Fn imsg_create ,
154.Fn imsg_add
155and
156.Fn imsg_close
157are generic construction routines for messages that are to be sent using an
158imsgbuf.
159.Pp
160.Fn imsg_create
161creates a new message with header specified by
162.Fa type ,
163.Fa peerid
164and
165.Fa pid .
166A
167.Fa pid
168of zero uses the process ID returned by
169.Xr getpid 2
170when
171.Fa ibuf
172was initialized.
173In addition to this common imsg header,
174.Fa datalen
175bytes of space may be reserved for attaching to this imsg.
176This space is populated using
177.Fn imsg_add .
178Additionally, the file descriptor
179.Fa fd
180may be passed over the socket to the other process.
181If
182.Fa fd
183is given, it is closed in the sending program after the message is sent.
184A value of \-1 indicates no file descriptor should be passed.
185.Fn imsg_create
186returns a pointer to a new message if it succeeds, NULL otherwise.
187.Pp
188.Fn imsg_add
189appends to
190.Fa imsg
191.Fa len
192bytes of ancillary data pointed to by
193.Fa buf .
194It returns
195.Fa len
196if it succeeds, \-1 otherwise.
197.Pp
198.Fn imsg_close
199completes creation of
200.Fa imsg
201by adding it to
202.Fa imsgbuf
203output buffer.
204.Pp
205.Fn imsg_compose
206is a routine which is used to quickly create and queue an imsg.
207It takes the same parameters as the
208.Fn imsg_create ,
209.Fn imsg_add
210and
211.Fn imsg_close
212routines,
213except that only one ancillary data buffer can be provided.
214This routine returns 1 if it succeeds, \-1 otherwise.
215.Pp
216.Fn imsg_composev
217is similar to
218.Fn imsg_compose .
219It takes the same parameters, except that the ancillary data buffer is specified
220by
221.Fa iovec .
222.Pp
223.Fn imsg_flush
224is a function which calls
225.Fn msgbuf_write
226in a loop until all imsgs in the output buffer are sent.
227It returns 0 if it succeeds, \-1 otherwise.
228.Pp
229The
230.Fn imsg_read
231routine reads pending data with
232.Xr recvmsg 2
233and queues it as individual messages on
234.Fa imsgbuf .
235It returns the number of bytes read on success, or \-1 on error.
236A return value of \-1 from
237.Fn imsg_read
238invalidates
239.Fa imsgbuf ,
240and renders it suitable only for passing to
241.Fn imsg_clear .
242.Pp
243.Fn imsg_get
244fills in an individual imsg pending on
245.Fa imsgbuf
246into the structure pointed to by
247.Fa imsg .
248It returns the total size of the message, 0 if no messages are ready, or \-1
249for an error.
250Received messages are returned as a
251.Em struct imsg ,
252which must be freed by
253.Fn imsg_free
254when no longer required.
255.Em struct imsg
256has this form:
257.Bd -literal -offset indent
258struct imsg {
259	struct imsg_hdr	 hdr;
260	int		 fd;
261	void		*data;
262};
263
264struct imsg_hdr {
265	u_int32_t	 type;
266	u_int16_t	 len;
267	u_int16_t	 flags;
268	u_int32_t	 peerid;
269	u_int32_t	 pid;
270};
271.Ed
272.Pp
273The header members are:
274.Bl -tag -width Ds -offset indent
275.It type
276A integer identifier, typically used to express the meaning of the message.
277.It len
278The total length of the imsg, including the header and any ancillary data
279transmitted with the message (pointed to by the
280.Em data
281member of the message itself).
282.It flags
283Flags used internally by the imsg functions: should not be used by application
284programs.
285.It peerid, pid
28632-bit values specified on message creation and free for any use by the
287caller, normally used to identify the message sender.
288.El
289.Pp
290In addition,
291.Em struct imsg
292has the following:
293.Bl -tag -width Ds -offset indent
294.It fd
295The file descriptor specified when the message was created and passed using the
296socket control message API, or \-1 if no file descriptor was sent.
297.It data
298A pointer to the ancillary data transmitted with the imsg.
299.El
300.Pp
301The IMSG_HEADER_SIZE define is the size of the imsg message header, which
302may be subtracted from the
303.Fa len
304member of
305.Em struct imsg_hdr
306to obtain the length of any additional data passed with the message.
307.Pp
308MAX_IMSGSIZE is defined as the maximum size of a single imsg, currently
30916384 bytes.
310.Sh BUFFERS
311The imsg API defines functions to manipulate buffers, used internally and during
312construction of imsgs with
313.Fn imsg_create .
314A
315.Em struct ibuf
316is a single buffer and a
317.Em struct msgbuf
318a queue of output buffers for transmission:
319.Bd -literal -offset indent
320struct ibuf {
321	TAILQ_ENTRY(ibuf)	 entry;
322	u_char			*buf;
323	size_t			 size;
324	size_t			 max;
325	size_t			 wpos;
326	size_t			 rpos;
327	int			 fd;
328};
329
330struct msgbuf {
331	TAILQ_HEAD(, ibuf)	 bufs;
332	u_int32_t		 queued;
333	int			 fd;
334};
335.Ed
336.Pp
337The
338.Fn ibuf_open
339function allocates a fixed-length buffer.
340The buffer may not be resized and may contain a maximum of
341.Fa len
342bytes.
343On success
344.Fn ibuf_open
345returns a pointer to the buffer; on failure it returns NULL.
346.Pp
347.Fn ibuf_dynamic
348allocates a resizable buffer of initial length
349.Fa len
350and maximum size
351.Fa max .
352Buffers allocated with
353.Fn ibuf_dynamic
354are automatically grown if necessary when data is added.
355.Pp
356.Fn ibuf_add
357is a routine which appends a block of data to
358.Fa buf .
3590 is returned on success and \-1 on failure.
360.Pp
361.Fn ibuf_reserve
362is used to reserve
363.Fa len
364bytes in
365.Fa buf .
366A pointer to the start of the reserved space is returned, or NULL on error.
367.Pp
368.Fn ibuf_seek
369is a function which returns a pointer to the part of the buffer at offset
370.Fa pos
371and of extent
372.Fa len .
373NULL is returned if the requested range is outside the part of the buffer
374in use.
375.Pp
376.Fn ibuf_size
377and
378.Fn ibuf_left
379are functions which return the total bytes used and available in
380.Fa buf
381respectively.
382.Pp
383.Fn ibuf_close
384appends
385.Fa buf
386to
387.Fa msgbuf
388ready to be sent.
389.Pp
390The
391.Fn ibuf_write
392routine transmits as many pending buffers as possible from
393.Fn msgbuf
394using
395.Xr writev 2 .
396It returns 1 if it succeeds, \-1 on error and 0 when no buffers were
397pending or an EOF condition on the socket is detected.
398Temporary resource shortages are returned with errno
399.Er EAGAIN
400and require the application to retry again in the future.
401.Pp
402.Fn ibuf_free
403frees
404.Fa buf
405and any associated storage.
406.Pp
407The
408.Fn msgbuf_init
409function initializes
410.Fa msgbuf
411so that buffers may be appended to it.
412The
413.Em fd
414member should also be set directly before
415.Fn msgbuf_write
416is used.
417.Pp
418.Fn msgbuf_clear
419empties a msgbuf, removing and discarding any queued buffers.
420.Pp
421The
422.Fn msgbuf_write
423routine calls
424.Xr sendmsg 2
425to transmit buffers queued in
426.Fa msgbuf .
427It returns 1 if it succeeds, \-1 on error, and 0 when the queue was empty
428or an EOF condition on the socket is detected.
429Temporary resource shortages are returned with errno
430.Er EAGAIN
431and require the application to retry again in the future.
432.Pp
433.Fn msgbuf_drain
434discards data from buffers queued in
435.Fa msgbuf
436until
437.Fa n
438bytes have been removed or
439.Fa msgbuf
440is empty.
441.Sh EXAMPLES
442In a typical program, a channel between two processes is created with
443.Xr socketpair 2 ,
444and an
445.Em imsgbuf
446created around one file descriptor in each process:
447.Bd -literal -offset indent
448struct imsgbuf	parent_ibuf, child_ibuf;
449int		imsg_fds[2];
450
451if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1)
452	err(1, "socketpair");
453
454switch (fork()) {
455case -1:
456	err(1, "fork");
457case 0:
458	/* child */
459	close(imsg_fds[0]);
460	imsg_init(&child_ibuf, imsg_fds[1]);
461	exit(child_main(&child_ibuf));
462}
463
464/* parent */
465close(imsg_fds[1]);
466imsg_init(&parent_ibuf, imsg_fds[0]);
467exit(parent_main(&parent_ibuf));
468.Ed
469.Pp
470Messages may then be composed and queued on the
471.Em imsgbuf ,
472for example using the
473.Fn imsg_compose
474function:
475.Bd -literal -offset indent
476enum imsg_type {
477	IMSG_A_MESSAGE,
478	IMSG_MESSAGE2
479};
480
481int
482child_main(struct imsgbuf *ibuf)
483{
484	int	idata;
485	...
486	idata = 42;
487	imsg_compose(ibuf, IMSG_A_MESSAGE,
488		0, 0, -1, &idata, sizeof idata);
489	...
490}
491.Ed
492.Pp
493A mechanism such as
494.Xr poll 2
495or the
496.Xr event 3
497library is used to monitor the socket file descriptor.
498When the socket is ready for writing, queued messages are transmitted with
499.Fn msgbuf_write :
500.Bd -literal -offset indent
501	if (msgbuf_write(&ibuf-\*(Gtw) \*(Lt= 0 && errno != EAGAIN) {
502		/* handle write failure */
503	}
504.Ed
505.Pp
506And when ready for reading, messages are first received using
507.Fn imsg_read
508and then extracted with
509.Fn imsg_get :
510.Bd -literal -offset indent
511void
512dispatch_imsg(struct imsgbuf *ibuf)
513{
514	struct imsg	imsg;
515	ssize_t         n, datalen;
516	int		idata;
517
518	if ((n = imsg_read(ibuf)) == -1 || n == 0) {
519		/* handle socket error */
520	}
521
522	for (;;) {
523		if ((n = imsg_get(ibuf, &imsg)) == -1) {
524			/* handle read error */
525		}
526		if (n == 0)	/* no more messages */
527			return;
528		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
529
530		switch (imsg.hdr.type) {
531		case IMSG_A_MESSAGE:
532			if (datalen \*(Lt sizeof idata) {
533				/* handle corrupt message */
534			}
535			memcpy(&idata, imsg.data, sizeof idata);
536			/* handle message received */
537			break;
538		...
539		}
540
541		imsg_free(&imsg);
542	}
543}
544.Ed
545.Sh SEE ALSO
546.Xr socketpair 2 ,
547.Xr unix 4
548