xref: /openbsd-src/lib/libutil/imsg_init.3 (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1.\" $OpenBSD: imsg_init.3,v 1.15 2015/12/29 18:05:23 benno 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: December 29 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 resizeable 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.
406If
407.Fa buf
408is a NULL pointer, no action occurs.
409.Pp
410The
411.Fn msgbuf_init
412function initializes
413.Fa msgbuf
414so that buffers may be appended to it.
415The
416.Em fd
417member should also be set directly before
418.Fn msgbuf_write
419is used.
420.Pp
421.Fn msgbuf_clear
422empties a msgbuf, removing and discarding any queued buffers.
423.Pp
424The
425.Fn msgbuf_write
426routine calls
427.Xr sendmsg 2
428to transmit buffers queued in
429.Fa msgbuf .
430It returns 1 if it succeeds, \-1 on error, and 0 when the queue was empty
431or an EOF condition on the socket is detected.
432Temporary resource shortages are returned with errno
433.Er EAGAIN
434and require the application to retry again in the future.
435.Pp
436.Fn msgbuf_drain
437discards data from buffers queued in
438.Fa msgbuf
439until
440.Fa n
441bytes have been removed or
442.Fa msgbuf
443is empty.
444.Sh EXAMPLES
445In a typical program, a channel between two processes is created with
446.Xr socketpair 2 ,
447and an
448.Em imsgbuf
449created around one file descriptor in each process:
450.Bd -literal -offset indent
451struct imsgbuf	parent_ibuf, child_ibuf;
452int		imsg_fds[2];
453
454if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1)
455	err(1, "socketpair");
456
457switch (fork()) {
458case -1:
459	err(1, "fork");
460case 0:
461	/* child */
462	close(imsg_fds[0]);
463	imsg_init(&child_ibuf, imsg_fds[1]);
464	exit(child_main(&child_ibuf));
465}
466
467/* parent */
468close(imsg_fds[1]);
469imsg_init(&parent_ibuf, imsg_fds[0]);
470exit(parent_main(&parent_ibuf));
471.Ed
472.Pp
473Messages may then be composed and queued on the
474.Em imsgbuf ,
475for example using the
476.Fn imsg_compose
477function:
478.Bd -literal -offset indent
479enum imsg_type {
480	IMSG_A_MESSAGE,
481	IMSG_MESSAGE2
482};
483
484int
485child_main(struct imsgbuf *ibuf)
486{
487	int	idata;
488	...
489	idata = 42;
490	imsg_compose(ibuf, IMSG_A_MESSAGE,
491		0, 0, -1, &idata, sizeof idata);
492	...
493}
494.Ed
495.Pp
496A mechanism such as
497.Xr poll 2
498or the
499.Xr event 3
500library is used to monitor the socket file descriptor.
501When the socket is ready for writing, queued messages are transmitted with
502.Fn msgbuf_write :
503.Bd -literal -offset indent
504	if (msgbuf_write(&ibuf-\*(Gtw) \*(Lt= 0 && errno != EAGAIN) {
505		/* handle write failure */
506	}
507.Ed
508.Pp
509And when ready for reading, messages are first received using
510.Fn imsg_read
511and then extracted with
512.Fn imsg_get :
513.Bd -literal -offset indent
514void
515dispatch_imsg(struct imsgbuf *ibuf)
516{
517	struct imsg	imsg;
518	ssize_t         n, datalen;
519	int		idata;
520
521	if (((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) || n == 0) {
522		/* handle socket error */
523	}
524
525	for (;;) {
526		if ((n = imsg_get(ibuf, &imsg)) == -1) {
527			/* handle read error */
528		}
529		if (n == 0)	/* no more messages */
530			return;
531		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
532
533		switch (imsg.hdr.type) {
534		case IMSG_A_MESSAGE:
535			if (datalen \*(Lt sizeof idata) {
536				/* handle corrupt message */
537			}
538			memcpy(&idata, imsg.data, sizeof idata);
539			/* handle message received */
540			break;
541		...
542		}
543
544		imsg_free(&imsg);
545	}
546}
547.Ed
548.Sh SEE ALSO
549.Xr socketpair 2 ,
550.Xr unix 4
551