1 /* 2 * Copyright 2010 Andreas Färber <andreas.faerber@web.de> 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 7 /* 8 * NOTE This is a cleanroom TCP implementation with some known issues. 9 * Protection Against Wrapping Sequence (PAWS) needs to be added. 10 * Congestion control needs to be implemented (slow start, recv. window size). 11 * The use of *Packets needs to be re-evaluated in the context of TCP; 12 * probably a singly-linked list of received data chunks is more efficient. 13 * Debug output should be tuned for better aspect oriented tracing. 14 * While Little Endian systems have been considered, this still needs testing. 15 */ 16 17 18 #include <boot/net/TCP.h> 19 20 #include <stdio.h> 21 22 #include <KernelExport.h> 23 24 #include <boot/net/ChainBuffer.h> 25 #include <boot/net/NetStack.h> 26 27 #include "real_time_clock.h" 28 29 30 //#define TRACE_TCP 31 //#define TRACE_TCP_RANDOMNESS 32 //#define TRACE_TCP_CHECKSUM 33 //#define TRACE_TCP_QUEUE 34 35 36 #ifdef TRACE_TCP 37 # define TRACE(x, ...) dprintf(x, ## __VA_ARGS__) 38 #else 39 # define TRACE(x, ...) ; 40 #endif 41 #ifdef TRACE_TCP_RANDOMNESS 42 # define TRACE_PORT(x, ...) dprintf(x, ## __VA_ARGS__) 43 #else 44 # define TRACE_PORT(x, ...) ; 45 #endif 46 #if defined(TRACE_TCP_CHECKSUM) 47 # define TRACE_CHECKSUM(x, ...) dprintf(x, ## __VA_ARGS__) 48 #else 49 # define TRACE_CHECKSUM(x, ...) ; 50 #endif 51 #if defined(TRACE_TCP_QUEUE) 52 # define TRACE_QUEUE(x, ...) dprintf(x, ## __VA_ARGS__) 53 #else 54 # define TRACE_QUEUE(x, ...) ; 55 #endif 56 57 58 static unsigned int 59 _rand32(void) 60 { 61 static unsigned int next = 0; 62 if (next == 0) 63 next = real_time_clock_usecs() / 1000000; 64 65 next = (next >> 1) ^ (unsigned int)((0 - (next & 1U)) & 0xd0000001U); 66 // characteristic polynomial: x^32 + x^31 + x^29 + x + 1 67 return next; 68 } 69 70 71 static unsigned short 72 _rand14(void) 73 { 74 // TODO: Find suitable generator polynomial. 75 return _rand32() & 0x3fff; 76 } 77 78 79 TCPPacket::TCPPacket() 80 : 81 fData(NULL), 82 fNext(NULL) 83 { 84 } 85 86 87 TCPPacket::~TCPPacket() 88 { 89 free(fData); 90 } 91 92 93 status_t 94 TCPPacket::SetTo(const void* data, size_t size, ip_addr_t sourceAddress, 95 uint16 sourcePort, ip_addr_t destinationAddress, uint16 destinationPort, 96 uint32 sequenceNumber, uint32 acknowledgmentNumber, uint8 flags) 97 { 98 if (data == NULL && size > 0) 99 return B_BAD_VALUE; 100 101 if (size > 0) { 102 fData = malloc(size); 103 if (fData == NULL) 104 return B_NO_MEMORY; 105 memcpy(fData, data, size); 106 } else 107 fData = NULL; 108 109 fSize = size; 110 fSourceAddress = sourceAddress; 111 fSourcePort = sourcePort; 112 fDestinationAddress = destinationAddress; 113 fDestinationPort = destinationPort; 114 fSequenceNumber = sequenceNumber; 115 fAcknowledgmentNumber = acknowledgmentNumber; 116 fFlags = flags; 117 118 return B_OK; 119 } 120 121 122 ip_addr_t 123 TCPPacket::SourceAddress() const 124 { 125 return fSourceAddress; 126 } 127 128 129 ip_addr_t 130 TCPPacket::DestinationAddress() const 131 { 132 return fDestinationAddress; 133 } 134 135 136 uint16 137 TCPPacket::SourcePort() const 138 { 139 return fSourcePort; 140 } 141 142 143 uint16 144 TCPPacket::DestinationPort() const 145 { 146 return fDestinationPort; 147 } 148 149 150 uint32 151 TCPPacket::SequenceNumber() const 152 { 153 return fSequenceNumber; 154 } 155 156 157 uint32 158 TCPPacket::AcknowledgmentNumber() const 159 { 160 return fAcknowledgmentNumber; 161 } 162 163 164 bool 165 TCPPacket::ProvidesSequenceNumber(uint32 sequenceNumber) const 166 { 167 // TODO PAWS 168 return fSequenceNumber <= sequenceNumber 169 && fSequenceNumber + fSize > sequenceNumber; 170 } 171 172 173 TCPPacket* 174 TCPPacket::Next() const 175 { 176 return fNext; 177 } 178 179 180 void 181 TCPPacket::SetNext(TCPPacket* packet) 182 { 183 fNext = packet; 184 } 185 186 187 188 189 TCPSocket::TCPSocket() 190 : 191 fTCPService(NetStack::Default()->GetTCPService()), 192 fAddress(INADDR_ANY), 193 fPort(0), 194 fSequenceNumber(0), 195 fFirstPacket(NULL), 196 fLastPacket(NULL), 197 fFirstSentPacket(NULL), 198 fLastSentPacket(NULL), 199 fState(TCP_SOCKET_STATE_INITIAL), 200 fRemoteState(TCP_SOCKET_STATE_INITIAL) 201 { 202 } 203 204 205 TCPSocket::~TCPSocket() 206 { 207 if (fTCPService != NULL && fPort != 0) 208 fTCPService->UnbindSocket(this); 209 } 210 211 212 uint16 213 TCPSocket::WindowSize() const 214 { 215 // TODO A large window size leads to read timeouts 216 // due to resends occuring too late. 217 #if 0 218 size_t windowSize = 0xffff; 219 for (TCPPacket* packet = fFirstPacket; 220 packet != NULL && windowSize > packet->DataSize(); 221 packet = packet->Next()) 222 windowSize -= packet->DataSize(); 223 return windowSize; 224 #else 225 return 4096; 226 #endif 227 } 228 229 230 status_t 231 TCPSocket::Connect(ip_addr_t address, uint16 port) 232 { 233 fRemoteAddress = address; 234 fRemotePort = port; 235 fSequenceNumber = _rand32(); 236 fPort = 0xC000 + (_rand14() & ~0xc000); 237 TRACE_PORT("TCPSocket::Connect(): connecting from port %u\n", fPort); 238 fAcknowledgeNumber = 0; 239 fNextSequence = 0; 240 241 status_t error = fTCPService->BindSocket(this); 242 if (error != B_OK) 243 return error; 244 245 // send SYN 246 TCPPacket* packet = new(nothrow) TCPPacket(); 247 if (packet == NULL) 248 return B_NO_MEMORY; 249 error = packet->SetTo(NULL, 0, fAddress, fPort, address, port, 250 fSequenceNumber, fAcknowledgeNumber, TCP_SYN); 251 if (error != B_OK) { 252 delete packet; 253 return error; 254 } 255 error = _Send(packet); 256 if (error != B_OK) 257 return error; 258 fState = TCP_SOCKET_STATE_SYN_SENT; 259 fSequenceNumber++; 260 TRACE("SYN sent\n"); 261 262 // receive SYN-ACK 263 error = _WaitForState(TCP_SOCKET_STATE_OPEN, 1000000LL); 264 if (error != B_OK) { 265 TRACE("no SYN-ACK received\n"); 266 return error; 267 } 268 TRACE("SYN-ACK received\n"); 269 270 return B_OK; 271 } 272 273 274 status_t 275 TCPSocket::Close() 276 { 277 // send FIN 278 TCPPacket* packet = new(nothrow) TCPPacket(); 279 if (packet == NULL) 280 return B_NO_MEMORY; 281 status_t error = packet->SetTo(NULL, 0, fAddress, fPort, fRemoteAddress, 282 fRemotePort, fSequenceNumber, fAcknowledgeNumber, TCP_FIN | TCP_ACK); 283 if (error != B_OK) { 284 delete packet; 285 return error; 286 } 287 error = _Send(packet); 288 if (error != B_OK) 289 return error; 290 fState = TCP_SOCKET_STATE_FIN_SENT; 291 TRACE("FIN sent\n"); 292 293 error = _WaitForState(TCP_SOCKET_STATE_CLOSED, 1000000LL); 294 if (error != B_OK) 295 return error; 296 297 return B_OK; 298 } 299 300 301 status_t 302 TCPSocket::Read(void* buffer, size_t bufferSize, size_t* bytesRead, 303 bigtime_t timeout) 304 { 305 TRACE("TCPSocket::Read(): size = %lu\n", bufferSize); 306 if (bytesRead == NULL) 307 return B_BAD_VALUE; 308 309 *bytesRead = 0; 310 TCPPacket* packet = NULL; 311 312 bigtime_t startTime = system_time(); 313 do { 314 fTCPService->ProcessIncomingPackets(); 315 //_ResendQueue(); 316 packet = _PeekPacket(); 317 if (packet == NULL && fRemoteState != TCP_SOCKET_STATE_OPEN) 318 return B_ERROR; 319 if (packet == NULL && timeout > 0LL) 320 _Ack(); 321 } while (packet == NULL && system_time() - startTime < timeout); 322 if (packet == NULL) { 323 #ifdef TRACE_TCP_QUEUE 324 _DumpQueue(); 325 #endif 326 return (timeout == 0) ? B_WOULD_BLOCK : B_TIMED_OUT; 327 } 328 uint32 packetOffset = fNextSequence - packet->SequenceNumber(); 329 size_t readBytes = packet->DataSize() - packetOffset; 330 if (readBytes > bufferSize) 331 readBytes = bufferSize; 332 if (buffer != NULL) 333 memcpy(buffer, (uint8*)packet->Data() + packetOffset, readBytes); 334 *bytesRead = readBytes; 335 if (!packet->ProvidesSequenceNumber(fNextSequence + readBytes)) { 336 _DequeuePacket(); 337 delete packet; 338 packet = NULL; 339 } 340 fNextSequence += readBytes; 341 342 if (packet == NULL && *bytesRead < bufferSize) { 343 do { 344 if (buffer != NULL) 345 buffer = (uint8*)buffer + readBytes; 346 bufferSize -= readBytes; 347 fTCPService->ProcessIncomingPackets(); 348 packet = _PeekPacket(); 349 if (packet == NULL && fRemoteState != TCP_SOCKET_STATE_OPEN) 350 break; 351 readBytes = 0; 352 if (packet == NULL) { 353 _Ack(); 354 continue; 355 } 356 readBytes = packet->DataSize(); 357 if (readBytes > bufferSize) 358 readBytes = bufferSize; 359 if (buffer != NULL) 360 memcpy(buffer, packet->Data(), readBytes); 361 *bytesRead += readBytes; 362 if (readBytes == packet->DataSize()) { 363 _DequeuePacket(); 364 delete packet; 365 } 366 fNextSequence += readBytes; 367 } while (readBytes < bufferSize && 368 system_time() - startTime < timeout); 369 #ifdef TRACE_TCP_QUEUE 370 if (readBytes < bufferSize) { 371 TRACE_QUEUE("TCP: Unable to deliver more data!\n"); 372 _DumpQueue(); 373 } 374 #endif 375 } 376 377 return B_OK; 378 } 379 380 381 status_t 382 TCPSocket::Write(const void* buffer, size_t bufferSize) 383 { 384 if (buffer == NULL || bufferSize == 0) 385 return B_BAD_VALUE; 386 387 // TODO: Check for MTU and create multiple packets if necessary. 388 389 TCPPacket* packet = new(nothrow) TCPPacket(); 390 if (packet == NULL) 391 return B_NO_MEMORY; 392 status_t error = packet->SetTo(buffer, bufferSize, fAddress, fPort, 393 fRemoteAddress, fRemotePort, fSequenceNumber, fAcknowledgeNumber, 394 TCP_ACK); 395 if (error != B_OK) { 396 delete packet; 397 return error; 398 } 399 return _Send(packet); 400 } 401 402 403 void 404 TCPSocket::Acknowledge(uint32 number) 405 { 406 TRACE("TCPSocket::Acknowledge(): %lu\n", number); 407 // dequeue packets 408 for (TCPPacket* packet = fFirstSentPacket; packet != NULL; 409 packet = fFirstSentPacket) { 410 if (packet->SequenceNumber() >= number) 411 return; 412 fFirstSentPacket = packet->Next(); 413 delete packet; 414 } 415 fLastSentPacket = NULL; 416 } 417 418 419 void 420 TCPSocket::ProcessPacket(TCPPacket* packet) 421 { 422 TRACE("TCPSocket::ProcessPacket()\n"); 423 424 if ((packet->Flags() & TCP_FIN) != 0) { 425 fRemoteState = TCP_SOCKET_STATE_FIN_SENT; 426 TRACE("FIN received\n"); 427 _Ack(); 428 } 429 430 if (fState == TCP_SOCKET_STATE_SYN_SENT) { 431 if ((packet->Flags() & TCP_SYN) != 0 432 && (packet->Flags() & TCP_ACK) != 0) { 433 fNextSequence = fAcknowledgeNumber = packet->SequenceNumber() + 1; 434 fRemoteState = TCP_SOCKET_STATE_SYN_SENT; 435 delete packet; 436 _Ack(); 437 fState = fRemoteState = TCP_SOCKET_STATE_OPEN; 438 return; 439 } 440 } else if (fState == TCP_SOCKET_STATE_OPEN) { 441 } else if (fState == TCP_SOCKET_STATE_FIN_SENT) { 442 if ((packet->Flags() & TCP_ACK) != 0) { 443 TRACE("FIN-ACK received\n"); 444 if (fRemoteState == TCP_SOCKET_STATE_FIN_SENT) 445 fState = TCP_SOCKET_STATE_CLOSED; 446 } 447 } 448 449 if (packet->DataSize() == 0) { 450 TRACE("TCPSocket::ProcessPacket(): not queuing due to lack of data\n"); 451 delete packet; 452 return; 453 } 454 455 // For now rather protect us against being flooded with packets already 456 // acknowledged. "If it's important, they'll send it again." 457 // TODO PAWS 458 if (packet->SequenceNumber() < fAcknowledgeNumber) { 459 TRACE_QUEUE("TCPSocket::ProcessPacket(): not queuing due to wraparound\n"); 460 delete packet; 461 return; 462 } 463 464 if (fLastPacket == NULL) { 465 // no packets enqueued 466 TRACE("TCPSocket::ProcessPacket(): first in queue\n"); 467 packet->SetNext(NULL); 468 fFirstPacket = fLastPacket = packet; 469 } else if (fLastPacket->SequenceNumber() < packet->SequenceNumber()) { 470 // enqueue in back 471 TRACE("TCPSocket::ProcessPacket(): enqueue in back\n"); 472 packet->SetNext(NULL); 473 fLastPacket->SetNext(packet); 474 fLastPacket = packet; 475 } else if (fFirstPacket->SequenceNumber() > packet->SequenceNumber()) { 476 // enqueue in front 477 TRACE("TCPSocket::ProcessPacket(): enqueue in front\n"); 478 TRACE_QUEUE("TCP: Enqueuing %lx - %lx in front! (next is %lx)\n", 479 packet->SequenceNumber(), 480 packet->SequenceNumber() + packet->DataSize() - 1, 481 fNextSequence); 482 packet->SetNext(fFirstPacket); 483 fFirstPacket = packet; 484 } else if (fFirstPacket->SequenceNumber() == packet->SequenceNumber()) { 485 TRACE_QUEUE("%s(): dropping due to identical first packet\n", __func__); 486 delete packet; 487 return; 488 } else { 489 // enqueue in middle 490 TRACE("TCPSocket::ProcessPacket(): enqueue in middle\n"); 491 for (TCPPacket* queuedPacket = fFirstPacket; queuedPacket != NULL; 492 queuedPacket = queuedPacket->Next()) { 493 if (queuedPacket->SequenceNumber() == packet->SequenceNumber()) { 494 TRACE_QUEUE("TCPSocket::EnqueuePacket(): TCP packet dropped\n"); 495 // we may be waiting for a previous packet 496 delete packet; 497 return; 498 } 499 if (queuedPacket->Next()->SequenceNumber() 500 > packet->SequenceNumber()) { 501 packet->SetNext(queuedPacket->Next()); 502 queuedPacket->SetNext(packet); 503 break; 504 } 505 } 506 } 507 while (packet != NULL && packet->SequenceNumber() == fAcknowledgeNumber) { 508 fAcknowledgeNumber = packet->SequenceNumber() + packet->DataSize(); 509 packet = packet->Next(); 510 } 511 } 512 513 514 TCPPacket* 515 TCPSocket::_PeekPacket() 516 { 517 TRACE("TCPSocket::_PeekPacket(): fNextSequence = %lu\n", fNextSequence); 518 for (TCPPacket* packet = fFirstPacket; packet != NULL; 519 packet = packet->Next()) { 520 if (packet->ProvidesSequenceNumber(fNextSequence)) 521 return packet; 522 } 523 return NULL; 524 } 525 526 527 TCPPacket* 528 TCPSocket::_DequeuePacket() 529 { 530 //TRACE("TCPSocket::DequeuePacket()\n"); 531 if (fFirstPacket == NULL) 532 return NULL; 533 534 if (fFirstPacket->ProvidesSequenceNumber(fNextSequence)) { 535 TCPPacket* packet = fFirstPacket; 536 fFirstPacket = packet->Next(); 537 if (fFirstPacket == NULL) 538 fLastPacket = NULL; 539 packet->SetNext(NULL); 540 TRACE("TCP: Dequeuing %lx - %lx from front.\n", 541 packet->SequenceNumber(), 542 packet->SequenceNumber() + packet->DataSize() - 1); 543 return packet; 544 } 545 546 for (TCPPacket* packet = fFirstPacket; 547 packet != NULL && packet->Next() != NULL; 548 packet = packet->Next()) { 549 if (packet->Next()->ProvidesSequenceNumber(fNextSequence)) { 550 TCPPacket* nextPacket = packet->Next(); 551 packet->SetNext(nextPacket->Next()); 552 if (fLastPacket == nextPacket) 553 fLastPacket = packet; 554 TRACE("TCP: Dequeuing %lx - %lx.\n", 555 nextPacket->SequenceNumber(), 556 nextPacket->SequenceNumber() + nextPacket->DataSize() - 1); 557 return nextPacket; 558 } 559 } 560 TRACE_QUEUE("dequeue failed!\n"); 561 return NULL; 562 } 563 564 565 status_t 566 TCPSocket::_Send(TCPPacket* packet, bool enqueue) 567 { 568 ChainBuffer buffer((void*)packet->Data(), packet->DataSize()); 569 status_t error = fTCPService->Send(fPort, fRemoteAddress, fRemotePort, 570 packet->SequenceNumber(), fAcknowledgeNumber, packet->Flags(), 571 WindowSize(), &buffer); 572 if (error != B_OK) 573 return error; 574 if (packet->SequenceNumber() == fSequenceNumber) 575 fSequenceNumber += packet->DataSize(); 576 577 if (enqueue) 578 _EnqueueOutgoingPacket(packet); 579 580 return B_OK; 581 } 582 583 584 status_t 585 TCPSocket::_ResendQueue() 586 { 587 TRACE("resending queue\n"); 588 for (TCPPacket* packet = fFirstSentPacket; packet != NULL; 589 packet = packet->Next()) { 590 ChainBuffer buffer((void*)packet->Data(), packet->DataSize()); 591 status_t error = fTCPService->Send(fPort, fRemoteAddress, fRemotePort, 592 packet->SequenceNumber(), fAcknowledgeNumber, packet->Flags(), 593 WindowSize(), &buffer); 594 if (error != B_OK) 595 return error; 596 } 597 return B_OK; 598 } 599 600 601 void 602 TCPSocket::_EnqueueOutgoingPacket(TCPPacket* packet) 603 { 604 if (fLastSentPacket != NULL) { 605 fLastSentPacket->SetNext(packet); 606 fLastSentPacket = packet; 607 } else { 608 fFirstSentPacket = fLastSentPacket = packet; 609 } 610 } 611 612 613 #ifdef TRACE_TCP_QUEUE 614 615 inline void 616 TCPSocket::_DumpQueue() 617 { 618 TRACE_QUEUE("TCP: waiting for %lx (ack'ed %lx)\n", fNextSequence, fAcknowledgeNumber); 619 if (fFirstPacket == NULL) 620 TRACE_QUEUE("TCP: Queue is empty.\n"); 621 else { 622 for (TCPPacket* packet = fFirstPacket; packet != NULL; 623 packet = packet->Next()) { 624 TRACE_QUEUE("TCP: Queue: %lx\n", packet->SequenceNumber()); 625 } 626 } 627 if (fFirstSentPacket != NULL) 628 TRACE_QUEUE("TCP: Send queue is non-empty.\n"); 629 else 630 TRACE_QUEUE("TCP: Send queue is empty.\n"); 631 } 632 633 #endif 634 635 636 status_t 637 TCPSocket::_Ack() 638 { 639 TCPPacket* packet = new(nothrow) TCPPacket(); 640 if (packet == NULL) 641 return B_NO_MEMORY; 642 status_t error = packet->SetTo(NULL, 0, fAddress, fPort, fRemoteAddress, 643 fRemotePort, fSequenceNumber, fAcknowledgeNumber, TCP_ACK); 644 if (error != B_OK) { 645 delete packet; 646 return error; 647 } 648 error = _Send(packet, false); 649 delete packet; 650 if (error != B_OK) 651 return error; 652 return B_OK; 653 } 654 655 656 status_t 657 TCPSocket::_WaitForState(TCPSocketState state, bigtime_t timeout) 658 { 659 if (fTCPService == NULL) 660 return B_NO_INIT; 661 662 bigtime_t startTime = system_time(); 663 do { 664 fTCPService->ProcessIncomingPackets(); 665 if (fState == state) 666 return B_OK; 667 } while (system_time() - startTime < timeout); 668 return timeout == 0 ? B_WOULD_BLOCK : B_TIMED_OUT; 669 } 670 671 672 673 674 TCPService::TCPService(IPService* ipService) 675 : 676 IPSubService(kTCPServiceName), 677 fIPService(ipService) 678 { 679 } 680 681 682 TCPService::~TCPService() 683 { 684 if (fIPService != NULL) 685 fIPService->UnregisterIPSubService(this); 686 } 687 688 689 status_t 690 TCPService::Init() 691 { 692 if (fIPService == NULL) 693 return B_BAD_VALUE; 694 695 if (!fIPService->RegisterIPSubService(this)) 696 return B_NO_MEMORY; 697 698 return B_OK; 699 } 700 701 702 uint8 703 TCPService::IPProtocol() const 704 { 705 return IPPROTO_TCP; 706 } 707 708 709 void 710 TCPService::HandleIPPacket(IPService* ipService, ip_addr_t sourceIP, 711 ip_addr_t destinationIP, const void* data, size_t size) 712 { 713 TRACE("TCPService::HandleIPPacket(): source = %08lx, " 714 "destination = %08lx, %lu - %lu bytes\n", sourceIP, destinationIP, 715 size, sizeof(tcp_header)); 716 717 if (data == NULL || size < sizeof(tcp_header)) 718 return; 719 720 const tcp_header* header = (const tcp_header*)data; 721 722 uint16 chksum = _ChecksumData(data, size, sourceIP, destinationIP); 723 if (chksum != 0) { 724 TRACE_CHECKSUM("TCPService::HandleIPPacket(): invalid checksum " 725 "(%04x vs. %04x), padding %lu\n", 726 header->checksum, chksum, size % 2); 727 return; 728 } 729 730 uint16 source = ntohs(header->source); 731 uint16 destination = ntohs(header->destination); 732 uint32 sequenceNumber = ntohl(header->seqNumber); 733 uint32 ackedNumber = ntohl(header->ackNumber); 734 TRACE("\tsource = %u, dest = %u, seq = %lu, ack = %lu, dataOffset = %u, " 735 "flags %s %s %s %s\n", source, destination, sequenceNumber, 736 ackedNumber, header->dataOffset, 737 (header->flags & TCP_ACK) != 0 ? "ACK" : "", 738 (header->flags & TCP_SYN) != 0 ? "SYN" : "", 739 (header->flags & TCP_FIN) != 0 ? "FIN" : "", 740 (header->flags & TCP_RST) != 0 ? "RST" : ""); 741 if (header->dataOffset > 5) { 742 uint8* option = (uint8*)data + sizeof(tcp_header); 743 while ((uint32*)option < (uint32*)data + header->dataOffset) { 744 uint8 optionKind = option[0]; 745 if (optionKind == 0) 746 break; 747 uint8 optionLength = 1; 748 if (optionKind > 1) { 749 optionLength = option[1]; 750 TRACE("\tTCP option kind %u, length %u\n", 751 optionKind, optionLength); 752 if (optionKind == 2) 753 TRACE("\tTCP MSS = %04hu\n", *(uint16_t*)&option[2]); 754 } 755 option += optionLength; 756 } 757 } 758 759 TCPSocket* socket = _FindSocket(destinationIP, destination); 760 if (socket == NULL) { 761 // TODO If SYN, answer with RST? 762 TRACE("TCPService::HandleIPPacket(): no socket\n"); 763 return; 764 } 765 766 if ((header->flags & TCP_ACK) != 0) { 767 socket->Acknowledge(ackedNumber); 768 } 769 770 TCPPacket* packet = new(nothrow) TCPPacket(); 771 if (packet == NULL) 772 return; 773 status_t error = packet->SetTo((uint32*)data + header->dataOffset, 774 size - header->dataOffset * 4, sourceIP, source, destinationIP, 775 destination, sequenceNumber, ackedNumber, header->flags); 776 if (error == B_OK) 777 socket->ProcessPacket(packet); 778 else 779 delete packet; 780 } 781 782 783 status_t 784 TCPService::Send(uint16 sourcePort, ip_addr_t destinationAddress, 785 uint16 destinationPort, uint32 sequenceNumber, 786 uint32 acknowledgmentNumber, uint8 flags, uint16 windowSize, 787 ChainBuffer* buffer) 788 { 789 TRACE("TCPService::Send(): seq = %lu, ack = %lu\n", 790 sequenceNumber, acknowledgmentNumber); 791 if (fIPService == NULL) 792 return B_NO_INIT; 793 if (buffer == NULL) 794 return B_BAD_VALUE; 795 796 tcp_header header; 797 ChainBuffer headerBuffer(&header, sizeof(header), buffer); 798 memset(&header, 0, sizeof(header)); 799 header.source = htons(sourcePort); 800 header.destination = htons(destinationPort); 801 header.seqNumber = htonl(sequenceNumber); 802 header.ackNumber = htonl(acknowledgmentNumber); 803 header.dataOffset = 5; 804 header.flags = flags; 805 header.window = htons(windowSize); 806 807 header.checksum = 0; 808 header.checksum = htons(_ChecksumBuffer(&headerBuffer, 809 fIPService->IPAddress(), destinationAddress, 810 headerBuffer.TotalSize())); 811 812 return fIPService->Send(destinationAddress, IPPROTO_TCP, &headerBuffer); 813 } 814 815 816 void 817 TCPService::ProcessIncomingPackets() 818 { 819 if (fIPService != NULL) 820 fIPService->ProcessIncomingPackets(); 821 } 822 823 824 status_t 825 TCPService::BindSocket(TCPSocket* socket) 826 { 827 if (socket == NULL) 828 return B_BAD_VALUE; 829 830 if (_FindSocket(socket->Address(), socket->Port()) != NULL) 831 return EADDRINUSE; 832 833 return fSockets.Add(socket); 834 } 835 836 837 void 838 TCPService::UnbindSocket(TCPSocket* socket) 839 { 840 fSockets.Remove(socket); 841 } 842 843 844 uint16 845 TCPService::_ChecksumBuffer(ChainBuffer* buffer, ip_addr_t source, 846 ip_addr_t destination, uint16 length) 847 { 848 struct pseudo_header { 849 ip_addr_t source; 850 ip_addr_t destination; 851 uint8 pad; 852 uint8 protocol; 853 uint16 length; 854 } __attribute__ ((__packed__)); 855 pseudo_header header = { 856 htonl(source), 857 htonl(destination), 858 0, 859 IPPROTO_TCP, 860 htons(length) 861 }; 862 863 ChainBuffer headerBuffer(&header, sizeof(header), buffer); 864 uint16 checksum = ip_checksum(&headerBuffer); 865 headerBuffer.DetachNext(); 866 return checksum; 867 } 868 869 870 uint16 871 TCPService::_ChecksumData(const void* data, uint16 length, ip_addr_t source, 872 ip_addr_t destination) 873 { 874 ChainBuffer buffer((void*)data, length); 875 return _ChecksumBuffer(&buffer, source, destination, length); 876 } 877 878 879 TCPSocket* 880 TCPService::_FindSocket(ip_addr_t address, uint16 port) 881 { 882 for (int i = 0; i < fSockets.Count(); i++) { 883 TCPSocket* socket = fSockets.ElementAt(i); 884 // TODO Remove socket->Address() INADDR_ANY check once the socket is 885 // aware of both its IP addresses (local one is INADDR_ANY for now). 886 if ((address == INADDR_ANY || socket->Address() == INADDR_ANY 887 || socket->Address() == address) 888 && socket->Port() == port) { 889 return socket; 890 } 891 } 892 return NULL; 893 } 894