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