1 3bb9eb8b 2024-01-18 thomas /* $OpenBSD: imsg-buffer.c,v 1.18 2023/12/12 15:47:41 claudio Exp $ */
4 3bb9eb8b 2024-01-18 thomas * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
5 dd038bc6 2021-09-21 thomas.ad * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7 dd038bc6 2021-09-21 thomas.ad * Permission to use, copy, modify, and distribute this software for any
8 dd038bc6 2021-09-21 thomas.ad * purpose with or without fee is hereby granted, provided that the above
9 dd038bc6 2021-09-21 thomas.ad * copyright notice and this permission notice appear in all copies.
11 dd038bc6 2021-09-21 thomas.ad * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 dd038bc6 2021-09-21 thomas.ad * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 dd038bc6 2021-09-21 thomas.ad * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 dd038bc6 2021-09-21 thomas.ad * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 dd038bc6 2021-09-21 thomas.ad * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 dd038bc6 2021-09-21 thomas.ad * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 dd038bc6 2021-09-21 thomas.ad * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 dd038bc6 2021-09-21 thomas.ad #include <sys/types.h>
21 dd038bc6 2021-09-21 thomas.ad #include <sys/socket.h>
22 dd038bc6 2021-09-21 thomas.ad #include <sys/uio.h>
23 3bb9eb8b 2024-01-18 thomas #include <arpa/inet.h>
25 dd038bc6 2021-09-21 thomas.ad #include <limits.h>
26 dd038bc6 2021-09-21 thomas.ad #include <errno.h>
27 3bb9eb8b 2024-01-18 thomas #include <stdint.h>
28 dd038bc6 2021-09-21 thomas.ad #include <stdlib.h>
29 dd038bc6 2021-09-21 thomas.ad #include <string.h>
30 dd038bc6 2021-09-21 thomas.ad #include <unistd.h>
32 dd038bc6 2021-09-21 thomas.ad #include "got_compat.h"
33 4fccd2fe 2023-03-08 thomas #include "imsg.h"
35 dd038bc6 2021-09-21 thomas.ad static int ibuf_realloc(struct ibuf *, size_t);
36 dd038bc6 2021-09-21 thomas.ad static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
37 dd038bc6 2021-09-21 thomas.ad static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
38 3ef3f36a 2023-07-05 op static void msgbuf_drain(struct msgbuf *, size_t);
40 dd038bc6 2021-09-21 thomas.ad struct ibuf *
41 dd038bc6 2021-09-21 thomas.ad ibuf_open(size_t len)
43 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
45 3ef3f36a 2023-07-05 op if (len == 0) {
46 3ef3f36a 2023-07-05 op errno = EINVAL;
47 3ef3f36a 2023-07-05 op return (NULL);
49 dd038bc6 2021-09-21 thomas.ad if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
50 dd038bc6 2021-09-21 thomas.ad return (NULL);
51 3ef3f36a 2023-07-05 op if ((buf->buf = calloc(len, 1)) == NULL) {
52 dd038bc6 2021-09-21 thomas.ad free(buf);
53 dd038bc6 2021-09-21 thomas.ad return (NULL);
55 dd038bc6 2021-09-21 thomas.ad buf->size = buf->max = len;
56 dd038bc6 2021-09-21 thomas.ad buf->fd = -1;
58 dd038bc6 2021-09-21 thomas.ad return (buf);
61 dd038bc6 2021-09-21 thomas.ad struct ibuf *
62 dd038bc6 2021-09-21 thomas.ad ibuf_dynamic(size_t len, size_t max)
64 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
66 3bb9eb8b 2024-01-18 thomas if (max == 0 || max < len) {
67 3ef3f36a 2023-07-05 op errno = EINVAL;
68 dd038bc6 2021-09-21 thomas.ad return (NULL);
71 3ef3f36a 2023-07-05 op if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
72 dd038bc6 2021-09-21 thomas.ad return (NULL);
73 3ef3f36a 2023-07-05 op if (len > 0) {
74 3ef3f36a 2023-07-05 op if ((buf->buf = calloc(len, 1)) == NULL) {
76 3ef3f36a 2023-07-05 op return (NULL);
79 3ef3f36a 2023-07-05 op buf->size = len;
80 3ef3f36a 2023-07-05 op buf->max = max;
83 dd038bc6 2021-09-21 thomas.ad return (buf);
86 dd038bc6 2021-09-21 thomas.ad static int
87 dd038bc6 2021-09-21 thomas.ad ibuf_realloc(struct ibuf *buf, size_t len)
89 3ef3f36a 2023-07-05 op unsigned char *b;
91 dd038bc6 2021-09-21 thomas.ad /* on static buffers max is eq size and so the following fails */
92 3ef3f36a 2023-07-05 op if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
93 dd038bc6 2021-09-21 thomas.ad errno = ERANGE;
94 dd038bc6 2021-09-21 thomas.ad return (-1);
97 c0faa645 2021-09-21 thomas.ad b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
98 dd038bc6 2021-09-21 thomas.ad if (b == NULL)
99 dd038bc6 2021-09-21 thomas.ad return (-1);
100 dd038bc6 2021-09-21 thomas.ad buf->buf = b;
101 dd038bc6 2021-09-21 thomas.ad buf->size = buf->wpos + len;
103 dd038bc6 2021-09-21 thomas.ad return (0);
106 dd038bc6 2021-09-21 thomas.ad void *
107 dd038bc6 2021-09-21 thomas.ad ibuf_reserve(struct ibuf *buf, size_t len)
109 dd038bc6 2021-09-21 thomas.ad void *b;
111 3bb9eb8b 2024-01-18 thomas if (len > SIZE_MAX - buf->wpos || buf->max == 0) {
112 3ef3f36a 2023-07-05 op errno = ERANGE;
113 3ef3f36a 2023-07-05 op return (NULL);
116 dd038bc6 2021-09-21 thomas.ad if (buf->wpos + len > buf->size)
117 dd038bc6 2021-09-21 thomas.ad if (ibuf_realloc(buf, len) == -1)
118 dd038bc6 2021-09-21 thomas.ad return (NULL);
120 dd038bc6 2021-09-21 thomas.ad b = buf->buf + buf->wpos;
121 dd038bc6 2021-09-21 thomas.ad buf->wpos += len;
122 dd038bc6 2021-09-21 thomas.ad return (b);
126 3ef3f36a 2023-07-05 op ibuf_add(struct ibuf *buf, const void *data, size_t len)
130 3ef3f36a 2023-07-05 op if ((b = ibuf_reserve(buf, len)) == NULL)
133 3ef3f36a 2023-07-05 op memcpy(b, data, len);
138 3bb9eb8b 2024-01-18 thomas ibuf_add_ibuf(struct ibuf *buf, const struct ibuf *from)
140 3bb9eb8b 2024-01-18 thomas return ibuf_add(buf, ibuf_data(from), ibuf_size(from));
143 3bb9eb8b 2024-01-18 thomas /* remove after tree is converted */
145 3ef3f36a 2023-07-05 op ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
147 3bb9eb8b 2024-01-18 thomas return ibuf_add_ibuf(buf, from);
151 3ef3f36a 2023-07-05 op ibuf_add_n8(struct ibuf *buf, uint64_t value)
155 3ef3f36a 2023-07-05 op if (value > UINT8_MAX) {
156 3ef3f36a 2023-07-05 op errno = EINVAL;
160 3ef3f36a 2023-07-05 op return ibuf_add(buf, &v, sizeof(v));
164 3ef3f36a 2023-07-05 op ibuf_add_n16(struct ibuf *buf, uint64_t value)
168 3ef3f36a 2023-07-05 op if (value > UINT16_MAX) {
169 3ef3f36a 2023-07-05 op errno = EINVAL;
172 3ef3f36a 2023-07-05 op v = htobe16(value);
173 3ef3f36a 2023-07-05 op return ibuf_add(buf, &v, sizeof(v));
177 3ef3f36a 2023-07-05 op ibuf_add_n32(struct ibuf *buf, uint64_t value)
181 3ef3f36a 2023-07-05 op if (value > UINT32_MAX) {
182 3ef3f36a 2023-07-05 op errno = EINVAL;
185 3ef3f36a 2023-07-05 op v = htobe32(value);
186 3ef3f36a 2023-07-05 op return ibuf_add(buf, &v, sizeof(v));
190 3ef3f36a 2023-07-05 op ibuf_add_n64(struct ibuf *buf, uint64_t value)
192 3ef3f36a 2023-07-05 op value = htobe64(value);
193 3bb9eb8b 2024-01-18 thomas return ibuf_add(buf, &value, sizeof(value));
197 3bb9eb8b 2024-01-18 thomas ibuf_add_h16(struct ibuf *buf, uint64_t value)
199 3bb9eb8b 2024-01-18 thomas uint16_t v;
201 3bb9eb8b 2024-01-18 thomas if (value > UINT16_MAX) {
202 3bb9eb8b 2024-01-18 thomas errno = EINVAL;
203 3bb9eb8b 2024-01-18 thomas return (-1);
205 3bb9eb8b 2024-01-18 thomas v = value;
206 3bb9eb8b 2024-01-18 thomas return ibuf_add(buf, &v, sizeof(v));
210 3bb9eb8b 2024-01-18 thomas ibuf_add_h32(struct ibuf *buf, uint64_t value)
212 3bb9eb8b 2024-01-18 thomas uint32_t v;
214 3bb9eb8b 2024-01-18 thomas if (value > UINT32_MAX) {
215 3bb9eb8b 2024-01-18 thomas errno = EINVAL;
216 3bb9eb8b 2024-01-18 thomas return (-1);
218 3bb9eb8b 2024-01-18 thomas v = value;
219 3bb9eb8b 2024-01-18 thomas return ibuf_add(buf, &v, sizeof(v));
223 3bb9eb8b 2024-01-18 thomas ibuf_add_h64(struct ibuf *buf, uint64_t value)
225 3ef3f36a 2023-07-05 op return ibuf_add(buf, &value, sizeof(value));
229 3ef3f36a 2023-07-05 op ibuf_add_zero(struct ibuf *buf, size_t len)
233 3ef3f36a 2023-07-05 op if ((b = ibuf_reserve(buf, len)) == NULL)
235 3bb9eb8b 2024-01-18 thomas memset(b, 0, len);
239 dd038bc6 2021-09-21 thomas.ad void *
240 dd038bc6 2021-09-21 thomas.ad ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
242 3bb9eb8b 2024-01-18 thomas /* only allow seeking between rpos and wpos */
243 3bb9eb8b 2024-01-18 thomas if (ibuf_size(buf) < pos || SIZE_MAX - pos < len ||
244 3bb9eb8b 2024-01-18 thomas ibuf_size(buf) < pos + len) {
245 3ef3f36a 2023-07-05 op errno = ERANGE;
246 dd038bc6 2021-09-21 thomas.ad return (NULL);
249 3bb9eb8b 2024-01-18 thomas return (buf->buf + buf->rpos + pos);
253 3ef3f36a 2023-07-05 op ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
257 3ef3f36a 2023-07-05 op if ((b = ibuf_seek(buf, pos, len)) == NULL)
260 3ef3f36a 2023-07-05 op memcpy(b, data, len);
265 3ef3f36a 2023-07-05 op ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
269 3ef3f36a 2023-07-05 op if (value > UINT8_MAX) {
270 3ef3f36a 2023-07-05 op errno = EINVAL;
274 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &v, sizeof(v)));
278 3ef3f36a 2023-07-05 op ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
282 3ef3f36a 2023-07-05 op if (value > UINT16_MAX) {
283 3ef3f36a 2023-07-05 op errno = EINVAL;
286 3ef3f36a 2023-07-05 op v = htobe16(value);
287 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &v, sizeof(v)));
291 3ef3f36a 2023-07-05 op ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
295 3ef3f36a 2023-07-05 op if (value > UINT32_MAX) {
296 3ef3f36a 2023-07-05 op errno = EINVAL;
299 3ef3f36a 2023-07-05 op v = htobe32(value);
300 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &v, sizeof(v)));
304 3ef3f36a 2023-07-05 op ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
306 3ef3f36a 2023-07-05 op value = htobe64(value);
307 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &value, sizeof(value)));
311 3bb9eb8b 2024-01-18 thomas ibuf_set_h16(struct ibuf *buf, size_t pos, uint64_t value)
313 3bb9eb8b 2024-01-18 thomas uint16_t v;
315 3bb9eb8b 2024-01-18 thomas if (value > UINT16_MAX) {
316 3bb9eb8b 2024-01-18 thomas errno = EINVAL;
317 3bb9eb8b 2024-01-18 thomas return (-1);
319 3bb9eb8b 2024-01-18 thomas v = value;
320 3bb9eb8b 2024-01-18 thomas return (ibuf_set(buf, pos, &v, sizeof(v)));
324 3bb9eb8b 2024-01-18 thomas ibuf_set_h32(struct ibuf *buf, size_t pos, uint64_t value)
326 3bb9eb8b 2024-01-18 thomas uint32_t v;
328 3bb9eb8b 2024-01-18 thomas if (value > UINT32_MAX) {
329 3bb9eb8b 2024-01-18 thomas errno = EINVAL;
330 3bb9eb8b 2024-01-18 thomas return (-1);
332 3bb9eb8b 2024-01-18 thomas v = value;
333 3bb9eb8b 2024-01-18 thomas return (ibuf_set(buf, pos, &v, sizeof(v)));
337 3bb9eb8b 2024-01-18 thomas ibuf_set_h64(struct ibuf *buf, size_t pos, uint64_t value)
339 3bb9eb8b 2024-01-18 thomas return (ibuf_set(buf, pos, &value, sizeof(value)));
343 3bb9eb8b 2024-01-18 thomas ibuf_data(const struct ibuf *buf)
345 3bb9eb8b 2024-01-18 thomas return (buf->buf + buf->rpos);
348 dd038bc6 2021-09-21 thomas.ad size_t
349 3bb9eb8b 2024-01-18 thomas ibuf_size(const struct ibuf *buf)
351 3bb9eb8b 2024-01-18 thomas return (buf->wpos - buf->rpos);
355 3bb9eb8b 2024-01-18 thomas ibuf_left(const struct ibuf *buf)
357 3bb9eb8b 2024-01-18 thomas if (buf->max == 0)
358 3bb9eb8b 2024-01-18 thomas return (0);
359 dd038bc6 2021-09-21 thomas.ad return (buf->max - buf->wpos);
363 3bb9eb8b 2024-01-18 thomas ibuf_truncate(struct ibuf *buf, size_t len)
365 3bb9eb8b 2024-01-18 thomas if (ibuf_size(buf) >= len) {
366 3bb9eb8b 2024-01-18 thomas buf->wpos = buf->rpos + len;
367 3bb9eb8b 2024-01-18 thomas return (0);
369 3bb9eb8b 2024-01-18 thomas if (buf->max == 0) {
370 3bb9eb8b 2024-01-18 thomas /* only allow to truncate down */
371 3bb9eb8b 2024-01-18 thomas errno = ERANGE;
372 3bb9eb8b 2024-01-18 thomas return (-1);
374 3bb9eb8b 2024-01-18 thomas return ibuf_add_zero(buf, len - ibuf_size(buf));
378 3bb9eb8b 2024-01-18 thomas ibuf_rewind(struct ibuf *buf)
380 3bb9eb8b 2024-01-18 thomas buf->rpos = 0;
384 dd038bc6 2021-09-21 thomas.ad ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
386 dd038bc6 2021-09-21 thomas.ad ibuf_enqueue(msgbuf, buf);
390 3bb9eb8b 2024-01-18 thomas ibuf_from_buffer(struct ibuf *buf, void *data, size_t len)
392 3bb9eb8b 2024-01-18 thomas memset(buf, 0, sizeof(*buf));
393 3bb9eb8b 2024-01-18 thomas buf->buf = data;
394 3bb9eb8b 2024-01-18 thomas buf->size = buf->wpos = len;
395 3bb9eb8b 2024-01-18 thomas buf->fd = -1;
399 3bb9eb8b 2024-01-18 thomas ibuf_from_ibuf(struct ibuf *buf, const struct ibuf *from)
401 3bb9eb8b 2024-01-18 thomas ibuf_from_buffer(buf, ibuf_data(from), ibuf_size(from));
405 3bb9eb8b 2024-01-18 thomas ibuf_get(struct ibuf *buf, void *data, size_t len)
407 3bb9eb8b 2024-01-18 thomas if (ibuf_size(buf) < len) {
408 3bb9eb8b 2024-01-18 thomas errno = EBADMSG;
409 3bb9eb8b 2024-01-18 thomas return (-1);
412 3bb9eb8b 2024-01-18 thomas memcpy(data, ibuf_data(buf), len);
413 3bb9eb8b 2024-01-18 thomas buf->rpos += len;
414 3bb9eb8b 2024-01-18 thomas return (0);
418 3bb9eb8b 2024-01-18 thomas ibuf_get_ibuf(struct ibuf *buf, size_t len, struct ibuf *new)
420 3bb9eb8b 2024-01-18 thomas if (ibuf_size(buf) < len) {
421 3bb9eb8b 2024-01-18 thomas errno = EBADMSG;
422 3bb9eb8b 2024-01-18 thomas return (-1);
425 3bb9eb8b 2024-01-18 thomas ibuf_from_buffer(new, ibuf_data(buf), len);
426 3bb9eb8b 2024-01-18 thomas buf->rpos += len;
427 3bb9eb8b 2024-01-18 thomas return (0);
431 3bb9eb8b 2024-01-18 thomas ibuf_get_n8(struct ibuf *buf, uint8_t *value)
433 3bb9eb8b 2024-01-18 thomas return ibuf_get(buf, value, sizeof(*value));
437 3bb9eb8b 2024-01-18 thomas ibuf_get_n16(struct ibuf *buf, uint16_t *value)
441 3bb9eb8b 2024-01-18 thomas rv = ibuf_get(buf, value, sizeof(*value));
442 3bb9eb8b 2024-01-18 thomas *value = be16toh(*value);
443 3bb9eb8b 2024-01-18 thomas return (rv);
447 3bb9eb8b 2024-01-18 thomas ibuf_get_n32(struct ibuf *buf, uint32_t *value)
451 3bb9eb8b 2024-01-18 thomas rv = ibuf_get(buf, value, sizeof(*value));
452 3bb9eb8b 2024-01-18 thomas *value = be32toh(*value);
453 3bb9eb8b 2024-01-18 thomas return (rv);
457 3bb9eb8b 2024-01-18 thomas ibuf_get_n64(struct ibuf *buf, uint64_t *value)
461 3bb9eb8b 2024-01-18 thomas rv = ibuf_get(buf, value, sizeof(*value));
462 3bb9eb8b 2024-01-18 thomas *value = be64toh(*value);
463 3bb9eb8b 2024-01-18 thomas return (rv);
467 3bb9eb8b 2024-01-18 thomas ibuf_get_h16(struct ibuf *buf, uint16_t *value)
469 3bb9eb8b 2024-01-18 thomas return ibuf_get(buf, value, sizeof(*value));
473 3bb9eb8b 2024-01-18 thomas ibuf_get_h32(struct ibuf *buf, uint32_t *value)
475 3bb9eb8b 2024-01-18 thomas return ibuf_get(buf, value, sizeof(*value));
479 3bb9eb8b 2024-01-18 thomas ibuf_get_h64(struct ibuf *buf, uint64_t *value)
481 3bb9eb8b 2024-01-18 thomas return ibuf_get(buf, value, sizeof(*value));
485 3bb9eb8b 2024-01-18 thomas ibuf_skip(struct ibuf *buf, size_t len)
487 3bb9eb8b 2024-01-18 thomas if (ibuf_size(buf) < len) {
488 3bb9eb8b 2024-01-18 thomas errno = EBADMSG;
489 3bb9eb8b 2024-01-18 thomas return (-1);
492 3bb9eb8b 2024-01-18 thomas buf->rpos += len;
493 3bb9eb8b 2024-01-18 thomas return (0);
497 3ef3f36a 2023-07-05 op ibuf_free(struct ibuf *buf)
499 3ef3f36a 2023-07-05 op if (buf == NULL)
501 3bb9eb8b 2024-01-18 thomas if (buf->max == 0) /* if buf lives on the stack */
502 3bb9eb8b 2024-01-18 thomas abort(); /* abort before causing more harm */
503 3ef3f36a 2023-07-05 op if (buf->fd != -1)
504 3ef3f36a 2023-07-05 op close(buf->fd);
505 3ef3f36a 2023-07-05 op freezero(buf->buf, buf->size);
510 3ef3f36a 2023-07-05 op ibuf_fd_avail(struct ibuf *buf)
512 3ef3f36a 2023-07-05 op return (buf->fd != -1);
516 3ef3f36a 2023-07-05 op ibuf_fd_get(struct ibuf *buf)
520 3ef3f36a 2023-07-05 op fd = buf->fd;
521 3ef3f36a 2023-07-05 op buf->fd = -1;
526 3ef3f36a 2023-07-05 op ibuf_fd_set(struct ibuf *buf, int fd)
528 3bb9eb8b 2024-01-18 thomas if (buf->max == 0) /* if buf lives on the stack */
529 3bb9eb8b 2024-01-18 thomas abort(); /* abort before causing more harm */
530 3ef3f36a 2023-07-05 op if (buf->fd != -1)
531 3ef3f36a 2023-07-05 op close(buf->fd);
532 3ef3f36a 2023-07-05 op buf->fd = fd;
536 dd038bc6 2021-09-21 thomas.ad ibuf_write(struct msgbuf *msgbuf)
538 dd038bc6 2021-09-21 thomas.ad struct iovec iov[IOV_MAX];
539 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
540 dd038bc6 2021-09-21 thomas.ad unsigned int i = 0;
541 dd038bc6 2021-09-21 thomas.ad ssize_t n;
543 dd038bc6 2021-09-21 thomas.ad memset(&iov, 0, sizeof(iov));
544 dd038bc6 2021-09-21 thomas.ad TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
545 dd038bc6 2021-09-21 thomas.ad if (i >= IOV_MAX)
546 dd038bc6 2021-09-21 thomas.ad break;
547 3bb9eb8b 2024-01-18 thomas iov[i].iov_base = ibuf_data(buf);
548 3bb9eb8b 2024-01-18 thomas iov[i].iov_len = ibuf_size(buf);
552 dd038bc6 2021-09-21 thomas.ad again:
553 dd038bc6 2021-09-21 thomas.ad if ((n = writev(msgbuf->fd, iov, i)) == -1) {
554 dd038bc6 2021-09-21 thomas.ad if (errno == EINTR)
555 dd038bc6 2021-09-21 thomas.ad goto again;
556 dd038bc6 2021-09-21 thomas.ad if (errno == ENOBUFS)
557 dd038bc6 2021-09-21 thomas.ad errno = EAGAIN;
558 dd038bc6 2021-09-21 thomas.ad return (-1);
561 dd038bc6 2021-09-21 thomas.ad if (n == 0) { /* connection closed */
562 dd038bc6 2021-09-21 thomas.ad errno = 0;
563 dd038bc6 2021-09-21 thomas.ad return (0);
566 dd038bc6 2021-09-21 thomas.ad msgbuf_drain(msgbuf, n);
568 dd038bc6 2021-09-21 thomas.ad return (1);
572 dd038bc6 2021-09-21 thomas.ad msgbuf_init(struct msgbuf *msgbuf)
574 dd038bc6 2021-09-21 thomas.ad msgbuf->queued = 0;
575 dd038bc6 2021-09-21 thomas.ad msgbuf->fd = -1;
576 dd038bc6 2021-09-21 thomas.ad TAILQ_INIT(&msgbuf->bufs);
580 dd038bc6 2021-09-21 thomas.ad msgbuf_drain(struct msgbuf *msgbuf, size_t n)
582 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf, *next;
584 dd038bc6 2021-09-21 thomas.ad for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
585 dd038bc6 2021-09-21 thomas.ad buf = next) {
586 dd038bc6 2021-09-21 thomas.ad next = TAILQ_NEXT(buf, entry);
587 3bb9eb8b 2024-01-18 thomas if (n >= ibuf_size(buf)) {
588 3bb9eb8b 2024-01-18 thomas n -= ibuf_size(buf);
589 dd038bc6 2021-09-21 thomas.ad ibuf_dequeue(msgbuf, buf);
590 dd038bc6 2021-09-21 thomas.ad } else {
591 dd038bc6 2021-09-21 thomas.ad buf->rpos += n;
592 dd038bc6 2021-09-21 thomas.ad n = 0;
598 dd038bc6 2021-09-21 thomas.ad msgbuf_clear(struct msgbuf *msgbuf)
600 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
602 dd038bc6 2021-09-21 thomas.ad while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
603 dd038bc6 2021-09-21 thomas.ad ibuf_dequeue(msgbuf, buf);
607 dd038bc6 2021-09-21 thomas.ad msgbuf_write(struct msgbuf *msgbuf)
609 dd038bc6 2021-09-21 thomas.ad struct iovec iov[IOV_MAX];
610 3ef3f36a 2023-07-05 op struct ibuf *buf, *buf0 = NULL;
611 dd038bc6 2021-09-21 thomas.ad unsigned int i = 0;
612 dd038bc6 2021-09-21 thomas.ad ssize_t n;
613 dd038bc6 2021-09-21 thomas.ad struct msghdr msg;
614 dd038bc6 2021-09-21 thomas.ad struct cmsghdr *cmsg;
615 dd038bc6 2021-09-21 thomas.ad union {
616 dd038bc6 2021-09-21 thomas.ad struct cmsghdr hdr;
617 dd038bc6 2021-09-21 thomas.ad char buf[CMSG_SPACE(sizeof(int))];
618 dd038bc6 2021-09-21 thomas.ad } cmsgbuf;
620 dd038bc6 2021-09-21 thomas.ad memset(&iov, 0, sizeof(iov));
621 dd038bc6 2021-09-21 thomas.ad memset(&msg, 0, sizeof(msg));
622 dd038bc6 2021-09-21 thomas.ad memset(&cmsgbuf, 0, sizeof(cmsgbuf));
623 dd038bc6 2021-09-21 thomas.ad TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
624 dd038bc6 2021-09-21 thomas.ad if (i >= IOV_MAX)
625 dd038bc6 2021-09-21 thomas.ad break;
626 3ef3f36a 2023-07-05 op if (i > 0 && buf->fd != -1)
628 3bb9eb8b 2024-01-18 thomas iov[i].iov_base = ibuf_data(buf);
629 3bb9eb8b 2024-01-18 thomas iov[i].iov_len = ibuf_size(buf);
631 dd038bc6 2021-09-21 thomas.ad if (buf->fd != -1)
635 dd038bc6 2021-09-21 thomas.ad msg.msg_iov = iov;
636 dd038bc6 2021-09-21 thomas.ad msg.msg_iovlen = i;
638 3ef3f36a 2023-07-05 op if (buf0 != NULL) {
639 dd038bc6 2021-09-21 thomas.ad msg.msg_control = (caddr_t)&cmsgbuf.buf;
640 dd038bc6 2021-09-21 thomas.ad msg.msg_controllen = sizeof(cmsgbuf.buf);
641 dd038bc6 2021-09-21 thomas.ad cmsg = CMSG_FIRSTHDR(&msg);
642 dd038bc6 2021-09-21 thomas.ad cmsg->cmsg_len = CMSG_LEN(sizeof(int));
643 dd038bc6 2021-09-21 thomas.ad cmsg->cmsg_level = SOL_SOCKET;
644 dd038bc6 2021-09-21 thomas.ad cmsg->cmsg_type = SCM_RIGHTS;
645 3ef3f36a 2023-07-05 op *(int *)CMSG_DATA(cmsg) = buf0->fd;
648 dd038bc6 2021-09-21 thomas.ad again:
649 dd038bc6 2021-09-21 thomas.ad if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
650 dd038bc6 2021-09-21 thomas.ad if (errno == EINTR)
651 dd038bc6 2021-09-21 thomas.ad goto again;
652 dd038bc6 2021-09-21 thomas.ad if (errno == ENOBUFS)
653 dd038bc6 2021-09-21 thomas.ad errno = EAGAIN;
654 dd038bc6 2021-09-21 thomas.ad return (-1);
657 dd038bc6 2021-09-21 thomas.ad if (n == 0) { /* connection closed */
658 dd038bc6 2021-09-21 thomas.ad errno = 0;
659 dd038bc6 2021-09-21 thomas.ad return (0);
663 dd038bc6 2021-09-21 thomas.ad * assumption: fd got sent if sendmsg sent anything
664 dd038bc6 2021-09-21 thomas.ad * this works because fds are passed one at a time
666 3ef3f36a 2023-07-05 op if (buf0 != NULL) {
667 3ef3f36a 2023-07-05 op close(buf0->fd);
668 3ef3f36a 2023-07-05 op buf0->fd = -1;
671 dd038bc6 2021-09-21 thomas.ad msgbuf_drain(msgbuf, n);
673 dd038bc6 2021-09-21 thomas.ad return (1);
677 3bb9eb8b 2024-01-18 thomas msgbuf_queuelen(struct msgbuf *msgbuf)
679 3bb9eb8b 2024-01-18 thomas return (msgbuf->queued);
682 dd038bc6 2021-09-21 thomas.ad static void
683 dd038bc6 2021-09-21 thomas.ad ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
685 3bb9eb8b 2024-01-18 thomas if (buf->max == 0) /* if buf lives on the stack */
686 3bb9eb8b 2024-01-18 thomas abort(); /* abort before causing more harm */
687 dd038bc6 2021-09-21 thomas.ad TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
688 dd038bc6 2021-09-21 thomas.ad msgbuf->queued++;
691 dd038bc6 2021-09-21 thomas.ad static void
692 dd038bc6 2021-09-21 thomas.ad ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
694 dd038bc6 2021-09-21 thomas.ad TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
695 dd038bc6 2021-09-21 thomas.ad msgbuf->queued--;
696 dd038bc6 2021-09-21 thomas.ad ibuf_free(buf);