Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
IMSG_INIT(3)		 BSD Library Functions Manual		  IMSG_INIT(3)

NAME
     imsg_init,	imsg_read, imsg_get, imsg_compose, imsg_composev, imsg_create,
     imsg_add, imsg_close, imsg_free, imsg_flush, imsg_clear, ibuf_open,
     ibuf_dynamic, ibuf_add, ibuf_reserve, ibuf_seek, ibuf_size, ibuf_left,
     ibuf_close, ibuf_write, ibuf_free,	msgbuf_init, msgbuf_clear,
     msgbuf_write, msgbuf_drain	-- IPC messaging functions

LIBRARY
     OpenBSD Utilities Library (libopenbsd, -lopenbsd)

SYNOPSIS
     #include <sys/types.h>
     #include <sys/queue.h>
     #include <sys/uio.h>
     #include <imsg.h>

     void
     imsg_init(struct imsgbuf *ibuf, int fd);

     ssize_t
     imsg_read(struct imsgbuf *ibuf);

     ssize_t
     imsg_get(struct imsgbuf *ibuf, struct imsg	*imsg);

     int
     imsg_compose(struct imsgbuf *ibuf,	u_int32_t type,	uint32_t peerid,
	 pid_t pid, int	fd, const void *data, u_int16_t	datalen);

     int
     imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
	 pid_t pid, int	fd, const struct iovec *iov, int iovcnt);

     struct ibuf *
     imsg_create(struct	imsgbuf	*ibuf, u_int32_t type, u_int32_t peerid,
	 pid_t pid, u_int16_t datalen);

     int
     imsg_add(struct ibuf *buf,	const void *data, u_int16_t datalen);

     void
     imsg_close(struct imsgbuf *ibuf, struct ibuf *msg);

     void
     imsg_free(struct imsg *imsg);

     int
     imsg_flush(struct imsgbuf *ibuf);

     void
     imsg_clear(struct imsgbuf *ibuf);

     struct ibuf *
     ibuf_open(size_t len);

     struct ibuf *
     ibuf_dynamic(size_t len, size_t max);

     int
     ibuf_add(struct ibuf *buf,	const void *data, size_t len);

     void *
     ibuf_reserve(struct ibuf *buf, size_t len);

     void *
     ibuf_seek(struct ibuf *buf, size_t	pos, size_t len);

     size_t
     ibuf_size(struct ibuf *buf);

     size_t
     ibuf_left(struct ibuf *buf);

     void
     ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf);

     int
     ibuf_write(struct msgbuf *msgbuf);

     void
     ibuf_free(struct ibuf *buf);

     void
     msgbuf_init(struct	msgbuf *msgbuf);

     void
     msgbuf_clear(struct msgbuf	*msgbuf);

     int
     msgbuf_write(struct msgbuf	*msgbuf);

     void
     msgbuf_drain(struct msgbuf	*msgbuf, size_t	n);

