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