xref: /haiku/src/system/boot/loader/net/TCP.cpp (revision 837b16251d4b2b6249ebcaa19bb319cbe82c6126)
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