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 60 bytes (0xf * 4). 57 static const int kMaxOptionSize = 60 - 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.sackCount > 0) { 143 int sackCount = ((int)(bufferSize - length) - 4) / sizeof(tcp_sack); 144 if (sackCount > segment.sackCount) 145 sackCount = segment.sackCount; 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 case TCP_OPTION_SACK: 221 if (size >= option->length) { 222 segment.options |= TCP_HAS_SACK; 223 segment.sackCount = min_c((option->length - 2) 224 / sizeof(tcp_sack), MAX_SACK_BLKS); 225 for(int i = 0; i < segment.sackCount; ++i) { 226 segment.sacks[i].left_edge = ntohl( 227 option->sack[i].left_edge); 228 segment.sacks[i].right_edge = ntohl( 229 option->sack[i].right_edge); 230 } 231 } 232 break; 233 } 234 235 if (length < 0) { 236 length = option->length; 237 if (length == 0 || length > (ssize_t)size) 238 break; 239 } 240 241 option = (tcp_option *)((uint8 *)option + length); 242 size -= length; 243 } 244 } 245 246 247 #if 0 248 static void 249 dump_tcp_header(tcp_header &header) 250 { 251 dprintf(" source port: %u\n", ntohs(header.source_port)); 252 dprintf(" dest port: %u\n", ntohs(header.destination_port)); 253 dprintf(" sequence: %lu\n", header.Sequence()); 254 dprintf(" ack: %lu\n", header.Acknowledge()); 255 dprintf(" flags: %s%s%s%s%s%s\n", (header.flags & TCP_FLAG_FINISH) ? "FIN " : "", 256 (header.flags & TCP_FLAG_SYNCHRONIZE) ? "SYN " : "", 257 (header.flags & TCP_FLAG_RESET) ? "RST " : "", 258 (header.flags & TCP_FLAG_PUSH) ? "PUSH " : "", 259 (header.flags & TCP_FLAG_ACKNOWLEDGE) ? "ACK " : "", 260 (header.flags & TCP_FLAG_URGENT) ? "URG " : ""); 261 dprintf(" window: %u\n", header.AdvertisedWindow()); 262 dprintf(" urgent offset: %u\n", header.UrgentOffset()); 263 } 264 #endif 265 266 267 static int 268 dump_endpoints(int argc, char** argv) 269 { 270 for (int i = 0; i < AF_MAX; i++) { 271 EndpointManager* manager = sEndpointManagers[i]; 272 if (manager != NULL) 273 manager->Dump(); 274 } 275 276 return 0; 277 } 278 279 280 static int 281 dump_endpoint(int argc, char** argv) 282 { 283 if (argc < 2) { 284 kprintf("usage: tcp_endpoint [address]\n"); 285 return 0; 286 } 287 288 TCPEndpoint* endpoint = (TCPEndpoint*)parse_expression(argv[1]); 289 endpoint->Dump(); 290 291 return 0; 292 } 293 294 295 // #pragma mark - internal API 296 297 298 /*! Creates a new endpoint manager for the specified domain, or returns 299 an existing one for this domain. 300 */ 301 EndpointManager* 302 get_endpoint_manager(net_domain* domain) 303 { 304 // See if there is one already 305 EndpointManager* endpointManager = endpoint_manager_for(domain); 306 if (endpointManager != NULL) 307 return endpointManager; 308 309 WriteLocker _(sEndpointManagersLock); 310 311 endpointManager = endpoint_manager_for_locked(domain->family); 312 if (endpointManager != NULL) 313 return endpointManager; 314 315 // There is no endpoint manager for this domain yet, so we need 316 // to create one. 317 318 endpointManager = new(std::nothrow) EndpointManager(domain); 319 if (endpointManager == NULL) 320 return NULL; 321 322 if (endpointManager->Init() != B_OK) { 323 delete endpointManager; 324 return NULL; 325 } 326 327 sEndpointManagers[domain->family] = endpointManager; 328 return endpointManager; 329 } 330 331 332 void 333 put_endpoint_manager(EndpointManager* endpointManager) 334 { 335 // TODO: we may want to use reference counting instead of only discarding 336 // them on unload. But since there is likely only IPv4/v6 there is not much 337 // point to it. 338 } 339 340 341 const char* 342 name_for_state(tcp_state state) 343 { 344 switch (state) { 345 case CLOSED: 346 return "closed"; 347 case LISTEN: 348 return "listen"; 349 case SYNCHRONIZE_SENT: 350 return "syn-sent"; 351 case SYNCHRONIZE_RECEIVED: 352 return "syn-received"; 353 case ESTABLISHED: 354 return "established"; 355 356 // peer closes the connection 357 case FINISH_RECEIVED: 358 return "close-wait"; 359 case WAIT_FOR_FINISH_ACKNOWLEDGE: 360 return "last-ack"; 361 362 // we close the connection 363 case FINISH_SENT: 364 return "fin-wait1"; 365 case FINISH_ACKNOWLEDGED: 366 return "fin-wait2"; 367 case CLOSING: 368 return "closing"; 369 370 case TIME_WAIT: 371 return "time-wait"; 372 } 373 374 return "-"; 375 } 376 377 378 /*! Constructs a TCP header on \a buffer with the specified values 379 for \a flags, \a seq \a ack and \a advertisedWindow. 380 */ 381 status_t 382 add_tcp_header(net_address_module_info* addressModule, 383 tcp_segment_header& segment, net_buffer* buffer) 384 { 385 buffer->protocol = IPPROTO_TCP; 386 387 uint8 optionsBuffer[kMaxOptionSize]; 388 uint32 optionsLength = add_options(segment, optionsBuffer, 389 sizeof(optionsBuffer)); 390 391 NetBufferPrepend<tcp_header> bufferHeader(buffer, 392 sizeof(tcp_header) + optionsLength); 393 if (bufferHeader.Status() != B_OK) 394 return bufferHeader.Status(); 395 396 tcp_header& header = bufferHeader.Data(); 397 398 header.source_port = addressModule->get_port(buffer->source); 399 header.destination_port = addressModule->get_port(buffer->destination); 400 header.sequence = htonl(segment.sequence); 401 header.acknowledge = (segment.flags & TCP_FLAG_ACKNOWLEDGE) 402 ? htonl(segment.acknowledge) : 0; 403 header.reserved = 0; 404 header.header_length = (sizeof(tcp_header) + optionsLength) >> 2; 405 header.flags = segment.flags; 406 header.advertised_window = htons(segment.advertised_window); 407 header.checksum = 0; 408 header.urgent_offset = htons(segment.urgent_offset); 409 410 // we must detach before calculating the checksum as we may 411 // not have a contiguous buffer. 412 bufferHeader.Sync(); 413 414 if (optionsLength > 0) { 415 gBufferModule->write(buffer, sizeof(tcp_header), optionsBuffer, 416 optionsLength); 417 } 418 419 TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %lu, ack %lu, up %u, " 420 "win %u\n", buffer, segment.flags, segment.sequence, 421 segment.acknowledge, segment.urgent_offset, segment.advertised_window)); 422 423 *TCPChecksumField(buffer) = Checksum::PseudoHeader(addressModule, 424 gBufferModule, buffer, IPPROTO_TCP); 425 426 return B_OK; 427 } 428 429 430 size_t 431 tcp_options_length(tcp_segment_header& segment) 432 { 433 size_t length = 0; 434 435 if (segment.max_segment_size > 0) 436 length += 4; 437 438 if (segment.options & TCP_HAS_TIMESTAMPS) 439 length += 12; 440 441 if (segment.options & TCP_HAS_WINDOW_SCALE) 442 length += 4; 443 444 if (segment.options & TCP_SACK_PERMITTED) 445 length += 2; 446 447 if (segment.sackCount > 0) { 448 int sackCount = min_c((int)((kMaxOptionSize - length - 4) 449 / sizeof(tcp_sack)), segment.sackCount); 450 if (sackCount > 0) 451 length += 4 + sackCount * sizeof(tcp_sack); 452 } 453 454 if ((length & 3) == 0) 455 return length; 456 457 return (length + 3) & ~3; 458 } 459 460 461 // #pragma mark - protocol API 462 463 464 net_protocol* 465 tcp_init_protocol(net_socket* socket) 466 { 467 socket->send.buffer_size = 32768; 468 // override net_socket default 469 470 TCPEndpoint* protocol = new (std::nothrow) TCPEndpoint(socket); 471 if (protocol == NULL) 472 return NULL; 473 474 if (protocol->InitCheck() != B_OK) { 475 delete protocol; 476 return NULL; 477 } 478 479 TRACE(("Creating new TCPEndpoint: %p\n", protocol)); 480 socket->protocol = IPPROTO_TCP; 481 return protocol; 482 } 483 484 485 status_t 486 tcp_uninit_protocol(net_protocol* protocol) 487 { 488 TRACE(("Deleting TCPEndpoint: %p\n", protocol)); 489 delete (TCPEndpoint*)protocol; 490 return B_OK; 491 } 492 493 494 status_t 495 tcp_open(net_protocol* protocol) 496 { 497 return ((TCPEndpoint*)protocol)->Open(); 498 } 499 500 501 status_t 502 tcp_close(net_protocol* protocol) 503 { 504 return ((TCPEndpoint*)protocol)->Close(); 505 } 506 507 508 status_t 509 tcp_free(net_protocol* protocol) 510 { 511 ((TCPEndpoint*)protocol)->Free(); 512 return B_OK; 513 } 514 515 516 status_t 517 tcp_connect(net_protocol* protocol, const struct sockaddr* address) 518 { 519 return ((TCPEndpoint*)protocol)->Connect(address); 520 } 521 522 523 status_t 524 tcp_accept(net_protocol* protocol, struct net_socket** _acceptedSocket) 525 { 526 return ((TCPEndpoint*)protocol)->Accept(_acceptedSocket); 527 } 528 529 530 status_t 531 tcp_control(net_protocol* _protocol, int level, int option, void* value, 532 size_t* _length) 533 { 534 TCPEndpoint* protocol = (TCPEndpoint*)_protocol; 535 536 if ((level & LEVEL_MASK) == IPPROTO_TCP) { 537 if (option == NET_STAT_SOCKET) 538 return protocol->FillStat((net_stat*)value); 539 } 540 541 return protocol->next->module->control(protocol->next, level, option, 542 value, _length); 543 } 544 545 546 status_t 547 tcp_getsockopt(net_protocol* _protocol, int level, int option, void* value, 548 int* _length) 549 { 550 TCPEndpoint* protocol = (TCPEndpoint*)_protocol; 551 552 if (level == IPPROTO_TCP) 553 return protocol->GetOption(option, value, _length); 554 555 return protocol->next->module->getsockopt(protocol->next, level, option, 556 value, _length); 557 } 558 559 560 status_t 561 tcp_setsockopt(net_protocol* _protocol, int level, int option, 562 const void* _value, int length) 563 { 564 TCPEndpoint* protocol = (TCPEndpoint*)_protocol; 565 566 if (level == SOL_SOCKET) { 567 if (option == SO_SNDBUF || option == SO_RCVBUF) { 568 if (length != sizeof(int)) 569 return B_BAD_VALUE; 570 571 status_t status; 572 const int* value = (const int*)_value; 573 574 if (option == SO_SNDBUF) 575 status = protocol->SetSendBufferSize(*value); 576 else 577 status = protocol->SetReceiveBufferSize(*value); 578 579 if (status < B_OK) 580 return status; 581 } 582 } else if (level == IPPROTO_TCP) 583 return protocol->SetOption(option, _value, length); 584 585 return protocol->next->module->setsockopt(protocol->next, level, option, 586 _value, length); 587 } 588 589 590 status_t 591 tcp_bind(net_protocol* protocol, const struct sockaddr* address) 592 { 593 return ((TCPEndpoint*)protocol)->Bind(address); 594 } 595 596 597 status_t 598 tcp_unbind(net_protocol* protocol, struct sockaddr* address) 599 { 600 return ((TCPEndpoint*)protocol)->Unbind(address); 601 } 602 603 604 status_t 605 tcp_listen(net_protocol* protocol, int count) 606 { 607 return ((TCPEndpoint*)protocol)->Listen(count); 608 } 609 610 611 status_t 612 tcp_shutdown(net_protocol* protocol, int direction) 613 { 614 return ((TCPEndpoint*)protocol)->Shutdown(direction); 615 } 616 617 618 status_t 619 tcp_send_data(net_protocol* protocol, net_buffer* buffer) 620 { 621 return ((TCPEndpoint*)protocol)->SendData(buffer); 622 } 623 624 625 status_t 626 tcp_send_routed_data(net_protocol* protocol, struct net_route* route, 627 net_buffer* buffer) 628 { 629 // TCP never sends routed data 630 return B_ERROR; 631 } 632 633 634 ssize_t 635 tcp_send_avail(net_protocol* protocol) 636 { 637 return ((TCPEndpoint*)protocol)->SendAvailable(); 638 } 639 640 641 status_t 642 tcp_read_data(net_protocol* protocol, size_t numBytes, uint32 flags, 643 net_buffer** _buffer) 644 { 645 return ((TCPEndpoint*)protocol)->ReadData(numBytes, flags, _buffer); 646 } 647 648 649 ssize_t 650 tcp_read_avail(net_protocol* protocol) 651 { 652 return ((TCPEndpoint*)protocol)->ReadAvailable(); 653 } 654 655 656 struct net_domain* 657 tcp_get_domain(net_protocol* protocol) 658 { 659 return protocol->next->module->get_domain(protocol->next); 660 } 661 662 663 size_t 664 tcp_get_mtu(net_protocol* protocol, const struct sockaddr* address) 665 { 666 return protocol->next->module->get_mtu(protocol->next, address); 667 } 668 669 670 status_t 671 tcp_receive_data(net_buffer* buffer) 672 { 673 TRACE(("TCP: Received buffer %p\n", buffer)); 674 675 if (buffer->interface_address == NULL 676 || buffer->interface_address->domain == NULL) 677 return B_ERROR; 678 679 net_domain* domain = buffer->interface_address->domain; 680 net_address_module_info* addressModule = domain->address_module; 681 682 NetBufferHeaderReader<tcp_header> bufferHeader(buffer); 683 if (bufferHeader.Status() < B_OK) 684 return bufferHeader.Status(); 685 686 tcp_header& header = bufferHeader.Data(); 687 688 uint16 headerLength = header.HeaderLength(); 689 if (headerLength < sizeof(tcp_header)) 690 return B_BAD_DATA; 691 692 if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, 693 IPPROTO_TCP) != 0) 694 return B_BAD_DATA; 695 696 addressModule->set_port(buffer->source, header.source_port); 697 addressModule->set_port(buffer->destination, header.destination_port); 698 699 TRACE((" Looking for: peer %s, local %s\n", 700 AddressString(domain, buffer->source, true).Data(), 701 AddressString(domain, buffer->destination, true).Data())); 702 //dump_tcp_header(header); 703 //gBufferModule->dump(buffer); 704 705 tcp_segment_header segment(header.flags); 706 segment.sequence = header.Sequence(); 707 segment.acknowledge = header.Acknowledge(); 708 segment.advertised_window = header.AdvertisedWindow(); 709 segment.urgent_offset = header.UrgentOffset(); 710 process_options(segment, buffer, headerLength - sizeof(tcp_header)); 711 712 bufferHeader.Remove(headerLength); 713 // we no longer need to keep the header around 714 715 EndpointManager* endpointManager = endpoint_manager_for(domain); 716 if (endpointManager == NULL) { 717 TRACE((" No endpoint manager!\n")); 718 return B_ERROR; 719 } 720 721 int32 segmentAction = DROP; 722 723 TCPEndpoint* endpoint = endpointManager->FindConnection( 724 buffer->destination, buffer->source); 725 if (endpoint != NULL) { 726 segmentAction = endpoint->SegmentReceived(segment, buffer); 727 728 // There are some states in which the socket could have been deleted 729 // while handling a segment. If this flag is set in segmentAction 730 // then we know the socket has been freed and can skip releasing 731 // the reference acquired in EndpointManager::FindConnection() 732 // above. 733 if ((segmentAction & DELETED_ENDPOINT) == 0) 734 gSocketModule->release_socket(endpoint->socket); 735 } else if ((segment.flags & TCP_FLAG_RESET) == 0) 736 segmentAction = DROP | RESET; 737 738 if ((segmentAction & RESET) != 0) { 739 // send reset 740 endpointManager->ReplyWithReset(segment, buffer); 741 } 742 if ((segmentAction & DROP) != 0) 743 gBufferModule->free(buffer); 744 745 return B_OK; 746 } 747 748 749 status_t 750 tcp_error_received(net_error error, net_buffer* data) 751 { 752 return B_ERROR; 753 } 754 755 756 status_t 757 tcp_error_reply(net_protocol* protocol, net_buffer* cause, net_error error, 758 net_error_data* errorData) 759 { 760 return B_ERROR; 761 } 762 763 764 // #pragma mark - 765 766 767 static status_t 768 tcp_init() 769 { 770 rw_lock_init(&sEndpointManagersLock, "endpoint managers"); 771 772 status_t status = gStackModule->register_domain_protocols(AF_INET, 773 SOCK_STREAM, 0, 774 "network/protocols/tcp/v1", 775 "network/protocols/ipv4/v1", 776 NULL); 777 if (status < B_OK) 778 return status; 779 status = gStackModule->register_domain_protocols(AF_INET6, 780 SOCK_STREAM, 0, 781 "network/protocols/tcp/v1", 782 "network/protocols/ipv6/v1", 783 NULL); 784 if (status < B_OK) 785 return status; 786 787 status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM, 788 IPPROTO_TCP, 789 "network/protocols/tcp/v1", 790 "network/protocols/ipv4/v1", 791 NULL); 792 if (status < B_OK) 793 return status; 794 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_STREAM, 795 IPPROTO_TCP, 796 "network/protocols/tcp/v1", 797 "network/protocols/ipv6/v1", 798 NULL); 799 if (status < B_OK) 800 return status; 801 802 status = gStackModule->register_domain_receiving_protocol(AF_INET, 803 IPPROTO_TCP, "network/protocols/tcp/v1"); 804 if (status < B_OK) 805 return status; 806 status = gStackModule->register_domain_receiving_protocol(AF_INET6, 807 IPPROTO_TCP, "network/protocols/tcp/v1"); 808 if (status < B_OK) 809 return status; 810 811 add_debugger_command("tcp_endpoints", dump_endpoints, 812 "lists all open TCP endpoints"); 813 add_debugger_command("tcp_endpoint", dump_endpoint, 814 "dumps a TCP endpoint internal state"); 815 816 return B_OK; 817 } 818 819 820 static status_t 821 tcp_uninit() 822 { 823 remove_debugger_command("tcp_endpoint", dump_endpoint); 824 remove_debugger_command("tcp_endpoints", dump_endpoints); 825 826 rw_lock_destroy(&sEndpointManagersLock); 827 828 for (int i = 0; i < AF_MAX; i++) { 829 delete sEndpointManagers[i]; 830 } 831 832 return B_OK; 833 } 834 835 836 static status_t 837 tcp_std_ops(int32 op, ...) 838 { 839 switch (op) { 840 case B_MODULE_INIT: 841 return tcp_init(); 842 843 case B_MODULE_UNINIT: 844 return tcp_uninit(); 845 846 default: 847 return B_ERROR; 848 } 849 } 850 851 852 net_protocol_module_info sTCPModule = { 853 { 854 "network/protocols/tcp/v1", 855 0, 856 tcp_std_ops 857 }, 858 0, 859 860 tcp_init_protocol, 861 tcp_uninit_protocol, 862 tcp_open, 863 tcp_close, 864 tcp_free, 865 tcp_connect, 866 tcp_accept, 867 tcp_control, 868 tcp_getsockopt, 869 tcp_setsockopt, 870 tcp_bind, 871 tcp_unbind, 872 tcp_listen, 873 tcp_shutdown, 874 tcp_send_data, 875 tcp_send_routed_data, 876 tcp_send_avail, 877 tcp_read_data, 878 tcp_read_avail, 879 tcp_get_domain, 880 tcp_get_mtu, 881 tcp_receive_data, 882 NULL, // deliver_data() 883 tcp_error_received, 884 tcp_error_reply, 885 NULL, // add_ancillary_data() 886 NULL, // process_ancillary_data() 887 NULL, // process_ancillary_data_no_container() 888 NULL, // send_data_no_buffer() 889 NULL // read_data_no_buffer() 890 }; 891 892 module_dependency module_dependencies[] = { 893 {NET_STACK_MODULE_NAME, (module_info **)&gStackModule}, 894 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 895 {NET_DATALINK_MODULE_NAME, (module_info **)&gDatalinkModule}, 896 {NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule}, 897 {} 898 }; 899 900 module_info *modules[] = { 901 (module_info *)&sTCPModule, 902 NULL 903 }; 904