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 17extern "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 */ 34INLINE uint16_t 35sldns_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 45INLINE uint32_t 46sldns_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 */ 63INLINE void 64sldns_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 75INLINE void 76sldns_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 90INLINE void 91sldns_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 */ 116struct 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}; 138typedef struct sldns_buffer sldns_buffer; 139 140#ifdef NDEBUG 141INLINE void 142sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer)) 143{ 144} 145#else 146INLINE void 147sldns_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 */ 162sldns_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 */ 173void 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 */ 182void 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 */ 189INLINE 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 */ 206INLINE 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 */ 219INLINE 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 */ 231INLINE size_t 232sldns_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 */ 243INLINE void 244sldns_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 */ 257INLINE void 258sldns_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 */ 269INLINE size_t 270sldns_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 */ 281INLINE void 282sldns_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 */ 295INLINE size_t 296sldns_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 */ 309int 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 */ 321int 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 */ 329INLINE uint8_t * 330sldns_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 */ 342INLINE uint8_t * 343sldns_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 */ 354INLINE uint8_t * 355sldns_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 */ 365INLINE uint8_t * 366sldns_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 */ 378INLINE size_t 379sldns_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 */ 392INLINE size_t 393sldns_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 */ 407INLINE int 408sldns_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 */ 419INLINE int 420sldns_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 */ 432INLINE void 433sldns_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 447INLINE void 448sldns_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 */ 461INLINE void 462sldns_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 */ 474INLINE void 475sldns_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 */ 485INLINE void 486sldns_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 */ 497INLINE void 498sldns_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 */ 509INLINE void 510sldns_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 */ 522INLINE void 523sldns_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 */ 534INLINE void 535sldns_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 */ 547INLINE void 548sldns_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 */ 560INLINE void 561sldns_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 */ 572INLINE void 573sldns_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 */ 584INLINE void 585sldns_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 */ 598INLINE void 599sldns_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 */ 611INLINE void 612sldns_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 */ 624INLINE uint8_t 625sldns_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 */ 636INLINE uint8_t 637sldns_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 */ 650INLINE uint16_t 651sldns_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 */ 662INLINE uint16_t 663sldns_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 */ 676INLINE uint32_t 677sldns_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 */ 688INLINE uint32_t 689sldns_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 */ 701INLINE int 702sldns_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 */ 712INLINE int 713sldns_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 */ 728int 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 */ 735void 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 */ 744void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from); 745 746#ifdef __cplusplus 747} 748#endif 749 750#endif /* LDNS_SBUFFER_H */ 751