1 /* 2 * buffer.h -- generic memory buffer. 3 * 4 * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 * 9 * The buffer module implements a generic buffer. The API is based on 10 * the java.nio.Buffer interface. 11 */ 12 13 #ifndef LDNS_SBUFFER_H 14 #define LDNS_SBUFFER_H 15 16 #ifdef __cplusplus 17 extern "C" { 18 #endif 19 20 #ifdef S_SPLINT_S 21 # define INLINE 22 #else 23 # ifdef SWIG 24 # define INLINE static 25 # else 26 # define INLINE static inline 27 # endif 28 #endif 29 30 /* 31 * Copy data allowing for unaligned accesses in network byte order 32 * (big endian). 33 */ 34 INLINE uint16_t 35 sldns_read_uint16(const void *src) 36 { 37 #ifdef ALLOW_UNALIGNED_ACCESSES 38 return ntohs(*(const uint16_t *) src); 39 #else 40 const uint8_t *p = (const uint8_t *) src; 41 return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; 42 #endif 43 } 44 45 INLINE uint32_t 46 sldns_read_uint32(const void *src) 47 { 48 #ifdef ALLOW_UNALIGNED_ACCESSES 49 return ntohl(*(const uint32_t *) src); 50 #else 51 const uint8_t *p = (const uint8_t *) src; 52 return ( ((uint32_t) p[0] << 24) 53 | ((uint32_t) p[1] << 16) 54 | ((uint32_t) p[2] << 8) 55 | (uint32_t) p[3]); 56 #endif 57 } 58 59 /* 60 * Copy data allowing for unaligned accesses in network byte order 61 * (big endian). 62 */ 63 INLINE void 64 sldns_write_uint16(void *dst, uint16_t data) 65 { 66 #ifdef ALLOW_UNALIGNED_ACCESSES 67 * (uint16_t *) dst = htons(data); 68 #else 69 uint8_t *p = (uint8_t *) dst; 70 p[0] = (uint8_t) ((data >> 8) & 0xff); 71 p[1] = (uint8_t) (data & 0xff); 72 #endif 73 } 74 75 INLINE void 76 sldns_write_uint32(void *dst, uint32_t data) 77 { 78 #ifdef ALLOW_UNALIGNED_ACCESSES 79 * (uint32_t *) dst = htonl(data); 80 #else 81 uint8_t *p = (uint8_t *) dst; 82 p[0] = (uint8_t) ((data >> 24) & 0xff); 83 p[1] = (uint8_t) ((data >> 16) & 0xff); 84 p[2] = (uint8_t) ((data >> 8) & 0xff); 85 p[3] = (uint8_t) (data & 0xff); 86 #endif 87 } 88 89 90 INLINE void 91 sldns_write_uint48(void *dst, uint64_t data) 92 { 93 uint8_t *p = (uint8_t *) dst; 94 p[0] = (uint8_t) ((data >> 40) & 0xff); 95 p[1] = (uint8_t) ((data >> 32) & 0xff); 96 p[2] = (uint8_t) ((data >> 24) & 0xff); 97 p[3] = (uint8_t) ((data >> 16) & 0xff); 98 p[4] = (uint8_t) ((data >> 8) & 0xff); 99 p[5] = (uint8_t) (data & 0xff); 100 } 101 102 103 /** 104 * \file sbuffer.h 105 * 106 * This file contains the definition of sldns_buffer, and functions to manipulate those. 107 */ 108 109 /** 110 * implementation of buffers to ease operations 111 * 112 * sldns_buffers can contain arbitrary information, per octet. You can write 113 * to the current end of a buffer, read from the current position, and 114 * access any data within it. 115 */ 116 struct sldns_buffer 117 { 118 /** The current position used for reading/writing */ 119 size_t _position; 120 121 /** The read/write limit */ 122 size_t _limit; 123 124 /** The amount of data the buffer can contain */ 125 size_t _capacity; 126 127 /** The data contained in the buffer */ 128 uint8_t *_data; 129 130 /** If the buffer is fixed it cannot be resized */ 131 unsigned _fixed : 1; 132 133 /** The current state of the buffer. If writing to the buffer fails 134 * for any reason, this value is changed. This way, you can perform 135 * multiple writes in sequence and check for success afterwards. */ 136 unsigned _status_err : 1; 137 }; 138 typedef struct sldns_buffer sldns_buffer; 139 140 #ifdef NDEBUG 141 INLINE void 142 sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer)) 143 { 144 } 145 #else 146 INLINE void 147 sldns_buffer_invariant(sldns_buffer *buffer) 148 { 149 assert(buffer != NULL); 150 assert(buffer->_position <= buffer->_limit); 151 assert(buffer->_limit <= buffer->_capacity); 152 assert(buffer->_data != NULL); 153 } 154 #endif 155 156 /** 157 * creates a new buffer with the specified capacity. 158 * 159 * \param[in] capacity the size (in bytes) to allocate for the buffer 160 * \return the created buffer 161 */ 162 sldns_buffer *sldns_buffer_new(size_t capacity); 163 164 /** 165 * creates a buffer with the specified data. The data IS copied 166 * and MEMORY allocations are done. The buffer is not fixed and can 167 * be resized using buffer_reserve(). 168 * 169 * \param[in] buffer pointer to the buffer to put the data in 170 * \param[in] data the data to encapsulate in the buffer 171 * \param[in] size the size of the data 172 */ 173 void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size); 174 175 /** 176 * Setup a buffer with the data pointed to. No data copied, no memory allocs. 177 * The buffer is fixed. 178 * \param[in] buffer pointer to the buffer to put the data in 179 * \param[in] data the data to encapsulate in the buffer 180 * \param[in] size the size of the data 181 */ 182 void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size); 183 184 /** 185 * clears the buffer and make it ready for writing. The buffer's limit 186 * is set to the capacity and the position is set to 0. 187 * \param[in] buffer the buffer to clear 188 */ 189 INLINE void sldns_buffer_clear(sldns_buffer *buffer) 190 { 191 sldns_buffer_invariant(buffer); 192 193 /* reset status here? */ 194 195 buffer->_position = 0; 196 buffer->_limit = buffer->_capacity; 197 } 198 199 /** 200 * makes the buffer ready for reading the data that has been written to 201 * the buffer. The buffer's limit is set to the current position and 202 * the position is set to 0. 203 * 204 * \param[in] buffer the buffer to flip 205 * \return void 206 */ 207 INLINE void sldns_buffer_flip(sldns_buffer *buffer) 208 { 209 sldns_buffer_invariant(buffer); 210 211 buffer->_limit = buffer->_position; 212 buffer->_position = 0; 213 } 214 215 /** 216 * make the buffer ready for re-reading the data. The buffer's 217 * position is reset to 0. 218 * \param[in] buffer the buffer to rewind 219 */ 220 INLINE void sldns_buffer_rewind(sldns_buffer *buffer) 221 { 222 sldns_buffer_invariant(buffer); 223 224 buffer->_position = 0; 225 } 226 227 /** 228 * returns the current position in the buffer (as a number of bytes) 229 * \param[in] buffer the buffer 230 * \return the current position 231 */ 232 INLINE size_t 233 sldns_buffer_position(sldns_buffer *buffer) 234 { 235 return buffer->_position; 236 } 237 238 /** 239 * sets the buffer's position to MARK. The position must be less than 240 * or equal to the buffer's limit. 241 * \param[in] buffer the buffer 242 * \param[in] mark the mark to use 243 */ 244 INLINE void 245 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark) 246 { 247 assert(mark <= buffer->_limit); 248 buffer->_position = mark; 249 } 250 251 /** 252 * changes the buffer's position by COUNT bytes. The position must not 253 * be moved behind the buffer's limit or before the beginning of the 254 * buffer. 255 * \param[in] buffer the buffer 256 * \param[in] count the count to use 257 */ 258 INLINE void 259 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count) 260 { 261 assert(buffer->_position + count <= buffer->_limit); 262 buffer->_position += count; 263 } 264 265 /** 266 * returns the maximum size of the buffer 267 * \param[in] buffer 268 * \return the size 269 */ 270 INLINE size_t 271 sldns_buffer_limit(sldns_buffer *buffer) 272 { 273 return buffer->_limit; 274 } 275 276 /** 277 * changes the buffer's limit. If the buffer's position is greater 278 * than the new limit the position is set to the limit. 279 * \param[in] buffer the buffer 280 * \param[in] limit the new limit 281 */ 282 INLINE void 283 sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit) 284 { 285 assert(limit <= buffer->_capacity); 286 buffer->_limit = limit; 287 if (buffer->_position > buffer->_limit) 288 buffer->_position = buffer->_limit; 289 } 290 291 /** 292 * returns the number of bytes the buffer can hold. 293 * \param[in] buffer the buffer 294 * \return the number of bytes 295 */ 296 INLINE size_t 297 sldns_buffer_capacity(sldns_buffer *buffer) 298 { 299 return buffer->_capacity; 300 } 301 302 /** 303 * changes the buffer's capacity. The data is reallocated so any 304 * pointers to the data may become invalid. The buffer's limit is set 305 * to the buffer's new capacity. 306 * \param[in] buffer the buffer 307 * \param[in] capacity the capacity to use 308 * \return whether this failed or succeeded 309 */ 310 int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity); 311 312 /** 313 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's 314 * capacity is increased if necessary using buffer_set_capacity(). 315 * 316 * The buffer's limit is always set to the (possibly increased) 317 * capacity. 318 * \param[in] buffer the buffer 319 * \param[in] amount amount to use 320 * \return whether this failed or succeeded 321 */ 322 int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount); 323 324 /** 325 * returns a pointer to the data at the indicated position. 326 * \param[in] buffer the buffer 327 * \param[in] at position 328 * \return the pointer to the data 329 */ 330 INLINE uint8_t * 331 sldns_buffer_at(const sldns_buffer *buffer, size_t at) 332 { 333 assert(at <= buffer->_limit); 334 return buffer->_data + at; 335 } 336 337 /** 338 * returns a pointer to the beginning of the buffer (the data at 339 * position 0). 340 * \param[in] buffer the buffer 341 * \return the pointer 342 */ 343 INLINE uint8_t * 344 sldns_buffer_begin(const sldns_buffer *buffer) 345 { 346 return sldns_buffer_at(buffer, 0); 347 } 348 349 /** 350 * returns a pointer to the end of the buffer (the data at the buffer's 351 * limit). 352 * \param[in] buffer the buffer 353 * \return the pointer 354 */ 355 INLINE uint8_t * 356 sldns_buffer_end(sldns_buffer *buffer) 357 { 358 return sldns_buffer_at(buffer, buffer->_limit); 359 } 360 361 /** 362 * returns a pointer to the data at the buffer's current position. 363 * \param[in] buffer the buffer 364 * \return the pointer 365 */ 366 INLINE uint8_t * 367 sldns_buffer_current(sldns_buffer *buffer) 368 { 369 return sldns_buffer_at(buffer, buffer->_position); 370 } 371 372 /** 373 * returns the number of bytes remaining between the indicated position and 374 * the limit. 375 * \param[in] buffer the buffer 376 * \param[in] at indicated position 377 * \return number of bytes 378 */ 379 INLINE size_t 380 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at) 381 { 382 sldns_buffer_invariant(buffer); 383 assert(at <= buffer->_limit); 384 return at < buffer->_limit ? buffer->_limit - at : 0; 385 } 386 387 /** 388 * returns the number of bytes remaining between the buffer's position and 389 * limit. 390 * \param[in] buffer the buffer 391 * \return the number of bytes 392 */ 393 INLINE size_t 394 sldns_buffer_remaining(sldns_buffer *buffer) 395 { 396 return sldns_buffer_remaining_at(buffer, buffer->_position); 397 } 398 399 /** 400 * checks if the buffer has at least COUNT more bytes available. 401 * Before reading or writing the caller needs to ensure enough space 402 * is available! 403 * \param[in] buffer the buffer 404 * \param[in] at indicated position 405 * \param[in] count how much is available 406 * \return true or false (as int?) 407 */ 408 INLINE int 409 sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count) 410 { 411 return count <= sldns_buffer_remaining_at(buffer, at); 412 } 413 414 /** 415 * checks if the buffer has count bytes available at the current position 416 * \param[in] buffer the buffer 417 * \param[in] count how much is available 418 * \return true or false (as int?) 419 */ 420 INLINE int 421 sldns_buffer_available(sldns_buffer *buffer, size_t count) 422 { 423 return sldns_buffer_available_at(buffer, buffer->_position, count); 424 } 425 426 /** 427 * writes the given data to the buffer at the specified position 428 * \param[in] buffer the buffer 429 * \param[in] at the position (in number of bytes) to write the data at 430 * \param[in] data pointer to the data to write to the buffer 431 * \param[in] count the number of bytes of data to write 432 */ 433 INLINE void 434 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count) 435 { 436 assert(sldns_buffer_available_at(buffer, at, count)); 437 memcpy(buffer->_data + at, data, count); 438 } 439 440 /** 441 * set the given byte to the buffer at the specified position 442 * \param[in] buffer the buffer 443 * \param[in] at the position (in number of bytes) to write the data at 444 * \param[in] c the byte to set to the buffer 445 * \param[in] count the number of bytes of bytes to write 446 */ 447 448 INLINE void 449 sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count) 450 { 451 assert(sldns_buffer_available_at(buffer, at, count)); 452 memset(buffer->_data + at, c, count); 453 } 454 455 456 /** 457 * writes count bytes of data to the current position of the buffer 458 * \param[in] buffer the buffer 459 * \param[in] data the data to write 460 * \param[in] count the length of the data to write 461 */ 462 INLINE void 463 sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count) 464 { 465 sldns_buffer_write_at(buffer, buffer->_position, data, count); 466 buffer->_position += count; 467 } 468 469 /** 470 * copies the given (null-delimited) string to the specified position at the buffer 471 * \param[in] buffer the buffer 472 * \param[in] at the position in the buffer 473 * \param[in] str the string to write 474 */ 475 INLINE void 476 sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str) 477 { 478 sldns_buffer_write_at(buffer, at, str, strlen(str)); 479 } 480 481 /** 482 * copies the given (null-delimited) string to the current position at the buffer 483 * \param[in] buffer the buffer 484 * \param[in] str the string to write 485 */ 486 INLINE void 487 sldns_buffer_write_string(sldns_buffer *buffer, const char *str) 488 { 489 sldns_buffer_write(buffer, str, strlen(str)); 490 } 491 492 /** 493 * writes the given byte of data at the given position in the buffer 494 * \param[in] buffer the buffer 495 * \param[in] at the position in the buffer 496 * \param[in] data the 8 bits to write 497 */ 498 INLINE void 499 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data) 500 { 501 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 502 buffer->_data[at] = data; 503 } 504 505 /** 506 * writes the given byte of data at the current position in the buffer 507 * \param[in] buffer the buffer 508 * \param[in] data the 8 bits to write 509 */ 510 INLINE void 511 sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data) 512 { 513 sldns_buffer_write_u8_at(buffer, buffer->_position, data); 514 buffer->_position += sizeof(data); 515 } 516 517 /** 518 * writes the given 2 byte integer at the given position in the buffer 519 * \param[in] buffer the buffer 520 * \param[in] at the position in the buffer 521 * \param[in] data the 16 bits to write 522 */ 523 INLINE void 524 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data) 525 { 526 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 527 sldns_write_uint16(buffer->_data + at, data); 528 } 529 530 /** 531 * writes the given 2 byte integer at the current position in the buffer 532 * \param[in] buffer the buffer 533 * \param[in] data the 16 bits to write 534 */ 535 INLINE void 536 sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data) 537 { 538 sldns_buffer_write_u16_at(buffer, buffer->_position, data); 539 buffer->_position += sizeof(data); 540 } 541 542 /** 543 * writes the given 4 byte integer at the given position in the buffer 544 * \param[in] buffer the buffer 545 * \param[in] at the position in the buffer 546 * \param[in] data the 32 bits to write 547 */ 548 INLINE void 549 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data) 550 { 551 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 552 sldns_write_uint32(buffer->_data + at, data); 553 } 554 555 /** 556 * writes the given 6 byte integer at the given position in the buffer 557 * \param[in] buffer the buffer 558 * \param[in] at the position in the buffer 559 * \param[in] data the (lower) 48 bits to write 560 */ 561 INLINE void 562 sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data) 563 { 564 assert(sldns_buffer_available_at(buffer, at, 6)); 565 sldns_write_uint48(buffer->_data + at, data); 566 } 567 568 /** 569 * writes the given 4 byte integer at the current position in the buffer 570 * \param[in] buffer the buffer 571 * \param[in] data the 32 bits to write 572 */ 573 INLINE void 574 sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data) 575 { 576 sldns_buffer_write_u32_at(buffer, buffer->_position, data); 577 buffer->_position += sizeof(data); 578 } 579 580 /** 581 * writes the given 6 byte integer at the current position in the buffer 582 * \param[in] buffer the buffer 583 * \param[in] data the 48 bits to write 584 */ 585 INLINE void 586 sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data) 587 { 588 sldns_buffer_write_u48_at(buffer, buffer->_position, data); 589 buffer->_position += 6; 590 } 591 592 /** 593 * copies count bytes of data at the given position to the given data-array 594 * \param[in] buffer the buffer 595 * \param[in] at the position in the buffer to start 596 * \param[out] data buffer to copy to 597 * \param[in] count the length of the data to copy 598 */ 599 INLINE void 600 sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count) 601 { 602 assert(sldns_buffer_available_at(buffer, at, count)); 603 memcpy(data, buffer->_data + at, count); 604 } 605 606 /** 607 * copies count bytes of data at the current position to the given data-array 608 * \param[in] buffer the buffer 609 * \param[out] data buffer to copy to 610 * \param[in] count the length of the data to copy 611 */ 612 INLINE void 613 sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count) 614 { 615 sldns_buffer_read_at(buffer, buffer->_position, data, count); 616 buffer->_position += count; 617 } 618 619 /** 620 * returns the byte value at the given position in the buffer 621 * \param[in] buffer the buffer 622 * \param[in] at the position in the buffer 623 * \return 1 byte integer 624 */ 625 INLINE uint8_t 626 sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at) 627 { 628 assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t))); 629 return buffer->_data[at]; 630 } 631 632 /** 633 * returns the byte value at the current position in the buffer 634 * \param[in] buffer the buffer 635 * \return 1 byte integer 636 */ 637 INLINE uint8_t 638 sldns_buffer_read_u8(sldns_buffer *buffer) 639 { 640 uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position); 641 buffer->_position += sizeof(uint8_t); 642 return result; 643 } 644 645 /** 646 * returns the 2-byte integer value at the given position in the buffer 647 * \param[in] buffer the buffer 648 * \param[in] at position in the buffer 649 * \return 2 byte integer 650 */ 651 INLINE uint16_t 652 sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at) 653 { 654 assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t))); 655 return sldns_read_uint16(buffer->_data + at); 656 } 657 658 /** 659 * returns the 2-byte integer value at the current position in the buffer 660 * \param[in] buffer the buffer 661 * \return 2 byte integer 662 */ 663 INLINE uint16_t 664 sldns_buffer_read_u16(sldns_buffer *buffer) 665 { 666 uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position); 667 buffer->_position += sizeof(uint16_t); 668 return result; 669 } 670 671 /** 672 * returns the 4-byte integer value at the given position in the buffer 673 * \param[in] buffer the buffer 674 * \param[in] at position in the buffer 675 * \return 4 byte integer 676 */ 677 INLINE uint32_t 678 sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at) 679 { 680 assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t))); 681 return sldns_read_uint32(buffer->_data + at); 682 } 683 684 /** 685 * returns the 4-byte integer value at the current position in the buffer 686 * \param[in] buffer the buffer 687 * \return 4 byte integer 688 */ 689 INLINE uint32_t 690 sldns_buffer_read_u32(sldns_buffer *buffer) 691 { 692 uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position); 693 buffer->_position += sizeof(uint32_t); 694 return result; 695 } 696 697 /** 698 * returns the status of the buffer 699 * \param[in] buffer 700 * \return the status 701 */ 702 INLINE int 703 sldns_buffer_status(sldns_buffer *buffer) 704 { 705 return (int)buffer->_status_err; 706 } 707 708 /** 709 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise 710 * \param[in] buffer the buffer 711 * \return true or false 712 */ 713 INLINE int 714 sldns_buffer_status_ok(sldns_buffer *buffer) 715 { 716 if (buffer) { 717 return sldns_buffer_status(buffer) == 0; 718 } else { 719 return 0; 720 } 721 } 722 723 /** 724 * prints to the buffer, increasing the capacity if required using 725 * buffer_reserve(). The buffer's position is set to the terminating '\\0' 726 * Returns the number of characters written (not including the 727 * terminating '\\0') or -1 on failure. 728 */ 729 int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) 730 ATTR_FORMAT(printf, 2, 3); 731 732 /** 733 * frees the buffer. 734 * \param[in] *buffer the buffer to be freed 735 * \return void 736 */ 737 void sldns_buffer_free(sldns_buffer *buffer); 738 739 /** 740 * Copy contents of the from buffer to the result buffer and then flips 741 * the result buffer. Data will be silently truncated if the result buffer is 742 * too small. 743 * \param[out] *result resulting buffer which is copied to. 744 * \param[in] *from what to copy to result. 745 */ 746 void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from); 747 748 #ifdef __cplusplus 749 } 750 #endif 751 752 #endif /* LDNS_SBUFFER_H */ 753