jcs's openbsd hax
openbsd
at jcs 1063 lines 19 kB view raw
1/* $OpenBSD: imsg-buffer.c,v 1.36 2025/08/25 08:29:49 claudio Exp $ */ 2 3/* 4 * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/types.h> 21#include <sys/queue.h> 22#include <sys/socket.h> 23#include <sys/uio.h> 24 25#include <limits.h> 26#include <errno.h> 27#include <endian.h> 28#include <stdint.h> 29#include <stdlib.h> 30#include <string.h> 31#include <unistd.h> 32 33#include "imsg.h" 34 35struct ibufqueue { 36 TAILQ_HEAD(, ibuf) bufs; 37 uint32_t queued; 38}; 39 40struct msgbuf { 41 struct ibufqueue bufs; 42 struct ibufqueue rbufs; 43 char *rbuf; 44 struct ibuf *rpmsg; 45 struct ibuf *(*readhdr)(struct ibuf *, void *, int *); 46 void *rarg; 47 size_t roff; 48 size_t hdrsize; 49}; 50 51static void msgbuf_drain(struct msgbuf *, size_t); 52static void ibufq_init(struct ibufqueue *); 53 54#define IBUF_FD_MARK_ON_STACK -2 55 56struct ibuf * 57ibuf_open(size_t len) 58{ 59 struct ibuf *buf; 60 61 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) 62 return (NULL); 63 if (len > 0) { 64 if ((buf->buf = calloc(len, 1)) == NULL) { 65 free(buf); 66 return (NULL); 67 } 68 } 69 buf->size = buf->max = len; 70 buf->fd = -1; 71 72 return (buf); 73} 74 75struct ibuf * 76ibuf_dynamic(size_t len, size_t max) 77{ 78 struct ibuf *buf; 79 80 if (max == 0 || max < len) { 81 errno = EINVAL; 82 return (NULL); 83 } 84 85 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) 86 return (NULL); 87 if (len > 0) { 88 if ((buf->buf = calloc(len, 1)) == NULL) { 89 free(buf); 90 return (NULL); 91 } 92 } 93 buf->size = len; 94 buf->max = max; 95 buf->fd = -1; 96 97 return (buf); 98} 99 100void * 101ibuf_reserve(struct ibuf *buf, size_t len) 102{ 103 void *b; 104 105 if (len > SIZE_MAX - buf->wpos) { 106 errno = ERANGE; 107 return (NULL); 108 } 109 if (buf->fd == IBUF_FD_MARK_ON_STACK) { 110 /* can not grow stack buffers */ 111 errno = EINVAL; 112 return (NULL); 113 } 114 115 if (buf->wpos + len > buf->size) { 116 unsigned char *nb; 117 118 /* check if buffer is allowed to grow */ 119 if (buf->wpos + len > buf->max) { 120 errno = ERANGE; 121 return (NULL); 122 } 123 nb = realloc(buf->buf, buf->wpos + len); 124 if (nb == NULL) 125 return (NULL); 126 memset(nb + buf->size, 0, buf->wpos + len - buf->size); 127 buf->buf = nb; 128 buf->size = buf->wpos + len; 129 } 130 131 b = buf->buf + buf->wpos; 132 buf->wpos += len; 133 return (b); 134} 135 136int 137ibuf_add(struct ibuf *buf, const void *data, size_t len) 138{ 139 void *b; 140 141 if (len == 0) 142 return (0); 143 144 if ((b = ibuf_reserve(buf, len)) == NULL) 145 return (-1); 146 147 memcpy(b, data, len); 148 return (0); 149} 150 151int 152ibuf_add_ibuf(struct ibuf *buf, const struct ibuf *from) 153{ 154 return ibuf_add(buf, ibuf_data(from), ibuf_size(from)); 155} 156 157int 158ibuf_add_n8(struct ibuf *buf, uint64_t value) 159{ 160 uint8_t v; 161 162 if (value > UINT8_MAX) { 163 errno = EINVAL; 164 return (-1); 165 } 166 v = value; 167 return ibuf_add(buf, &v, sizeof(v)); 168} 169 170int 171ibuf_add_n16(struct ibuf *buf, uint64_t value) 172{ 173 uint16_t v; 174 175 if (value > UINT16_MAX) { 176 errno = EINVAL; 177 return (-1); 178 } 179 v = htobe16(value); 180 return ibuf_add(buf, &v, sizeof(v)); 181} 182 183int 184ibuf_add_n32(struct ibuf *buf, uint64_t value) 185{ 186 uint32_t v; 187 188 if (value > UINT32_MAX) { 189 errno = EINVAL; 190 return (-1); 191 } 192 v = htobe32(value); 193 return ibuf_add(buf, &v, sizeof(v)); 194} 195 196int 197ibuf_add_n64(struct ibuf *buf, uint64_t value) 198{ 199 value = htobe64(value); 200 return ibuf_add(buf, &value, sizeof(value)); 201} 202 203int 204ibuf_add_h16(struct ibuf *buf, uint64_t value) 205{ 206 uint16_t v; 207 208 if (value > UINT16_MAX) { 209 errno = EINVAL; 210 return (-1); 211 } 212 v = value; 213 return ibuf_add(buf, &v, sizeof(v)); 214} 215 216int 217ibuf_add_h32(struct ibuf *buf, uint64_t value) 218{ 219 uint32_t v; 220 221 if (value > UINT32_MAX) { 222 errno = EINVAL; 223 return (-1); 224 } 225 v = value; 226 return ibuf_add(buf, &v, sizeof(v)); 227} 228 229int 230ibuf_add_h64(struct ibuf *buf, uint64_t value) 231{ 232 return ibuf_add(buf, &value, sizeof(value)); 233} 234 235int 236ibuf_add_zero(struct ibuf *buf, size_t len) 237{ 238 void *b; 239 240 if (len == 0) 241 return (0); 242 243 if ((b = ibuf_reserve(buf, len)) == NULL) 244 return (-1); 245 memset(b, 0, len); 246 return (0); 247} 248 249int 250ibuf_add_strbuf(struct ibuf *buf, const char *str, size_t len) 251{ 252 char *b; 253 size_t n; 254 255 if ((b = ibuf_reserve(buf, len)) == NULL) 256 return (-1); 257 258 n = strlcpy(b, str, len); 259 if (n >= len) { 260 /* also covers the case where len == 0 */ 261 errno = EOVERFLOW; 262 return (-1); 263 } 264 memset(b + n, 0, len - n); 265 return (0); 266} 267 268void * 269ibuf_seek(struct ibuf *buf, size_t pos, size_t len) 270{ 271 /* only allow seeking between rpos and wpos */ 272 if (ibuf_size(buf) < pos || SIZE_MAX - pos < len || 273 ibuf_size(buf) < pos + len) { 274 errno = ERANGE; 275 return (NULL); 276 } 277 278 return (buf->buf + buf->rpos + pos); 279} 280 281int 282ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len) 283{ 284 void *b; 285 286 if ((b = ibuf_seek(buf, pos, len)) == NULL) 287 return (-1); 288 289 if (len == 0) 290 return (0); 291 memcpy(b, data, len); 292 return (0); 293} 294 295int 296ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value) 297{ 298 uint8_t v; 299 300 if (value > UINT8_MAX) { 301 errno = EINVAL; 302 return (-1); 303 } 304 v = value; 305 return (ibuf_set(buf, pos, &v, sizeof(v))); 306} 307 308int 309ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value) 310{ 311 uint16_t v; 312 313 if (value > UINT16_MAX) { 314 errno = EINVAL; 315 return (-1); 316 } 317 v = htobe16(value); 318 return (ibuf_set(buf, pos, &v, sizeof(v))); 319} 320 321int 322ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value) 323{ 324 uint32_t v; 325 326 if (value > UINT32_MAX) { 327 errno = EINVAL; 328 return (-1); 329 } 330 v = htobe32(value); 331 return (ibuf_set(buf, pos, &v, sizeof(v))); 332} 333 334int 335ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value) 336{ 337 value = htobe64(value); 338 return (ibuf_set(buf, pos, &value, sizeof(value))); 339} 340 341int 342ibuf_set_h16(struct ibuf *buf, size_t pos, uint64_t value) 343{ 344 uint16_t v; 345 346 if (value > UINT16_MAX) { 347 errno = EINVAL; 348 return (-1); 349 } 350 v = value; 351 return (ibuf_set(buf, pos, &v, sizeof(v))); 352} 353 354int 355ibuf_set_h32(struct ibuf *buf, size_t pos, uint64_t value) 356{ 357 uint32_t v; 358 359 if (value > UINT32_MAX) { 360 errno = EINVAL; 361 return (-1); 362 } 363 v = value; 364 return (ibuf_set(buf, pos, &v, sizeof(v))); 365} 366 367int 368ibuf_set_h64(struct ibuf *buf, size_t pos, uint64_t value) 369{ 370 return (ibuf_set(buf, pos, &value, sizeof(value))); 371} 372 373int 374ibuf_set_maxsize(struct ibuf *buf, size_t max) 375{ 376 if (buf->fd == IBUF_FD_MARK_ON_STACK) { 377 /* can't fiddle with stack buffers */ 378 errno = EINVAL; 379 return (-1); 380 } 381 if (max > buf->max) { 382 errno = ERANGE; 383 return (-1); 384 } 385 buf->max = max; 386 return (0); 387} 388 389void * 390ibuf_data(const struct ibuf *buf) 391{ 392 return (buf->buf + buf->rpos); 393} 394 395size_t 396ibuf_size(const struct ibuf *buf) 397{ 398 return (buf->wpos - buf->rpos); 399} 400 401size_t 402ibuf_left(const struct ibuf *buf) 403{ 404 /* on stack buffers have no space left */ 405 if (buf->fd == IBUF_FD_MARK_ON_STACK) 406 return (0); 407 return (buf->max - buf->wpos); 408} 409 410int 411ibuf_truncate(struct ibuf *buf, size_t len) 412{ 413 if (ibuf_size(buf) >= len) { 414 buf->wpos = buf->rpos + len; 415 return (0); 416 } 417 if (buf->fd == IBUF_FD_MARK_ON_STACK) { 418 /* only allow to truncate down for stack buffers */ 419 errno = ERANGE; 420 return (-1); 421 } 422 return ibuf_add_zero(buf, len - ibuf_size(buf)); 423} 424 425void 426ibuf_rewind(struct ibuf *buf) 427{ 428 buf->rpos = 0; 429} 430 431void 432ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) 433{ 434 ibufq_push(&msgbuf->bufs, buf); 435} 436 437void 438ibuf_from_buffer(struct ibuf *buf, void *data, size_t len) 439{ 440 memset(buf, 0, sizeof(*buf)); 441 buf->buf = data; 442 buf->size = buf->wpos = len; 443 buf->fd = IBUF_FD_MARK_ON_STACK; 444} 445 446void 447ibuf_from_ibuf(struct ibuf *buf, const struct ibuf *from) 448{ 449 ibuf_from_buffer(buf, ibuf_data(from), ibuf_size(from)); 450} 451 452int 453ibuf_get(struct ibuf *buf, void *data, size_t len) 454{ 455 if (ibuf_size(buf) < len) { 456 errno = EBADMSG; 457 return (-1); 458 } 459 460 memcpy(data, ibuf_data(buf), len); 461 buf->rpos += len; 462 return (0); 463} 464 465int 466ibuf_get_ibuf(struct ibuf *buf, size_t len, struct ibuf *new) 467{ 468 if (ibuf_size(buf) < len) { 469 errno = EBADMSG; 470 return (-1); 471 } 472 473 ibuf_from_buffer(new, ibuf_data(buf), len); 474 buf->rpos += len; 475 return (0); 476} 477 478int 479ibuf_get_h16(struct ibuf *buf, uint16_t *value) 480{ 481 return ibuf_get(buf, value, sizeof(*value)); 482} 483 484int 485ibuf_get_h32(struct ibuf *buf, uint32_t *value) 486{ 487 return ibuf_get(buf, value, sizeof(*value)); 488} 489 490int 491ibuf_get_h64(struct ibuf *buf, uint64_t *value) 492{ 493 return ibuf_get(buf, value, sizeof(*value)); 494} 495 496int 497ibuf_get_n8(struct ibuf *buf, uint8_t *value) 498{ 499 return ibuf_get(buf, value, sizeof(*value)); 500} 501 502int 503ibuf_get_n16(struct ibuf *buf, uint16_t *value) 504{ 505 int rv; 506 507 rv = ibuf_get(buf, value, sizeof(*value)); 508 *value = be16toh(*value); 509 return (rv); 510} 511 512int 513ibuf_get_n32(struct ibuf *buf, uint32_t *value) 514{ 515 int rv; 516 517 rv = ibuf_get(buf, value, sizeof(*value)); 518 *value = be32toh(*value); 519 return (rv); 520} 521 522int 523ibuf_get_n64(struct ibuf *buf, uint64_t *value) 524{ 525 int rv; 526 527 rv = ibuf_get(buf, value, sizeof(*value)); 528 *value = be64toh(*value); 529 return (rv); 530} 531 532char * 533ibuf_get_string(struct ibuf *buf, size_t len) 534{ 535 char *str; 536 537 if (ibuf_size(buf) < len) { 538 errno = EBADMSG; 539 return (NULL); 540 } 541 542 str = strndup(ibuf_data(buf), len); 543 if (str == NULL) 544 return (NULL); 545 buf->rpos += len; 546 return (str); 547} 548 549int 550ibuf_get_strbuf(struct ibuf *buf, char *str, size_t len) 551{ 552 if (len == 0) { 553 errno = EINVAL; 554 return (-1); 555 } 556 557 if (ibuf_get(buf, str, len) == -1) 558 return -1; 559 if (str[len - 1] != '\0') { 560 str[len - 1] = '\0'; 561 errno = EOVERFLOW; 562 return -1; 563 } 564 return 0; 565} 566 567int 568ibuf_skip(struct ibuf *buf, size_t len) 569{ 570 if (ibuf_size(buf) < len) { 571 errno = EBADMSG; 572 return (-1); 573 } 574 575 buf->rpos += len; 576 return (0); 577} 578 579void 580ibuf_free(struct ibuf *buf) 581{ 582 int save_errno = errno; 583 584 if (buf == NULL) 585 return; 586 /* if buf lives on the stack abort before causing more harm */ 587 if (buf->fd == IBUF_FD_MARK_ON_STACK) 588 abort(); 589 if (buf->fd >= 0) 590 close(buf->fd); 591 freezero(buf->buf, buf->size); 592 free(buf); 593 errno = save_errno; 594} 595 596int 597ibuf_fd_avail(struct ibuf *buf) 598{ 599 return (buf->fd >= 0); 600} 601 602int 603ibuf_fd_get(struct ibuf *buf) 604{ 605 int fd; 606 607 /* negative fds are internal use and equivalent to -1 */ 608 if (buf->fd < 0) 609 return (-1); 610 fd = buf->fd; 611 buf->fd = -1; 612 return (fd); 613} 614 615void 616ibuf_fd_set(struct ibuf *buf, int fd) 617{ 618 /* if buf lives on the stack abort before causing more harm */ 619 if (buf->fd == IBUF_FD_MARK_ON_STACK) 620 abort(); 621 if (buf->fd >= 0) 622 close(buf->fd); 623 buf->fd = -1; 624 if (fd >= 0) 625 buf->fd = fd; 626} 627 628struct msgbuf * 629msgbuf_new(void) 630{ 631 struct msgbuf *msgbuf; 632 633 if ((msgbuf = calloc(1, sizeof(*msgbuf))) == NULL) 634 return (NULL); 635 ibufq_init(&msgbuf->bufs); 636 ibufq_init(&msgbuf->rbufs); 637 638 return msgbuf; 639} 640 641struct msgbuf * 642msgbuf_new_reader(size_t hdrsz, 643 struct ibuf *(*readhdr)(struct ibuf *, void *, int *), void *arg) 644{ 645 struct msgbuf *msgbuf; 646 char *buf; 647 648 if (hdrsz == 0 || hdrsz > IBUF_READ_SIZE / 2) { 649 errno = EINVAL; 650 return (NULL); 651 } 652 653 if ((buf = malloc(IBUF_READ_SIZE)) == NULL) 654 return (NULL); 655 656 msgbuf = msgbuf_new(); 657 if (msgbuf == NULL) { 658 free(buf); 659 return (NULL); 660 } 661 662 msgbuf->rbuf = buf; 663 msgbuf->hdrsize = hdrsz; 664 msgbuf->readhdr = readhdr; 665 msgbuf->rarg = arg; 666 667 return (msgbuf); 668} 669 670void 671msgbuf_free(struct msgbuf *msgbuf) 672{ 673 if (msgbuf == NULL) 674 return; 675 msgbuf_clear(msgbuf); 676 free(msgbuf->rbuf); 677 free(msgbuf); 678} 679 680uint32_t 681msgbuf_queuelen(struct msgbuf *msgbuf) 682{ 683 return ibufq_queuelen(&msgbuf->bufs); 684} 685 686void 687msgbuf_clear(struct msgbuf *msgbuf) 688{ 689 /* write side */ 690 ibufq_flush(&msgbuf->bufs); 691 692 /* read side */ 693 ibufq_flush(&msgbuf->rbufs); 694 msgbuf->roff = 0; 695 ibuf_free(msgbuf->rpmsg); 696 msgbuf->rpmsg = NULL; 697} 698 699struct ibuf * 700msgbuf_get(struct msgbuf *msgbuf) 701{ 702 return ibufq_pop(&msgbuf->rbufs); 703} 704 705void 706msgbuf_concat(struct msgbuf *msgbuf, struct ibufqueue *from) 707{ 708 ibufq_concat(&msgbuf->bufs, from); 709} 710 711int 712ibuf_write(int fd, struct msgbuf *msgbuf) 713{ 714 struct iovec iov[IOV_MAX]; 715 struct ibuf *buf; 716 unsigned int i = 0; 717 ssize_t n; 718 719 memset(&iov, 0, sizeof(iov)); 720 TAILQ_FOREACH(buf, &msgbuf->bufs.bufs, entry) { 721 if (i >= IOV_MAX) 722 break; 723 iov[i].iov_base = ibuf_data(buf); 724 iov[i].iov_len = ibuf_size(buf); 725 i++; 726 } 727 if (i == 0) 728 return (0); /* nothing queued */ 729 730 again: 731 if ((n = writev(fd, iov, i)) == -1) { 732 if (errno == EINTR) 733 goto again; 734 if (errno == EAGAIN || errno == ENOBUFS) 735 /* lets retry later again */ 736 return (0); 737 return (-1); 738 } 739 740 msgbuf_drain(msgbuf, n); 741 return (0); 742} 743 744int 745msgbuf_write(int fd, struct msgbuf *msgbuf) 746{ 747 struct iovec iov[IOV_MAX]; 748 struct ibuf *buf, *buf0 = NULL; 749 unsigned int i = 0; 750 ssize_t n; 751 struct msghdr msg; 752 struct cmsghdr *cmsg; 753 union { 754 struct cmsghdr hdr; 755 char buf[CMSG_SPACE(sizeof(int))]; 756 } cmsgbuf; 757 758 memset(&iov, 0, sizeof(iov)); 759 memset(&msg, 0, sizeof(msg)); 760 memset(&cmsgbuf, 0, sizeof(cmsgbuf)); 761 TAILQ_FOREACH(buf, &msgbuf->bufs.bufs, entry) { 762 if (i >= IOV_MAX) 763 break; 764 if (i > 0 && buf->fd != -1) 765 break; 766 iov[i].iov_base = ibuf_data(buf); 767 iov[i].iov_len = ibuf_size(buf); 768 i++; 769 if (buf->fd != -1) 770 buf0 = buf; 771 } 772 773 if (i == 0) 774 return (0); /* nothing queued */ 775 776 msg.msg_iov = iov; 777 msg.msg_iovlen = i; 778 779 if (buf0 != NULL) { 780 msg.msg_control = (caddr_t)&cmsgbuf.buf; 781 msg.msg_controllen = sizeof(cmsgbuf.buf); 782 cmsg = CMSG_FIRSTHDR(&msg); 783 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 784 cmsg->cmsg_level = SOL_SOCKET; 785 cmsg->cmsg_type = SCM_RIGHTS; 786 *(int *)CMSG_DATA(cmsg) = buf0->fd; 787 } 788 789 again: 790 if ((n = sendmsg(fd, &msg, 0)) == -1) { 791 if (errno == EINTR) 792 goto again; 793 if (errno == EAGAIN || errno == ENOBUFS) 794 /* lets retry later again */ 795 return (0); 796 return (-1); 797 } 798 799 /* 800 * assumption: fd got sent if sendmsg sent anything 801 * this works because fds are passed one at a time 802 */ 803 if (buf0 != NULL) { 804 close(buf0->fd); 805 buf0->fd = -1; 806 } 807 808 msgbuf_drain(msgbuf, n); 809 810 return (0); 811} 812 813static int 814ibuf_read_process(struct msgbuf *msgbuf, int fd) 815{ 816 struct ibuf rbuf, msg; 817 ssize_t sz; 818 819 ibuf_from_buffer(&rbuf, msgbuf->rbuf, msgbuf->roff); 820 821 do { 822 if (msgbuf->rpmsg == NULL) { 823 if (ibuf_size(&rbuf) < msgbuf->hdrsize) 824 break; 825 /* get size from header */ 826 ibuf_from_buffer(&msg, ibuf_data(&rbuf), 827 msgbuf->hdrsize); 828 if ((msgbuf->rpmsg = msgbuf->readhdr(&msg, 829 msgbuf->rarg, &fd)) == NULL) 830 goto fail; 831 } 832 833 if (ibuf_left(msgbuf->rpmsg) <= ibuf_size(&rbuf)) 834 sz = ibuf_left(msgbuf->rpmsg); 835 else 836 sz = ibuf_size(&rbuf); 837 838 /* neither call below can fail */ 839 if (ibuf_get_ibuf(&rbuf, sz, &msg) == -1 || 840 ibuf_add_ibuf(msgbuf->rpmsg, &msg) == -1) 841 goto fail; 842 843 if (ibuf_left(msgbuf->rpmsg) == 0) { 844 ibufq_push(&msgbuf->rbufs, msgbuf->rpmsg); 845 msgbuf->rpmsg = NULL; 846 } 847 } while (ibuf_size(&rbuf) > 0); 848 849 if (ibuf_size(&rbuf) > 0) 850 memmove(msgbuf->rbuf, ibuf_data(&rbuf), ibuf_size(&rbuf)); 851 msgbuf->roff = ibuf_size(&rbuf); 852 853 if (fd != -1) 854 close(fd); 855 return (1); 856 857 fail: 858 /* XXX how to properly clean up is unclear */ 859 if (fd != -1) 860 close(fd); 861 return (-1); 862} 863 864int 865ibuf_read(int fd, struct msgbuf *msgbuf) 866{ 867 struct iovec iov; 868 ssize_t n; 869 870 if (msgbuf->rbuf == NULL) { 871 errno = EINVAL; 872 return (-1); 873 } 874 875 iov.iov_base = msgbuf->rbuf + msgbuf->roff; 876 iov.iov_len = IBUF_READ_SIZE - msgbuf->roff; 877 878 again: 879 if ((n = readv(fd, &iov, 1)) == -1) { 880 if (errno == EINTR) 881 goto again; 882 if (errno == EAGAIN) 883 /* lets retry later again */ 884 return (1); 885 return (-1); 886 } 887 if (n == 0) /* connection closed */ 888 return (0); 889 890 msgbuf->roff += n; 891 /* new data arrived, try to process it */ 892 return (ibuf_read_process(msgbuf, -1)); 893} 894 895int 896msgbuf_read(int fd, struct msgbuf *msgbuf) 897{ 898 struct msghdr msg; 899 struct cmsghdr *cmsg; 900 union { 901 struct cmsghdr hdr; 902 char buf[CMSG_SPACE(sizeof(int) * 1)]; 903 } cmsgbuf; 904 struct iovec iov; 905 ssize_t n; 906 int fdpass = -1; 907 908 if (msgbuf->rbuf == NULL) { 909 errno = EINVAL; 910 return (-1); 911 } 912 913 memset(&msg, 0, sizeof(msg)); 914 memset(&cmsgbuf, 0, sizeof(cmsgbuf)); 915 916 iov.iov_base = msgbuf->rbuf + msgbuf->roff; 917 iov.iov_len = IBUF_READ_SIZE - msgbuf->roff; 918 msg.msg_iov = &iov; 919 msg.msg_iovlen = 1; 920 msg.msg_control = &cmsgbuf.buf; 921 msg.msg_controllen = sizeof(cmsgbuf.buf); 922 923again: 924 if ((n = recvmsg(fd, &msg, 0)) == -1) { 925 if (errno == EINTR) 926 goto again; 927 if (errno == EMSGSIZE) 928 /* 929 * Not enough fd slots: fd passing failed, retry 930 * to receive the message without fd. 931 * imsg_get_fd() will return -1 in that case. 932 */ 933 goto again; 934 if (errno == EAGAIN) 935 /* lets retry later again */ 936 return (1); 937 return (-1); 938 } 939 if (n == 0) /* connection closed */ 940 return (0); 941 942 msgbuf->roff += n; 943 944 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 945 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 946 if (cmsg->cmsg_level == SOL_SOCKET && 947 cmsg->cmsg_type == SCM_RIGHTS) { 948 int i, j, f; 949 950 /* 951 * We only accept one file descriptor. Due to C 952 * padding rules, our control buffer might contain 953 * more than one fd, and we must close them. 954 */ 955 j = ((char *)cmsg + cmsg->cmsg_len - 956 (char *)CMSG_DATA(cmsg)) / sizeof(int); 957 for (i = 0; i < j; i++) { 958 f = ((int *)CMSG_DATA(cmsg))[i]; 959 if (i == 0) 960 fdpass = f; 961 else 962 close(f); 963 } 964 } 965 /* we do not handle other ctl data level */ 966 } 967 968 /* new data arrived, try to process it */ 969 return (ibuf_read_process(msgbuf, fdpass)); 970} 971 972static void 973msgbuf_drain(struct msgbuf *msgbuf, size_t n) 974{ 975 struct ibuf *buf; 976 977 while ((buf = TAILQ_FIRST(&msgbuf->bufs.bufs)) != NULL) { 978 if (n >= ibuf_size(buf)) { 979 n -= ibuf_size(buf); 980 TAILQ_REMOVE(&msgbuf->bufs.bufs, buf, entry); 981 msgbuf->bufs.queued--; 982 ibuf_free(buf); 983 } else { 984 buf->rpos += n; 985 return; 986 } 987 } 988} 989 990static void 991ibufq_init(struct ibufqueue *bufq) 992{ 993 TAILQ_INIT(&bufq->bufs); 994 bufq->queued = 0; 995} 996 997struct ibufqueue * 998ibufq_new(void) 999{ 1000 struct ibufqueue *bufq; 1001 1002 if ((bufq = calloc(1, sizeof(*bufq))) == NULL) 1003 return NULL; 1004 ibufq_init(bufq); 1005 return bufq; 1006} 1007 1008void 1009ibufq_free(struct ibufqueue *bufq) 1010{ 1011 if (bufq == NULL) 1012 return; 1013 ibufq_flush(bufq); 1014 free(bufq); 1015} 1016 1017struct ibuf * 1018ibufq_pop(struct ibufqueue *bufq) 1019{ 1020 struct ibuf *buf; 1021 1022 if ((buf = TAILQ_FIRST(&bufq->bufs)) == NULL) 1023 return NULL; 1024 TAILQ_REMOVE(&bufq->bufs, buf, entry); 1025 bufq->queued--; 1026 return buf; 1027} 1028 1029void 1030ibufq_push(struct ibufqueue *bufq, struct ibuf *buf) 1031{ 1032 /* if buf lives on the stack abort before causing more harm */ 1033 if (buf->fd == IBUF_FD_MARK_ON_STACK) 1034 abort(); 1035 TAILQ_INSERT_TAIL(&bufq->bufs, buf, entry); 1036 bufq->queued++; 1037} 1038 1039uint32_t 1040ibufq_queuelen(struct ibufqueue *bufq) 1041{ 1042 return (bufq->queued); 1043} 1044 1045void 1046ibufq_concat(struct ibufqueue *to, struct ibufqueue *from) 1047{ 1048 to->queued += from->queued; 1049 TAILQ_CONCAT(&to->bufs, &from->bufs, entry); 1050 from->queued = 0; 1051} 1052 1053void 1054ibufq_flush(struct ibufqueue *bufq) 1055{ 1056 struct ibuf *buf; 1057 1058 while ((buf = TAILQ_FIRST(&bufq->bufs)) != NULL) { 1059 TAILQ_REMOVE(&bufq->bufs, buf, entry); 1060 ibuf_free(buf); 1061 } 1062 bufq->queued = 0; 1063}