1 /*
2 * Copyright 2006-2023, 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 */
8
9
10 #include "argv.h"
11 #include "tcp.h"
12 #include "pcap.h"
13 #include "utility.h"
14
15 #include <AutoDeleter.h>
16 #include <NetBufferUtilities.h>
17 #include <Referenceable.h>
18 #include <net_buffer.h>
19 #include <net_datalink.h>
20 #include <net_protocol.h>
21 #include <net_socket.h>
22 #include <net_stack.h>
23 #include <slab/Slab.h>
24 #include <util/AutoLock.h>
25 #include <util/DoublyLinkedList.h>
26
27 #include <KernelExport.h>
28 #include <Select.h>
29 #include <module.h>
30 #include <Locker.h>
31
32 #include <netinet/in.h>
33 #include <netinet/ip.h>
34
35 #include <ctype.h>
36 #include <errno.h>
37 #include <new>
38 #include <set>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43
44 struct context {
45 BLocker lock;
46 sem_id wait_sem;
47 struct list list;
48 net_route route;
49 bool server;
50 thread_id thread;
51 };
52
53 struct cmd_entry {
54 const char* name;
55 void (*func)(int argc, char **argv);
56 const char* help;
57 };
58
59
60 struct net_socket_private;
61 typedef DoublyLinkedList<net_socket_private> SocketList;
62
63 struct net_socket_private : net_socket,
64 DoublyLinkedListLinkImpl<net_socket_private> {
65 struct net_socket *parent;
66
67 team_id owner;
68 uint32 max_backlog;
69 uint32 child_count;
70 SocketList pending_children;
71 SocketList connected_children;
72
73 struct select_sync_pool *select_pool;
74 mutex lock;
75 };
76
77
78 struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>,
79 net_interface_address, BReferenceable {
80 };
81
82
83 extern "C" status_t _add_builtin_module(module_info *info);
84 extern "C" status_t _get_builtin_dependencies(void);
85 extern bool gDebugOutputEnabled;
86 // from libkernelland_emu.so
87
88 extern struct net_buffer_module_info gNetBufferModule;
89 // from net_buffer.cpp
90 extern net_address_module_info gIPv4AddressModule;
91 // from ipv4_address.cpp
92 extern module_info *modules[];
93 // from tcp.cpp
94
95
96 extern struct net_protocol_module_info gDomainModule;
97 struct InterfaceAddress gInterfaceAddress;
98 extern struct net_socket_module_info gNetSocketModule;
99 struct net_protocol_module_info *gTCPModule;
100 struct net_socket *gServerSocket, *gClientSocket;
101 static struct context sClientContext, sServerContext;
102
103 static int32 sPacketNumber = 1;
104 static double sRandomDrop = 0.0;
105 static std::set<uint32> sDropList;
106 static bigtime_t sRoundTripTime = 0;
107 static bool sIncreasingRoundTrip = false;
108 static bool sRandomRoundTrip = false;
109 static void (*sPacketMonitor)(net_buffer *, int32, bool) = NULL;
110 static int sPcapFD = -1;
111 static bigtime_t sStartTime;
112 static double sRandomReorder = 0.0;
113 static std::set<uint32> sReorderList;
114 static bool sSimultaneousConnect = false;
115 static bool sSimultaneousClose = false;
116 static bool sServerActiveClose = false;
117
118 static struct net_domain sDomain = {
119 "ipv4",
120 AF_INET,
121
122 &gDomainModule,
123 &gIPv4AddressModule
124 };
125
126
127 static bool
is_server(const sockaddr * addr)128 is_server(const sockaddr* addr)
129 {
130 return ((sockaddr_in*)addr)->sin_port == htons(1024);
131 }
132
133
134 static uint8
tcp_segment_flags(net_buffer * buffer)135 tcp_segment_flags(net_buffer* buffer)
136 {
137 NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
138 if (bufferHeader.Status() < B_OK)
139 return bufferHeader.Status();
140
141 tcp_header &header = bufferHeader.Data();
142 return header.flags;
143 }
144
145
146 static bool
is_syn(net_buffer * buffer)147 is_syn(net_buffer* buffer)
148 {
149 return (tcp_segment_flags(buffer) & TCP_FLAG_SYNCHRONIZE) != 0;
150 }
151
152
153 static bool
is_fin(net_buffer * buffer)154 is_fin(net_buffer* buffer)
155 {
156 return (tcp_segment_flags(buffer) & TCP_FLAG_FINISH) != 0;
157 }
158
159
160 // #pragma mark - stack
161
162
163 status_t
std_ops(int32,...)164 std_ops(int32, ...)
165 {
166 return B_OK;
167 }
168
169
170 net_domain *
get_domain(int family)171 get_domain(int family)
172 {
173 return &sDomain;
174 }
175
176
177 status_t
register_domain_protocols(int family,int type,int protocol,...)178 register_domain_protocols(int family, int type, int protocol, ...)
179 {
180 return B_OK;
181 }
182
183
184 status_t
register_domain_datalink_protocols(int family,int type,...)185 register_domain_datalink_protocols(int family, int type, ...)
186 {
187 return B_OK;
188 }
189
190
191 static status_t
register_domain_receiving_protocol(int family,int type,const char * moduleName)192 register_domain_receiving_protocol(int family, int type, const char *moduleName)
193 {
194 return B_OK;
195 }
196
197
198 static bool
dummy_is_syscall(void)199 dummy_is_syscall(void)
200 {
201 return false;
202 }
203
204
205 static bool
dummy_is_restarted_syscall(void)206 dummy_is_restarted_syscall(void)
207 {
208 return false;
209 }
210
211
212 static void
dummy_store_syscall_restart_timeout(bigtime_t timeout)213 dummy_store_syscall_restart_timeout(bigtime_t timeout)
214 {
215 }
216
217
218 static net_stack_module_info gNetStackModule = {
219 {
220 NET_STACK_MODULE_NAME,
221 0,
222 std_ops
223 },
224 NULL, // register_domain,
225 NULL, // unregister_domain,
226 get_domain,
227
228 register_domain_protocols,
229 register_domain_datalink_protocols,
230 register_domain_receiving_protocol,
231
232 NULL, // get_domain_receiving_protocol,
233 NULL, // put_domain_receiving_protocol,
234
235 NULL, // register_device_deframer,
236 NULL, // unregister_device_deframer,
237 NULL, // register_domain_device_handler,
238 NULL, // register_device_handler,
239 NULL, // unregister_device_handler,
240 NULL, // register_device_monitor,
241 NULL, // unregister_device_monitor,
242 NULL, // device_link_changed,
243 NULL, // device_removed,
244 NULL, // device_enqueue_buffer,
245
246 notify_socket,
247
248 checksum,
249
250 init_fifo,
251 uninit_fifo,
252 fifo_enqueue_buffer,
253 fifo_dequeue_buffer,
254 clear_fifo,
255 fifo_socket_enqueue_buffer,
256
257 init_timer,
258 set_timer,
259 cancel_timer,
260 wait_for_timer,
261 is_timer_active,
262 is_timer_running,
263
264 dummy_is_syscall,
265 dummy_is_restarted_syscall,
266 dummy_store_syscall_restart_timeout,
267 NULL, // restore_syscall_restart_timeout
268
269 // ancillary data is not used by TCP
270 };
271
272
273 // #pragma mark - socket
274
275
276 status_t
socket_create(int family,int type,int protocol,net_socket ** _socket)277 socket_create(int family, int type, int protocol, net_socket **_socket)
278 {
279 net_protocol* domainProtocol;
280
281 struct net_socket_private *socket = new (std::nothrow) net_socket_private;
282 if (socket == NULL)
283 return B_NO_MEMORY;
284
285 memset(socket, 0, sizeof(net_socket));
286 socket->family = family;
287 socket->type = type;
288 socket->protocol = protocol;
289
290 mutex_init(&socket->lock, "socket");
291
292 // set defaults (may be overridden by the protocols)
293 socket->send.buffer_size = 65535;
294 socket->send.low_water_mark = 1;
295 socket->send.timeout = B_INFINITE_TIMEOUT;
296 socket->receive.buffer_size = 65535;
297 socket->receive.low_water_mark = 1;
298 socket->receive.timeout = B_INFINITE_TIMEOUT;
299
300 socket->first_protocol = gTCPModule->init_protocol(socket);
301 if (socket->first_protocol == NULL) {
302 fprintf(stderr, "tcp_tester: cannot create protocol\n");
303 mutex_destroy(&socket->lock);
304 delete socket;
305 return B_ERROR;
306 }
307
308 socket->first_info = gTCPModule;
309
310 domainProtocol = new net_protocol;
311 domainProtocol->module = &gDomainModule;
312 domainProtocol->socket = socket;
313
314 socket->first_protocol->next = domainProtocol;
315 socket->first_protocol->module = gTCPModule;
316 socket->first_protocol->socket = socket;
317
318 *_socket = socket;
319 return B_OK;
320 }
321
322
323 void
socket_delete(net_socket * _socket)324 socket_delete(net_socket *_socket)
325 {
326 net_socket_private *socket = (net_socket_private *)_socket;
327
328 if (socket->parent != NULL)
329 panic("socket still has a parent!");
330
331 socket->first_info->uninit_protocol(socket->first_protocol);
332 mutex_destroy(&socket->lock);
333 delete socket;
334 }
335
336
337 int
socket_accept(net_socket * socket,struct sockaddr * address,socklen_t * _addressLength,net_socket ** _acceptedSocket)338 socket_accept(net_socket *socket, struct sockaddr *address,
339 socklen_t *_addressLength, net_socket **_acceptedSocket)
340 {
341 net_socket *accepted;
342 status_t status = socket->first_info->accept(socket->first_protocol,
343 &accepted);
344 if (status < B_OK)
345 return status;
346
347 if (address && *_addressLength > 0) {
348 memcpy(address, &accepted->peer, min_c(*_addressLength,
349 accepted->peer.ss_len));
350 *_addressLength = accepted->peer.ss_len;
351 }
352
353 *_acceptedSocket = accepted;
354 return B_OK;
355 }
356
357
358 int
socket_bind(net_socket * socket,const struct sockaddr * address,socklen_t addressLength)359 socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength)
360 {
361 sockaddr empty;
362 if (address == NULL) {
363 // special - try to bind to an empty address, like INADDR_ANY
364 memset(&empty, 0, sizeof(sockaddr));
365 empty.sa_len = sizeof(sockaddr);
366 empty.sa_family = socket->family;
367
368 address = ∅
369 addressLength = sizeof(sockaddr);
370 }
371
372 if (socket->address.ss_len != 0) {
373 status_t status = socket->first_info->unbind(socket->first_protocol,
374 (sockaddr *)&socket->address);
375 if (status < B_OK)
376 return status;
377 }
378
379 memcpy(&socket->address, address, sizeof(sockaddr));
380
381 status_t status = socket->first_info->bind(socket->first_protocol,
382 (sockaddr *)address);
383 if (status < B_OK) {
384 // clear address again, as binding failed
385 socket->address.ss_len = 0;
386 }
387
388 return status;
389 }
390
391
392 int
socket_connect(net_socket * socket,const struct sockaddr * address,socklen_t addressLength)393 socket_connect(net_socket *socket, const struct sockaddr *address, socklen_t addressLength)
394 {
395 if (address == NULL || addressLength == 0)
396 return ENETUNREACH;
397
398 if (socket->address.ss_len == 0) {
399 // try to bind first
400 status_t status = socket_bind(socket, NULL, 0);
401 if (status < B_OK)
402 return status;
403 }
404
405 return socket->first_info->connect(socket->first_protocol, address);
406 }
407
408
409 int
socket_listen(net_socket * socket,int backlog)410 socket_listen(net_socket *socket, int backlog)
411 {
412 status_t status = socket->first_info->listen(socket->first_protocol, backlog);
413 if (status == B_OK)
414 socket->options |= SO_ACCEPTCONN;
415
416 return status;
417 }
418
419
420 ssize_t
socket_send(net_socket * socket,const void * data,size_t length,int flags)421 socket_send(net_socket *socket, const void *data, size_t length, int flags)
422 {
423 if (socket->peer.ss_len == 0)
424 return EDESTADDRREQ;
425
426 if (socket->address.ss_len == 0) {
427 // try to bind first
428 status_t status = socket_bind(socket, NULL, 0);
429 if (status < B_OK)
430 return status;
431 }
432
433 // TODO: useful, maybe even computed header space!
434 net_buffer *buffer = gNetBufferModule.create(256);
435 if (buffer == NULL)
436 return ENOBUFS;
437
438 // copy data into buffer
439 if (gNetBufferModule.append(buffer, data, length) < B_OK) {
440 gNetBufferModule.free(buffer);
441 return ENOBUFS;
442 }
443
444 buffer->msg_flags = flags;
445 memcpy(buffer->source, &socket->address, socket->address.ss_len);
446 memcpy(buffer->destination, &socket->peer, socket->peer.ss_len);
447
448 status_t status = socket->first_info->send_data(socket->first_protocol, buffer);
449 if (status < B_OK) {
450 gNetBufferModule.free(buffer);
451 return status;
452 }
453
454 return length;
455 }
456
457
458 ssize_t
socket_recv(net_socket * socket,void * data,size_t length,int flags)459 socket_recv(net_socket *socket, void *data, size_t length, int flags)
460 {
461 net_buffer *buffer;
462 ssize_t status = socket->first_info->read_data(
463 socket->first_protocol, length, flags, &buffer);
464 if (status < B_OK)
465 return status;
466
467 // if 0 bytes we're received, no buffer will be created
468 if (buffer == NULL)
469 return 0;
470
471 ssize_t bytesReceived = buffer->size;
472 gNetBufferModule.read(buffer, 0, data, bytesReceived);
473 gNetBufferModule.free(buffer);
474
475 return bytesReceived;
476 }
477
478
479 bool
socket_acquire(net_socket * _socket)480 socket_acquire(net_socket* _socket)
481 {
482 return true;
483 }
484
485
486 bool
socket_release(net_socket * _socket)487 socket_release(net_socket* _socket)
488 {
489 return true;
490 }
491
492
493 status_t
socket_spawn_pending(net_socket * _parent,net_socket ** _socket)494 socket_spawn_pending(net_socket *_parent, net_socket **_socket)
495 {
496 net_socket_private *parent = (net_socket_private *)_parent;
497
498 MutexLocker locker(parent->lock);
499
500 // We actually accept more pending connections to compensate for those
501 // that never complete, and also make sure at least a single connection
502 // can always be accepted
503 if (parent->child_count > 3 * parent->max_backlog / 2)
504 return ENOBUFS;
505
506 net_socket_private *socket;
507 status_t status = socket_create(parent->family, parent->type, parent->protocol,
508 (net_socket **)&socket);
509 if (status < B_OK)
510 return status;
511
512 // inherit parent's properties
513 socket->send = parent->send;
514 socket->receive = parent->receive;
515 socket->options = parent->options & ~SO_ACCEPTCONN;
516 socket->linger = parent->linger;
517 memcpy(&socket->address, &parent->address, parent->address.ss_len);
518 memcpy(&socket->peer, &parent->peer, parent->peer.ss_len);
519
520 // add to the parent's list of pending connections
521 parent->pending_children.Add(socket);
522 socket->parent = parent;
523 parent->child_count++;
524
525 *_socket = socket;
526 return B_OK;
527 }
528
529
530 status_t
socket_dequeue_connected(net_socket * _parent,net_socket ** _socket)531 socket_dequeue_connected(net_socket *_parent, net_socket **_socket)
532 {
533 net_socket_private *parent = (net_socket_private *)_parent;
534
535 mutex_lock(&parent->lock);
536
537 net_socket_private *socket = parent->connected_children.RemoveHead();
538 if (socket != NULL) {
539 socket->parent = NULL;
540 parent->child_count--;
541 *_socket = socket;
542 }
543
544 mutex_unlock(&parent->lock);
545 return socket != NULL ? B_OK : B_ENTRY_NOT_FOUND;
546 }
547
548
549 ssize_t
socket_count_connected(net_socket * _parent)550 socket_count_connected(net_socket *_parent)
551 {
552 net_socket_private *parent = (net_socket_private *)_parent;
553
554 MutexLocker _(parent->lock);
555
556 return parent->connected_children.Count();
557 }
558
559
560 status_t
socket_set_max_backlog(net_socket * _socket,uint32 backlog)561 socket_set_max_backlog(net_socket *_socket, uint32 backlog)
562 {
563 net_socket_private *socket = (net_socket_private *)_socket;
564
565 // we enforce an upper limit of connections waiting to be accepted
566 if (backlog > 256)
567 backlog = 256;
568
569 mutex_lock(&socket->lock);
570
571 // first remove the pending connections, then the already connected ones as needed
572 net_socket_private *child;
573 while (socket->child_count > backlog
574 && (child = socket->pending_children.RemoveTail()) != NULL) {
575 child->parent = NULL;
576 socket->child_count--;
577 }
578 while (socket->child_count > backlog
579 && (child = socket->connected_children.RemoveTail()) != NULL) {
580 child->parent = NULL;
581 socket_delete(child);
582 socket->child_count--;
583 }
584
585 socket->max_backlog = backlog;
586 mutex_unlock(&socket->lock);
587 return B_OK;
588 }
589
590
591 bool
socket_has_parent(net_socket * _socket)592 socket_has_parent(net_socket* _socket)
593 {
594 net_socket_private* socket = (net_socket_private*)_socket;
595 return socket->parent != NULL;
596 }
597
598
599 status_t
socket_connected(net_socket * socket)600 socket_connected(net_socket *socket)
601 {
602 net_socket_private *socket_private = (net_socket_private *)socket;
603 net_socket_private *parent = (net_socket_private *)socket_private->parent;
604 if (parent == NULL)
605 return B_BAD_VALUE;
606
607 mutex_lock(&parent->lock);
608
609 parent->pending_children.Remove(socket_private);
610 parent->connected_children.Add(socket_private);
611
612 mutex_unlock(&parent->lock);
613 return B_OK;
614 }
615
616
617 status_t
socket_notify(net_socket * _socket,uint8 event,int32 value)618 socket_notify(net_socket *_socket, uint8 event, int32 value)
619 {
620 net_socket_private *socket = (net_socket_private *)_socket;
621
622 mutex_lock(&socket->lock);
623
624 bool notify = true;
625
626 switch (event) {
627 case B_SELECT_READ:
628 {
629 if ((ssize_t)socket->receive.low_water_mark > value && value >= B_OK)
630 notify = false;
631 break;
632 }
633 case B_SELECT_WRITE:
634 {
635 if ((ssize_t)socket->send.low_water_mark > value && value >= B_OK)
636 notify = false;
637 break;
638 }
639 case B_SELECT_ERROR:
640 socket->error = value;
641 break;
642 }
643
644 if (notify)
645 ;
646
647 mutex_unlock(&socket->lock);
648 return B_OK;
649 }
650
651
652 net_socket_module_info gNetSocketModule = {
653 {
654 NET_SOCKET_MODULE_NAME,
655 0,
656 std_ops
657 },
658 NULL, // open,
659 NULL, // close,
660 NULL, // free,
661
662 NULL, // control,
663
664 NULL, // read_avail,
665 NULL, // send_avail,
666
667 NULL, // send_data,
668 NULL, // receive_data,
669
670 NULL, // get_option,
671 NULL, // set_option,
672 NULL, // get_next_stat,
673
674 socket_acquire,
675 socket_release,
676
677 // connections
678 socket_spawn_pending,
679 socket_dequeue_connected,
680 socket_count_connected,
681 socket_set_max_backlog,
682 socket_has_parent,
683 socket_connected,
684 NULL, // set_aborted
685
686 // notifications
687 NULL, // request_notification,
688 NULL, // cancel_notification,
689 socket_notify,
690
691 // standard socket API
692 NULL, // accept,
693 NULL, // bind,
694 NULL, // connect,
695 NULL, // getpeername,
696 NULL, // getsockname,
697 NULL, // getsockopt,
698 NULL, // listen,
699 NULL, // receive,
700 NULL, // send,
701 NULL, // setsockopt,
702 NULL, // shutdown,
703 NULL, // socketpair
704 };
705
706
707 // #pragma mark - protocol
708
709
710 net_protocol*
init_protocol(net_socket ** _socket)711 init_protocol(net_socket** _socket)
712 {
713 net_socket *socket;
714 status_t status = socket_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &socket);
715 if (status < B_OK)
716 return NULL;
717
718 status = socket->first_info->open(socket->first_protocol);
719 if (status < B_OK) {
720 fprintf(stderr, "tcp_tester: cannot open client: %s\n", strerror(status));
721 socket_delete(socket);
722 return NULL;
723 }
724
725 *_socket = socket;
726 return socket->first_protocol;
727 }
728
729
730 void
close_protocol(net_protocol * protocol)731 close_protocol(net_protocol* protocol)
732 {
733 gTCPModule->close(protocol);
734 if (gTCPModule->free(protocol) == B_OK)
735 gTCPModule->uninit_protocol(protocol);
736 //socket_delete(protocol->socket);
737 }
738
739
740 // #pragma mark - datalink
741
742
743 status_t
datalink_send_data(struct net_route * route,net_buffer * buffer)744 datalink_send_data(struct net_route *route, net_buffer *buffer)
745 {
746 struct context* context = (struct context*)route->gateway;
747
748 buffer->interface_address = &gInterfaceAddress;
749 gInterfaceAddress.AcquireReference();
750
751 context->lock.Lock();
752 list_add_item(&context->list, buffer);
753 context->lock.Unlock();
754
755 release_sem(context->wait_sem);
756 return B_OK;
757 }
758
759
760 status_t
datalink_send_datagram(net_protocol * protocol,net_domain * domain,net_buffer * buffer)761 datalink_send_datagram(net_protocol *protocol, net_domain *domain,
762 net_buffer *buffer)
763 {
764 panic("called");
765 return B_ERROR;
766 }
767
768
769 struct net_route *
get_route(struct net_domain * _domain,const struct sockaddr * address)770 get_route(struct net_domain *_domain, const struct sockaddr *address)
771 {
772 if (is_server(address)) {
773 // to the server
774 return &sServerContext.route;
775 }
776
777 return &sClientContext.route;
778 }
779
780
781 static void
put_route(struct net_domain * _domain,net_route * route)782 put_route(struct net_domain* _domain, net_route* route)
783 {
784 }
785
786
787 net_datalink_module_info gNetDatalinkModule = {
788 {
789 NET_DATALINK_MODULE_NAME,
790 0,
791 std_ops
792 },
793
794 NULL, // control
795 datalink_send_data,
796 datalink_send_datagram,
797
798 NULL, // is_local_address
799 NULL, // is_local_link_address
800
801 NULL, // get_interface
802 NULL, // get_interface_with_address
803 NULL, // put_interface
804
805 NULL, // get_interface_address
806 NULL, // get_next_interface_address,
807 NULL, // put_interface_address
808
809 NULL, // join_multicast
810 NULL, // leave_multicast
811
812 NULL, // add_route,
813 NULL, // remove_route,
814 get_route,
815 NULL, // get_buffer_route
816 put_route,
817 NULL, // register_route_info,
818 NULL, // unregister_route_info,
819 NULL, // update_route_info
820 };
821
822
823 // #pragma mark - domain
824
825
826 status_t
domain_open(net_protocol * protocol)827 domain_open(net_protocol *protocol)
828 {
829 return B_OK;
830 }
831
832
833 status_t
domain_close(net_protocol * protocol)834 domain_close(net_protocol *protocol)
835 {
836 return B_OK;
837 }
838
839
840 status_t
domain_free(net_protocol * protocol)841 domain_free(net_protocol *protocol)
842 {
843 return B_OK;
844 }
845
846
847 status_t
domain_connect(net_protocol * protocol,const struct sockaddr * address)848 domain_connect(net_protocol *protocol, const struct sockaddr *address)
849 {
850 return B_ERROR;
851 }
852
853
854 status_t
domain_accept(net_protocol * protocol,struct net_socket ** _acceptedSocket)855 domain_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
856 {
857 return EOPNOTSUPP;
858 }
859
860
861 status_t
domain_control(net_protocol * protocol,int level,int option,void * value,size_t * _length)862 domain_control(net_protocol *protocol, int level, int option, void *value,
863 size_t *_length)
864 {
865 return B_ERROR;
866 }
867
868
869 status_t
domain_bind(net_protocol * protocol,const struct sockaddr * address)870 domain_bind(net_protocol *protocol, const struct sockaddr *address)
871 {
872 memcpy(&protocol->socket->address, address, sizeof(struct sockaddr_in));
873 protocol->socket->address.ss_len = sizeof(struct sockaddr_in);
874 // explicitly set length, as our callers can't be trusted to
875 // always provide the correct length!
876 return B_OK;
877 }
878
879
880 status_t
domain_unbind(net_protocol * protocol,struct sockaddr * address)881 domain_unbind(net_protocol *protocol, struct sockaddr *address)
882 {
883 return B_OK;
884 }
885
886
887 status_t
domain_listen(net_protocol * protocol,int count)888 domain_listen(net_protocol *protocol, int count)
889 {
890 return EOPNOTSUPP;
891 }
892
893
894 status_t
domain_shutdown(net_protocol * protocol,int direction)895 domain_shutdown(net_protocol *protocol, int direction)
896 {
897 return EOPNOTSUPP;
898 }
899
900
901 status_t
domain_send_data(net_protocol * protocol,net_buffer * buffer)902 domain_send_data(net_protocol *protocol, net_buffer *buffer)
903 {
904 // find route
905 struct net_route *route = get_route(&sDomain, (sockaddr *)&buffer->destination);
906 if (route == NULL)
907 return ENETUNREACH;
908
909 return datalink_send_data(route, buffer);
910 }
911
912
913 status_t
domain_send_routed_data(net_protocol * protocol,struct net_route * route,net_buffer * buffer)914 domain_send_routed_data(net_protocol *protocol, struct net_route *route,
915 net_buffer *buffer)
916 {
917 return datalink_send_data(route, buffer);
918 }
919
920
921 ssize_t
domain_send_avail(net_protocol * protocol)922 domain_send_avail(net_protocol *protocol)
923 {
924 return B_ERROR;
925 }
926
927
928 status_t
domain_read_data(net_protocol * protocol,size_t numBytes,uint32 flags,net_buffer ** _buffer)929 domain_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
930 net_buffer **_buffer)
931 {
932 return B_ERROR;
933 }
934
935
936 ssize_t
domain_read_avail(net_protocol * protocol)937 domain_read_avail(net_protocol *protocol)
938 {
939 return B_ERROR;
940 }
941
942
943 struct net_domain *
domain_get_domain(net_protocol * protocol)944 domain_get_domain(net_protocol *protocol)
945 {
946 return &sDomain;
947 }
948
949
950 size_t
domain_get_mtu(net_protocol * protocol,const struct sockaddr * address)951 domain_get_mtu(net_protocol *protocol, const struct sockaddr *address)
952 {
953 return 1480;
954 // 1500 ethernet - IPv4 header
955 }
956
957
958 status_t
domain_receive_data(net_buffer * buffer)959 domain_receive_data(net_buffer *buffer)
960 {
961 uint32 packetNumber = atomic_add(&sPacketNumber, 1);
962
963 bool drop = false;
964 if (sDropList.find(packetNumber) != sDropList.end()
965 || (sRandomDrop > 0.0 && (1.0 * rand() / RAND_MAX) > sRandomDrop))
966 drop = true;
967
968 if (!drop && (sRoundTripTime > 0 || sRandomRoundTrip || sIncreasingRoundTrip)) {
969 bigtime_t add = 0;
970 if (sRandomRoundTrip)
971 add = (bigtime_t)(1.0 * rand() / RAND_MAX * 500000) - 250000;
972 if (sIncreasingRoundTrip)
973 sRoundTripTime += (bigtime_t)(1.0 * rand() / RAND_MAX * 150000);
974
975 snooze(sRoundTripTime / 2 + add);
976 }
977
978 if (sPacketMonitor != NULL) {
979 sPacketMonitor(buffer, packetNumber, drop);
980 } else if (drop)
981 printf("<**** DROPPED %ld ****>\n", packetNumber);
982
983 if (drop) {
984 gNetBufferModule.free(buffer);
985 return B_OK;
986 }
987
988 return gTCPModule->receive_data(buffer);
989 }
990
991
992 status_t
domain_error(net_error error,net_buffer * data)993 domain_error(net_error error, net_buffer* data)
994 {
995 return B_ERROR;
996 }
997
998
999 status_t
domain_error_reply(net_protocol * self,net_buffer * cause,net_error error,net_error_data * errorData)1000 domain_error_reply(net_protocol* self, net_buffer* cause,
1001 net_error error, net_error_data* errorData)
1002 {
1003 return B_ERROR;
1004 }
1005
1006
1007 net_protocol_module_info gDomainModule = {
1008 {
1009 NULL,
1010 0,
1011 std_ops
1012 },
1013 NET_PROTOCOL_ATOMIC_MESSAGES,
1014
1015 NULL, // init
1016 NULL, // uninit
1017 domain_open,
1018 domain_close,
1019 domain_free,
1020 domain_connect,
1021 domain_accept,
1022 domain_control,
1023 NULL, // getsockopt
1024 NULL, // setsockopt
1025 domain_bind,
1026 domain_unbind,
1027 domain_listen,
1028 domain_shutdown,
1029 domain_send_data,
1030 domain_send_routed_data,
1031 domain_send_avail,
1032 domain_read_data,
1033 domain_read_avail,
1034 domain_get_domain,
1035 domain_get_mtu,
1036 domain_receive_data,
1037 NULL, // deliver_data
1038 domain_error,
1039 domain_error_reply,
1040 NULL, // attach_ancillary_data
1041 NULL, // process_ancillary_data
1042 };
1043
1044
1045 // #pragma mark - packet capture
1046
1047
1048 static void
dump_printf(net_buffer * buffer,int32 packetNumber,bool willBeDropped)1049 dump_printf(net_buffer* buffer, int32 packetNumber, bool willBeDropped)
1050 {
1051 static bigtime_t lastTime = 0;
1052
1053 NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
1054 if (bufferHeader.Status() < B_OK)
1055 return;
1056
1057 tcp_header &header = bufferHeader.Data();
1058
1059 bigtime_t now = system_time();
1060 if (lastTime == 0)
1061 lastTime = now;
1062
1063 printf("\33[0m% 3ld %8.6f (%8.6f) ", packetNumber, (now - sStartTime) / 1000000.0,
1064 (now - lastTime) / 1000000.0);
1065 lastTime = now;
1066
1067 if (is_server((sockaddr *)buffer->source))
1068 printf("\33[31mserver > client: ");
1069 else
1070 printf("client > server: ");
1071
1072 int32 length = buffer->size - header.HeaderLength();
1073
1074 if ((header.flags & TCP_FLAG_PUSH) != 0)
1075 putchar('P');
1076 if ((header.flags & TCP_FLAG_SYNCHRONIZE) != 0)
1077 putchar('S');
1078 if ((header.flags & TCP_FLAG_FINISH) != 0)
1079 putchar('F');
1080 if ((header.flags & TCP_FLAG_RESET) != 0)
1081 putchar('R');
1082 if ((header.flags
1083 & (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_PUSH | TCP_FLAG_RESET)) == 0)
1084 putchar('.');
1085
1086 printf(" %lu:%lu (%lu)", header.Sequence(), header.Sequence() + length, length);
1087 if ((header.flags & TCP_FLAG_ACKNOWLEDGE) != 0)
1088 printf(" ack %lu", header.Acknowledge());
1089
1090 printf(" win %u", header.AdvertisedWindow());
1091
1092 if (header.HeaderLength() > sizeof(tcp_header)) {
1093 int32 size = header.HeaderLength() - sizeof(tcp_header);
1094
1095 tcp_option *option;
1096 uint8 optionsBuffer[1024];
1097 if (gBufferModule->direct_access(buffer, sizeof(tcp_header),
1098 size, (void **)&option) != B_OK) {
1099 if (size > 1024) {
1100 printf("options too large to take into account (%ld bytes)\n", size);
1101 size = 1024;
1102 }
1103
1104 gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size);
1105 option = (tcp_option *)optionsBuffer;
1106 }
1107
1108 while (size > 0) {
1109 uint32 length = 1;
1110 switch (option->kind) {
1111 case TCP_OPTION_END:
1112 case TCP_OPTION_NOP:
1113 break;
1114 case TCP_OPTION_MAX_SEGMENT_SIZE:
1115 printf(" <mss %u>", ntohs(option->max_segment_size));
1116 length = 4;
1117 break;
1118 case TCP_OPTION_WINDOW_SHIFT:
1119 printf(" <ws %u>", option->window_shift);
1120 length = 3;
1121 break;
1122 case TCP_OPTION_TIMESTAMP:
1123 printf(" <ts %lu:%lu>", option->timestamp.value, option->timestamp.reply);
1124 length = 10;
1125 break;
1126
1127 default:
1128 length = option->length;
1129 // make sure we don't end up in an endless loop
1130 if (length == 0)
1131 size = 0;
1132 break;
1133 }
1134
1135 size -= length;
1136 option = (tcp_option *)((uint8 *)option + length);
1137 }
1138 }
1139
1140 if (willBeDropped)
1141 printf(" <DROPPED>");
1142 printf("\33[0m\n");
1143 }
1144
1145
1146 static void
dump_pcap(net_buffer * buffer,int32 packetNumber,bool willBeDropped)1147 dump_pcap(net_buffer* buffer, int32 packetNumber, bool willBeDropped)
1148 {
1149 if (willBeDropped) {
1150 printf(" <DROPPED>\n");
1151 return;
1152 }
1153
1154 const bigtime_t time = real_time_clock_usecs();
1155
1156 struct pcap_packet_header pcap_header;
1157 pcap_header.ts_sec = time / 1000000;
1158 pcap_header.ts_usec = time % 1000000;
1159 pcap_header.included_len = sizeof(struct ip) + buffer->size;
1160 pcap_header.original_len = pcap_header.included_len;
1161
1162 struct ip ip_header;
1163 ip_header.ip_v = IPVERSION;
1164 ip_header.ip_hl = sizeof(struct ip) >> 2;
1165 ip_header.ip_tos = 0;
1166 ip_header.ip_len = htons(sizeof(struct ip) + buffer->size);
1167 ip_header.ip_id = htons(packetNumber);
1168 ip_header.ip_off = 0;
1169 ip_header.ip_ttl = 254;
1170 ip_header.ip_p = IPPROTO_TCP;
1171 ip_header.ip_sum = 0;
1172 ip_header.ip_src.s_addr = ((sockaddr_in*)buffer->source)->sin_addr.s_addr;
1173 ip_header.ip_dst.s_addr = ((sockaddr_in*)buffer->destination)->sin_addr.s_addr;
1174
1175 size_t count = 16, used = 0;
1176 iovec vecs[count];
1177
1178 vecs[used].iov_base = &pcap_header;
1179 vecs[used].iov_len = sizeof(pcap_header);
1180 used++;
1181
1182 vecs[used].iov_base = &ip_header;
1183 vecs[used].iov_len = sizeof(ip_header);
1184 used++;
1185
1186 used += gNetBufferModule.get_iovecs(buffer, vecs + used, count - used);
1187
1188 static mutex writesLock = MUTEX_INITIALIZER("pcap writes");
1189 MutexLocker _(writesLock);
1190 ssize_t written = writev(sPcapFD, vecs, used);
1191 if (written != (pcap_header.included_len + sizeof(pcap_packet_header))) {
1192 fprintf(stderr, "writing to pcap file failed\n");
1193 exit(1);
1194 }
1195 }
1196
1197
1198 static bool
setup_dump_pcap(const char * file)1199 setup_dump_pcap(const char* file)
1200 {
1201 sPcapFD = open(file, O_CREAT | O_WRONLY | O_TRUNC);
1202 if (sPcapFD < 0) {
1203 fprintf(stderr, "tcp_shell: Failed to open output pcap file: %d\n",
1204 errno);
1205 return false;
1206 }
1207
1208 struct pcap_header header;
1209 header.magic = PCAP_MAGIC;
1210 header.version_major = 2;
1211 header.version_minor = 4;
1212 header.timezone = 0;
1213 header.timestamp_accuracy = 0;
1214 header.max_packet_length = 65535;
1215 header.linktype = PCAP_LINKTYPE_IPV4;
1216 if (write(sPcapFD, &header, sizeof(header)) != sizeof(header)) {
1217 fprintf(stderr, "tcp_shell: Failed to write pcap file header: %d\n",
1218 errno);
1219 return false;
1220 }
1221
1222 sPacketMonitor = dump_pcap;
1223 return true;
1224 }
1225
1226
1227 // #pragma mark - test
1228
1229
1230 int32
receiving_thread(void * _data)1231 receiving_thread(void* _data)
1232 {
1233 struct context* context = (struct context*)_data;
1234 struct net_buffer* reorderBuffer = NULL;
1235
1236 while (true) {
1237 status_t status;
1238 do {
1239 status = acquire_sem(context->wait_sem);
1240 } while (status == B_INTERRUPTED);
1241
1242 if (status < B_OK)
1243 break;
1244
1245 while (true) {
1246 context->lock.Lock();
1247 net_buffer* buffer = (net_buffer*)list_remove_head_item(
1248 &context->list);
1249 context->lock.Unlock();
1250
1251 if (buffer == NULL)
1252 break;
1253
1254 if (sSimultaneousConnect && context->server && is_syn(buffer)) {
1255 // delay getting the SYN request, and connect as well
1256 sockaddr_in address;
1257 memset(&address, 0, sizeof(address));
1258 address.sin_family = AF_INET;
1259 address.sin_port = htons(1023);
1260 address.sin_addr.s_addr = htonl(0xc0a80001);
1261
1262 status_t status = socket_connect(gServerSocket,
1263 (struct sockaddr *)&address, sizeof(struct sockaddr));
1264 if (status < B_OK)
1265 fprintf(stderr, "tcp_tester: simultaneous connect failed: %s\n", strerror(status));
1266
1267 sSimultaneousConnect = false;
1268 }
1269 if (sSimultaneousClose && !context->server && is_fin(buffer)) {
1270 close_protocol(gClientSocket->first_protocol);
1271 sSimultaneousClose = false;
1272 }
1273 if ((sRandomReorder > 0.0
1274 || sReorderList.find(sPacketNumber) != sReorderList.end())
1275 && reorderBuffer == NULL
1276 && (1.0 * rand() / RAND_MAX) > sRandomReorder) {
1277 reorderBuffer = buffer;
1278 } else {
1279 if (sDomain.module->receive_data(buffer) < B_OK)
1280 gNetBufferModule.free(buffer);
1281
1282 if (reorderBuffer != NULL) {
1283 if (sDomain.module->receive_data(reorderBuffer) < B_OK)
1284 gNetBufferModule.free(reorderBuffer);
1285 reorderBuffer = NULL;
1286 }
1287 }
1288 }
1289 }
1290
1291 return 0;
1292 }
1293
1294
1295 int32
server_thread(void *)1296 server_thread(void*)
1297 {
1298 while (true) {
1299 // main accept() loop
1300 net_socket* connectionSocket;
1301 sockaddr_in address;
1302 socklen_t size = sizeof(struct sockaddr_in);
1303 status_t status = socket_accept(gServerSocket,
1304 (struct sockaddr *)&address, &size, &connectionSocket);
1305 if (status < B_OK) {
1306 fprintf(stderr, "SERVER: accepting failed: %s\n", strerror(status));
1307 break;
1308 }
1309
1310 printf("server: got connection from %08x\n", address.sin_addr.s_addr);
1311
1312 char buffer[1024];
1313 ssize_t bytesRead;
1314 while ((bytesRead = socket_recv(connectionSocket, buffer,
1315 sizeof(buffer), 0)) > 0) {
1316 printf("server: received %ld bytes\n", bytesRead);
1317
1318 if (sServerActiveClose) {
1319 printf("server: active close\n");
1320 close_protocol(connectionSocket->first_protocol);
1321 return 0;
1322 }
1323 }
1324 if (bytesRead < 0)
1325 printf("server: receiving failed: %s\n", strerror(bytesRead));
1326 else
1327 printf("server: peer closed connection.\n");
1328
1329 snooze(1000000);
1330 close_protocol(connectionSocket->first_protocol);
1331 }
1332
1333 return 0;
1334 }
1335
1336
1337 void
setup_server()1338 setup_server()
1339 {
1340 sockaddr_in address;
1341 memset(&address, 0, sizeof(address));
1342 address.sin_len = sizeof(sockaddr_in);
1343 address.sin_family = AF_INET;
1344 address.sin_port = htons(1024);
1345 address.sin_addr.s_addr = INADDR_ANY;
1346
1347 status_t status = socket_bind(gServerSocket, (struct sockaddr*)&address,
1348 sizeof(struct sockaddr));
1349 if (status < B_OK) {
1350 fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status));
1351 exit(1);
1352 }
1353 status = socket_listen(gServerSocket, 40);
1354 if (status < B_OK) {
1355 fprintf(stderr, "tcp_tester: server cannot listen: %s\n",
1356 strerror(status));
1357 exit(1);
1358 }
1359
1360 thread_id serverThread = spawn_thread(server_thread, "server",
1361 B_NORMAL_PRIORITY, NULL);
1362 if (serverThread < B_OK) {
1363 fprintf(stderr, "tcp_tester: cannot start server: %s\n",
1364 strerror(serverThread));
1365 exit(1);
1366 }
1367
1368 resume_thread(serverThread);
1369 }
1370
1371
1372 void
setup_context(struct context & context,bool server)1373 setup_context(struct context& context, bool server)
1374 {
1375 list_init(&context.list);
1376 context.route.interface_address = &gInterfaceAddress;
1377 context.route.gateway = (sockaddr *)&context;
1378 // backpointer to the context
1379 context.route.mtu = 1500;
1380 context.server = server;
1381 context.wait_sem = create_sem(0, "receive wait");
1382
1383 context.thread = spawn_thread(receiving_thread,
1384 server ? "server receiver" : "client receiver", B_NORMAL_PRIORITY,
1385 &context);
1386 resume_thread(context.thread);
1387 }
1388
1389
1390 void
cleanup_context(struct context & context)1391 cleanup_context(struct context& context)
1392 {
1393 delete_sem(context.wait_sem);
1394
1395 status_t status;
1396 wait_for_thread(context.thread, &status);
1397 }
1398
1399
1400 // #pragma mark -
1401
1402
1403 static void do_help(int argc, char** argv);
1404
1405
1406 static void
do_connect(int argc,char ** argv)1407 do_connect(int argc, char** argv)
1408 {
1409 sSimultaneousConnect = false;
1410
1411 int port = 1024;
1412 if (argc > 1) {
1413 if (!strcmp(argv[1], "-s"))
1414 sSimultaneousConnect = true;
1415 else if (isdigit(argv[1][0]))
1416 port = atoi(argv[1]);
1417 else {
1418 fprintf(stderr, "usage: connect [-s|<port-number>]\n");
1419 return;
1420 }
1421 }
1422
1423 if (sSimultaneousConnect) {
1424 // bind to a port first, so the other end can find us
1425 sockaddr_in address;
1426 memset(&address, 0, sizeof(address));
1427 address.sin_family = AF_INET;
1428 address.sin_port = htons(1023);
1429 address.sin_addr.s_addr = htonl(0xc0a80001);
1430
1431 status_t status = socket_bind(gClientSocket, (struct sockaddr *)&address,
1432 sizeof(struct sockaddr));
1433 if (status < B_OK) {
1434 fprintf(stderr, "Could not bind to port 1023: %s\n", strerror(status));
1435 sSimultaneousConnect = false;
1436 return;
1437 }
1438 }
1439
1440 sStartTime = system_time();
1441
1442 sockaddr_in address;
1443 memset(&address, 0, sizeof(address));
1444 address.sin_family = AF_INET;
1445 address.sin_port = htons(port);
1446 address.sin_addr.s_addr = htonl(0xc0a80001);
1447
1448 status_t status = socket_connect(gClientSocket, (struct sockaddr *)&address,
1449 sizeof(struct sockaddr));
1450 if (status < B_OK)
1451 fprintf(stderr, "tcp_tester: could not connect: %s\n", strerror(status));
1452 }
1453
1454
1455 static ssize_t
parse_size(const char * arg)1456 parse_size(const char* arg)
1457 {
1458 char *unit;
1459 ssize_t size = strtoul(arg, &unit, 0);
1460 if (unit != NULL && unit[0]) {
1461 if (unit[0] == 'k' || unit[0] == 'K')
1462 size *= 1024;
1463 else if (unit[0] == 'm' || unit[0] == 'M')
1464 size *= 1024 * 1024;
1465 else {
1466 fprintf(stderr, "unknown unit specified!\n");
1467 return -1;
1468 }
1469 }
1470 return size;
1471 }
1472
1473
1474 static void
do_send(int argc,char ** argv)1475 do_send(int argc, char** argv)
1476 {
1477 ssize_t size = 1024;
1478 if (argc > 1 && isdigit(argv[1][0])) {
1479 size = parse_size(argv[1]);
1480 if (size < 0)
1481 return;
1482 } else if (argc > 1) {
1483 fprintf(stderr, "invalid args!\n");
1484 return;
1485 }
1486
1487 if (size > 4 * 1024 * 1024) {
1488 printf("amount to send will be limited to 4 MB\n");
1489 size = 4 * 1024 * 1024;
1490 }
1491
1492 char *buffer = (char *)malloc(size);
1493 if (buffer == NULL) {
1494 fprintf(stderr, "not enough memory!\n");
1495 return;
1496 }
1497 MemoryDeleter bufferDeleter(buffer);
1498
1499 // initialize buffer with some not so random data
1500 for (uint32 i = 0; i < size; i++) {
1501 buffer[i] = (char)(i & 0xff);
1502 }
1503
1504 ssize_t bytesWritten = socket_send(gClientSocket, buffer, size, 0);
1505 if (bytesWritten < B_OK) {
1506 fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten));
1507 return;
1508 }
1509 }
1510
1511
1512 static void
do_send_loop(int argc,char ** argv)1513 do_send_loop(int argc, char** argv)
1514 {
1515 if (argc != 2 || !isdigit(argv[1][0])) {
1516 fprintf(stderr, "invalid args!\n");
1517 return;
1518 }
1519 ssize_t size = parse_size(argv[1]);
1520 if (size < 0)
1521 return;
1522
1523 const size_t bufferSize = 4096;
1524 char *buffer = (char *)malloc(bufferSize);
1525 if (buffer == NULL) {
1526 fprintf(stderr, "not enough memory!\n");
1527 return;
1528 }
1529 MemoryDeleter bufferDeleter(buffer);
1530
1531 // initialize buffer with some not so random data
1532 for (uint32 i = 0; i < bufferSize; i++) {
1533 buffer[i] = (char)(i & 0xff);
1534 }
1535
1536 for (ssize_t total = 0; total < size; ) {
1537 ssize_t bytesWritten = socket_send(gClientSocket, buffer, bufferSize, 0);
1538 if (bytesWritten < B_OK) {
1539 fprintf(stderr, "failed sending buffer (after %" B_PRIdSSIZE "): %s\n",
1540 total, strerror(bytesWritten));
1541 return;
1542 }
1543
1544 total += bufferSize;
1545 }
1546 }
1547
1548
1549 static void
do_close(int argc,char ** argv)1550 do_close(int argc, char** argv)
1551 {
1552 sSimultaneousClose = false;
1553 sServerActiveClose = true;
1554
1555 if (argc > 1) {
1556 if (!strcmp(argv[1], "-s"))
1557 sSimultaneousClose = true;
1558 else {
1559 fprintf(stderr, "usage: close [-s]\n");
1560 return;
1561 }
1562 }
1563
1564 gClientSocket->send.timeout = 0;
1565
1566 char buffer[32767] = {'q'};
1567 ssize_t bytesWritten = socket_send(gClientSocket, buffer, sizeof(buffer), 0);
1568 if (bytesWritten < B_OK) {
1569 fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten));
1570 return;
1571 }
1572 }
1573
1574
1575 static void
do_drop(int argc,char ** argv)1576 do_drop(int argc, char** argv)
1577 {
1578 if (argc == 1) {
1579 // show list of dropped packets
1580 if (sRandomDrop > 0.0)
1581 printf("Drop probability is %f\n", sRandomDrop);
1582
1583 printf("Drop pakets:\n");
1584
1585 std::set<uint32>::iterator iterator = sDropList.begin();
1586 uint32 count = 0;
1587 for (; iterator != sDropList.end(); iterator++) {
1588 printf("%4lu\n", *iterator);
1589 count++;
1590 }
1591
1592 if (count == 0)
1593 printf("<empty>\n");
1594 } else if (!strcmp(argv[1], "-f")) {
1595 // flush drop list
1596 sDropList.clear();
1597 puts("drop list cleared.");
1598 } else if (!strcmp(argv[1], "-r")) {
1599 if (argc < 3) {
1600 fprintf(stderr, "No drop probability specified.\n");
1601 return;
1602 }
1603
1604 sRandomDrop = atof(argv[2]);
1605 if (sRandomDrop < 0.0)
1606 sRandomDrop = 0;
1607 else if (sRandomDrop > 1.0)
1608 sRandomDrop = 1.0;
1609 } else if (isdigit(argv[1][0])) {
1610 // add to drop list
1611 for (int i = 1; i < argc; i++) {
1612 uint32 packet = strtoul(argv[i], NULL, 0);
1613 if (packet == 0) {
1614 fprintf(stderr, "invalid packet number: %s\n", argv[i]);
1615 break;
1616 }
1617
1618 sDropList.insert(packet);
1619 }
1620 } else {
1621 // print usage
1622 puts("usage: drop <packet-number> [...]\n"
1623 " or: drop -r <probability>\n\n"
1624 " or: drop [-f]\n\n"
1625 "Specifiying -f flushes the drop list, -r sets the probability a packet\n"
1626 "is dropped; if you called drop without any arguments, the current\n"
1627 "drop list is dumped.");
1628 }
1629 }
1630
1631
1632 static void
do_reorder(int argc,char ** argv)1633 do_reorder(int argc, char** argv)
1634 {
1635 if (argc == 1) {
1636 // show list of dropped packets
1637 if (sRandomReorder > 0.0)
1638 printf("Reorder probability is %f\n", sRandomReorder);
1639
1640 printf("Reorder packets:\n");
1641
1642 std::set<uint32>::iterator iterator = sReorderList.begin();
1643 uint32 count = 0;
1644 for (; iterator != sReorderList.end(); iterator++) {
1645 printf("%4lu\n", *iterator);
1646 count++;
1647 }
1648
1649 if (count == 0)
1650 printf("<empty>\n");
1651 } else if (!strcmp(argv[1], "-f")) {
1652 // flush reorder list
1653 sReorderList.clear();
1654 puts("reorder list cleared.");
1655 } else if (!strcmp(argv[1], "-r")) {
1656 if (argc < 3) {
1657 fprintf(stderr, "No reorder probability specified.\n");
1658 return;
1659 }
1660
1661 sRandomReorder = atof(argv[2]);
1662 if (sRandomReorder < 0.0)
1663 sRandomReorder = 0;
1664 else if (sRandomReorder > 1.0)
1665 sRandomReorder = 1.0;
1666 } else if (isdigit(argv[1][0])) {
1667 // add to reorder list
1668 for (int i = 1; i < argc; i++) {
1669 uint32 packet = strtoul(argv[i], NULL, 0);
1670 if (packet == 0) {
1671 fprintf(stderr, "invalid packet number: %s\n", argv[i]);
1672 break;
1673 }
1674
1675 sReorderList.insert(packet);
1676 }
1677 } else {
1678 // print usage
1679 puts("usage: reorder <packet-number> [...]\n"
1680 " or: reorder -r <probability>\n\n"
1681 " or: reorder [-f]\n\n"
1682 "Specifiying -f flushes the reorder list, -r sets the probability a packet\n"
1683 "is reordered; if you called reorder without any arguments, the current\n"
1684 "reorder list is dumped.");
1685 }
1686 }
1687
1688
1689 static void
do_round_trip_time(int argc,char ** argv)1690 do_round_trip_time(int argc, char** argv)
1691 {
1692 if (argc == 1) {
1693 // show current time
1694 printf("Current round trip time: %g ms\n", sRoundTripTime / 1000.0);
1695 } else if (!strcmp(argv[1], "-r")) {
1696 // toggle random time
1697 sRandomRoundTrip = !sRandomRoundTrip;
1698 printf("Round trip time is now %s.\n", sRandomRoundTrip ? "random" : "fixed");
1699 } else if (!strcmp(argv[1], "-i")) {
1700 // toggle increasing time
1701 sIncreasingRoundTrip = !sIncreasingRoundTrip;
1702 printf("Round trip time is now %s.\n", sIncreasingRoundTrip ? "increasing" : "fixed");
1703 } else if (isdigit(argv[1][0])) {
1704 // set time
1705 sRoundTripTime = 1000LL * strtoul(argv[1], NULL, 0);
1706 } else {
1707 // print usage
1708 puts("usage: rtt <time in ms>\n"
1709 " or: rtt [-r|-i]\n\n"
1710 "Specifiying -r sets random time, -i causes the times to increase over time;\n"
1711 "witout any arguments, the current time is printed.");
1712 }
1713 }
1714
1715
1716 static void
do_dprintf(int argc,char ** argv)1717 do_dprintf(int argc, char** argv)
1718 {
1719 if (argc > 1)
1720 gDebugOutputEnabled = !strcmp(argv[1], "on");
1721 else
1722 gDebugOutputEnabled = !gDebugOutputEnabled;
1723
1724 printf("debug output turned %s.\n", gDebugOutputEnabled ? "on" : "off");
1725 }
1726
1727
1728 static cmd_entry sBuiltinCommands[] = {
1729 {"connect", do_connect, "Connects the client"},
1730 {"send", do_send, "Sends data from the client to the server"},
1731 {"send_loop", do_send_loop, "Sends data in a loop"},
1732 {"close", do_close, "Performs an active or simultaneous close"},
1733 {"dprintf", do_dprintf, "Toggles debug output"},
1734 {"drop", do_drop, "Lets you drop packets during transfer"},
1735 {"reorder", do_reorder, "Lets you reorder packets during transfer"},
1736 {"help", do_help, "prints this help text"},
1737 {"rtt", do_round_trip_time, "Specifies the round trip time"},
1738 {"quit", NULL, "exits the application"},
1739 {NULL, NULL, NULL},
1740 };
1741
1742
1743 static void
do_help(int argc,char ** argv)1744 do_help(int argc, char** argv)
1745 {
1746 printf("Available commands:\n");
1747
1748 for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) {
1749 printf("%8s - %s\n", command->name, command->help);
1750 }
1751 }
1752
1753
1754 // #pragma mark -
1755
1756
1757 int
main(int argc,char * argv[])1758 main(int argc, char* argv[])
1759 {
1760 for (int i = 1; i < argc; i++) {
1761 if (strcmp(argv[i], "-w") == 0 && (i + 1) < argc) {
1762 if (!setup_dump_pcap(argv[++i]))
1763 return 1;
1764 }
1765 }
1766
1767 if (sPacketMonitor == NULL)
1768 sPacketMonitor = dump_printf;
1769
1770 status_t status = init_timers();
1771 if (status < B_OK) {
1772 fprintf(stderr, "tcp_tester: Could not initialize timers: %s\n",
1773 strerror(status));
1774 return 1;
1775 }
1776
1777 _add_builtin_module((module_info*)&gNetStackModule);
1778 _add_builtin_module((module_info*)&gNetBufferModule);
1779 _add_builtin_module((module_info*)&gNetSocketModule);
1780 _add_builtin_module((module_info*)&gNetDatalinkModule);
1781 _add_builtin_module(modules[0]);
1782 if (_get_builtin_dependencies() < B_OK) {
1783 fprintf(stderr, "tcp_tester: Could not initialize modules: %s\n",
1784 strerror(status));
1785 return 1;
1786 }
1787
1788 sockaddr_in interfaceAddress;
1789 interfaceAddress.sin_len = sizeof(sockaddr_in);
1790 interfaceAddress.sin_family = AF_INET;
1791 interfaceAddress.sin_addr.s_addr = htonl(0xc0a80001);
1792 gInterfaceAddress.local = (sockaddr*)&interfaceAddress;
1793 gInterfaceAddress.domain = &sDomain;
1794
1795 status = get_module("network/protocols/tcp/v1", (module_info **)&gTCPModule);
1796 if (status < B_OK) {
1797 fprintf(stderr, "tcp_tester: Could not open TCP module: %s\n",
1798 strerror(status));
1799 return 1;
1800 }
1801
1802 net_protocol* client = init_protocol(&gClientSocket);
1803 if (client == NULL)
1804 return 1;
1805 net_protocol* server = init_protocol(&gServerSocket);
1806 if (server == NULL)
1807 return 1;
1808
1809 setup_context(sClientContext, false);
1810 setup_context(sServerContext, true);
1811
1812 printf("*** Server: %p (%ld), Client: %p (%ld)\n", server,
1813 sServerContext.thread, client, sClientContext.thread);
1814
1815 setup_server();
1816
1817 while (true) {
1818 printf("> ");
1819 fflush(stdout);
1820
1821 char line[1024];
1822 if (fgets(line, sizeof(line), stdin) == NULL)
1823 break;
1824
1825 argc = 0;
1826 argv = build_argv(line, &argc);
1827 if (argv == NULL || argc == 0)
1828 continue;
1829
1830 int length = strlen(argv[0]);
1831
1832 #if 0
1833 char *newLine = strchr(line, '\n');
1834 if (newLine != NULL)
1835 newLine[0] = '\0';
1836 #endif
1837
1838 if (!strcmp(argv[0], "quit")
1839 || !strcmp(argv[0], "exit")
1840 || !strcmp(argv[0], "q"))
1841 break;
1842
1843 bool found = false;
1844
1845 for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) {
1846 if (!strncmp(command->name, argv[0], length)) {
1847 command->func(argc, argv);
1848 found = true;
1849 break;
1850 }
1851 }
1852
1853 if (!found)
1854 fprintf(stderr, "Unknown command \"%s\". Type \"help\" for a list of commands.\n", argv[0]);
1855
1856 free(argv);
1857 }
1858
1859 close_protocol(client);
1860 close_protocol(server);
1861
1862 snooze(2000000);
1863
1864 cleanup_context(sClientContext);
1865 cleanup_context(sServerContext);
1866
1867 put_module("network/protocols/tcp/v1");
1868 uninit_timers();
1869 return 0;
1870 }
1871