DESCRIPTION
     The imsg functions	provide	a simple mechanism for communication between
     processes using sockets.  Each transmitted	message	is guaranteed to be
     presented to the receiving	program	whole.	They are commonly used in
     privilege separated processes, where processes with different rights are
     required to cooperate.

     A program using these functions should be linked with -lutil.

     The basic imsg_init structure is the imsgbuf, which wraps a file descrip-
     tor and represents	one side of a channel on which messages	are sent and
     received:

	   struct imsgbuf {
		   TAILQ_HEAD(,	imsg_fd)   fds;
		   struct ibuf_read	   r;
		   struct msgbuf	   w;
		   int			   fd;
		   pid_t		   pid;
	   };

     imsg_init() is a routine which initializes	ibuf as	one side of a channel
     associated	with fd.  The file descriptor is used to send and receive mes-
     sages, but	is not closed by any of	the imsg functions.  An	imsgbuf	is
     initialized with the w member as the output buffer	queue, fd with the
     file descriptor passed to imsg_init() and the other members for internal
     use only.

     The imsg_clear() function frees any data allocated	as part	of an imsgbuf.

     imsg_create(), imsg_add() and imsg_close()	are generic construction rou-
     tines for messages	that are to be sent using an imsgbuf.

     imsg_create() creates a new message with header specified by type,	peerid
     and pid.  A pid of	zero uses the process ID returned by getpid(2) when
     ibuf was initialized.  In addition	to this	common imsg header, datalen
     bytes of space may	be reserved for	attaching to this imsg.	 This space is
     populated using imsg_add().  Additionally,	the file descriptor fd may be
     passed over the socket to the other process.  If fd is given, it is
     closed in the sending program after the message is	sent.  A value of -1
     indicates no file descriptor should be passed.  imsg_create() returns a
     pointer to	a new message if it succeeds, NULL otherwise.

     imsg_add()	appends	to imsg	len bytes of ancillary data pointed to by buf.
     It	returns	len if it succeeds, -1 otherwise.

     imsg_close() completes creation of	imsg by	adding it to imsgbuf output
     buffer.

     imsg_compose() is a routine which is used to quickly create and queue an
     imsg.  It takes the same parameters as the	imsg_create(), imsg_add() and
     imsg_close() routines, except that	only one ancillary data	buffer can be
     provided.	This routine returns 1 if it succeeds, -1 otherwise.

     imsg_composev() is	similar	to imsg_compose().  It takes the same parame-
     ters, except that the ancillary data buffer is specified by iovec.

     imsg_flush() is a function	which calls msgbuf_write() in a	loop until all
     imsgs in the output buffer	are sent.  It returns 0	if it succeeds,	-1
     otherwise.

     The imsg_read() routine reads pending data	with recvmsg(2)	and queues it
     as	individual messages on imsgbuf.	 It returns the	number of bytes	read
     on	success, or -1 on error.  A return value of -1 from imsg_read()	inval-
     idates imsgbuf, and renders it suitable only for passing to imsg_clear().

     imsg_get()	fills in an individual imsg pending on imsgbuf into the	struc-
     ture pointed to by	imsg.  It returns the total size of the	message, 0 if
     no	messages are ready, or -1 for an error.	 Received messages are re-
     turned as a struct	imsg, which must be freed by imsg_free() when no
     longer required.  struct imsg has this form:

	   struct imsg {
		   struct imsg_hdr  hdr;
		   int		    fd;
		   void		   *data;
	   };

	   struct imsg_hdr {
		   u_int32_t	    type;
		   u_int16_t	    len;
		   u_int16_t	    flags;
		   u_int32_t	    peerid;
		   u_int32_t	    pid;
	   };

     The header	members	are:

	   type	   A integer identifier, typically used	to express the meaning
		   of the message.

	   len	   The total length of the imsg, including the header and any
		   ancillary data transmitted with the message (pointed	to by
		   the data member of the message itself).

	   flags   Flags used internally by the	imsg functions:	should not be
		   used	by application programs.

	   peerid, pid
		   32-bit values specified on message creation and free	for
		   any use by the caller, normally used	to identify the	mes-
		   sage	sender.

     In	addition, struct imsg has the following:

	   fd	   The file descriptor specified when the message was created
		   and passed using the	socket control message API, or -1 if
		   no file descriptor was sent.

	   data	   A pointer to	the ancillary data transmitted with the	imsg.

     The IMSG_HEADER_SIZE define is the	size of	the imsg message header, which
     may be subtracted from the	len member of struct imsg_hdr to obtain	the
     length of any additional data passed with the message.

     MAX_IMSGSIZE is defined as	the maximum size of a single imsg, currently
     16384 bytes.

