1 /* $NetBSD: buffer.h,v 1.10 2025/01/26 16:25:40 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 /***** 19 ***** Module Info 20 *****/ 21 22 /*! \file isc/buffer.h 23 * 24 * \brief A buffer is a region of memory, together with a set of related 25 * subregions. Buffers are used for parsing and I/O operations. 26 * 27 * The 'used region' and the 'available region' are disjoint, and their 28 * union is the buffer's region. The used region extends from the beginning 29 * of the buffer region to the last used byte. The available region 30 * extends from one byte greater than the last used byte to the end of the 31 * buffer's region. The size of the used region can be changed using various 32 * buffer commands. Initially, the used region is empty. 33 * 34 * The used region is further subdivided into two disjoint regions: the 35 * 'consumed region' and the 'remaining region'. The union of these two 36 * regions is the used region. The consumed region extends from the beginning 37 * of the used region to the byte before the 'current' offset (if any). The 38 * 'remaining' region extends from the current offset to the end of the used 39 * region. The size of the consumed region can be changed using various 40 * buffer commands. Initially, the consumed region is empty. 41 * 42 * The 'active region' is an (optional) subregion of the remaining region. 43 * It extends from the current offset to an offset in the remaining region 44 * that is selected with isc_buffer_setactive(). Initially, the active region 45 * is empty. If the current offset advances beyond the chosen offset, the 46 * active region will also be empty. 47 * 48 * \verbatim 49 * /------------entire length---------------\ 50 * /----- used region -----\/-- available --\ 51 * +----------------------------------------+ 52 * | consumed | remaining | | 53 * +----------------------------------------+ 54 * a b c d e 55 * 56 * a == base of buffer. 57 * b == current pointer. Can be anywhere between a and d. 58 * c == active pointer. Meaningful between b and d. 59 * d == used pointer. 60 * e == length of buffer. 61 * 62 * a-e == entire length of buffer. 63 * a-d == used region. 64 * a-b == consumed region. 65 * b-d == remaining region. 66 * b-c == optional active region. 67 *\endverbatim 68 * 69 * The following invariants are maintained by all routines: 70 * 71 *\code 72 * length > 0 73 * 74 * base is a valid pointer to length bytes of memory 75 * 76 * 0 <= used <= length 77 * 78 * 0 <= current <= used 79 * 80 * 0 <= active <= used 81 * (although active < current implies empty active region) 82 *\endcode 83 * 84 * \li MP: 85 * Buffers have no synchronization. Clients must ensure exclusive 86 * access. 87 * 88 * \li Reliability: 89 * No anticipated impact. 90 * 91 * \li Resources: 92 * Memory: 1 pointer + 6 unsigned integers per buffer. 93 * 94 * \li Security: 95 * No anticipated impact. 96 * 97 * \li Standards: 98 * None. 99 */ 100 101 /*** 102 *** Imports 103 ***/ 104 105 #include <inttypes.h> 106 #include <stdbool.h> 107 108 #include <isc/assertions.h> 109 #include <isc/endian.h> 110 #include <isc/formatcheck.h> 111 #include <isc/lang.h> 112 #include <isc/list.h> 113 #include <isc/magic.h> 114 #include <isc/mem.h> 115 #include <isc/region.h> 116 #include <isc/string.h> 117 #include <isc/types.h> 118 #include <isc/util.h> 119 120 ISC_LANG_BEGINDECLS 121 122 /*@{*/ 123 /*! 124 *** Magic numbers 125 ***/ 126 #define ISC_BUFFER_MAGIC 0x42756621U /* Buf!. */ 127 #define ISC_BUFFER_VALID(b) ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC) 128 /*@}*/ 129 130 /*! 131 * Size granularity for dynamically resizable buffers; when reserving 132 * space in a buffer, we round the allocated buffer length up to the 133 * nearest * multiple of this value. 134 */ 135 #define ISC_BUFFER_INCR 512 136 137 /* 138 * The following macros MUST be used only on valid buffers. It is the 139 * caller's responsibility to ensure this by using the ISC_BUFFER_VALID 140 * check above, or by calling another isc_buffer_*() function (rather than 141 * another macro.) 142 */ 143 144 /*@{*/ 145 /*! 146 * Fundamental buffer elements. (A through E in the introductory comment.) 147 */ 148 #define isc_buffer_base(b) ((void *)(b)->base) /*a*/ 149 #define isc_buffer_current(b) \ 150 ((void *)((unsigned char *)(b)->base + (b)->current)) /*b*/ 151 #define isc_buffer_active(b) \ 152 ((void *)((unsigned char *)(b)->base + (b)->active)) /*c*/ 153 #define isc_buffer_used(b) \ 154 ((void *)((unsigned char *)(b)->base + (b)->used)) /*d*/ 155 #define isc_buffer_length(b) ((b)->length) /*e*/ 156 /*@}*/ 157 158 /*@{*/ 159 /*! 160 * Derived lengths. (Described in the introductory comment.) 161 */ 162 #define isc_buffer_usedlength(b) ((b)->used) /* d-a */ 163 #define isc_buffer_consumedlength(b) ((b)->current) /* b-a */ 164 #define isc_buffer_remaininglength(b) ((b)->used - (b)->current) /* d-b */ 165 #define isc_buffer_activelength(b) ((b)->active - (b)->current) /* c-b */ 166 #define isc_buffer_availablelength(b) ((b)->length - (b)->used) /* e-d */ 167 /*@}*/ 168 169 /*! 170 * Note that the buffer structure is public. This is principally so buffer 171 * operations can be implemented using macros. Applications are strongly 172 * discouraged from directly manipulating the structure. 173 */ 174 175 struct isc_buffer { 176 unsigned int magic; 177 void *base; 178 /*@{*/ 179 /*! The following integers are byte offsets from 'base'. */ 180 unsigned int length; 181 unsigned int used; 182 unsigned int current; 183 unsigned int active; 184 /*@}*/ 185 /*! The extra bytes allocated for static buffer */ 186 unsigned int extra; 187 bool dynamic; 188 /*! linkable */ 189 ISC_LINK(isc_buffer_t) link; 190 /*! private internal elements */ 191 isc_mem_t *mctx; 192 }; 193 194 /*** 195 *** Functions 196 ***/ 197 198 static inline void 199 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **restrict dynbuffer, 200 const unsigned int length); 201 /*!< 202 * \brief Allocate a dynamic linkable buffer which has "length" bytes in the 203 * data region. 204 * 205 * Requires: 206 *\li "mctx" is valid. 207 * 208 *\li "dynbuffer" is non-NULL, and "*dynbuffer" is NULL. 209 * 210 * Note: 211 *\li Changing the buffer's length field is not permitted. 212 */ 213 214 static inline void 215 isc_buffer_setmctx(isc_buffer_t *restrict b, isc_mem_t *mctx); 216 static inline void 217 isc_buffer_clearmctx(isc_buffer_t *restrict b); 218 /*!< 219 * \brief Sets/Clears the internal memory context, so isc_buffer_reserve() can 220 * be used on previously 'static' buffer. 221 */ 222 223 static inline isc_result_t 224 isc_buffer_reserve(isc_buffer_t *restrict dynbuffer, const unsigned int size); 225 /*!< 226 * \brief Make "size" bytes of space available in the buffer. The buffer 227 * pointer may move when you call this function. 228 * 229 * Requires: 230 *\li "dynbuffer" is a valid dynamic buffer. 231 * 232 * Returns: 233 *\li ISC_R_SUCCESS - success 234 *\li ISC_R_NOMEMORY - no memory available 235 */ 236 237 static inline void 238 isc_buffer_free(isc_buffer_t **restrict dynbuffer); 239 /*!< 240 * \brief Release resources allocated for a dynamic buffer. 241 * 242 * Requires: 243 *\li "dynbuffer" is not NULL. 244 * 245 *\li "*dynbuffer" is a valid dynamic buffer. 246 * 247 * Ensures: 248 *\li "*dynbuffer" will be NULL on return, and all memory associated with 249 * the dynamic buffer is returned to the memory context used in 250 * isc_buffer_allocate(). 251 */ 252 253 static inline void 254 isc_buffer_initnull(isc_buffer_t *restrict b); 255 256 static inline void 257 isc_buffer_reinit(isc_buffer_t *restrict b, void *base, 258 const unsigned int length); 259 /*!< 260 * \brief Make 'b' refer to the 'length'-byte region starting at base. 261 * Any existing data will be copied. 262 * 263 * Requires: 264 * 265 *\li 'length' > 0 AND length >= previous length 266 * 267 *\li 'base' is a pointer to a sequence of 'length' bytes. 268 * 269 */ 270 271 static inline void 272 isc_buffer_trycompact(isc_buffer_t *restrict b); 273 static inline void 274 isc_buffer_compact(isc_buffer_t *restrict b); 275 /*!< 276 * \brief Compact the used region by moving the remaining region so it occurs 277 * at the start of the buffer. The used region is shrunk by the size of 278 * the consumed region, and the consumed region is then made empty. 279 * 280 * Requires: 281 * 282 *\li 'b' is a valid buffer 283 * 284 * Ensures: 285 * 286 *\li current == 0 287 * 288 *\li The size of the used region is now equal to the size of the remaining 289 * region (as it was before the call). The contents of the used region 290 * are those of the remaining region (as it was before the call). 291 */ 292 293 static inline isc_result_t 294 isc_buffer_peekuint8(const isc_buffer_t *restrict b, uint8_t *valp); 295 static inline uint8_t 296 isc_buffer_getuint8(isc_buffer_t *restrict b); 297 static inline void 298 isc_buffer_putuint8(isc_buffer_t *restrict b, const uint8_t val); 299 /*!< 300 * \brief Peek/Read/Write an unsigned 8-bit integer from/to 'b'. 301 * 302 * Requires: 303 * 304 *\li 'b' is a valid buffer. 305 * 306 *\li The length of the available region of 'b' is at least 1 307 * or the buffer has autoreallocation enabled. 308 * 309 * Ensures (for Read): 310 * 311 *\li The current pointer in 'b' is advanced by 1. 312 * 313 * Ensures (for Write): 314 * 315 *\li The used pointer in 'b' is advanced by 1. 316 * 317 * Returns (for Peek and Read): 318 * 319 *\li A 8-bit unsigned integer. (peek and get) 320 */ 321 322 static inline isc_result_t 323 isc_buffer_peekuint16(const isc_buffer_t *restrict b, uint16_t *valp); 324 static inline uint16_t 325 isc_buffer_getuint16(isc_buffer_t *restrict b); 326 static inline void 327 isc_buffer_putuint16(isc_buffer_t *restrict b, const uint16_t val); 328 /*!< 329 * \brief Peek/Read/Write an unsigned 16-bit integer in network byte order 330 * from/to 'b', convert it to/from host byte order.. 331 * 332 * Requires: 333 * 334 *\li 'b' is a valid buffer. 335 * 336 *\li The length of the available region of 'b' is at least 2 337 * or the buffer has autoreallocation enabled. 338 * 339 * Ensures (for Read): 340 * 341 *\li The current pointer in 'b' is advanced by 2. 342 * 343 * Ensures (for Write): 344 * 345 *\li The used pointer in 'b' is advanced by 2. 346 * 347 * Returns (for Peek and Read): 348 * 349 *\li A 16-bit unsigned integer. 350 */ 351 352 static inline isc_result_t 353 isc_buffer_peekuint32(const isc_buffer_t *restrict b, uint32_t *restrict valp); 354 static inline uint32_t 355 isc_buffer_getuint32(isc_buffer_t *restrict b); 356 static inline void 357 isc_buffer_putuint32(isc_buffer_t *restrict b, uint32_t const val); 358 /*!< 359 * \brief Peek/Read/Write an unsigned 32-bit integer in network byte order 360 * from/to 'b', convert it to/from host byte order. 361 * 362 * Requires: 363 * 364 *\li 'b' is a valid buffer. 365 * 366 *\li The length of the available region of 'b' is at least 4 367 * or the buffer has autoreallocation enabled. 368 * 369 * Ensures (for Read): 370 * 371 *\li The current pointer in 'b' is advanced by 4. 372 * 373 * Ensures (for Write): 374 * 375 *\li The used pointer in 'b' is advanced by 4. 376 * 377 * Returns (for Peek and Read): 378 * 379 *\li A 32-bit unsigned integer. 380 */ 381 382 static inline isc_result_t 383 isc_buffer_peekuint48(const isc_buffer_t *restrict b, uint64_t *valp); 384 static inline uint64_t 385 isc_buffer_getuint48(isc_buffer_t *restrict b); 386 static inline void 387 isc_buffer_putuint48(isc_buffer_t *restrict b, const uint64_t val); 388 /*!< 389 * \brief Peek/Read/Write an unsigned 48-bit integer in network byte order 390 * from/to 'b', convert it to/from host byte order. 391 * 392 * Requires: 393 * 394 *\li 'b' is a valid buffer. 395 * 396 *\li The length of the available region of 'b' is at least 6 397 * or the buffer has autoreallocation enabled. 398 * 399 * Ensures (for Read): 400 * 401 *\li The current pointer in 'b' is advanced by 6. 402 * 403 * Ensures (for Write): 404 * 405 *\li The used pointer in 'b' is advanced by 6. 406 * 407 * Returns (for Peek and Read): 408 * 409 *\li A 48-bit unsigned integer (stored in a 64-bit integer). 410 */ 411 412 static inline void 413 isc_buffer_putmem(isc_buffer_t *restrict b, const unsigned char *restrict base, 414 const unsigned int length); 415 /*!< 416 * \brief Copy 'length' bytes of memory at 'base' into 'b'. 417 * 418 * Requires: 419 *\li 'b' is a valid buffer. 420 * 421 *\li 'base' points to 'length' bytes of valid memory. 422 * 423 *\li The length of the available region of 'b' is at least 'length' 424 * or the buffer has autoreallocation enabled. 425 * 426 * Ensures: 427 *\li The used pointer in 'b' is advanced by 'length'. 428 */ 429 430 static inline isc_result_t 431 isc_buffer_copyregion(isc_buffer_t *restrict b, const isc_region_t *restrict r); 432 /*!< 433 * \brief Copy the contents of 'r' into 'b'. 434 * 435 * Notes: 436 *\li If 'b' has autoreallocation enabled, and the length of 'r' is greater 437 * than the length of the available region of 'b', 'b' is reallocated. 438 * 439 * Requires: 440 *\li 'b' is a valid buffer. 441 * 442 *\li 'r' is a valid region. 443 * 444 * Returns: 445 *\li ISC_R_SUCCESS 446 *\li ISC_R_NOSPACE The available region of 'b' is not 447 * big enough. 448 */ 449 450 static inline isc_result_t 451 isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **restrict dstp, 452 const isc_buffer_t *restrict src); 453 /*!< 454 * \brief Allocate 'dst' and copy used contents of 'src' into it. 455 * 456 * Requires: 457 *\li 'dstp' is not NULL and *dst is NULL. 458 *\li 'src' is a valid buffer. 459 * 460 * Returns: 461 *\li ISC_R_SUCCESS 462 */ 463 464 static inline isc_result_t 465 isc_buffer_printf(isc_buffer_t *restrict b, const char *restrict format, ...) 466 ISC_FORMAT_PRINTF(2, 3); 467 /*!< 468 * \brief Append a formatted string to the used region of 'b'. 469 * 470 * Notes: 471 * 472 *\li The 'format' argument is a printf(3) string, with additional arguments 473 * as necessary. 474 * 475 *\li If 'b' has autoreallocation enabled, and the length of the formatted 476 * string is greater than the length of the available region of 'b', 'b' 477 * is reallocated. 478 * 479 * Requires: 480 * 481 *\li 'b' is a valid buffer. 482 * 483 * Ensures: 484 * 485 *\li The used pointer in 'b' is advanced by the number of bytes appended 486 * (excluding the terminating NULL byte). 487 * 488 * Returns: 489 * 490 *\li #ISC_R_SUCCESS Operation succeeded. 491 *\li #ISC_R_NOSPACE 'b' does not allow reallocation and appending the 492 * formatted string to it would cause it to overflow. 493 *\li #ISC_R_NOMEMORY Reallocation failed. 494 *\li #ISC_R_FAILURE Other error occurred. 495 */ 496 497 /* 498 * Buffer functions implemented as inline. 499 */ 500 501 /*! \note 502 * XXXDCL Something more could be done with initializing buffers that 503 * point to const data. For example, isc_buffer_constinit() could 504 * set a new boolean flag in the buffer structure indicating whether 505 * the buffer was initialized with that function. Then if the 506 * boolean were true, the isc_buffer_put* functions could assert a 507 * contractual requirement for a non-const buffer. 508 * 509 * One drawback is that the isc_buffer_* functions that return 510 * pointers would still need to return non-const pointers to avoid compiler 511 * warnings, so it would be up to code that uses them to have to deal 512 * with the possibility that the buffer was initialized as const -- 513 * a problem that they *already* have to deal with but have absolutely 514 * no ability to. With a new isc_buffer_isconst() function returning 515 * true/false, they could at least assert a contractual requirement for 516 * non-const buffers when needed. 517 */ 518 519 /*! 520 * \brief Make 'b' refer to the 'length'-byte region starting at 'base'. 521 * 522 * Requires: 523 * 524 *\li 'length' > 0 525 * 526 *\li 'base' is a pointer to a sequence of 'length' bytes. 527 */ 528 static inline void 529 isc_buffer_init(isc_buffer_t *restrict b, void *base, 530 const unsigned int length) { 531 REQUIRE(b != NULL); 532 533 *b = (isc_buffer_t){ 534 .base = base, 535 .length = length, 536 .link = ISC_LINK_INITIALIZER, 537 .magic = ISC_BUFFER_MAGIC, 538 }; 539 } 540 541 /*! 542 *\brief Initialize a buffer 'b' with a null data field and zero length. 543 * This can later be grown as needed and swapped in place. 544 */ 545 static inline void 546 isc_buffer_initnull(isc_buffer_t *restrict b) { 547 *b = (isc_buffer_t){ 548 .link = ISC_LINK_INITIALIZER, 549 .magic = ISC_BUFFER_MAGIC, 550 }; 551 } 552 553 /*! 554 * \brief Make 'b' refer to the 'length'-byte constant region starting 555 * at 'base'. 556 * 557 * Requires: 558 * 559 *\li 'length' > 0 560 *\li 'base' is a pointer to a sequence of 'length' bytes. 561 */ 562 #define isc_buffer_constinit(_b, _d, _l) \ 563 do { \ 564 union { \ 565 void *_var; \ 566 const void *_const; \ 567 } _deconst; \ 568 _deconst._const = (_d); \ 569 isc_buffer_init((_b), _deconst._var, (_l)); \ 570 } while (0) 571 572 /*! 573 * \brief Make 'b' an invalid buffer. 574 * 575 * Requires: 576 *\li 'b' is a valid buffer. 577 * 578 * Ensures: 579 *\li Future attempts to use 'b' without calling isc_buffer_init() on 580 * it will cause an assertion failure. 581 */ 582 static inline void 583 isc_buffer_invalidate(isc_buffer_t *restrict b) { 584 REQUIRE(ISC_BUFFER_VALID(b)); 585 REQUIRE(!ISC_LINK_LINKED(b, link)); 586 REQUIRE(b->mctx == NULL); 587 588 *b = (isc_buffer_t){ 589 .magic = 0, 590 }; 591 } 592 593 /*! 594 * \brief Make 'r' refer to the region of 'b'. 595 * 596 * Requires: 597 * 598 *\li 'b' is a valid buffer. 599 * 600 *\li 'r' points to a region structure. 601 */ 602 static inline void 603 isc_buffer_region(isc_buffer_t *restrict b, isc_region_t *restrict r) { 604 REQUIRE(ISC_BUFFER_VALID(b)); 605 REQUIRE(r != NULL); 606 607 r->base = b->base; 608 r->length = b->length; 609 } 610 611 /*! 612 * \brief Make 'r' refer to the used region of 'b'. 613 * 614 * Requires: 615 * 616 *\li 'b' is a valid buffer. 617 * 618 *\li 'r' points to a region structure. 619 */ 620 static inline void 621 isc_buffer_usedregion(const isc_buffer_t *restrict b, 622 isc_region_t *restrict r) { 623 REQUIRE(ISC_BUFFER_VALID(b)); 624 REQUIRE(r != NULL); 625 626 r->base = b->base; 627 r->length = b->used; 628 } 629 630 /*! 631 * \brief Make 'r' refer to the available region of 'b'. 632 * 633 * Requires: 634 * 635 *\li 'b' is a valid buffer. 636 * 637 *\li 'r' points to a region structure. 638 */ 639 static inline void 640 isc_buffer_availableregion(isc_buffer_t *restrict b, isc_region_t *restrict r) { 641 REQUIRE(ISC_BUFFER_VALID(b)); 642 REQUIRE(r != NULL); 643 644 r->base = isc_buffer_used(b); 645 r->length = isc_buffer_availablelength(b); 646 } 647 648 /*! 649 * \brief Increase the 'used' region of 'b' by 'n' bytes. 650 * 651 * Requires: 652 * 653 *\li 'b' is a valid buffer 654 * 655 *\li used + n <= length 656 */ 657 static inline void 658 isc_buffer_add(isc_buffer_t *restrict b, const unsigned int n) { 659 REQUIRE(ISC_BUFFER_VALID(b)); 660 REQUIRE(b->used + n <= b->length); 661 662 b->used += n; 663 } 664 665 /*! 666 * \brief Decrease the 'used' region of 'b' by 'n' bytes. 667 * 668 * Requires: 669 * 670 *\li 'b' is a valid buffer 671 * 672 *\li used >= n 673 */ 674 static inline void 675 isc_buffer_subtract(isc_buffer_t *restrict b, const unsigned int n) { 676 REQUIRE(ISC_BUFFER_VALID(b)); 677 REQUIRE(b->used >= n); 678 679 b->used -= n; 680 if (b->current > b->used) { 681 b->current = b->used; 682 } 683 if (b->active > b->used) { 684 b->active = b->used; 685 } 686 } 687 688 /*!< 689 * \brief Make the used region empty. 690 * 691 * Requires: 692 * 693 *\li 'b' is a valid buffer 694 * 695 * Ensures: 696 * 697 *\li used = 0 698 */ 699 static inline void 700 isc_buffer_clear(isc_buffer_t *restrict b) { 701 REQUIRE(ISC_BUFFER_VALID(b)); 702 703 b->used = 0; 704 b->current = 0; 705 b->active = 0; 706 } 707 708 /*! 709 * \brief Make 'r' refer to the consumed region of 'b'. 710 * 711 * Requires: 712 * 713 *\li 'b' is a valid buffer. 714 * 715 *\li 'r' points to a region structure. 716 */ 717 static inline void 718 isc_buffer_consumedregion(isc_buffer_t *restrict b, isc_region_t *restrict r) { 719 REQUIRE(ISC_BUFFER_VALID(b)); 720 REQUIRE(r != NULL); 721 722 r->base = b->base; 723 r->length = b->current; 724 } 725 726 /*! 727 * \brief Make 'r' refer to the remaining region of 'b'. 728 * 729 * Requires: 730 * 731 *\li 'b' is a valid buffer. 732 * 733 *\li 'r' points to a region structure. 734 */ 735 static inline void 736 isc_buffer_remainingregion(isc_buffer_t *restrict b, isc_region_t *restrict r) { 737 REQUIRE(ISC_BUFFER_VALID(b)); 738 REQUIRE(r != NULL); 739 740 r->base = isc_buffer_current(b); 741 r->length = isc_buffer_remaininglength(b); 742 } 743 744 /*! 745 * \brief Make 'r' refer to the active region of 'b'. 746 * 747 * Requires: 748 * 749 *\li 'b' is a valid buffer. 750 * 751 *\li 'r' points to a region structure. 752 */ 753 static inline void 754 isc_buffer_activeregion(isc_buffer_t *restrict b, isc_region_t *restrict r) { 755 REQUIRE(ISC_BUFFER_VALID(b)); 756 REQUIRE(r != NULL); 757 758 if (b->current < b->active) { 759 r->base = isc_buffer_current(b); 760 r->length = isc_buffer_activelength(b); 761 } else { 762 r->base = NULL; 763 r->length = 0; 764 } 765 } 766 767 /*! 768 * \brief Sets the end of the active region 'n' bytes after current. 769 * 770 * Requires: 771 * 772 *\li 'b' is a valid buffer. 773 * 774 *\li current + n <= used 775 */ 776 static inline void 777 isc_buffer_setactive(isc_buffer_t *restrict b, const unsigned int n) { 778 REQUIRE(ISC_BUFFER_VALID(b)); 779 REQUIRE(b->current + n <= b->used); 780 781 b->active = b->current + n; 782 } 783 784 /*!< 785 * \brief Make the consumed region empty. 786 * 787 * Requires: 788 * 789 *\li 'b' is a valid buffer 790 * 791 * Ensures: 792 * 793 *\li current == 0 794 */ 795 static inline void 796 isc_buffer_first(isc_buffer_t *restrict b) { 797 REQUIRE(ISC_BUFFER_VALID(b)); 798 799 b->current = 0; 800 } 801 802 /*! 803 * \brief Increase the 'consumed' region of 'b' by 'n' bytes. 804 * 805 * Requires: 806 * 807 *\li 'b' is a valid buffer 808 * 809 *\li current + n <= used 810 */ 811 static inline void 812 isc_buffer_forward(isc_buffer_t *restrict b, const unsigned int n) { 813 REQUIRE(ISC_BUFFER_VALID(b)); 814 REQUIRE(b->current + n <= b->used); 815 816 b->current += n; 817 } 818 819 /*! 820 * \brief Decrease the 'consumed' region of 'b' by 'n' bytes. 821 * 822 * Requires: 823 * 824 *\li 'b' is a valid buffer 825 * 826 *\li n <= current 827 */ 828 static inline void 829 isc_buffer_back(isc_buffer_t *restrict b, const unsigned int n) { 830 REQUIRE(ISC_BUFFER_VALID(b)); 831 REQUIRE(n <= b->current); 832 833 b->current -= n; 834 } 835 836 #define ISC_BUFFER_PEEK_CHECK(b, s) \ 837 { \ 838 REQUIRE(ISC_BUFFER_VALID(b)); \ 839 if ((b)->used - (b)->current < s) { \ 840 return (ISC_R_NOMORE); \ 841 } \ 842 } 843 844 static inline isc_result_t 845 isc_buffer_peekuint8(const isc_buffer_t *restrict b, uint8_t *valp) { 846 ISC_BUFFER_PEEK_CHECK(b, sizeof(*valp)); 847 848 uint8_t *cp = isc_buffer_current(b); 849 SET_IF_NOT_NULL(valp, (uint8_t)(cp[0])); 850 return ISC_R_SUCCESS; 851 } 852 853 static inline uint8_t 854 isc_buffer_getuint8(isc_buffer_t *restrict b) { 855 uint8_t val = 0; 856 isc_result_t result = isc_buffer_peekuint8(b, &val); 857 ENSURE(result == ISC_R_SUCCESS); 858 b->current += sizeof(val); 859 return val; 860 } 861 862 #define ISC_BUFFER_PUT_RESERVE(b, v, s) \ 863 { \ 864 REQUIRE(ISC_BUFFER_VALID(b)); \ 865 \ 866 if (b->mctx) { \ 867 isc_result_t result = isc_buffer_reserve(b, s); \ 868 ENSURE(result == ISC_R_SUCCESS); \ 869 } \ 870 \ 871 REQUIRE(isc_buffer_availablelength(b) >= s); \ 872 } 873 874 static inline void 875 isc_buffer_putuint8(isc_buffer_t *restrict b, const uint8_t val) { 876 ISC_BUFFER_PUT_RESERVE(b, val, sizeof(val)); 877 878 uint8_t *cp = isc_buffer_used(b); 879 b->used += sizeof(val); 880 cp[0] = val; 881 } 882 883 static inline isc_result_t 884 isc_buffer_peekuint16(const isc_buffer_t *restrict b, uint16_t *valp) { 885 ISC_BUFFER_PEEK_CHECK(b, sizeof(*valp)); 886 887 uint8_t *cp = isc_buffer_current(b); 888 889 SET_IF_NOT_NULL(valp, ISC_U8TO16_BE(cp)); 890 return ISC_R_SUCCESS; 891 } 892 893 static inline uint16_t 894 isc_buffer_getuint16(isc_buffer_t *restrict b) { 895 uint16_t val = 0; 896 isc_result_t result = isc_buffer_peekuint16(b, &val); 897 ENSURE(result == ISC_R_SUCCESS); 898 b->current += sizeof(val); 899 return val; 900 } 901 902 static inline void 903 isc_buffer_putuint16(isc_buffer_t *restrict b, const uint16_t val) { 904 ISC_BUFFER_PUT_RESERVE(b, val, sizeof(val)); 905 906 uint8_t *cp = isc_buffer_used(b); 907 b->used += sizeof(val); 908 ISC_U16TO8_BE(cp, val); 909 } 910 911 static inline isc_result_t 912 isc_buffer_peekuint32(const isc_buffer_t *restrict b, uint32_t *valp) { 913 ISC_BUFFER_PEEK_CHECK(b, sizeof(*valp)); 914 915 uint8_t *cp = isc_buffer_current(b); 916 917 SET_IF_NOT_NULL(valp, ISC_U8TO32_BE(cp)); 918 return ISC_R_SUCCESS; 919 } 920 921 uint32_t 922 isc_buffer_getuint32(isc_buffer_t *restrict b) { 923 uint32_t val = 0; 924 isc_result_t result = isc_buffer_peekuint32(b, &val); 925 ENSURE(result == ISC_R_SUCCESS); 926 b->current += sizeof(val); 927 return val; 928 } 929 930 static inline void 931 isc_buffer_putuint32(isc_buffer_t *restrict b, const uint32_t val) { 932 ISC_BUFFER_PUT_RESERVE(b, val, sizeof(val)); 933 934 uint8_t *cp = isc_buffer_used(b); 935 b->used += sizeof(val); 936 937 ISC_U32TO8_BE(cp, val); 938 } 939 940 static inline isc_result_t 941 isc_buffer_peekuint48(const isc_buffer_t *restrict b, uint64_t *valp) { 942 ISC_BUFFER_PEEK_CHECK(b, 6); /* 48-bits */ 943 944 uint8_t *cp = isc_buffer_current(b); 945 946 SET_IF_NOT_NULL(valp, ISC_U8TO48_BE(cp)); 947 return ISC_R_SUCCESS; 948 } 949 950 static inline uint64_t 951 isc_buffer_getuint48(isc_buffer_t *restrict b) { 952 uint64_t val = 0; 953 isc_result_t result = isc_buffer_peekuint48(b, &val); 954 ENSURE(result == ISC_R_SUCCESS); 955 b->current += 6; /* 48-bits */ 956 return val; 957 } 958 959 static inline void 960 isc_buffer_putuint48(isc_buffer_t *restrict b, const uint64_t val) { 961 ISC_BUFFER_PUT_RESERVE(b, val, 6); /* 48-bits */ 962 963 uint8_t *cp = isc_buffer_used(b); 964 b->used += 6; 965 966 ISC_U48TO8_BE(cp, val); 967 } 968 969 static inline void 970 isc_buffer_putmem(isc_buffer_t *restrict b, const unsigned char *restrict base, 971 const unsigned int length) { 972 REQUIRE(ISC_BUFFER_VALID(b)); 973 974 if (b->mctx) { 975 isc_result_t result = isc_buffer_reserve(b, length); 976 REQUIRE(result == ISC_R_SUCCESS); 977 } 978 979 REQUIRE(isc_buffer_availablelength(b) >= (unsigned int)length); 980 981 if (length > 0U) { 982 memmove(isc_buffer_used(b), base, length); 983 b->used += length; 984 } 985 } 986 987 /*! 988 * \brief Copy 'source' into 'b', not including terminating NUL. 989 * 990 * Requires: 991 *\li 'b' is a valid buffer. 992 * 993 *\li 'source' is a valid NULL terminated string. 994 * 995 *\li The length of the available region of 'b' is at least strlen('source') 996 * or the buffer has autoreallocation enabled. 997 * 998 * Ensures: 999 *\li The used pointer in 'b' is advanced by strlen('source'). 1000 */ 1001 static inline void 1002 isc_buffer_putstr(isc_buffer_t *restrict b, const char *restrict source) { 1003 unsigned int length; 1004 unsigned char *cp; 1005 1006 REQUIRE(ISC_BUFFER_VALID(b)); 1007 REQUIRE(source != NULL); 1008 1009 length = (unsigned int)strlen(source); 1010 if (b->mctx) { 1011 isc_result_t result = isc_buffer_reserve(b, length); 1012 ENSURE(result == ISC_R_SUCCESS); 1013 } 1014 1015 REQUIRE(isc_buffer_availablelength(b) >= length); 1016 1017 cp = isc_buffer_used(b); 1018 memmove(cp, source, length); 1019 b->used += length; 1020 } 1021 1022 static inline void 1023 isc_buffer_reinit(isc_buffer_t *restrict b, void *base, 1024 const unsigned int length) { 1025 /* 1026 * Re-initialize the buffer enough to reconfigure the base of the 1027 * buffer. We will swap in the new buffer, after copying any 1028 * data we contain into the new buffer and adjusting all of our 1029 * internal pointers. 1030 * 1031 * The buffer must not be smaller than the length of the original 1032 * buffer. 1033 */ 1034 REQUIRE(b->length <= length); 1035 REQUIRE(base != NULL); 1036 REQUIRE(b->mctx == NULL); 1037 1038 if (b->length > 0U) { 1039 (void)memmove(base, b->base, b->length); 1040 } 1041 1042 b->base = base; 1043 b->length = length; 1044 } 1045 1046 static inline void 1047 isc_buffer_trycompact(isc_buffer_t *restrict b) { 1048 if (isc_buffer_consumedlength(b) >= isc_buffer_remaininglength(b)) { 1049 isc_buffer_compact(b); 1050 } 1051 } 1052 1053 static inline void 1054 isc_buffer_compact(isc_buffer_t *restrict b) { 1055 unsigned int length; 1056 void *src; 1057 1058 /* 1059 * Compact the used region by moving the remaining region so it occurs 1060 * at the start of the buffer. The used region is shrunk by the size 1061 * of the consumed region, and the consumed region is then made empty. 1062 */ 1063 1064 REQUIRE(ISC_BUFFER_VALID(b)); 1065 1066 src = isc_buffer_current(b); 1067 length = isc_buffer_remaininglength(b); 1068 if (length > 0U) { 1069 (void)memmove(b->base, src, (size_t)length); 1070 } 1071 1072 if (b->active > b->current) { 1073 b->active -= b->current; 1074 } else { 1075 b->active = 0; 1076 } 1077 b->current = 0; 1078 b->used = length; 1079 } 1080 1081 static inline void 1082 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **restrict dbufp, 1083 const unsigned int length) { 1084 REQUIRE(dbufp != NULL && *dbufp == NULL); 1085 1086 isc_buffer_t *dbuf = isc_mem_get(mctx, sizeof(*dbuf) + length); 1087 uint8_t *bdata = (uint8_t *)dbuf + sizeof(*dbuf); 1088 1089 isc_buffer_init(dbuf, bdata, length); 1090 dbuf->extra = length; 1091 isc_buffer_setmctx(dbuf, mctx); 1092 1093 *dbufp = dbuf; 1094 } 1095 1096 static inline void 1097 isc_buffer_setmctx(isc_buffer_t *restrict b, isc_mem_t *mctx) { 1098 REQUIRE(ISC_BUFFER_VALID(b)); 1099 1100 b->mctx = mctx; 1101 } 1102 1103 static inline void 1104 isc_buffer_clearmctx(isc_buffer_t *restrict b) { 1105 REQUIRE(ISC_BUFFER_VALID(b)); 1106 1107 if (b->dynamic) { 1108 isc_mem_put(b->mctx, b->base, b->length); 1109 b->dynamic = false; 1110 } 1111 1112 b->mctx = NULL; 1113 } 1114 1115 static inline isc_result_t 1116 isc_buffer_reserve(isc_buffer_t *restrict dbuf, const unsigned int size) { 1117 REQUIRE(ISC_BUFFER_VALID(dbuf)); 1118 1119 size_t len; 1120 1121 len = dbuf->length; 1122 if ((len - dbuf->used) >= size) { 1123 return ISC_R_SUCCESS; 1124 } 1125 1126 if (dbuf->mctx == NULL) { 1127 return ISC_R_NOSPACE; 1128 } 1129 1130 /* Round to nearest buffer size increment */ 1131 len = size + dbuf->used; 1132 len = ISC_ALIGN(len, ISC_BUFFER_INCR); 1133 1134 /* Cap at UINT_MAX */ 1135 if (len > UINT_MAX) { 1136 len = UINT_MAX; 1137 } 1138 1139 if ((len - dbuf->used) < size) { 1140 return ISC_R_NOMEMORY; 1141 } 1142 1143 if (!dbuf->dynamic) { 1144 void *old_base = dbuf->base; 1145 dbuf->base = isc_mem_get(dbuf->mctx, len); 1146 if (old_base != NULL) { 1147 memmove(dbuf->base, old_base, dbuf->used); 1148 } 1149 dbuf->dynamic = true; 1150 } else { 1151 dbuf->base = isc_mem_creget(dbuf->mctx, dbuf->base, 1152 dbuf->length, len, sizeof(char)); 1153 } 1154 dbuf->length = (unsigned int)len; 1155 1156 return ISC_R_SUCCESS; 1157 } 1158 1159 static inline void 1160 isc_buffer_free(isc_buffer_t **restrict dbufp) { 1161 REQUIRE(dbufp != NULL && ISC_BUFFER_VALID(*dbufp)); 1162 REQUIRE((*dbufp)->mctx != NULL); 1163 1164 isc_buffer_t *dbuf = *dbufp; 1165 isc_mem_t *mctx = dbuf->mctx; 1166 unsigned int extra = dbuf->extra; 1167 1168 *dbufp = NULL; /* destroy external reference */ 1169 1170 isc_buffer_clearmctx(dbuf); 1171 1172 isc_buffer_invalidate(dbuf); 1173 isc_mem_put(mctx, dbuf, sizeof(*dbuf) + extra); 1174 } 1175 1176 static inline isc_result_t 1177 isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **restrict dstp, 1178 const isc_buffer_t *restrict src) { 1179 isc_buffer_t *dst = NULL; 1180 isc_region_t region; 1181 isc_result_t result; 1182 1183 REQUIRE(dstp != NULL && *dstp == NULL); 1184 REQUIRE(ISC_BUFFER_VALID(src)); 1185 1186 isc_buffer_usedregion(src, ®ion); 1187 1188 isc_buffer_allocate(mctx, &dst, region.length); 1189 1190 result = isc_buffer_copyregion(dst, ®ion); 1191 RUNTIME_CHECK(result == ISC_R_SUCCESS); /* NOSPACE is impossible */ 1192 *dstp = dst; 1193 return ISC_R_SUCCESS; 1194 } 1195 1196 static inline isc_result_t 1197 isc_buffer_copyregion(isc_buffer_t *restrict b, 1198 const isc_region_t *restrict r) { 1199 isc_result_t result; 1200 1201 REQUIRE(ISC_BUFFER_VALID(b)); 1202 REQUIRE(r != NULL); 1203 1204 if (b->mctx) { 1205 result = isc_buffer_reserve(b, r->length); 1206 if (result != ISC_R_SUCCESS) { 1207 return result; 1208 } 1209 } 1210 1211 if (r->length > isc_buffer_availablelength(b)) { 1212 return ISC_R_NOSPACE; 1213 } 1214 1215 if (r->length > 0U) { 1216 memmove(isc_buffer_used(b), r->base, r->length); 1217 b->used += r->length; 1218 } 1219 1220 return ISC_R_SUCCESS; 1221 } 1222 1223 static inline isc_result_t 1224 isc_buffer_printf(isc_buffer_t *restrict b, const char *restrict format, ...) { 1225 va_list ap; 1226 int n; 1227 isc_result_t result; 1228 1229 REQUIRE(ISC_BUFFER_VALID(b)); 1230 1231 va_start(ap, format); 1232 n = vsnprintf(NULL, 0, format, ap); 1233 va_end(ap); 1234 1235 if (n < 0) { 1236 return ISC_R_FAILURE; 1237 } 1238 1239 if (b->mctx) { 1240 result = isc_buffer_reserve(b, n + 1); 1241 if (result != ISC_R_SUCCESS) { 1242 return result; 1243 } 1244 } 1245 1246 if (isc_buffer_availablelength(b) < (unsigned int)n + 1) { 1247 return ISC_R_NOSPACE; 1248 } 1249 1250 va_start(ap, format); 1251 n = vsnprintf(isc_buffer_used(b), n + 1, format, ap); 1252 va_end(ap); 1253 1254 if (n < 0) { 1255 return ISC_R_FAILURE; 1256 } 1257 1258 b->used += n; 1259 1260 return ISC_R_SUCCESS; 1261 } 1262 1263 ISC_LANG_ENDDECLS 1264