1 /*
2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 * Andrew Galante, haiku.galante@gmail.com
8 * Hugo Santos, hugosantos@gmail.com
9 */
10
11
12 #include "EndpointManager.h"
13 #include "TCPEndpoint.h"
14 #include "tcp.h"
15
16 #include <net_protocol.h>
17 #include <net_stat.h>
18
19 #include <KernelExport.h>
20 #include <util/list.h>
21
22 #include <netinet/in.h>
23 #include <netinet/ip.h>
24 #include <new>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <lock.h>
29 #include <util/AutoLock.h>
30
31 #include <NetBufferUtilities.h>
32 #include <NetUtilities.h>
33
34
35 //#define TRACE_TCP
36 #ifdef TRACE_TCP
37 # define TRACE(x) dprintf x
38 #else
39 # define TRACE(x)
40 #endif
41
42
43 typedef NetBufferField<uint16, offsetof(tcp_header, checksum)> TCPChecksumField;
44
45
46 net_buffer_module_info *gBufferModule;
47 net_datalink_module_info *gDatalinkModule;
48 net_socket_module_info *gSocketModule;
49 net_stack_module_info *gStackModule;
50
51
52 static EndpointManager* sEndpointManagers[AF_MAX];
53 static rw_lock sEndpointManagersLock;
54
55
56 // The TCP header length is at most 60 bytes (0xf * 4).
57 static const int kMaxOptionSize = 60 - sizeof(tcp_header);
58
59
60 /*! Returns an endpoint manager for the specified domain, if any.
61 You need to hold the sEndpointManagersLock when calling this function.
62 */
63 static inline EndpointManager*
endpoint_manager_for_locked(int family)64 endpoint_manager_for_locked(int family)
65 {
66 if (family >= AF_MAX || family < 0)
67 return NULL;
68
69 return sEndpointManagers[family];
70 }
71
72
73 /*! Returns an endpoint manager for the specified domain, if any */
74 static inline EndpointManager*
endpoint_manager_for(net_domain * domain)75 endpoint_manager_for(net_domain* domain)
76 {
77 ReadLocker _(sEndpointManagersLock);
78
79 return endpoint_manager_for_locked(domain->family);
80 }
81
82
83 static inline void
bump_option(tcp_option * & option,size_t & length)84 bump_option(tcp_option *&option, size_t &length)
85 {
86 if (option->kind <= TCP_OPTION_NOP) {
87 length++;
88 option = (tcp_option *)((uint8 *)option + 1);
89 } else {
90 length += option->length;
91 option = (tcp_option *)((uint8 *)option + option->length);
92 }
93 }
94
95
96 static inline size_t
add_options(tcp_segment_header & segment,uint8 * buffer,size_t bufferSize)97 add_options(tcp_segment_header &segment, uint8 *buffer, size_t bufferSize)
98 {
99 // Some network devices can be very sensitive to the ordering of TCP options
100 // https://github.com/torvalds/linux/blob/9e9fb7655ed585da8f468e29221f0ba194a5f613/net/ipv4/tcp_output.c#L598
101
102 tcp_option *option = (tcp_option *)buffer;
103 size_t length = 0;
104
105 if (segment.max_segment_size > 0 && length + 8 <= bufferSize) {
106 option->kind = TCP_OPTION_MAX_SEGMENT_SIZE;
107 option->length = 4;
108 option->max_segment_size = htons(segment.max_segment_size);
109 bump_option(option, length);
110 }
111
112 if ((segment.options & TCP_HAS_TIMESTAMPS) != 0
113 && length + 12 <= bufferSize) {
114 if ((segment.options & TCP_SACK_PERMITTED) != 0) {
115 // combine with timestamp
116 option->kind = TCP_OPTION_SACK_PERMITTED;
117 option->length = 2;
118 bump_option(option, length);
119 } else {
120 // two NOPs so the timestamps get aligned to a 4 byte boundary
121 option->kind = TCP_OPTION_NOP;
122 bump_option(option, length);
123 option->kind = TCP_OPTION_NOP;
124 bump_option(option, length);
125 }
126 option->kind = TCP_OPTION_TIMESTAMP;
127 option->length = 10;
128 option->timestamp.value = htonl(segment.timestamp_value);
129 option->timestamp.reply = htonl(segment.timestamp_reply);
130 bump_option(option, length);
131 } else if ((segment.options & TCP_SACK_PERMITTED) != 0
132 && length + 4 <= bufferSize) {
133 // two NOPs so that the subsequent data is aligned on a 4 byte boundary
134 option->kind = TCP_OPTION_NOP;
135 bump_option(option, length);
136 option->kind = TCP_OPTION_NOP;
137 bump_option(option, length);
138 option->kind = TCP_OPTION_SACK_PERMITTED;
139 option->length = 2;
140 bump_option(option, length);
141 }
142
143 if ((segment.options & TCP_HAS_WINDOW_SCALE) != 0
144 && length + 4 <= bufferSize) {
145 // one NOP so that the subsequent data is aligned on a 4 byte boundary
146 option->kind = TCP_OPTION_NOP;
147 bump_option(option, length);
148
149 option->kind = TCP_OPTION_WINDOW_SHIFT;
150 option->length = 3;
151 option->window_shift = segment.window_shift;
152 bump_option(option, length);
153 }
154
155 if (segment.sackCount > 0) {
156 int sackCount = ((int)(bufferSize - length) - 4) / sizeof(tcp_sack);
157 if (sackCount > segment.sackCount)
158 sackCount = segment.sackCount;
159
160 if (sackCount > 0) {
161 option->kind = TCP_OPTION_NOP;
162 bump_option(option, length);
163 option->kind = TCP_OPTION_NOP;
164 bump_option(option, length);
165 option->kind = TCP_OPTION_SACK;
166 option->length = 2 + sackCount * sizeof(tcp_sack);
167 memcpy(option->sack, segment.sacks, sackCount * sizeof(tcp_sack));
168 bump_option(option, length);
169 }
170 }
171
172 if ((length & 3) == 0) {
173 // options completely fill out the option space
174 return length;
175 }
176
177 option->kind = TCP_OPTION_END;
178 return (length + 3) & ~3;
179 // bump to a multiple of 4 length
180 }
181
182
183 static void
process_options(tcp_segment_header & segment,net_buffer * buffer,size_t size)184 process_options(tcp_segment_header &segment, net_buffer *buffer, size_t size)
185 {
186 if (size == 0)
187 return;
188
189 tcp_option *option;
190
191 uint8 optionsBuffer[kMaxOptionSize];
192 if (gBufferModule->direct_access(buffer, sizeof(tcp_header), size,
193 (void **)&option) != B_OK) {
194 if ((size_t)size > sizeof(optionsBuffer)) {
195 dprintf("Ignoring TCP options larger than expected.\n");
196 return;
197 }
198
199 gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size);
200 option = (tcp_option *)optionsBuffer;
201 }
202
203 while (size > 0) {
204 int32 length = -1;
205
206 switch (option->kind) {
207 case TCP_OPTION_END:
208 case TCP_OPTION_NOP:
209 length = 1;
210 break;
211 case TCP_OPTION_MAX_SEGMENT_SIZE:
212 if (option->length == 4 && size >= 4)
213 segment.max_segment_size = ntohs(option->max_segment_size);
214 break;
215 case TCP_OPTION_WINDOW_SHIFT:
216 if (option->length == 3 && size >= 3) {
217 segment.options |= TCP_HAS_WINDOW_SCALE;
218 segment.window_shift = option->window_shift;
219 }
220 break;
221 case TCP_OPTION_TIMESTAMP:
222 if (option->length == 10 && size >= 10) {
223 segment.options |= TCP_HAS_TIMESTAMPS;
224 segment.timestamp_value = ntohl(option->timestamp.value);
225 segment.timestamp_reply =
226 ntohl(option->timestamp.reply);
227 }
228 break;
229 case TCP_OPTION_SACK_PERMITTED:
230 if (option->length == 2 && size >= 2)
231 segment.options |= TCP_SACK_PERMITTED;
232 break;
233 case TCP_OPTION_SACK:
234 if (size >= option->length) {
235 segment.options |= TCP_HAS_SACK;
236 segment.sackCount = min_c((option->length - 2)
237 / sizeof(tcp_sack), MAX_SACK_BLKS);
238 for(int i = 0; i < segment.sackCount; ++i) {
239 segment.sacks[i].left_edge = ntohl(
240 option->sack[i].left_edge);
241 segment.sacks[i].right_edge = ntohl(
242 option->sack[i].right_edge);
243 }
244 }
245 break;
246 }
247
248 if (length < 0) {
249 length = option->length;
250 if (length == 0 || length > (ssize_t)size)
251 break;
252 }
253
254 option = (tcp_option *)((uint8 *)option + length);
255 size -= length;
256 }
257 }
258
259
260 #if 0
261 static void
262 dump_tcp_header(tcp_header &header)
263 {
264 dprintf(" source port: %u\n", ntohs(header.source_port));
265 dprintf(" dest port: %u\n", ntohs(header.destination_port));
266 dprintf(" sequence: %lu\n", header.Sequence());
267 dprintf(" ack: %lu\n", header.Acknowledge());
268 dprintf(" flags: %s%s%s%s%s%s\n", (header.flags & TCP_FLAG_FINISH) ? "FIN " : "",
269 (header.flags & TCP_FLAG_SYNCHRONIZE) ? "SYN " : "",
270 (header.flags & TCP_FLAG_RESET) ? "RST " : "",
271 (header.flags & TCP_FLAG_PUSH) ? "PUSH " : "",
272 (header.flags & TCP_FLAG_ACKNOWLEDGE) ? "ACK " : "",
273 (header.flags & TCP_FLAG_URGENT) ? "URG " : "");
274 dprintf(" window: %u\n", header.AdvertisedWindow());
275 dprintf(" urgent offset: %u\n", header.UrgentOffset());
276 }
277 #endif
278
279
280 static int
dump_endpoints(int argc,char ** argv)281 dump_endpoints(int argc, char** argv)
282 {
283 for (int i = 0; i < AF_MAX; i++) {
284 EndpointManager* manager = sEndpointManagers[i];
285 if (manager != NULL)
286 manager->Dump();
287 }
288
289 return 0;
290 }
291
292
293 static int
dump_endpoint(int argc,char ** argv)294 dump_endpoint(int argc, char** argv)
295 {
296 if (argc < 2) {
297 kprintf("usage: tcp_endpoint [address]\n");
298 return 0;
299 }
300
301 TCPEndpoint* endpoint = (TCPEndpoint*)parse_expression(argv[1]);
302 endpoint->Dump();
303
304 return 0;
305 }
306
307
308 // #pragma mark - internal API
309
310
311 /*! Creates a new endpoint manager for the specified domain, or returns
312 an existing one for this domain.
313 */
314 EndpointManager*
get_endpoint_manager(net_domain * domain)315 get_endpoint_manager(net_domain* domain)
316 {
317 // See if there is one already
318 EndpointManager* endpointManager = endpoint_manager_for(domain);
319 if (endpointManager != NULL)
320 return endpointManager;
321
322 WriteLocker _(sEndpointManagersLock);
323
324 endpointManager = endpoint_manager_for_locked(domain->family);
325 if (endpointManager != NULL)
326 return endpointManager;
327
328 // There is no endpoint manager for this domain yet, so we need
329 // to create one.
330
331 endpointManager = new(std::nothrow) EndpointManager(domain);
332 if (endpointManager == NULL)
333 return NULL;
334
335 if (endpointManager->Init() != B_OK) {
336 delete endpointManager;
337 return NULL;
338 }
339
340 sEndpointManagers[domain->family] = endpointManager;
341 return endpointManager;
342 }
343
344
345 void
put_endpoint_manager(EndpointManager * endpointManager)346 put_endpoint_manager(EndpointManager* endpointManager)
347 {
348 // TODO: we may want to use reference counting instead of only discarding
349 // them on unload. But since there is likely only IPv4/v6 there is not much
350 // point to it.
351 }
352
353
354 const char*
name_for_state(tcp_state state)355 name_for_state(tcp_state state)
356 {
357 switch (state) {
358 case CLOSED:
359 return "closed";
360 case LISTEN:
361 return "listen";
362 case SYNCHRONIZE_SENT:
363 return "syn-sent";
364 case SYNCHRONIZE_RECEIVED:
365 return "syn-received";
366 case ESTABLISHED:
367 return "established";
368
369 // peer closes the connection
370 case FINISH_RECEIVED:
371 return "close-wait";
372 case WAIT_FOR_FINISH_ACKNOWLEDGE:
373 return "last-ack";
374
375 // we close the connection
376 case FINISH_SENT:
377 return "fin-wait1";
378 case FINISH_ACKNOWLEDGED:
379 return "fin-wait2";
380 case CLOSING:
381 return "closing";
382
383 case TIME_WAIT:
384 return "time-wait";
385 }
386
387 return "-";
388 }
389
390
391 /*! Constructs a TCP header on \a buffer with the specified values
392 for \a flags, \a seq \a ack and \a advertisedWindow.
393 */
394 status_t
add_tcp_header(net_address_module_info * addressModule,tcp_segment_header & segment,net_buffer * buffer)395 add_tcp_header(net_address_module_info* addressModule,
396 tcp_segment_header& segment, net_buffer* buffer)
397 {
398 buffer->protocol = IPPROTO_TCP;
399
400 uint8 optionsBuffer[kMaxOptionSize];
401 uint32 optionsLength = add_options(segment, optionsBuffer,
402 sizeof(optionsBuffer));
403
404 NetBufferPrepend<tcp_header> bufferHeader(buffer,
405 sizeof(tcp_header) + optionsLength);
406 if (bufferHeader.Status() != B_OK)
407 return bufferHeader.Status();
408
409 tcp_header& header = bufferHeader.Data();
410
411 header.source_port = addressModule->get_port(buffer->source);
412 header.destination_port = addressModule->get_port(buffer->destination);
413 header.sequence = htonl(segment.sequence);
414 header.acknowledge = (segment.flags & TCP_FLAG_ACKNOWLEDGE)
415 ? htonl(segment.acknowledge) : 0;
416 header.reserved = 0;
417 header.header_length = (sizeof(tcp_header) + optionsLength) >> 2;
418 header.flags = segment.flags;
419 header.advertised_window = htons(segment.advertised_window);
420 header.checksum = 0;
421 header.urgent_offset = htons(segment.urgent_offset);
422
423 // we must detach before calculating the checksum as we may
424 // not have a contiguous buffer.
425 bufferHeader.Sync();
426
427 if (optionsLength > 0) {
428 gBufferModule->write(buffer, sizeof(tcp_header), optionsBuffer,
429 optionsLength);
430 }
431
432 TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %" B_PRIu32 ", ack %" B_PRIu32 ", up %u, "
433 "win %u\n", buffer, segment.flags, segment.sequence,
434 segment.acknowledge, segment.urgent_offset, segment.advertised_window));
435
436 *TCPChecksumField(buffer) = Checksum::PseudoHeader(addressModule,
437 gBufferModule, buffer, IPPROTO_TCP);
438 buffer->buffer_flags |= NET_BUFFER_L4_CHECKSUM_VALID;
439
440 return B_OK;
441 }
442
443
444 size_t
tcp_options_length(tcp_segment_header & segment)445 tcp_options_length(tcp_segment_header& segment)
446 {
447 size_t length = 0;
448
449 if (segment.max_segment_size > 0)
450 length += 4;
451
452 if ((segment.options & TCP_HAS_TIMESTAMPS) != 0)
453 length += 12;
454 else if ((segment.options & TCP_SACK_PERMITTED) != 0)
455 length += 4;
456
457 if ((segment.options & TCP_HAS_WINDOW_SCALE) != 0)
458 length += 4;
459
460 if (segment.sackCount > 0) {
461 int sackCount = min_c((int)((kMaxOptionSize - length - 4)
462 / sizeof(tcp_sack)), segment.sackCount);
463 if (sackCount > 0)
464 length += 4 + sackCount * sizeof(tcp_sack);
465 }
466
467 if ((length & 3) == 0)
468 return length;
469
470 return (length + 3) & ~3;
471 }
472
473
474 // #pragma mark - protocol API
475
476
477 net_protocol*
tcp_init_protocol(net_socket * socket)478 tcp_init_protocol(net_socket* socket)
479 {
480 TCPEndpoint* protocol = new (std::nothrow) TCPEndpoint(socket);
481 if (protocol == NULL)
482 return NULL;
483
484 if (protocol->InitCheck() != B_OK) {
485 delete protocol;
486 return NULL;
487 }
488
489 TRACE(("Creating new TCPEndpoint: %p\n", protocol));
490 socket->protocol = IPPROTO_TCP;
491 return protocol;
492 }
493
494
495 status_t
tcp_uninit_protocol(net_protocol * protocol)496 tcp_uninit_protocol(net_protocol* protocol)
497 {
498 TRACE(("Deleting TCPEndpoint: %p\n", protocol));
499 delete (TCPEndpoint*)protocol;
500 return B_OK;
501 }
502
503
504 status_t
tcp_open(net_protocol * protocol)505 tcp_open(net_protocol* protocol)
506 {
507 return ((TCPEndpoint*)protocol)->Open();
508 }
509
510
511 status_t
tcp_close(net_protocol * protocol)512 tcp_close(net_protocol* protocol)
513 {
514 return ((TCPEndpoint*)protocol)->Close();
515 }
516
517
518 status_t
tcp_free(net_protocol * protocol)519 tcp_free(net_protocol* protocol)
520 {
521 ((TCPEndpoint*)protocol)->Free();
522 return B_OK;
523 }
524
525
526 status_t
tcp_connect(net_protocol * protocol,const struct sockaddr * address)527 tcp_connect(net_protocol* protocol, const struct sockaddr* address)
528 {
529 return ((TCPEndpoint*)protocol)->Connect(address);
530 }
531
532
533 status_t
tcp_accept(net_protocol * protocol,struct net_socket ** _acceptedSocket)534 tcp_accept(net_protocol* protocol, struct net_socket** _acceptedSocket)
535 {
536 return ((TCPEndpoint*)protocol)->Accept(_acceptedSocket);
537 }
538
539
540 status_t
tcp_control(net_protocol * _protocol,int level,int option,void * value,size_t * _length)541 tcp_control(net_protocol* _protocol, int level, int option, void* value,
542 size_t* _length)
543 {
544 TCPEndpoint* protocol = (TCPEndpoint*)_protocol;
545
546 if ((level & LEVEL_MASK) == IPPROTO_TCP) {
547 if (option == NET_STAT_SOCKET)
548 return protocol->FillStat((net_stat*)value);
549 }
550
551 return protocol->next->module->control(protocol->next, level, option,
552 value, _length);
553 }
554
555
556 status_t
tcp_getsockopt(net_protocol * _protocol,int level,int option,void * value,int * _length)557 tcp_getsockopt(net_protocol* _protocol, int level, int option, void* value,
558 int* _length)
559 {
560 TCPEndpoint* protocol = (TCPEndpoint*)_protocol;
561
562 if (level == IPPROTO_TCP)
563 return protocol->GetOption(option, value, _length);
564
565 return protocol->next->module->getsockopt(protocol->next, level, option,
566 value, _length);
567 }
568
569
570 status_t
tcp_setsockopt(net_protocol * _protocol,int level,int option,const void * _value,int length)571 tcp_setsockopt(net_protocol* _protocol, int level, int option,
572 const void* _value, int length)
573 {
574 TCPEndpoint* protocol = (TCPEndpoint*)_protocol;
575
576 if (level == SOL_SOCKET) {
577 if (option == SO_SNDBUF || option == SO_RCVBUF) {
578 if (length != sizeof(int))
579 return B_BAD_VALUE;
580
581 status_t status;
582 const int* value = (const int*)_value;
583
584 if (option == SO_SNDBUF)
585 status = protocol->SetSendBufferSize(*value);
586 else
587 status = protocol->SetReceiveBufferSize(*value);
588
589 if (status < B_OK)
590 return status;
591 }
592 } else if (level == IPPROTO_TCP)
593 return protocol->SetOption(option, _value, length);
594
595 return protocol->next->module->setsockopt(protocol->next, level, option,
596 _value, length);
597 }
598
599
600 status_t
tcp_bind(net_protocol * protocol,const struct sockaddr * address)601 tcp_bind(net_protocol* protocol, const struct sockaddr* address)
602 {
603 return ((TCPEndpoint*)protocol)->Bind(address);
604 }
605
606
607 status_t
tcp_unbind(net_protocol * protocol,struct sockaddr * address)608 tcp_unbind(net_protocol* protocol, struct sockaddr* address)
609 {
610 return ((TCPEndpoint*)protocol)->Unbind(address);
611 }
612
613
614 status_t
tcp_listen(net_protocol * protocol,int count)615 tcp_listen(net_protocol* protocol, int count)
616 {
617 return ((TCPEndpoint*)protocol)->Listen(count);
618 }
619
620
621 status_t
tcp_shutdown(net_protocol * protocol,int direction)622 tcp_shutdown(net_protocol* protocol, int direction)
623 {
624 return ((TCPEndpoint*)protocol)->Shutdown(direction);
625 }
626
627
628 status_t
tcp_send_data(net_protocol * protocol,net_buffer * buffer)629 tcp_send_data(net_protocol* protocol, net_buffer* buffer)
630 {
631 return ((TCPEndpoint*)protocol)->SendData(buffer);
632 }
633
634
635 status_t
tcp_send_routed_data(net_protocol * protocol,struct net_route * route,net_buffer * buffer)636 tcp_send_routed_data(net_protocol* protocol, struct net_route* route,
637 net_buffer* buffer)
638 {
639 // TCP never sends routed data
640 return B_ERROR;
641 }
642
643
644 ssize_t
tcp_send_avail(net_protocol * protocol)645 tcp_send_avail(net_protocol* protocol)
646 {
647 return ((TCPEndpoint*)protocol)->SendAvailable();
648 }
649
650
651 status_t
tcp_read_data(net_protocol * protocol,size_t numBytes,uint32 flags,net_buffer ** _buffer)652 tcp_read_data(net_protocol* protocol, size_t numBytes, uint32 flags,
653 net_buffer** _buffer)
654 {
655 return ((TCPEndpoint*)protocol)->ReadData(numBytes, flags, _buffer);
656 }
657
658
659 ssize_t
tcp_read_avail(net_protocol * protocol)660 tcp_read_avail(net_protocol* protocol)
661 {
662 return ((TCPEndpoint*)protocol)->ReadAvailable();
663 }
664
665
666 struct net_domain*
tcp_get_domain(net_protocol * protocol)667 tcp_get_domain(net_protocol* protocol)
668 {
669 return protocol->next->module->get_domain(protocol->next);
670 }
671
672
673 size_t
tcp_get_mtu(net_protocol * protocol,const struct sockaddr * address)674 tcp_get_mtu(net_protocol* protocol, const struct sockaddr* address)
675 {
676 return protocol->next->module->get_mtu(protocol->next, address);
677 }
678
679
680 status_t
tcp_receive_data(net_buffer * buffer)681 tcp_receive_data(net_buffer* buffer)
682 {
683 TRACE(("TCP: Received buffer %p\n", buffer));
684
685 if (buffer->interface_address == NULL
686 || buffer->interface_address->domain == NULL)
687 return B_ERROR;
688
689 net_domain* domain = buffer->interface_address->domain;
690 net_address_module_info* addressModule = domain->address_module;
691
692 NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
693 if (bufferHeader.Status() < B_OK)
694 return bufferHeader.Status();
695
696 tcp_header& header = bufferHeader.Data();
697
698 uint16 headerLength = header.HeaderLength();
699 if (headerLength < sizeof(tcp_header))
700 return B_BAD_DATA;
701
702 if ((buffer->buffer_flags & NET_BUFFER_L4_CHECKSUM_VALID) == 0) {
703 if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, IPPROTO_TCP) != 0)
704 return B_BAD_DATA;
705 }
706
707 addressModule->set_port(buffer->source, header.source_port);
708 addressModule->set_port(buffer->destination, header.destination_port);
709
710 TRACE((" Looking for: peer %s, local %s\n",
711 AddressString(domain, buffer->source, true).Data(),
712 AddressString(domain, buffer->destination, true).Data()));
713 //dump_tcp_header(header);
714 //gBufferModule->dump(buffer);
715
716 tcp_segment_header segment(header.flags);
717 segment.sequence = header.Sequence();
718 segment.acknowledge = header.Acknowledge();
719 segment.advertised_window = header.AdvertisedWindow();
720 segment.urgent_offset = header.UrgentOffset();
721 process_options(segment, buffer, headerLength - sizeof(tcp_header));
722
723 bufferHeader.Remove(headerLength);
724 // we no longer need to keep the header around
725
726 EndpointManager* endpointManager = endpoint_manager_for(domain);
727 if (endpointManager == NULL) {
728 TRACE((" No endpoint manager!\n"));
729 return B_ERROR;
730 }
731
732 int32 segmentAction = DROP;
733
734 TCPEndpoint* endpoint = endpointManager->FindConnection(
735 buffer->destination, buffer->source);
736 if (endpoint != NULL) {
737 segmentAction = endpoint->SegmentReceived(segment, buffer);
738
739 // There are some states in which the socket could have been deleted
740 // while handling a segment. If this flag is set in segmentAction
741 // then we know the socket has been freed and can skip releasing
742 // the reference acquired in EndpointManager::FindConnection().
743 if ((segmentAction & DELETED_ENDPOINT) == 0)
744 gSocketModule->release_socket(endpoint->socket);
745 } else if ((segment.flags & TCP_FLAG_RESET) == 0)
746 segmentAction = DROP | RESET;
747
748 if ((segmentAction & RESET) != 0) {
749 // send reset
750 endpointManager->ReplyWithReset(segment, buffer);
751 }
752 if ((segmentAction & DROP) != 0)
753 gBufferModule->free(buffer);
754
755 return B_OK;
756 }
757
758
759 status_t
tcp_error_received(net_error error,net_buffer * data)760 tcp_error_received(net_error error, net_buffer* data)
761 {
762 return B_ERROR;
763 }
764
765
766 status_t
tcp_error_reply(net_protocol * protocol,net_buffer * cause,net_error error,net_error_data * errorData)767 tcp_error_reply(net_protocol* protocol, net_buffer* cause, net_error error,
768 net_error_data* errorData)
769 {
770 return B_ERROR;
771 }
772
773
774 // #pragma mark -
775
776
777 static status_t
tcp_init()778 tcp_init()
779 {
780 rw_lock_init(&sEndpointManagersLock, "endpoint managers");
781
782 status_t status = gStackModule->register_domain_protocols(AF_INET,
783 SOCK_STREAM, 0,
784 "network/protocols/tcp/v1",
785 "network/protocols/ipv4/v1",
786 NULL);
787 if (status < B_OK)
788 return status;
789 status = gStackModule->register_domain_protocols(AF_INET6,
790 SOCK_STREAM, 0,
791 "network/protocols/tcp/v1",
792 "network/protocols/ipv6/v1",
793 NULL);
794 if (status < B_OK)
795 return status;
796
797 status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM,
798 IPPROTO_TCP,
799 "network/protocols/tcp/v1",
800 "network/protocols/ipv4/v1",
801 NULL);
802 if (status < B_OK)
803 return status;
804 status = gStackModule->register_domain_protocols(AF_INET6, SOCK_STREAM,
805 IPPROTO_TCP,
806 "network/protocols/tcp/v1",
807 "network/protocols/ipv6/v1",
808 NULL);
809 if (status < B_OK)
810 return status;
811
812 status = gStackModule->register_domain_receiving_protocol(AF_INET,
813 IPPROTO_TCP, "network/protocols/tcp/v1");
814 if (status < B_OK)
815 return status;
816 status = gStackModule->register_domain_receiving_protocol(AF_INET6,
817 IPPROTO_TCP, "network/protocols/tcp/v1");
818 if (status < B_OK)
819 return status;
820
821 add_debugger_command("tcp_endpoints", dump_endpoints,
822 "lists all open TCP endpoints");
823 add_debugger_command("tcp_endpoint", dump_endpoint,
824 "dumps a TCP endpoint internal state");
825
826 return B_OK;
827 }
828
829
830 static status_t
tcp_uninit()831 tcp_uninit()
832 {
833 remove_debugger_command("tcp_endpoint", dump_endpoint);
834 remove_debugger_command("tcp_endpoints", dump_endpoints);
835
836 rw_lock_destroy(&sEndpointManagersLock);
837
838 for (int i = 0; i < AF_MAX; i++) {
839 delete sEndpointManagers[i];
840 }
841
842 return B_OK;
843 }
844
845
846 static status_t
tcp_std_ops(int32 op,...)847 tcp_std_ops(int32 op, ...)
848 {
849 switch (op) {
850 case B_MODULE_INIT:
851 return tcp_init();
852
853 case B_MODULE_UNINIT:
854 return tcp_uninit();
855
856 default:
857 return B_ERROR;
858 }
859 }
860
861
862 net_protocol_module_info sTCPModule = {
863 {
864 "network/protocols/tcp/v1",
865 0,
866 tcp_std_ops
867 },
868 0,
869
870 tcp_init_protocol,
871 tcp_uninit_protocol,
872 tcp_open,
873 tcp_close,
874 tcp_free,
875 tcp_connect,
876 tcp_accept,
877 tcp_control,
878 tcp_getsockopt,
879 tcp_setsockopt,
880 tcp_bind,
881 tcp_unbind,
882 tcp_listen,
883 tcp_shutdown,
884 tcp_send_data,
885 tcp_send_routed_data,
886 tcp_send_avail,
887 tcp_read_data,
888 tcp_read_avail,
889 tcp_get_domain,
890 tcp_get_mtu,
891 tcp_receive_data,
892 NULL, // deliver_data()
893 tcp_error_received,
894 tcp_error_reply,
895 NULL, // add_ancillary_data()
896 NULL, // process_ancillary_data()
897 NULL, // process_ancillary_data_no_container()
898 NULL, // send_data_no_buffer()
899 NULL // read_data_no_buffer()
900 };
901
902 module_dependency module_dependencies[] = {
903 {NET_STACK_MODULE_NAME, (module_info **)&gStackModule},
904 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
905 {NET_DATALINK_MODULE_NAME, (module_info **)&gDatalinkModule},
906 {NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule},
907 {}
908 };
909
910 module_info *modules[] = {
911 (module_info *)&sTCPModule,
912 NULL
913 };
914