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 58static 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 71static unsigned short 72_rand14(void) 73{ 74 // TODO: Find suitable generator polynomial. 75 return _rand32() & 0x3fff; 76} 77 78 79TCPPacket::TCPPacket() 80 : 81 fData(NULL), 82 fNext(NULL) 83{ 84} 85 86 87TCPPacket::~TCPPacket() 88{ 89 free(fData); 90} 91 92 93status_t 94TCPPacket::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 122ip_addr_t 123TCPPacket::SourceAddress() const 124{ 125 return fSourceAddress; 126} 127 128 129ip_addr_t 130TCPPacket::DestinationAddress() const 131{ 132 return fDestinationAddress; 133} 134 135 136uint16 137TCPPacket::SourcePort() const 138{ 139 return fSourcePort; 140} 141 142 143uint16 144TCPPacket::DestinationPort() const 145{ 146 return fDestinationPort; 147} 148 149 150uint32 151TCPPacket::SequenceNumber() const 152{ 153 return fSequenceNumber; 154} 155 156 157uint32 158TCPPacket::AcknowledgmentNumber() const 159{ 160 return fAcknowledgmentNumber; 161} 162 163 164bool 165TCPPacket::ProvidesSequenceNumber(uint32 sequenceNumber) const 166{ 167 // TODO PAWS 168 return fSequenceNumber <= sequenceNumber 169 && fSequenceNumber + fSize > sequenceNumber; 170} 171 172 173TCPPacket* 174TCPPacket::Next() const 175{ 176 return fNext; 177} 178 179 180void 181TCPPacket::SetNext(TCPPacket* packet) 182{ 183 fNext = packet; 184} 185 186 187 188 189TCPSocket::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 205TCPSocket::~TCPSocket() 206{ 207 if (fTCPService != NULL && fPort != 0) 208 fTCPService->UnbindSocket(this); 209} 210 211 212uint16 213TCPSocket::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 230status_t 231TCPSocket::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 274status_t 275TCPSocket::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 301status_t 302TCPSocket::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 381status_t 382TCPSocket::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 403void 404TCPSocket::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 419void 420TCPSocket::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 514TCPPacket* 515TCPSocket::_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 527TCPPacket* 528TCPSocket::_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 565status_t 566TCPSocket::_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 584status_t 585TCPSocket::_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 601void 602TCPSocket::_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 615inline void 616TCPSocket::_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 636status_t 637TCPSocket::_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 656status_t 657TCPSocket::_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 674TCPService::TCPService(IPService* ipService) 675 : 676 IPSubService(kTCPServiceName), 677 fIPService(ipService) 678{ 679} 680 681 682TCPService::~TCPService() 683{ 684 if (fIPService != NULL) 685 fIPService->UnregisterIPSubService(this); 686} 687 688 689status_t 690TCPService::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 702uint8 703TCPService::IPProtocol() const 704{ 705 return IPPROTO_TCP; 706} 707 708 709void 710TCPService::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 783status_t 784TCPService::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 816void 817TCPService::ProcessIncomingPackets() 818{ 819 if (fIPService != NULL) 820 fIPService->ProcessIncomingPackets(); 821} 822 823 824status_t 825TCPService::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 837void 838TCPService::UnbindSocket(TCPSocket* socket) 839{ 840 fSockets.Remove(socket); 841} 842 843 844uint16 845TCPService::_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 870uint16 871TCPService::_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 879TCPSocket* 880TCPService::_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