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 */ 206 INLINE void sldns_buffer_flip(sldns_buffer *buffer) 207 { 208 sldns_buffer_invariant(buffer); 209 210 buffer->_limit = buffer->_position; 211 buffer->_position = 0; 212 } 213 214 /** 215 * make the buffer ready for re-reading the data. The buffer's 216 * position is reset to 0. 217 * \param[in] buffer the buffer to rewind 218 */ 219 INLINE void sldns_buffer_rewind(sldns_buffer *buffer) 220 { 221 sldns_buffer_invariant(buffer); 222 223 buffer->_position = 0; 224 } 225 226 /** 227 * returns the current position in the buffer (as a number of bytes) 228 * \param[in] buffer the buffer 229 * \return the current position 230 */ 231 INLINE size_t 232 sldns_buffer_position(sldns_buffer *buffer) 233 { 234 return buffer->_position; 235 } 236 237 /** 238 * sets the buffer's position to MARK. The position must be less than 239 * or equal to the buffer's limit. 240 * \param[in] buffer the buffer 241 * \param[in] mark the mark to use 242 */ 243 INLINE void 244 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark) 245 { 246 assert(mark <= buffer->_limit); 247 buffer->_position = mark; 248 } 249 250 /** 251 * changes the buffer's position by COUNT bytes. The position must not 252 * be moved behind the buffer's limit or before the beginning of the 253 * buffer. 254 * \param[in] buffer the buffer 255 * \param[in] count the count to use 256 */ 257 INLINE void 258 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count) 259 { 260 assert(buffer->_position + count <= buffer->_limit); 261 buffer->_position += count; 262 } 263 264 /** 265 * returns the maximum size of the buffer 266 * \param[in] buffer 267 * \return the size 268 */ 269 INLINE size_t 270 sldns_buffer_limit(sldns_buffer *buffer) 271 { 272 return buffer->_limit; 273 } 274 275 /** 276 * changes the buffer's limit. If the buffer's position is greater 277 * than the new limit the position is set to the limit. 278 * \param[in] buffer the buffer 279 * \param[in] limit the new limit 280 */ 281 INLINE void 282 sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit) 283 { 284 assert(limit <= buffer->_capacity); 285 buffer->_limit = limit; 286 if (buffer->_position > buffer->_limit) 287 buffer->_position = buffer->_limit; 288 } 289 290 /** 291 * returns the number of bytes the buffer can hold. 292 * \param[in] buffer the buffer 293 * \return the number of bytes 294 */ 295 INLINE size_t 296 sldns_buffer_capacity(sldns_buffer *buffer) 297 { 298 return buffer->_capacity; 299 } 300 301 /** 302 * changes the buffer's capacity. The data is reallocated so any 303 * pointers to the data may become invalid. The buffer's limit is set 304 * to the buffer's new capacity. 305 * \param[in] buffer the buffer 306 * \param[in] capacity the capacity to use 307 * \return whether this failed or succeeded 308 */ 309 int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity); 310 311 /** 312 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's 313 * capacity is increased if necessary using buffer_set_capacity(). 314 * 315 * The buffer's limit is always set to the (possibly increased) 316 * capacity. 317 * \param[in] buffer the buffer 318 * \param[in] amount amount to use 319 * \return whether this failed or succeeded 320 */ 321 int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount); 322 323 /** 324 * returns a pointer to the data at the indicated position. 325 * \param[in] buffer the buffer 326 * \param[in] at position 327 * \return the pointer to the data 328 */ 329 INLINE uint8_t * 330 sldns_buffer_at(const sldns_buffer *buffer, size_t at) 331 { 332 assert(at <= buffer->_limit); 333 return buffer->_data + at; 334 } 335 336 /** 337 * returns a pointer to the beginning of the buffer (the data at 338 * position 0). 339 * \param[in] buffer the buffer 340 * \return the pointer 341 */ 342 INLINE uint8_t * 343 sldns_buffer_begin(const sldns_buffer *buffer) 344 { 345 return sldns_buffer_at(buffer, 0); 346 } 347 348 /** 349 * returns a pointer to the end of the buffer (the data at the buffer's 350 * limit). 351 * \param[in] buffer the buffer 352 * \return the pointer 353 */ 354 INLINE uint8_t * 355 sldns_buffer_end(sldns_buffer *buffer) 356 { 357 return sldns_buffer_at(buffer, buffer->_limit); 358 } 359 360 /** 361 * returns a pointer to the data at the buffer's current position. 362 * \param[in] buffer the buffer 363 * \return the pointer 364 */ 365 INLINE uint8_t * 366 sldns_buffer_current(sldns_buffer *buffer) 367 { 368 return sldns_buffer_at(buffer, buffer->_position); 369 } 370 371 /** 372 * returns the number of bytes remaining between the indicated position and 373 * the limit. 374 * \param[in] buffer the buffer 375 * \param[in] at indicated position 376 * \return number of bytes 377 */ 378 INLINE size_t 379 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at) 380 { 381 sldns_buffer_invariant(buffer); 382 assert(at <= buffer->_limit); 383 return at < buffer->_limit ? buffer->_limit - at : 0; 384 } 385 386 /** 387 * returns the number of bytes remaining between the buffer's position and 388 * limit. 389 * \param[in] buffer the buffer 390 * \return the number of bytes 391 */ 392 INLINE size_t 393 sldns_buffer_remaining(sldns_buffer *buffer) 394 { 395 return sldns_buffer_remaining_at(buffer, buffer->_position); 396 } 397 398 /** 399 * checks if the buffer has at least COUNT more bytes available. 400 * Before reading or writing the caller needs to ensure enough space 401 * is available! 402 * \param[in] buffer the buffer 403 * \param[in] at indicated position 404 * \param[in] count how much is available 405 * \return true or false (as int?) 406 */ 407 INLINE int 408 sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count) 409 { 410 return count <= sldns_buffer_remaining_at(buffer, at); 411 } 412 413 /** 414 * checks if the buffer has count bytes available at the current position 415 * \param[in] buffer the buffer 416 * \param[in] count how much is available 417 * \return true or false (as int?) 418 */ 419 INLINE int 420 sldns_buffer_available(sldns_buffer *buffer, size_t count) 421 { 422 return sldns_buffer_available_at(buffer, buffer->_position, count); 423 } 424 425 /** 426 * writes the given data to the buffer at the specified position 427 * \param[in] buffer the buffer 428 * \param[in] at the position (in number of bytes) to write the data at 429 * \param[in] data pointer to the data to write to the buffer 430 * \param[in] count the number of bytes of data to write 431 */ 432 INLINE void 433 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count) 434 { 435 assert(sldns_buffer_available_at(buffer, at, count)); 436 memcpy(buffer->_data + at, data, count); 437 } 438 439 /** 440 * set the given byte to the buffer at the specified position 441 * \param[in] buffer the buffer 442 * \param[in] at the position (in number of bytes) to write the data at 443 * \param[in] c the byte to set to the buffer 444 * \param[in] count the number of bytes of bytes to write 445 */ 446 447 INLINE void 448 sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count) 449 { 450 assert(sldns_buffer_available_at(buffer, at, count)); 451 memset(buffer->_data + at, c, count); 452 } 453 454 455 /** 456 * writes count bytes of data to the current position of the buffer 457 * \param[in] buffer the buffer 458 * \param[in] data the data to write 459 * \param[in] count the length of the data to write 460 */ 461 INLINE void 462 sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count) 463 { 464 sldns_buffer_write_at(buffer, buffer->_position, data, count); 465 buffer->_position += count; 466 } 467 468 /** 469 * copies the given (null-delimited) string to the specified position at the buffer 470 * \param[in] buffer the buffer 471 * \param[in] at the position in the buffer 472 * \param[in] str the string to write 473 */ 474 INLINE void 475 sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str) 476 { 477 sldns_buffer_write_at(buffer, at, str, strlen(str)); 478 } 479 480 /** 481 * copies the given (null-delimited) string to the current position at the buffer 482 * \param[in] buffer the buffer 483 * \param[in] str the string to write 484 */ 485 INLINE void 486 sldns_buffer_write_string(sldns_buffer *buffer, const char *str) 487 { 488 sldns_buffer_write(buffer, str, strlen(str)); 489 } 490 491 /** 492 * writes the given byte of data at the given position in the buffer 493 * \param[in] buffer the buffer 494 * \param[in] at the position in the buffer 495 * \param[in] data the 8 bits to write 496 */ 497 INLINE void 498 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data) 499 { 500 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 501 buffer->_data[at] = data; 502 } 503 504 /** 505 * writes the given byte of data at the current position in the buffer 506 * \param[in] buffer the buffer 507 * \param[in] data the 8 bits to write 508 */ 509 INLINE void 510 sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data) 511 { 512 sldns_buffer_write_u8_at(buffer, buffer->_position, data); 513 buffer->_position += sizeof(data); 514 } 515 516 /** 517 * writes the given 2 byte integer at the given position in the buffer 518 * \param[in] buffer the buffer 519 * \param[in] at the position in the buffer 520 * \param[in] data the 16 bits to write 521 */ 522 INLINE void 523 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data) 524 { 525 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 526 sldns_write_uint16(buffer->_data + at, data); 527 } 528 529 /** 530 * writes the given 2 byte integer at the current position in the buffer 531 * \param[in] buffer the buffer 532 * \param[in] data the 16 bits to write 533 */ 534 INLINE void 535 sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data) 536 { 537 sldns_buffer_write_u16_at(buffer, buffer->_position, data); 538 buffer->_position += sizeof(data); 539 } 540 541 /** 542 * writes the given 4 byte integer at the given position in the buffer 543 * \param[in] buffer the buffer 544 * \param[in] at the position in the buffer 545 * \param[in] data the 32 bits to write 546 */ 547 INLINE void 548 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data) 549 { 550 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 551 sldns_write_uint32(buffer->_data + at, data); 552 } 553 554 /** 555 * writes the given 6 byte integer at the given position in the buffer 556 * \param[in] buffer the buffer 557 * \param[in] at the position in the buffer 558 * \param[in] data the (lower) 48 bits to write 559 */ 560 INLINE void 561 sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data) 562 { 563 assert(sldns_buffer_available_at(buffer, at, 6)); 564 sldns_write_uint48(buffer->_data + at, data); 565 } 566 567 /** 568 * writes the given 4 byte integer at the current position in the buffer 569 * \param[in] buffer the buffer 570 * \param[in] data the 32 bits to write 571 */ 572 INLINE void 573 sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data) 574 { 575 sldns_buffer_write_u32_at(buffer, buffer->_position, data); 576 buffer->_position += sizeof(data); 577 } 578 579 /** 580 * writes the given 6 byte integer at the current position in the buffer 581 * \param[in] buffer the buffer 582 * \param[in] data the 48 bits to write 583 */ 584 INLINE void 585 sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data) 586 { 587 sldns_buffer_write_u48_at(buffer, buffer->_position, data); 588 buffer->_position += 6; 589 } 590 591 /** 592 * copies count bytes of data at the given position to the given data-array 593 * \param[in] buffer the buffer 594 * \param[in] at the position in the buffer to start 595 * \param[out] data buffer to copy to 596 * \param[in] count the length of the data to copy 597 */ 598 INLINE void 599 sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count) 600 { 601 assert(sldns_buffer_available_at(buffer, at, count)); 602 memcpy(data, buffer->_data + at, count); 603 } 604 605 /** 606 * copies count bytes of data at the current position to the given data-array 607 * \param[in] buffer the buffer 608 * \param[out] data buffer to copy to 609 * \param[in] count the length of the data to copy 610 */ 611 INLINE void 612 sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count) 613 { 614 sldns_buffer_read_at(buffer, buffer->_position, data, count); 615 buffer->_position += count; 616 } 617 618 /** 619 * returns the byte value at the given position in the buffer 620 * \param[in] buffer the buffer 621 * \param[in] at the position in the buffer 622 * \return 1 byte integer 623 */ 624 INLINE uint8_t 625 sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at) 626 { 627 assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t))); 628 return buffer->_data[at]; 629 } 630 631 /** 632 * returns the byte value at the current position in the buffer 633 * \param[in] buffer the buffer 634 * \return 1 byte integer 635 */ 636 INLINE uint8_t 637 sldns_buffer_read_u8(sldns_buffer *buffer) 638 { 639 uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position); 640 buffer->_position += sizeof(uint8_t); 641 return result; 642 } 643 644 /** 645 * returns the 2-byte integer value at the given position in the buffer 646 * \param[in] buffer the buffer 647 * \param[in] at position in the buffer 648 * \return 2 byte integer 649 */ 650 INLINE uint16_t 651 sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at) 652 { 653 assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t))); 654 return sldns_read_uint16(buffer->_data + at); 655 } 656 657 /** 658 * returns the 2-byte integer value at the current position in the buffer 659 * \param[in] buffer the buffer 660 * \return 2 byte integer 661 */ 662 INLINE uint16_t 663 sldns_buffer_read_u16(sldns_buffer *buffer) 664 { 665 uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position); 666 buffer->_position += sizeof(uint16_t); 667 return result; 668 } 669 670 /** 671 * returns the 4-byte integer value at the given position in the buffer 672 * \param[in] buffer the buffer 673 * \param[in] at position in the buffer 674 * \return 4 byte integer 675 */ 676 INLINE uint32_t 677 sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at) 678 { 679 assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t))); 680 return sldns_read_uint32(buffer->_data + at); 681 } 682 683 /** 684 * returns the 4-byte integer value at the current position in the buffer 685 * \param[in] buffer the buffer 686 * \return 4 byte integer 687 */ 688 INLINE uint32_t 689 sldns_buffer_read_u32(sldns_buffer *buffer) 690 { 691 uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position); 692 buffer->_position += sizeof(uint32_t); 693 return result; 694 } 695 696 /** 697 * returns the status of the buffer 698 * \param[in] buffer 699 * \return the status 700 */ 701 INLINE int 702 sldns_buffer_status(sldns_buffer *buffer) 703 { 704 return (int)buffer->_status_err; 705 } 706 707 /** 708 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise 709 * \param[in] buffer the buffer 710 * \return true or false 711 */ 712 INLINE int 713 sldns_buffer_status_ok(sldns_buffer *buffer) 714 { 715 if (buffer) { 716 return sldns_buffer_status(buffer) == 0; 717 } else { 718 return 0; 719 } 720 } 721 722 /** 723 * prints to the buffer, increasing the capacity if required using 724 * buffer_reserve(). The buffer's position is set to the terminating '\\0' 725 * Returns the number of characters written (not including the 726 * terminating '\\0') or -1 on failure. 727 */ 728 int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) 729 ATTR_FORMAT(printf, 2, 3); 730 731 /** 732 * frees the buffer. 733 * \param[in] *buffer the buffer to be freed 734 */ 735 void sldns_buffer_free(sldns_buffer *buffer); 736 737 /** 738 * Copy contents of the from buffer to the result buffer and then flips 739 * the result buffer. Data will be silently truncated if the result buffer is 740 * too small. 741 * \param[out] *result resulting buffer which is copied to. 742 * \param[in] *from what to copy to result. 743 */ 744 void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from); 745 746 #ifdef __cplusplus 747 } 748 #endif 749 750 #endif /* LDNS_SBUFFER_H */ 751