1 /* 2 * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Ingo Weinhold, ingo_weinhold@gmx.de 8 */ 9 10 #include "simple_net_buffer.h" 11 12 #include "utility.h" 13 14 #include <net_buffer.h> 15 #include <slab/Slab.h> 16 #include <tracing.h> 17 #include <util/list.h> 18 19 #include <ByteOrder.h> 20 #include <debug.h> 21 #include <KernelExport.h> 22 #include <util/AutoLock.h> 23 #include <util/DoublyLinkedList.h> 24 25 #include <algorithm> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <sys/uio.h> 29 30 #include "paranoia_config.h" 31 32 33 //#define TRACE_BUFFER 34 #ifdef TRACE_BUFFER 35 # define TRACE(x) dprintf x 36 #else 37 # define TRACE(x) ; 38 #endif 39 40 41 #define MAX_ANCILLARY_DATA_SIZE 128 42 43 struct ancillary_data : DoublyLinkedListLinkImpl<ancillary_data> { 44 void* Data() 45 { 46 return (char*)this + _ALIGN(sizeof(ancillary_data)); 47 } 48 49 static ancillary_data* FromData(void* data) 50 { 51 return (ancillary_data*)((char*)data - _ALIGN(sizeof(ancillary_data))); 52 } 53 54 ancillary_data_header header; 55 void (*destructor)(const ancillary_data_header*, void*); 56 }; 57 58 typedef DoublyLinkedList<ancillary_data> ancillary_data_list; 59 60 61 struct net_buffer_private : simple_net_buffer { 62 ancillary_data_list ancillary_data; 63 }; 64 65 66 static status_t append_data(net_buffer *buffer, const void *data, size_t size); 67 static status_t trim_data(net_buffer *_buffer, size_t newSize); 68 static status_t remove_header(net_buffer *_buffer, size_t bytes); 69 static status_t remove_trailer(net_buffer *_buffer, size_t bytes); 70 71 72 static void 73 copy_metadata(net_buffer *destination, const net_buffer *source) 74 { 75 memcpy(destination->source, source->source, 76 min_c(source->source->sa_len, sizeof(sockaddr_storage))); 77 memcpy(destination->destination, source->destination, 78 min_c(source->destination->sa_len, sizeof(sockaddr_storage))); 79 80 destination->flags = source->flags; 81 destination->interface = source->interface; 82 destination->offset = source->offset; 83 destination->size = source->size; 84 destination->protocol = source->protocol; 85 destination->type = source->type; 86 } 87 88 89 // #pragma mark - module API 90 91 92 static net_buffer * 93 create_buffer(size_t headerSpace) 94 { 95 net_buffer_private *buffer = new(nothrow) net_buffer_private; 96 if (buffer == NULL) 97 return NULL; 98 99 TRACE(("%ld: create buffer %p\n", find_thread(NULL), buffer)); 100 101 buffer->data = NULL; 102 new(&buffer->ancillary_data) ancillary_data_list; 103 104 buffer->source = (sockaddr *)&buffer->storage.source; 105 buffer->destination = (sockaddr *)&buffer->storage.destination; 106 107 buffer->storage.source.ss_len = 0; 108 buffer->storage.destination.ss_len = 0; 109 110 buffer->interface = NULL; 111 buffer->offset = 0; 112 buffer->flags = 0; 113 buffer->size = 0; 114 115 buffer->type = -1; 116 117 return buffer; 118 } 119 120 121 static void 122 free_buffer(net_buffer *_buffer) 123 { 124 net_buffer_private *buffer = (net_buffer_private *)_buffer; 125 126 free(buffer->data); 127 delete buffer; 128 } 129 130 131 /*! Creates a duplicate of the \a buffer. The new buffer does not share internal 132 storage; they are completely independent from each other. 133 */ 134 static net_buffer * 135 duplicate_buffer(net_buffer *_buffer) 136 { 137 net_buffer_private *buffer = (net_buffer_private *)_buffer; 138 139 net_buffer* duplicate = create_buffer(0); 140 if (duplicate == NULL) 141 return NULL; 142 143 if (append_data(duplicate, buffer->data, buffer->size) != B_OK) { 144 free_buffer(duplicate); 145 return NULL; 146 } 147 148 copy_metadata(duplicate, buffer); 149 150 return duplicate; 151 } 152 153 154 /*! Clones the buffer by grabbing another reference to the underlying data. 155 If that data changes, it will be changed in the clone as well. 156 157 If \a shareFreeSpace is \c true, the cloned buffer may claim the free 158 space in the original buffer as the original buffer can still do. If you 159 are using this, it's your responsibility that only one of the buffers 160 will do this. 161 */ 162 static net_buffer * 163 clone_buffer(net_buffer *_buffer, bool shareFreeSpace) 164 { 165 return duplicate_buffer(_buffer); 166 } 167 168 169 /*! 170 Split the buffer at offset, the header data 171 is returned as new buffer. 172 TODO: optimize and avoid making a copy. 173 */ 174 static net_buffer * 175 split_buffer(net_buffer *_from, uint32 offset) 176 { 177 net_buffer_private *from = (net_buffer_private *)_from; 178 179 if (offset > from->size) 180 return NULL; 181 182 net_buffer_private* buffer = (net_buffer_private*)create_buffer(0); 183 if (buffer == NULL) 184 return NULL; 185 186 // allocate space for the tail data 187 size_t remaining = from->size - offset; 188 uint8* tailData = (uint8*)malloc(remaining); 189 if (tailData == NULL) { 190 free_buffer(buffer); 191 return NULL; 192 } 193 194 memcpy(tailData, from->data + offset, remaining); 195 196 // truncate original data and move it to the new buffer 197 buffer->data = (uint8*)realloc(from->data, offset); 198 buffer->size = offset; 199 200 // the old buffer gets the newly allocated tail data 201 from->data = tailData; 202 from->size = remaining; 203 204 return buffer; 205 } 206 207 208 /*! 209 Merges the second buffer with the first. If \a after is \c true, the 210 second buffer's contents will be appended to the first ones, else they 211 will be prepended. 212 The second buffer will be freed if this function succeeds. 213 */ 214 static status_t 215 merge_buffer(net_buffer *_buffer, net_buffer *_with, bool after) 216 { 217 net_buffer_private *buffer = (net_buffer_private *)_buffer; 218 net_buffer_private *with = (net_buffer_private *)_with; 219 if (with == NULL) 220 return B_BAD_VALUE; 221 222 if (after) { 223 // the simple case: just append the second buffer 224 status_t error = append_data(buffer, with->data, with->size); 225 if (error != B_OK) 226 return error; 227 } else { 228 // append buffer to the second buffer, then switch the data 229 status_t error = append_data(with, buffer->data, buffer->size); 230 if (error != B_OK) 231 return error; 232 233 free(buffer->data); 234 buffer->data = with->data; 235 buffer->size = with->size; 236 237 with->data = NULL; 238 } 239 240 free_buffer(with); 241 242 return B_OK; 243 } 244 245 246 /*! Writes into existing allocated memory. 247 \return B_BAD_VALUE if you write outside of the buffers current 248 bounds. 249 */ 250 static status_t 251 write_data(net_buffer *_buffer, size_t offset, const void *data, size_t size) 252 { 253 net_buffer_private *buffer = (net_buffer_private *)_buffer; 254 255 if (offset + size > buffer->size) 256 return B_BAD_VALUE; 257 if (size == 0) 258 return B_OK; 259 260 memcpy(buffer->data + offset, data, size); 261 262 return B_OK; 263 } 264 265 266 static status_t 267 read_data(net_buffer *_buffer, size_t offset, void *data, size_t size) 268 { 269 net_buffer_private *buffer = (net_buffer_private *)_buffer; 270 271 if (offset + size > buffer->size) 272 return B_BAD_VALUE; 273 if (size == 0) 274 return B_OK; 275 276 memcpy(data, buffer->data + offset, size); 277 278 return B_OK; 279 } 280 281 282 static status_t 283 prepend_size(net_buffer *_buffer, size_t size, void **_contiguousBuffer) 284 { 285 if (size == 0) 286 return B_OK; 287 288 net_buffer_private *buffer = (net_buffer_private *)_buffer; 289 290 uint8* newData = (uint8*)malloc(buffer->size + size); 291 if (newData == NULL) 292 return B_NO_MEMORY; 293 294 memcpy(newData + size, buffer->data, buffer->size); 295 296 free(buffer->data); 297 buffer->data = newData; 298 buffer->size += size; 299 300 if (_contiguousBuffer != NULL) 301 *_contiguousBuffer = buffer->data; 302 303 return B_OK; 304 } 305 306 307 static status_t 308 prepend_data(net_buffer *buffer, const void *data, size_t size) 309 { 310 status_t status = prepend_size(buffer, size, NULL); 311 if (status < B_OK) 312 return status; 313 314 write_data(buffer, 0, data, size); 315 316 return B_OK; 317 } 318 319 320 static status_t 321 append_size(net_buffer *_buffer, size_t size, void **_contiguousBuffer) 322 { 323 if (size == 0) 324 return B_OK; 325 326 net_buffer_private *buffer = (net_buffer_private *)_buffer; 327 328 uint8* newData = (uint8*)realloc(buffer->data, buffer->size + size); 329 if (newData == NULL) 330 return B_NO_MEMORY; 331 332 if (_contiguousBuffer != NULL) 333 *_contiguousBuffer = newData + buffer->size; 334 335 buffer->data = newData; 336 buffer->size += size; 337 338 return B_OK; 339 } 340 341 342 static status_t 343 append_data(net_buffer *buffer, const void *data, size_t size) 344 { 345 size_t used = buffer->size; 346 347 status_t status = append_size(buffer, size, NULL); 348 if (status < B_OK) 349 return status; 350 351 write_data(buffer, used, data, size); 352 353 return B_OK; 354 } 355 356 357 /*! 358 Removes bytes from the beginning of the buffer. 359 */ 360 static status_t 361 remove_header(net_buffer *_buffer, size_t bytes) 362 { 363 net_buffer_private *buffer = (net_buffer_private *)_buffer; 364 365 if (bytes > buffer->size) 366 return B_BAD_VALUE; 367 if (bytes == 0) 368 return B_OK; 369 370 buffer->size -= bytes; 371 memmove(buffer->data, buffer->data + bytes, buffer->size); 372 buffer->data = (uint8*)realloc(buffer->data, buffer->size); 373 374 return B_OK; 375 } 376 377 378 /*! 379 Removes bytes from the end of the buffer. 380 */ 381 static status_t 382 remove_trailer(net_buffer *buffer, size_t bytes) 383 { 384 return trim_data(buffer, buffer->size - bytes); 385 } 386 387 388 /*! 389 Trims the buffer to the specified \a newSize by removing space from 390 the end of the buffer. 391 */ 392 static status_t 393 trim_data(net_buffer *_buffer, size_t newSize) 394 { 395 net_buffer_private *buffer = (net_buffer_private *)_buffer; 396 397 if (newSize > buffer->size) 398 return B_BAD_VALUE; 399 if (newSize == buffer->size) 400 return B_OK; 401 402 buffer->data = (uint8*)realloc(buffer->data, newSize); 403 buffer->size = newSize; 404 405 return B_OK; 406 } 407 408 409 /*! 410 Appends data coming from buffer \a source to the buffer \a buffer. It only 411 clones the data, though, that is the data is not copied, just referenced. 412 */ 413 static status_t 414 append_cloned_data(net_buffer *_buffer, net_buffer *_source, uint32 offset, 415 size_t bytes) 416 { 417 if (bytes == 0) 418 return B_OK; 419 420 net_buffer_private *buffer = (net_buffer_private *)_buffer; 421 net_buffer_private *source = (net_buffer_private *)_source; 422 423 if (offset + bytes > source->size) 424 return B_BAD_VALUE; 425 426 return append_data(buffer, source->data + offset, bytes); 427 } 428 429 430 /*! 431 Attaches ancillary data to the given buffer. The data are completely 432 orthogonal to the data the buffer stores. 433 434 \param buffer The buffer. 435 \param header Description of the data. 436 \param data If not \c NULL, the data are copied into the allocated storage. 437 \param destructor If not \c NULL, this function will be invoked with the 438 data as parameter when the buffer is destroyed. 439 \param _allocatedData Will be set to the storage allocated for the data. 440 \return \c B_OK when everything goes well, another error code otherwise. 441 */ 442 static status_t 443 attach_ancillary_data(net_buffer *_buffer, const ancillary_data_header *header, 444 const void *data, void (*destructor)(const ancillary_data_header*, void*), 445 void **_allocatedData) 446 { 447 // TODO: Obviously it would be nice to allocate the memory for the 448 // ancillary data in the buffer. 449 net_buffer_private *buffer = (net_buffer_private *)_buffer; 450 451 // check parameters 452 if (header == NULL) 453 return B_BAD_VALUE; 454 455 if (header->len > MAX_ANCILLARY_DATA_SIZE) 456 return ENOBUFS; 457 458 // allocate buffer 459 void *dataBuffer = malloc(_ALIGN(sizeof(ancillary_data)) + header->len); 460 if (dataBuffer == NULL) 461 return B_NO_MEMORY; 462 463 // init and attach the structure 464 ancillary_data *ancillaryData = new(dataBuffer) ancillary_data; 465 ancillaryData->header = *header; 466 ancillaryData->destructor = destructor; 467 468 buffer->ancillary_data.Add(ancillaryData); 469 470 if (data != NULL) 471 memcpy(ancillaryData->Data(), data, header->len); 472 473 if (_allocatedData != NULL) 474 *_allocatedData = ancillaryData->Data(); 475 476 return B_OK; 477 } 478 479 480 /*! 481 Detaches ancillary data from the given buffer. The associated memory is 482 free, i.e. the \a data pointer must no longer be used after calling this 483 function. Depending on \a destroy, the destructor is invoked before freeing 484 the data. 485 486 \param buffer The buffer. 487 \param data Pointer to the data to be removed (as returned by 488 attach_ancillary_data() or next_ancillary_data()). 489 \param destroy If \c true, the destructor, if one was passed to 490 attach_ancillary_data(), is invoked for the data. 491 \return \c B_OK when everything goes well, another error code otherwise. 492 */ 493 static status_t 494 detach_ancillary_data(net_buffer *_buffer, void *data, bool destroy) 495 { 496 net_buffer_private *buffer = (net_buffer_private *)_buffer; 497 498 if (data == NULL) 499 return B_BAD_VALUE; 500 501 ancillary_data *ancillaryData = ancillary_data::FromData(data); 502 503 buffer->ancillary_data.Remove(ancillaryData); 504 505 if (destroy && ancillaryData->destructor != NULL) { 506 ancillaryData->destructor(&ancillaryData->header, 507 ancillaryData->Data()); 508 } 509 510 free(ancillaryData); 511 512 return B_OK; 513 } 514 515 516 /*! 517 Moves all ancillary data from buffer \c from to the end of the list of 518 ancillary data of buffer \c to. Note, that this is the only function that 519 transfers or copies ancillary data from one buffer to another. 520 521 \param from The buffer from which to remove the ancillary data. 522 \param to The buffer to which to add teh ancillary data. 523 \return A pointer to the first of the moved ancillary data, if any, \c NULL 524 otherwise. 525 */ 526 static void * 527 transfer_ancillary_data(net_buffer *_from, net_buffer *_to) 528 { 529 net_buffer_private *from = (net_buffer_private *)_from; 530 net_buffer_private *to = (net_buffer_private *)_to; 531 532 if (from == NULL || to == NULL) 533 return NULL; 534 535 ancillary_data *ancillaryData = from->ancillary_data.Head(); 536 to->ancillary_data.MoveFrom(&from->ancillary_data); 537 538 return ancillaryData != NULL ? ancillaryData->Data() : NULL; 539 } 540 541 542 /*! 543 Returns the next ancillary data. When iterating over the data, initially 544 a \c NULL pointer shall be passed as \a previousData, subsequently the 545 previously returned data pointer. After the last item, \c NULL is returned. 546 547 Note, that it is not safe to call detach_ancillary_data() for a data item 548 and then pass that pointer to this function. First get the next item, then 549 detach the previous one. 550 551 \param buffer The buffer. 552 \param previousData The pointer to the previous data returned by this 553 function. Initially \c NULL shall be passed. 554 \param header Pointer to allocated storage into which the data description 555 is written. May be \c NULL. 556 \return A pointer to the next ancillary data in the buffer. \c NULL after 557 the last one. 558 */ 559 static void* 560 next_ancillary_data(net_buffer *_buffer, void *previousData, 561 ancillary_data_header *_header) 562 { 563 net_buffer_private *buffer = (net_buffer_private *)_buffer; 564 565 ancillary_data *ancillaryData; 566 567 if (previousData == NULL) { 568 ancillaryData = buffer->ancillary_data.Head(); 569 } else { 570 ancillaryData = ancillary_data::FromData(previousData); 571 ancillaryData = buffer->ancillary_data.GetNext(ancillaryData); 572 } 573 574 if (ancillaryData == NULL) 575 return NULL; 576 577 if (_header != NULL) 578 *_header = ancillaryData->header; 579 580 return ancillaryData->Data(); 581 } 582 583 584 /*! 585 Tries to directly access the requested space in the buffer. 586 If the space is contiguous, the function will succeed and place a pointer 587 to that space into \a _contiguousBuffer. 588 589 \return B_BAD_VALUE if the offset is outside of the buffer's bounds. 590 \return B_ERROR in case the buffer is not contiguous at that location. 591 */ 592 static status_t 593 direct_access(net_buffer *_buffer, uint32 offset, size_t size, 594 void **_contiguousBuffer) 595 { 596 net_buffer_private *buffer = (net_buffer_private *)_buffer; 597 598 if (offset + size > buffer->size) 599 return B_BAD_VALUE; 600 601 *_contiguousBuffer = buffer->data + offset; 602 return B_OK; 603 } 604 605 606 static int32 607 checksum_data(net_buffer *_buffer, uint32 offset, size_t size, bool finalize) 608 { 609 net_buffer_private *buffer = (net_buffer_private *)_buffer; 610 611 if (offset + size > buffer->size || size == 0) 612 return B_BAD_VALUE; 613 614 uint16 sum = compute_checksum(buffer->data + offset, size); 615 if ((offset & 1) != 0) { 616 // if we're at an uneven offset, we have to swap the checksum 617 sum = __swap_int16(sum); 618 } 619 620 if (!finalize) 621 return (uint16)sum; 622 623 return (uint16)~sum; 624 } 625 626 627 static uint32 628 get_iovecs(net_buffer *_buffer, struct iovec *iovecs, uint32 vecCount) 629 { 630 net_buffer_private *buffer = (net_buffer_private *)_buffer; 631 632 iovecs[0].iov_base = buffer->data; 633 iovecs[0].iov_len = buffer->size; 634 635 return 1; 636 } 637 638 639 static uint32 640 count_iovecs(net_buffer *_buffer) 641 { 642 return 1; 643 } 644 645 646 static void 647 swap_addresses(net_buffer *buffer) 648 { 649 std::swap(buffer->source, buffer->destination); 650 } 651 652 653 static void 654 dump_buffer(net_buffer *_buffer) 655 { 656 net_buffer_private *buffer = (net_buffer_private *)_buffer; 657 658 dprintf("buffer %p, size %ld, data: %p\n", buffer, buffer->size, 659 buffer->data); 660 dump_block((char*)buffer->data, min_c(buffer->size, 32), " "); 661 } 662 663 664 static status_t 665 std_ops(int32 op, ...) 666 { 667 switch (op) { 668 case B_MODULE_INIT: 669 return B_OK; 670 671 case B_MODULE_UNINIT: 672 return B_OK; 673 674 default: 675 return B_ERROR; 676 } 677 } 678 679 680 net_buffer_module_info gSimpleNetBufferModule = { 681 //net_buffer_module_info gNetBufferModule = { 682 { 683 NET_BUFFER_MODULE_NAME, 684 0, 685 std_ops 686 }, 687 create_buffer, 688 free_buffer, 689 690 duplicate_buffer, 691 clone_buffer, 692 split_buffer, 693 merge_buffer, 694 695 prepend_size, 696 prepend_data, 697 append_size, 698 append_data, 699 NULL, // insert 700 NULL, // remove 701 remove_header, 702 remove_trailer, 703 trim_data, 704 append_cloned_data, 705 706 NULL, // associate_data 707 708 attach_ancillary_data, 709 detach_ancillary_data, 710 transfer_ancillary_data, 711 next_ancillary_data, 712 713 direct_access, 714 read_data, 715 write_data, 716 717 checksum_data, 718 719 NULL, // get_memory_map 720 get_iovecs, 721 count_iovecs, 722 723 swap_addresses, 724 725 dump_buffer, // dump 726 }; 727 728