BUFFERS
     The imsg API defines functions to manipulate buffers, used	internally and
     during construction of imsgs with imsg_create().  A struct	ibuf is	a sin-
     gle buffer	and a struct msgbuf a queue of output buffers for transmis-
     sion:

	   struct ibuf {
		   TAILQ_ENTRY(ibuf)	    entry;
		   u_char		   *buf;
		   size_t		    size;
		   size_t		    max;
		   size_t		    wpos;
		   size_t		    rpos;
		   int			    fd;
	   };

	   struct msgbuf {
		   TAILQ_HEAD(,	ibuf)	    bufs;
		   u_int32_t		    queued;
		   int			    fd;
	   };

     The ibuf_open() function allocates	a fixed-length buffer.	The buffer may
     not be resized and	may contain a maximum of len bytes.  On	success
     ibuf_open() returns a pointer to the buffer; on failure it	returns	NULL.

     ibuf_dynamic() allocates a	resizeable buffer of initial length len	and
     maximum size max.	Buffers	allocated with ibuf_dynamic() are automati-
     cally grown if necessary when data	is added.

     ibuf_add()	is a routine which appends a block of data to buf.  0 is re-
     turned on success and -1 on failure.

     ibuf_reserve() is used to reserve len bytes in buf.  A pointer to the
     start of the reserved space is returned, or NULL on error.

     ibuf_seek() is a function which returns a pointer to the part of the buf-
     fer at offset pos and of extent len.  NULL	is returned if the requested
     range is outside the part of the buffer in	use.

     ibuf_size() and ibuf_left() are functions which return the	total bytes
     used and available	in buf respectively.

     ibuf_close() appends buf to msgbuf	ready to be sent.

     The ibuf_write() routine transmits	as many	pending	buffers	as possible
     from msgbuf() using writev(2).  It	returns	1 if it	succeeds, -1 on	error
     and 0 when	no buffers were	pending	or an EOF condition on the socket is
     detected.	Temporary resource shortages are returned with errno EAGAIN
     and require the application to retry again	in the future.

     ibuf_free() frees buf and any associated storage.

     The msgbuf_init() function	initializes msgbuf so that buffers may be ap-
     pended to it.  The	fd member should also be set directly before
     msgbuf_write() is used.

     msgbuf_clear() empties a msgbuf, removing and discarding any queued buf-
     fers.

     The msgbuf_write()	routine	calls sendmsg(2) to transmit buffers queued in
     msgbuf.  It returns 1 if it succeeds, -1 on error,	and 0 when the queue
     was empty or an EOF condition on the socket is detected.  Temporary re-
     source shortages are returned with	errno EAGAIN and require the applica-
     tion to retry again in the	future.

     msgbuf_drain() discards data from buffers queued in msgbuf	until n	bytes
     have been removed or msgbuf is empty.

EXAMPLES
     In	a typical program, a channel between two processes is created with
     socketpair(2), and	an imsgbuf created around one file descriptor in each
     process:

	   struct imsgbuf  parent_ibuf,	child_ibuf;
	   int		   imsg_fds[2];

	   if (socketpair(AF_UNIX, SOCK_STREAM,	PF_UNSPEC, imsg_fds) ==	-1)
		   err(1, "socketpair");

	   switch (fork()) {
	   case	-1:
		   err(1, "fork");
	   case	0:
		   /* child */
		   close(imsg_fds[0]);
		   imsg_init(&child_ibuf, imsg_fds[1]);
		   exit(child_main(&child_ibuf));
	   }

	   /* parent */
	   close(imsg_fds[1]);
	   imsg_init(&parent_ibuf, imsg_fds[0]);
	   exit(parent_main(&parent_ibuf));

     Messages may then be composed and queued on the imsgbuf, for example us-
     ing the imsg_compose() function:

	   enum	imsg_type {
		   IMSG_A_MESSAGE,
		   IMSG_MESSAGE2
	   };

	   int
	   child_main(struct imsgbuf *ibuf)
	   {
		   int	   idata;
		   ...
		   idata = 42;
		   imsg_compose(ibuf, IMSG_A_MESSAGE,
			   0, 0, -1, &idata, sizeof idata);
		   ...
	   }

     A mechanism such as poll(2) or the	event(3) library is used to monitor
     the socket	file descriptor.  When the socket is ready for writing,	queued
     messages are transmitted with msgbuf_write():

		   if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
			   /* handle write failure */
		   }

     And when ready for	reading, messages are first received using imsg_read()
     and then extracted	with imsg_get():

	   void
	   dispatch_imsg(struct	imsgbuf	*ibuf)
	   {
		   struct imsg	   imsg;
		   ssize_t	   n, datalen;
		   int		   idata;

		   if ((n = imsg_read(ibuf)) ==	-1 || n	== 0) {
			   /* handle socket error */
		   }

		   for (;;) {
			   if ((n = imsg_get(ibuf, &imsg)) == -1) {
				   /* handle read error	*/
			   }
			   if (n == 0)	   /* no more messages */
				   return;
			   datalen = imsg.hdr.len - IMSG_HEADER_SIZE;

			   switch (imsg.hdr.type) {
			   case	IMSG_A_MESSAGE:
				   if (datalen < sizeof	idata) {
					   /* handle corrupt message */
				   }
				   memcpy(&idata, imsg.data, sizeof idata);
				   /* handle message received */
				   break;
			   ...
			   }

			   imsg_free(&imsg);
		   }
	   }

SEE ALSO
     socketpair(2), unix(4)

BSD				 July 11, 2015				   BSD

NAME | LIBRARY | SYNOPSIS | DESCRIPTION | BUFFERS | EXAMPLES | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=imsg_init&sektion=3&manpath=FreeBSD+12.0-RELEASE+and+Ports>

home | help