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