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
_rand32(void)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
_rand14(void)72 _rand14(void)
73 {
74 // TODO: Find suitable generator polynomial.
75 return _rand32() & 0x3fff;
76 }
77
78
TCPPacket()79 TCPPacket::TCPPacket()
80 :
81 fData(NULL),
82 fNext(NULL)
83 {
84 }
85
86
~TCPPacket()87 TCPPacket::~TCPPacket()
88 {
89 free(fData);
90 }
91
92
93 status_t
SetTo(const void * data,size_t size,ip_addr_t sourceAddress,uint16 sourcePort,ip_addr_t destinationAddress,uint16 destinationPort,uint32 sequenceNumber,uint32 acknowledgmentNumber,uint8 flags)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
SourceAddress() const123 TCPPacket::SourceAddress() const
124 {
125 return fSourceAddress;
126 }
127
128
129 ip_addr_t
DestinationAddress() const130 TCPPacket::DestinationAddress() const
131 {
132 return fDestinationAddress;
133 }
134
135
136 uint16
SourcePort() const137 TCPPacket::SourcePort() const
138 {
139 return fSourcePort;
140 }
141
142
143 uint16
DestinationPort() const144 TCPPacket::DestinationPort() const
145 {
146 return fDestinationPort;
147 }
148
149
150 uint32
SequenceNumber() const151 TCPPacket::SequenceNumber() const
152 {
153 return fSequenceNumber;
154 }
155
156
157 uint32
AcknowledgmentNumber() const158 TCPPacket::AcknowledgmentNumber() const
159 {
160 return fAcknowledgmentNumber;
161 }
162
163
164 bool
ProvidesSequenceNumber(uint32 sequenceNumber) const165 TCPPacket::ProvidesSequenceNumber(uint32 sequenceNumber) const
166 {
167 // TODO PAWS
168 return fSequenceNumber <= sequenceNumber
169 && fSequenceNumber + fSize > sequenceNumber;
170 }
171
172
173 TCPPacket*
Next() const174 TCPPacket::Next() const
175 {
176 return fNext;
177 }
178
179
180 void
SetNext(TCPPacket * packet)181 TCPPacket::SetNext(TCPPacket* packet)
182 {
183 fNext = packet;
184 }
185
186
187
188
TCPSocket()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
~TCPSocket()205 TCPSocket::~TCPSocket()
206 {
207 if (fTCPService != NULL && fPort != 0)
208 fTCPService->UnbindSocket(this);
209 }
210
211
212 uint16
WindowSize() const213 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
Connect(ip_addr_t address,uint16 port)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
Close()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
Read(void * buffer,size_t bufferSize,size_t * bytesRead,bigtime_t timeout)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
Write(const void * buffer,size_t bufferSize)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
Acknowledge(uint32 number)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
ProcessPacket(TCPPacket * packet)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*
_PeekPacket()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*
_DequeuePacket()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
_Send(TCPPacket * packet,bool enqueue)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
_ResendQueue()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
_EnqueueOutgoingPacket(TCPPacket * packet)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
_DumpQueue()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
_Ack()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
_WaitForState(TCPSocketState state,bigtime_t timeout)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
TCPService(IPService * ipService)674 TCPService::TCPService(IPService* ipService)
675 :
676 IPSubService(kTCPServiceName),
677 fIPService(ipService)
678 {
679 }
680
681
~TCPService()682 TCPService::~TCPService()
683 {
684 if (fIPService != NULL)
685 fIPService->UnregisterIPSubService(this);
686 }
687
688
689 status_t
Init()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
IPProtocol() const703 TCPService::IPProtocol() const
704 {
705 return IPPROTO_TCP;
706 }
707
708
709 void
HandleIPPacket(IPService * ipService,ip_addr_t sourceIP,ip_addr_t destinationIP,const void * data,size_t size)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
Send(uint16 sourcePort,ip_addr_t destinationAddress,uint16 destinationPort,uint32 sequenceNumber,uint32 acknowledgmentNumber,uint8 flags,uint16 windowSize,ChainBuffer * buffer)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
ProcessIncomingPackets()817 TCPService::ProcessIncomingPackets()
818 {
819 if (fIPService != NULL)
820 fIPService->ProcessIncomingPackets();
821 }
822
823
824 status_t
BindSocket(TCPSocket * socket)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
UnbindSocket(TCPSocket * socket)838 TCPService::UnbindSocket(TCPSocket* socket)
839 {
840 fSockets.Remove(socket);
841 }
842
843
844 uint16
_ChecksumBuffer(ChainBuffer * buffer,ip_addr_t source,ip_addr_t destination,uint16 length)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
_ChecksumData(const void * data,uint16 length,ip_addr_t source,ip_addr_t destination)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*
_FindSocket(ip_addr_t address,uint16 port)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