1 /* 2 * Copyright 2006-2009, 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 * Andrew Galante, haiku.galante@gmail.com 8 * Hugo Santos, hugosantos@gmail.com 9 */ 10 11 12 #include "EndpointManager.h" 13 #include "TCPEndpoint.h" 14 #include "tcp.h" 15 16 #include <net_protocol.h> 17 #include <net_stat.h> 18 19 #include <KernelExport.h> 20 #include <util/list.h> 21 22 #include <netinet/in.h> 23 #include <netinet/ip.h> 24 #include <new> 25 #include <stdlib.h> 26 #include <string.h> 27 28 #include <lock.h> 29 #include <util/AutoLock.h> 30 31 #include <NetBufferUtilities.h> 32 #include <NetUtilities.h> 33 34 35 //#define TRACE_TCP 36 #ifdef TRACE_TCP 37 # define TRACE(x) dprintf x 38 #else 39 # define TRACE(x) 40 #endif 41 42 43 typedef NetBufferField<uint16, offsetof(tcp_header, checksum)> TCPChecksumField; 44 45 46 net_buffer_module_info *gBufferModule; 47 net_datalink_module_info *gDatalinkModule; 48 net_socket_module_info *gSocketModule; 49 net_stack_module_info *gStackModule; 50 51 52 static EndpointManager* sEndpointManagers[AF_MAX]; 53 static rw_lock sEndpointManagersLock; 54 55 56 // The TCP header length is at most 64 bytes. 57 static const int kMaxOptionSize = 64 - sizeof(tcp_header); 58 59 60 /*! Returns an endpoint manager for the specified domain, if any. 61 You need to hold the sEndpointManagersLock when calling this function. 62 */ 63 static inline EndpointManager* 64 endpoint_manager_for_locked(int family) 65 { 66 if (family >= AF_MAX || family < 0) 67 return NULL; 68 69 return sEndpointManagers[family]; 70 } 71 72 73 /*! Returns an endpoint manager for the specified domain, if any */ 74 static inline EndpointManager* 75 endpoint_manager_for(net_domain* domain) 76 { 77 ReadLocker _(sEndpointManagersLock); 78 79 return endpoint_manager_for_locked(domain->family); 80 } 81 82 83 static inline void 84 bump_option(tcp_option *&option, size_t &length) 85 { 86 if (option->kind <= TCP_OPTION_NOP) { 87 length++; 88 option = (tcp_option *)((uint8 *)option + 1); 89 } else { 90 length += option->length; 91 option = (tcp_option *)((uint8 *)option + option->length); 92 } 93 } 94 95 96 static inline size_t 97 add_options(tcp_segment_header &segment, uint8 *buffer, size_t bufferSize) 98 { 99 tcp_option *option = (tcp_option *)buffer; 100 size_t length = 0; 101 102 if (segment.max_segment_size > 0 && length + 8 <= bufferSize) { 103 option->kind = TCP_OPTION_MAX_SEGMENT_SIZE; 104 option->length = 4; 105 option->max_segment_size = htons(segment.max_segment_size); 106 bump_option(option, length); 107 } 108 109 if ((segment.options & TCP_HAS_TIMESTAMPS) != 0 110 && length + 12 <= bufferSize) { 111 // two NOPs so the timestamps get aligned to a 4 byte boundary 112 option->kind = TCP_OPTION_NOP; 113 bump_option(option, length); 114 option->kind = TCP_OPTION_NOP; 115 bump_option(option, length); 116 option->kind = TCP_OPTION_TIMESTAMP; 117 option->length = 10; 118 option->timestamp.value = htonl(segment.timestamp_value); 119 option->timestamp.reply = htonl(segment.timestamp_reply); 120 bump_option(option, length); 121 } 122 123 if ((segment.options & TCP_HAS_WINDOW_SCALE) != 0 124 && length + 4 <= bufferSize) { 125 // insert one NOP so that the subsequent data is aligned on a 4 byte boundary 126 option->kind = TCP_OPTION_NOP; 127 bump_option(option, length); 128 129 option->kind = TCP_OPTION_WINDOW_SHIFT; 130 option->length = 3; 131 option->window_shift = segment.window_shift; 132 bump_option(option, length); 133 } 134 135 if ((segment.options & TCP_SACK_PERMITTED) != 0 136 && length + 2 <= bufferSize) { 137 option->kind = TCP_OPTION_SACK_PERMITTED; 138 option->length = 2; 139 bump_option(option, length); 140 } 141 142 if (segment.sack_count > 0) { 143 int sackCount = ((int)(bufferSize - length) - 4) / sizeof(tcp_sack); 144 if (sackCount > segment.sack_count) 145 sackCount = segment.sack_count; 146 147 if (sackCount > 0) { 148 option->kind = TCP_OPTION_NOP; 149 bump_option(option, length); 150 option->kind = TCP_OPTION_NOP; 151 bump_option(option, length); 152 option->kind = TCP_OPTION_SACK; 153 option->length = 2 + sackCount * sizeof(tcp_sack); 154 memcpy(option->sack, segment.sacks, sackCount * sizeof(tcp_sack)); 155 bump_option(option, length); 156 } 157 } 158 159 if ((length & 3) == 0) { 160 // options completely fill out the option space 161 return length; 162 } 163 164 option->kind = TCP_OPTION_END; 165 return (length + 3) & ~3; 166 // bump to a multiple of 4 length 167 } 168 169 170 static void 171 process_options(tcp_segment_header &segment, net_buffer *buffer, size_t size) 172 { 173 if (size == 0) 174 return; 175 176 tcp_option *option; 177 178 uint8 optionsBuffer[kMaxOptionSize]; 179 if (gBufferModule->direct_access(buffer, sizeof(tcp_header), size, 180 (void **)&option) != B_OK) { 181 if ((size_t)size > sizeof(optionsBuffer)) { 182 dprintf("Ignoring TCP options larger than expected.\n"); 183 return; 184 } 185 186 gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size); 187 option = (tcp_option *)optionsBuffer; 188 } 189 190 while (size > 0) { 191 int32 length = -1; 192 193 switch (option->kind) { 194 case TCP_OPTION_END: 195 case TCP_OPTION_NOP: 196 length = 1; 197 break; 198 case TCP_OPTION_MAX_SEGMENT_SIZE: 199 if (option->length == 4 && size >= 4) 200 segment.max_segment_size = ntohs(option->max_segment_size); 201 break; 202 case TCP_OPTION_WINDOW_SHIFT: 203 if (option->length == 3 && size >= 3) { 204 segment.options |= TCP_HAS_WINDOW_SCALE; 205 segment.window_shift = option->window_shift; 206 } 207 break; 208 case TCP_OPTION_TIMESTAMP: 209 if (option->length == 10 && size >= 10) { 210 segment.options |= TCP_HAS_TIMESTAMPS; 211 segment.timestamp_value = ntohl(option->timestamp.value); 212 segment.timestamp_reply = 213 ntohl(option->timestamp.reply); 214 } 215 break; 216 case TCP_OPTION_SACK_PERMITTED: 217 if (option->length == 2 && size >= 2) 218 segment.options |= TCP_SACK_PERMITTED; 219 break; 220 } 221 222 if (length < 0) { 223 length = option->length; 224 if (length == 0 || length > (ssize_t)size) 225 break; 226 } 227 228 option = (tcp_option *)((uint8 *)option + length); 229 size -= length; 230 } 231 } 232 233 234 #if 0 235 static void 236 dump_tcp_header(tcp_header &header) 237 { 238 dprintf(" source port: %u\n", ntohs(header.source_port)); 239 dprintf(" dest port: %u\n", ntohs(header.destination_port)); 240 dprintf(" sequence: %lu\n", header.Sequence()); 241 dprintf(" ack: %lu\n", header.Acknowledge()); 242 dprintf(" flags: %s%s%s%s%s%s\n", (header.flags & TCP_FLAG_FINISH) ? "FIN " : "", 243 (header.flags & TCP_FLAG_SYNCHRONIZE) ? "SYN " : "", 244 (header.flags & TCP_FLAG_RESET) ? "RST " : "", 245 (header.flags & TCP_FLAG_PUSH) ? "PUSH " : "", 246 (header.flags & TCP_FLAG_ACKNOWLEDGE) ? "ACK " : "", 247 (header.flags & TCP_FLAG_URGENT) ? "URG " : ""); 248 dprintf(" window: %u\n", header.AdvertisedWindow()); 249 dprintf(" urgent offset: %u\n", header.UrgentOffset()); 250 } 251 #endif 252 253 254 static int 255 dump_endpoints(int argc, char** argv) 256 { 257 for (int i = 0; i < AF_MAX; i++) { 258 EndpointManager* manager = sEndpointManagers[i]; 259 if (manager != NULL) 260 manager->Dump(); 261 } 262 263 return 0; 264 } 265 266 267 static int 268 dump_endpoint(int argc, char** argv) 269 { 270 if (argc < 2) { 271 kprintf("usage: tcp_endpoint [address]\n"); 272 return 0; 273 } 274 275 TCPEndpoint* endpoint = (TCPEndpoint*)parse_expression(argv[1]); 276 endpoint->Dump(); 277 278 return 0; 279 } 280 281 282 // #pragma mark - internal API 283 284 285 /*! Creates a new endpoint manager for the specified domain, or returns 286 an existing one for this domain. 287 */ 288 EndpointManager* 289 get_endpoint_manager(net_domain* domain) 290 { 291 // See if there is one already 292 EndpointManager* endpointManager = endpoint_manager_for(domain); 293 if (endpointManager != NULL) 294 return endpointManager; 295 296 WriteLocker _(sEndpointManagersLock); 297 298 endpointManager = endpoint_manager_for_locked(domain->family); 299 if (endpointManager != NULL) 300 return endpointManager; 301 302 // There is no endpoint manager for this domain yet, so we need 303 // to create one. 304 305 endpointManager = new(std::nothrow) EndpointManager(domain); 306 if (endpointManager == NULL) 307 return NULL; 308 309 if (endpointManager->Init() != B_OK) { 310 delete endpointManager; 311 return NULL; 312 } 313 314 sEndpointManagers[domain->family] = endpointManager; 315 return endpointManager; 316 } 317 318 319 void 320 put_endpoint_manager(EndpointManager* endpointManager) 321 { 322 // TODO: we may want to use reference counting instead of only discarding 323 // them on unload. But since there is likely only IPv4/v6 there is not much 324 // point to it. 325 } 326 327 328 const char* 329 name_for_state(tcp_state state) 330 { 331 switch (state) { 332 case CLOSED: 333 return "closed"; 334 case LISTEN: 335 return "listen"; 336 case SYNCHRONIZE_SENT: 337 return "syn-sent"; 338 case SYNCHRONIZE_RECEIVED: 339 return "syn-received"; 340 case ESTABLISHED: 341 return "established"; 342 343 // peer closes the connection 344 case FINISH_RECEIVED: 345 return "close-wait"; 346 case WAIT_FOR_FINISH_ACKNOWLEDGE: 347 return "last-ack"; 348 349 // we close the connection 350 case FINISH_SENT: 351 return "fin-wait1"; 352 case FINISH_ACKNOWLEDGED: 353 return "fin-wait2"; 354 case CLOSING: 355 return "closing"; 356 357 case TIME_WAIT: 358 return "time-wait"; 359 } 360 361 return "-"; 362 } 363 364 365 /*! Constructs a TCP header on \a buffer with the specified values 366 for \a flags, \a seq \a ack and \a advertisedWindow. 367 */ 368 status_t 369 add_tcp_header(net_address_module_info* addressModule, 370 tcp_segment_header& segment, net_buffer* buffer) 371 { 372 buffer->protocol = IPPROTO_TCP; 373 374 uint8 optionsBuffer[kMaxOptionSize]; 375 uint32 optionsLength = add_options(segment, optionsBuffer, 376 sizeof(optionsBuffer)); 377 378 NetBufferPrepend<tcp_header> bufferHeader(buffer, 379 sizeof(tcp_header) + optionsLength); 380 if (bufferHeader.Status() != B_OK) 381 return bufferHeader.Status(); 382 383 tcp_header& header = bufferHeader.Data(); 384 385 header.source_port = addressModule->get_port(buffer->source); 386 header.destination_port = addressModule->get_port(buffer->destination); 387 header.sequence = htonl(segment.sequence); 388 header.acknowledge = (segment.flags & TCP_FLAG_ACKNOWLEDGE) 389 ? htonl(segment.acknowledge) : 0; 390 header.reserved = 0; 391 header.header_length = (sizeof(tcp_header) + optionsLength) >> 2; 392 header.flags = segment.flags; 393 header.advertised_window = htons(segment.advertised_window); 394 header.checksum = 0; 395 header.urgent_offset = htons(segment.urgent_offset); 396 397 // we must detach before calculating the checksum as we may 398 // not have a contiguous buffer. 399 bufferHeader.Sync(); 400 401 if (optionsLength > 0) { 402 gBufferModule->write(buffer, sizeof(tcp_header), optionsBuffer, 403 optionsLength); 404 } 405 406 TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %lu, ack %lu, up %u, " 407 "win %u\n", buffer, segment.flags, segment.sequence, 408 segment.acknowledge, segment.urgent_offset, segment.advertised_window)); 409 410 *TCPChecksumField(buffer) = Checksum::PseudoHeader(addressModule, 411 gBufferModule, buffer, IPPROTO_TCP); 412 413 return B_OK; 414 } 415 416 417 size_t 418 tcp_options_length(tcp_segment_header& segment) 419 { 420 size_t length = 0; 421 422 if (segment.max_segment_size > 0) 423 length += 4; 424 425 if (segment.options & TCP_HAS_TIMESTAMPS) 426 length += 12; 427 428 if (segment.options & TCP_HAS_WINDOW_SCALE) 429 length += 4; 430 431 if (segment.options & TCP_SACK_PERMITTED) 432 length += 2; 433 434 if (segment.sack_count > 0) { 435 int sackCount = min_c((int)((kMaxOptionSize - length - 4) 436 / sizeof(tcp_sack)), segment.sack_count); 437 if (sackCount > 0) 438 length += 4 + sackCount * sizeof(tcp_sack); 439 } 440 441 if ((length & 3) == 0) 442 return length; 443 444 return (length + 3) & ~3; 445 } 446 447 448 // #pragma mark - protocol API 449 450 451 net_protocol* 452 tcp_init_protocol(net_socket* socket) 453 { 454 socket->send.buffer_size = 32768; 455 // override net_socket default 456 457 TCPEndpoint* protocol = new (std::nothrow) TCPEndpoint(socket); 458 if (protocol == NULL) 459 return NULL; 460 461 if (protocol->InitCheck() != B_OK) { 462 delete protocol; 463 return NULL; 464 } 465 466 TRACE(("Creating new TCPEndpoint: %p\n", protocol)); 467 socket->protocol = IPPROTO_TCP; 468 return protocol; 469 } 470 471 472 status_t 473 tcp_uninit_protocol(net_protocol* protocol) 474 { 475 TRACE(("Deleting TCPEndpoint: %p\n", protocol)); 476 delete (TCPEndpoint*)protocol; 477 return B_OK; 478 } 479 480 481 status_t 482 tcp_open(net_protocol* protocol) 483 { 484 return ((TCPEndpoint*)protocol)->Open(); 485 } 486 487 488 status_t 489 tcp_close(net_protocol* protocol) 490 { 491 return ((TCPEndpoint*)protocol)->Close(); 492 } 493 494 495 status_t 496 tcp_free(net_protocol* protocol) 497 { 498 ((TCPEndpoint*)protocol)->Free(); 499 return B_OK; 500 } 501 502 503 status_t 504 tcp_connect(net_protocol* protocol, const struct sockaddr* address) 505 { 506 return ((TCPEndpoint*)protocol)->Connect(address); 507 } 508 509 510 status_t 511 tcp_accept(net_protocol* protocol, struct net_socket** _acceptedSocket) 512 { 513 return ((TCPEndpoint*)protocol)->Accept(_acceptedSocket); 514 } 515 516 517 status_t 518 tcp_control(net_protocol* _protocol, int level, int option, void* value, 519 size_t* _length) 520 { 521 TCPEndpoint* protocol = (TCPEndpoint*)_protocol; 522 523 if ((level & LEVEL_MASK) == IPPROTO_TCP) { 524 if (option == NET_STAT_SOCKET) 525 return protocol->FillStat((net_stat*)value); 526 } 527 528 return protocol->next->module->control(protocol->next, level, option, 529 value, _length); 530 } 531 532 533 status_t 534 tcp_getsockopt(net_protocol* _protocol, int level, int option, void* value, 535 int* _length) 536 { 537 TCPEndpoint* protocol = (TCPEndpoint*)_protocol; 538 539 if (level == IPPROTO_TCP) 540 return protocol->GetOption(option, value, _length); 541 542 return protocol->next->module->getsockopt(protocol->next, level, option, 543 value, _length); 544 } 545 546 547 status_t 548 tcp_setsockopt(net_protocol* _protocol, int level, int option, 549 const void* _value, int length) 550 { 551 TCPEndpoint* protocol = (TCPEndpoint*)_protocol; 552 553 if (level == SOL_SOCKET) { 554 if (option == SO_SNDBUF || option == SO_RCVBUF) { 555 if (length != sizeof(int)) 556 return B_BAD_VALUE; 557 558 status_t status; 559 const int* value = (const int*)_value; 560 561 if (option == SO_SNDBUF) 562 status = protocol->SetSendBufferSize(*value); 563 else 564 status = protocol->SetReceiveBufferSize(*value); 565 566 if (status < B_OK) 567 return status; 568 } 569 } else if (level == IPPROTO_TCP) 570 return protocol->SetOption(option, _value, length); 571 572 return protocol->next->module->setsockopt(protocol->next, level, option, 573 _value, length); 574 } 575 576 577 status_t 578 tcp_bind(net_protocol* protocol, const struct sockaddr* address) 579 { 580 return ((TCPEndpoint*)protocol)->Bind(address); 581 } 582 583 584 status_t 585 tcp_unbind(net_protocol* protocol, struct sockaddr* address) 586 { 587 return ((TCPEndpoint*)protocol)->Unbind(address); 588 } 589 590 591 status_t 592 tcp_listen(net_protocol* protocol, int count) 593 { 594 return ((TCPEndpoint*)protocol)->Listen(count); 595 } 596 597 598 status_t 599 tcp_shutdown(net_protocol* protocol, int direction) 600 { 601 return ((TCPEndpoint*)protocol)->Shutdown(direction); 602 } 603 604 605 status_t 606 tcp_send_data(net_protocol* protocol, net_buffer* buffer) 607 { 608 return ((TCPEndpoint*)protocol)->SendData(buffer); 609 } 610 611 612 status_t 613 tcp_send_routed_data(net_protocol* protocol, struct net_route* route, 614 net_buffer* buffer) 615 { 616 // TCP never sends routed data 617 return B_ERROR; 618 } 619 620 621 ssize_t 622 tcp_send_avail(net_protocol* protocol) 623 { 624 return ((TCPEndpoint*)protocol)->SendAvailable(); 625 } 626 627 628 status_t 629 tcp_read_data(net_protocol* protocol, size_t numBytes, uint32 flags, 630 net_buffer** _buffer) 631 { 632 return ((TCPEndpoint*)protocol)->ReadData(numBytes, flags, _buffer); 633 } 634 635 636 ssize_t 637 tcp_read_avail(net_protocol* protocol) 638 { 639 return ((TCPEndpoint*)protocol)->ReadAvailable(); 640 } 641 642 643 struct net_domain* 644 tcp_get_domain(net_protocol* protocol) 645 { 646 return protocol->next->module->get_domain(protocol->next); 647 } 648 649 650 size_t 651 tcp_get_mtu(net_protocol* protocol, const struct sockaddr* address) 652 { 653 return protocol->next->module->get_mtu(protocol->next, address); 654 } 655 656 657 status_t 658 tcp_receive_data(net_buffer* buffer) 659 { 660 TRACE(("TCP: Received buffer %p\n", buffer)); 661 662 if (buffer->interface_address == NULL 663 || buffer->interface_address->domain == NULL) 664 return B_ERROR; 665 666 net_domain* domain = buffer->interface_address->domain; 667 net_address_module_info* addressModule = domain->address_module; 668 669 NetBufferHeaderReader<tcp_header> bufferHeader(buffer); 670 if (bufferHeader.Status() < B_OK) 671 return bufferHeader.Status(); 672 673 tcp_header& header = bufferHeader.Data(); 674 675 uint16 headerLength = header.HeaderLength(); 676 if (headerLength < sizeof(tcp_header)) 677 return B_BAD_DATA; 678 679 if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, 680 IPPROTO_TCP) != 0) 681 return B_BAD_DATA; 682 683 addressModule->set_port(buffer->source, header.source_port); 684 addressModule->set_port(buffer->destination, header.destination_port); 685 686 TRACE((" Looking for: peer %s, local %s\n", 687 AddressString(domain, buffer->source, true).Data(), 688 AddressString(domain, buffer->destination, true).Data())); 689 //dump_tcp_header(header); 690 //gBufferModule->dump(buffer); 691 692 tcp_segment_header segment(header.flags); 693 segment.sequence = header.Sequence(); 694 segment.acknowledge = header.Acknowledge(); 695 segment.advertised_window = header.AdvertisedWindow(); 696 segment.urgent_offset = header.UrgentOffset(); 697 process_options(segment, buffer, headerLength - sizeof(tcp_header)); 698 699 bufferHeader.Remove(headerLength); 700 // we no longer need to keep the header around 701 702 EndpointManager* endpointManager = endpoint_manager_for(domain); 703 if (endpointManager == NULL) { 704 TRACE((" No endpoint manager!\n")); 705 return B_ERROR; 706 } 707 708 int32 segmentAction = DROP; 709 710 TCPEndpoint* endpoint = endpointManager->FindConnection( 711 buffer->destination, buffer->source); 712 if (endpoint != NULL) { 713 segmentAction = endpoint->SegmentReceived(segment, buffer); 714 715 // There are some states in which the socket could have been deleted 716 // while handling a segment. If this flag is set in segmentAction 717 // then we know the socket has been freed and can skip releasing 718 // the reference acquired in EndpointManager::FindConnection() 719 // above. 720 if ((segmentAction & DELETED_ENDPOINT) == 0) 721 gSocketModule->release_socket(endpoint->socket); 722 } else if ((segment.flags & TCP_FLAG_RESET) == 0) 723 segmentAction = DROP | RESET; 724 725 if ((segmentAction & RESET) != 0) { 726 // send reset 727 endpointManager->ReplyWithReset(segment, buffer); 728 } 729 if ((segmentAction & DROP) != 0) 730 gBufferModule->free(buffer); 731 732 return B_OK; 733 } 734 735 736 status_t 737 tcp_error_received(net_error error, net_buffer* data) 738 { 739 return B_ERROR; 740 } 741 742 743 status_t 744 tcp_error_reply(net_protocol* protocol, net_buffer* cause, net_error error, 745 net_error_data* errorData) 746 { 747 return B_ERROR; 748 } 749 750 751 // #pragma mark - 752 753 754 static status_t 755 tcp_init() 756 { 757 rw_lock_init(&sEndpointManagersLock, "endpoint managers"); 758 759 status_t status = gStackModule->register_domain_protocols(AF_INET, 760 SOCK_STREAM, 0, 761 "network/protocols/tcp/v1", 762 "network/protocols/ipv4/v1", 763 NULL); 764 if (status < B_OK) 765 return status; 766 status = gStackModule->register_domain_protocols(AF_INET6, 767 SOCK_STREAM, 0, 768 "network/protocols/tcp/v1", 769 "network/protocols/ipv6/v1", 770 NULL); 771 if (status < B_OK) 772 return status; 773 774 status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, 775 IPPROTO_TCP, 776 "network/protocols/tcp/v1", 777 "network/protocols/ipv4/v1", 778 NULL); 779 if (status < B_OK) 780 return status; 781 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_STREAM, 782 IPPROTO_TCP, 783 "network/protocols/tcp/v1", 784 "network/protocols/ipv6/v1", 785 NULL); 786 if (status < B_OK) 787 return status; 788 789 status = gStackModule->register_domain_receiving_protocol(AF_INET, 790 IPPROTO_TCP, "network/protocols/tcp/v1"); 791 if (status < B_OK) 792 return status; 793 status = gStackModule->register_domain_receiving_protocol(AF_INET6, 794 IPPROTO_TCP, "network/protocols/tcp/v1"); 795 if (status < B_OK) 796 return status; 797 798 add_debugger_command("tcp_endpoints", dump_endpoints, 799 "lists all open TCP endpoints"); 800 add_debugger_command("tcp_endpoint", dump_endpoint, 801 "dumps a TCP endpoint internal state"); 802 803 return B_OK; 804 } 805 806 807 static status_t 808 tcp_uninit() 809 { 810 remove_debugger_command("tcp_endpoint", dump_endpoint); 811 remove_debugger_command("tcp_endpoints", dump_endpoints); 812 813 rw_lock_destroy(&sEndpointManagersLock); 814 815 for (int i = 0; i < AF_MAX; i++) { 816 delete sEndpointManagers[i]; 817 } 818 819 return B_OK; 820 } 821 822 823 static status_t 824 tcp_std_ops(int32 op, ...) 825 { 826 switch (op) { 827 case B_MODULE_INIT: 828 return tcp_init(); 829 830 case B_MODULE_UNINIT: 831 return tcp_uninit(); 832 833 default: 834 return B_ERROR; 835 } 836 } 837 838 839 net_protocol_module_info sTCPModule = { 840 { 841 "network/protocols/tcp/v1", 842 0, 843 tcp_std_ops 844 }, 845 0, 846 847 tcp_init_protocol, 848 tcp_uninit_protocol, 849 tcp_open, 850 tcp_close, 851 tcp_free, 852 tcp_connect, 853 tcp_accept, 854 tcp_control, 855 tcp_getsockopt, 856 tcp_setsockopt, 857 tcp_bind, 858 tcp_unbind, 859 tcp_listen, 860 tcp_shutdown, 861 tcp_send_data, 862 tcp_send_routed_data, 863 tcp_send_avail, 864 tcp_read_data, 865 tcp_read_avail, 866 tcp_get_domain, 867 tcp_get_mtu, 868 tcp_receive_data, 869 NULL, // deliver_data() 870 tcp_error_received, 871 tcp_error_reply, 872 NULL, // add_ancillary_data() 873 NULL, // process_ancillary_data() 874 NULL, // process_ancillary_data_no_container() 875 NULL, // send_data_no_buffer() 876 NULL // read_data_no_buffer() 877 }; 878 879 module_dependency module_dependencies[] = { 880 {NET_STACK_MODULE_NAME, (module_info **)&gStackModule}, 881 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 882 {NET_DATALINK_MODULE_NAME, (module_info **)&gDatalinkModule}, 883 {NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule}, 884 {} 885 }; 886 887 module_info *modules[] = { 888 (module_info *)&sTCPModule, 889 NULL 890 }; 891