a54966531a647953df440ce0c47ec808830e909a
[linux-2.6-microblaze.git] / tools / testing / selftests / net / mptcp / mptcp_connect.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #define _GNU_SOURCE
4
5 #include <errno.h>
6 #include <limits.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <strings.h>
14 #include <signal.h>
15 #include <unistd.h>
16
17 #include <sys/poll.h>
18 #include <sys/sendfile.h>
19 #include <sys/stat.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <sys/mman.h>
23
24 #include <netdb.h>
25 #include <netinet/in.h>
26
27 #include <linux/tcp.h>
28
29 extern int optind;
30
31 #ifndef IPPROTO_MPTCP
32 #define IPPROTO_MPTCP 262
33 #endif
34 #ifndef TCP_ULP
35 #define TCP_ULP 31
36 #endif
37
38 static int  poll_timeout = 10 * 1000;
39 static bool listen_mode;
40 static bool quit;
41
42 enum cfg_mode {
43         CFG_MODE_POLL,
44         CFG_MODE_MMAP,
45         CFG_MODE_SENDFILE,
46 };
47
48 static enum cfg_mode cfg_mode = CFG_MODE_POLL;
49 static const char *cfg_host;
50 static const char *cfg_port     = "12000";
51 static int cfg_sock_proto       = IPPROTO_MPTCP;
52 static bool tcpulp_audit;
53 static int pf = AF_INET;
54 static int cfg_sndbuf;
55 static int cfg_rcvbuf;
56 static bool cfg_join;
57 static int cfg_wait;
58
59 static void die_usage(void)
60 {
61         fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]"
62                 "[-l] [-w sec] connect_address\n");
63         fprintf(stderr, "\t-6 use ipv6\n");
64         fprintf(stderr, "\t-t num -- set poll timeout to num\n");
65         fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
66         fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n");
67         fprintf(stderr, "\t-p num -- use port num\n");
68         fprintf(stderr, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\n");
69         fprintf(stderr, "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n");
70         fprintf(stderr, "\t-u -- check mptcp ulp\n");
71         fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
72         exit(1);
73 }
74
75 static void handle_signal(int nr)
76 {
77         quit = true;
78 }
79
80 static const char *getxinfo_strerr(int err)
81 {
82         if (err == EAI_SYSTEM)
83                 return strerror(errno);
84
85         return gai_strerror(err);
86 }
87
88 static void xgetnameinfo(const struct sockaddr *addr, socklen_t addrlen,
89                          char *host, socklen_t hostlen,
90                          char *serv, socklen_t servlen)
91 {
92         int flags = NI_NUMERICHOST | NI_NUMERICSERV;
93         int err = getnameinfo(addr, addrlen, host, hostlen, serv, servlen,
94                               flags);
95
96         if (err) {
97                 const char *errstr = getxinfo_strerr(err);
98
99                 fprintf(stderr, "Fatal: getnameinfo: %s\n", errstr);
100                 exit(1);
101         }
102 }
103
104 static void xgetaddrinfo(const char *node, const char *service,
105                          const struct addrinfo *hints,
106                          struct addrinfo **res)
107 {
108         int err = getaddrinfo(node, service, hints, res);
109
110         if (err) {
111                 const char *errstr = getxinfo_strerr(err);
112
113                 fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n",
114                         node ? node : "", service ? service : "", errstr);
115                 exit(1);
116         }
117 }
118
119 static void set_rcvbuf(int fd, unsigned int size)
120 {
121         int err;
122
123         err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
124         if (err) {
125                 perror("set SO_RCVBUF");
126                 exit(1);
127         }
128 }
129
130 static void set_sndbuf(int fd, unsigned int size)
131 {
132         int err;
133
134         err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
135         if (err) {
136                 perror("set SO_SNDBUF");
137                 exit(1);
138         }
139 }
140
141 static int sock_listen_mptcp(const char * const listenaddr,
142                              const char * const port)
143 {
144         int sock;
145         struct addrinfo hints = {
146                 .ai_protocol = IPPROTO_TCP,
147                 .ai_socktype = SOCK_STREAM,
148                 .ai_flags = AI_PASSIVE | AI_NUMERICHOST
149         };
150
151         hints.ai_family = pf;
152
153         struct addrinfo *a, *addr;
154         int one = 1;
155
156         xgetaddrinfo(listenaddr, port, &hints, &addr);
157         hints.ai_family = pf;
158
159         for (a = addr; a; a = a->ai_next) {
160                 sock = socket(a->ai_family, a->ai_socktype, cfg_sock_proto);
161                 if (sock < 0)
162                         continue;
163
164                 if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
165                                      sizeof(one)))
166                         perror("setsockopt");
167
168                 if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
169                         break; /* success */
170
171                 perror("bind");
172                 close(sock);
173                 sock = -1;
174         }
175
176         freeaddrinfo(addr);
177
178         if (sock < 0) {
179                 fprintf(stderr, "Could not create listen socket\n");
180                 return sock;
181         }
182
183         if (listen(sock, 20)) {
184                 perror("listen");
185                 close(sock);
186                 return -1;
187         }
188
189         return sock;
190 }
191
192 static bool sock_test_tcpulp(const char * const remoteaddr,
193                              const char * const port)
194 {
195         struct addrinfo hints = {
196                 .ai_protocol = IPPROTO_TCP,
197                 .ai_socktype = SOCK_STREAM,
198         };
199         struct addrinfo *a, *addr;
200         int sock = -1, ret = 0;
201         bool test_pass = false;
202
203         hints.ai_family = AF_INET;
204
205         xgetaddrinfo(remoteaddr, port, &hints, &addr);
206         for (a = addr; a; a = a->ai_next) {
207                 sock = socket(a->ai_family, a->ai_socktype, IPPROTO_TCP);
208                 if (sock < 0) {
209                         perror("socket");
210                         continue;
211                 }
212                 ret = setsockopt(sock, IPPROTO_TCP, TCP_ULP, "mptcp",
213                                  sizeof("mptcp"));
214                 if (ret == -1 && errno == EOPNOTSUPP)
215                         test_pass = true;
216                 close(sock);
217
218                 if (test_pass)
219                         break;
220                 if (!ret)
221                         fprintf(stderr,
222                                 "setsockopt(TCP_ULP) returned 0\n");
223                 else
224                         perror("setsockopt(TCP_ULP)");
225         }
226         return test_pass;
227 }
228
229 static int sock_connect_mptcp(const char * const remoteaddr,
230                               const char * const port, int proto)
231 {
232         struct addrinfo hints = {
233                 .ai_protocol = IPPROTO_TCP,
234                 .ai_socktype = SOCK_STREAM,
235         };
236         struct addrinfo *a, *addr;
237         int sock = -1;
238
239         hints.ai_family = pf;
240
241         xgetaddrinfo(remoteaddr, port, &hints, &addr);
242         for (a = addr; a; a = a->ai_next) {
243                 sock = socket(a->ai_family, a->ai_socktype, proto);
244                 if (sock < 0) {
245                         perror("socket");
246                         continue;
247                 }
248
249                 if (connect(sock, a->ai_addr, a->ai_addrlen) == 0)
250                         break; /* success */
251
252                 perror("connect()");
253                 close(sock);
254                 sock = -1;
255         }
256
257         freeaddrinfo(addr);
258         return sock;
259 }
260
261 static size_t do_rnd_write(const int fd, char *buf, const size_t len)
262 {
263         static bool first = true;
264         unsigned int do_w;
265         ssize_t bw;
266
267         do_w = rand() & 0xffff;
268         if (do_w == 0 || do_w > len)
269                 do_w = len;
270
271         if (cfg_join && first && do_w > 100)
272                 do_w = 100;
273
274         bw = write(fd, buf, do_w);
275         if (bw < 0)
276                 perror("write");
277
278         /* let the join handshake complete, before going on */
279         if (cfg_join && first) {
280                 usleep(200000);
281                 first = false;
282         }
283
284         return bw;
285 }
286
287 static size_t do_write(const int fd, char *buf, const size_t len)
288 {
289         size_t offset = 0;
290
291         while (offset < len) {
292                 size_t written;
293                 ssize_t bw;
294
295                 bw = write(fd, buf + offset, len - offset);
296                 if (bw < 0) {
297                         perror("write");
298                         return 0;
299                 }
300
301                 written = (size_t)bw;
302                 offset += written;
303         }
304
305         return offset;
306 }
307
308 static ssize_t do_rnd_read(const int fd, char *buf, const size_t len)
309 {
310         size_t cap = rand();
311
312         cap &= 0xffff;
313
314         if (cap == 0)
315                 cap = 1;
316         else if (cap > len)
317                 cap = len;
318
319         return read(fd, buf, cap);
320 }
321
322 static void set_nonblock(int fd)
323 {
324         int flags = fcntl(fd, F_GETFL);
325
326         if (flags == -1)
327                 return;
328
329         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
330 }
331
332 static int copyfd_io_poll(int infd, int peerfd, int outfd)
333 {
334         struct pollfd fds = {
335                 .fd = peerfd,
336                 .events = POLLIN | POLLOUT,
337         };
338         unsigned int woff = 0, wlen = 0;
339         char wbuf[8192];
340
341         set_nonblock(peerfd);
342
343         for (;;) {
344                 char rbuf[8192];
345                 ssize_t len;
346
347                 if (fds.events == 0)
348                         break;
349
350                 switch (poll(&fds, 1, poll_timeout)) {
351                 case -1:
352                         if (errno == EINTR)
353                                 continue;
354                         perror("poll");
355                         return 1;
356                 case 0:
357                         fprintf(stderr, "%s: poll timed out (events: "
358                                 "POLLIN %u, POLLOUT %u)\n", __func__,
359                                 fds.events & POLLIN, fds.events & POLLOUT);
360                         return 2;
361                 }
362
363                 if (fds.revents & POLLIN) {
364                         len = do_rnd_read(peerfd, rbuf, sizeof(rbuf));
365                         if (len == 0) {
366                                 /* no more data to receive:
367                                  * peer has closed its write side
368                                  */
369                                 fds.events &= ~POLLIN;
370
371                                 if ((fds.events & POLLOUT) == 0)
372                                         /* and nothing more to send */
373                                         break;
374
375                         /* Else, still have data to transmit */
376                         } else if (len < 0) {
377                                 perror("read");
378                                 return 3;
379                         }
380
381                         do_write(outfd, rbuf, len);
382                 }
383
384                 if (fds.revents & POLLOUT) {
385                         if (wlen == 0) {
386                                 woff = 0;
387                                 wlen = read(infd, wbuf, sizeof(wbuf));
388                         }
389
390                         if (wlen > 0) {
391                                 ssize_t bw;
392
393                                 bw = do_rnd_write(peerfd, wbuf + woff, wlen);
394                                 if (bw < 0)
395                                         return 111;
396
397                                 woff += bw;
398                                 wlen -= bw;
399                         } else if (wlen == 0) {
400                                 /* We have no more data to send. */
401                                 fds.events &= ~POLLOUT;
402
403                                 if ((fds.events & POLLIN) == 0)
404                                         /* ... and peer also closed already */
405                                         break;
406
407                                 /* ... but we still receive.
408                                  * Close our write side, ev. give some time
409                                  * for address notification and/or checking
410                                  * the current status
411                                  */
412                                 if (cfg_wait)
413                                         usleep(cfg_wait);
414                                 shutdown(peerfd, SHUT_WR);
415                         } else {
416                                 if (errno == EINTR)
417                                         continue;
418                                 perror("read");
419                                 return 4;
420                         }
421                 }
422
423                 if (fds.revents & (POLLERR | POLLNVAL)) {
424                         fprintf(stderr, "Unexpected revents: "
425                                 "POLLERR/POLLNVAL(%x)\n", fds.revents);
426                         return 5;
427                 }
428         }
429
430         /* leave some time for late join/announce */
431         if (cfg_join)
432                 usleep(cfg_wait);
433
434         close(peerfd);
435         return 0;
436 }
437
438 static int do_recvfile(int infd, int outfd)
439 {
440         ssize_t r;
441
442         do {
443                 char buf[16384];
444
445                 r = do_rnd_read(infd, buf, sizeof(buf));
446                 if (r > 0) {
447                         if (write(outfd, buf, r) != r)
448                                 break;
449                 } else if (r < 0) {
450                         perror("read");
451                 }
452         } while (r > 0);
453
454         return (int)r;
455 }
456
457 static int do_mmap(int infd, int outfd, unsigned int size)
458 {
459         char *inbuf = mmap(NULL, size, PROT_READ, MAP_SHARED, infd, 0);
460         ssize_t ret = 0, off = 0;
461         size_t rem;
462
463         if (inbuf == MAP_FAILED) {
464                 perror("mmap");
465                 return 1;
466         }
467
468         rem = size;
469
470         while (rem > 0) {
471                 ret = write(outfd, inbuf + off, rem);
472
473                 if (ret < 0) {
474                         perror("write");
475                         break;
476                 }
477
478                 off += ret;
479                 rem -= ret;
480         }
481
482         munmap(inbuf, size);
483         return rem;
484 }
485
486 static int get_infd_size(int fd)
487 {
488         struct stat sb;
489         ssize_t count;
490         int err;
491
492         err = fstat(fd, &sb);
493         if (err < 0) {
494                 perror("fstat");
495                 return -1;
496         }
497
498         if ((sb.st_mode & S_IFMT) != S_IFREG) {
499                 fprintf(stderr, "%s: stdin is not a regular file\n", __func__);
500                 return -2;
501         }
502
503         count = sb.st_size;
504         if (count > INT_MAX) {
505                 fprintf(stderr, "File too large: %zu\n", count);
506                 return -3;
507         }
508
509         return (int)count;
510 }
511
512 static int do_sendfile(int infd, int outfd, unsigned int count)
513 {
514         while (count > 0) {
515                 ssize_t r;
516
517                 r = sendfile(outfd, infd, NULL, count);
518                 if (r < 0) {
519                         perror("sendfile");
520                         return 3;
521                 }
522
523                 count -= r;
524         }
525
526         return 0;
527 }
528
529 static int copyfd_io_mmap(int infd, int peerfd, int outfd,
530                           unsigned int size)
531 {
532         int err;
533
534         if (listen_mode) {
535                 err = do_recvfile(peerfd, outfd);
536                 if (err)
537                         return err;
538
539                 err = do_mmap(infd, peerfd, size);
540         } else {
541                 err = do_mmap(infd, peerfd, size);
542                 if (err)
543                         return err;
544
545                 shutdown(peerfd, SHUT_WR);
546
547                 err = do_recvfile(peerfd, outfd);
548         }
549
550         return err;
551 }
552
553 static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
554                               unsigned int size)
555 {
556         int err;
557
558         if (listen_mode) {
559                 err = do_recvfile(peerfd, outfd);
560                 if (err)
561                         return err;
562
563                 err = do_sendfile(infd, peerfd, size);
564         } else {
565                 err = do_sendfile(infd, peerfd, size);
566                 if (err)
567                         return err;
568                 err = do_recvfile(peerfd, outfd);
569         }
570
571         return err;
572 }
573
574 static int copyfd_io(int infd, int peerfd, int outfd)
575 {
576         int file_size;
577
578         switch (cfg_mode) {
579         case CFG_MODE_POLL:
580                 return copyfd_io_poll(infd, peerfd, outfd);
581         case CFG_MODE_MMAP:
582                 file_size = get_infd_size(infd);
583                 if (file_size < 0)
584                         return file_size;
585                 return copyfd_io_mmap(infd, peerfd, outfd, file_size);
586         case CFG_MODE_SENDFILE:
587                 file_size = get_infd_size(infd);
588                 if (file_size < 0)
589                         return file_size;
590                 return copyfd_io_sendfile(infd, peerfd, outfd, file_size);
591         }
592
593         fprintf(stderr, "Invalid mode %d\n", cfg_mode);
594
595         die_usage();
596         return 1;
597 }
598
599 static void check_sockaddr(int pf, struct sockaddr_storage *ss,
600                            socklen_t salen)
601 {
602         struct sockaddr_in6 *sin6;
603         struct sockaddr_in *sin;
604         socklen_t wanted_size = 0;
605
606         switch (pf) {
607         case AF_INET:
608                 wanted_size = sizeof(*sin);
609                 sin = (void *)ss;
610                 if (!sin->sin_port)
611                         fprintf(stderr, "accept: something wrong: ip connection from port 0");
612                 break;
613         case AF_INET6:
614                 wanted_size = sizeof(*sin6);
615                 sin6 = (void *)ss;
616                 if (!sin6->sin6_port)
617                         fprintf(stderr, "accept: something wrong: ipv6 connection from port 0");
618                 break;
619         default:
620                 fprintf(stderr, "accept: Unknown pf %d, salen %u\n", pf, salen);
621                 return;
622         }
623
624         if (salen != wanted_size)
625                 fprintf(stderr, "accept: size mismatch, got %d expected %d\n",
626                         (int)salen, wanted_size);
627
628         if (ss->ss_family != pf)
629                 fprintf(stderr, "accept: pf mismatch, expect %d, ss_family is %d\n",
630                         (int)ss->ss_family, pf);
631 }
632
633 static void check_getpeername(int fd, struct sockaddr_storage *ss, socklen_t salen)
634 {
635         struct sockaddr_storage peerss;
636         socklen_t peersalen = sizeof(peerss);
637
638         if (getpeername(fd, (struct sockaddr *)&peerss, &peersalen) < 0) {
639                 perror("getpeername");
640                 return;
641         }
642
643         if (peersalen != salen) {
644                 fprintf(stderr, "%s: %d vs %d\n", __func__, peersalen, salen);
645                 return;
646         }
647
648         if (memcmp(ss, &peerss, peersalen)) {
649                 char a[INET6_ADDRSTRLEN];
650                 char b[INET6_ADDRSTRLEN];
651                 char c[INET6_ADDRSTRLEN];
652                 char d[INET6_ADDRSTRLEN];
653
654                 xgetnameinfo((struct sockaddr *)ss, salen,
655                              a, sizeof(a), b, sizeof(b));
656
657                 xgetnameinfo((struct sockaddr *)&peerss, peersalen,
658                              c, sizeof(c), d, sizeof(d));
659
660                 fprintf(stderr, "%s: memcmp failure: accept %s vs peername %s, %s vs %s salen %d vs %d\n",
661                         __func__, a, c, b, d, peersalen, salen);
662         }
663 }
664
665 static void check_getpeername_connect(int fd)
666 {
667         struct sockaddr_storage ss;
668         socklen_t salen = sizeof(ss);
669         char a[INET6_ADDRSTRLEN];
670         char b[INET6_ADDRSTRLEN];
671
672         if (getpeername(fd, (struct sockaddr *)&ss, &salen) < 0) {
673                 perror("getpeername");
674                 return;
675         }
676
677         xgetnameinfo((struct sockaddr *)&ss, salen,
678                      a, sizeof(a), b, sizeof(b));
679
680         if (strcmp(cfg_host, a) || strcmp(cfg_port, b))
681                 fprintf(stderr, "%s: %s vs %s, %s vs %s\n", __func__,
682                         cfg_host, a, cfg_port, b);
683 }
684
685 static void maybe_close(int fd)
686 {
687         unsigned int r = rand();
688
689         if (!cfg_join && (r & 1))
690                 close(fd);
691 }
692
693 int main_loop_s(int listensock)
694 {
695         struct sockaddr_storage ss;
696         struct pollfd polls;
697         socklen_t salen;
698         int remotesock;
699
700         polls.fd = listensock;
701         polls.events = POLLIN;
702
703         switch (poll(&polls, 1, poll_timeout)) {
704         case -1:
705                 perror("poll");
706                 return 1;
707         case 0:
708                 fprintf(stderr, "%s: timed out\n", __func__);
709                 close(listensock);
710                 return 2;
711         }
712
713         salen = sizeof(ss);
714         remotesock = accept(listensock, (struct sockaddr *)&ss, &salen);
715         if (remotesock >= 0) {
716                 maybe_close(listensock);
717                 check_sockaddr(pf, &ss, salen);
718                 check_getpeername(remotesock, &ss, salen);
719
720                 return copyfd_io(0, remotesock, 1);
721         }
722
723         perror("accept");
724
725         return 1;
726 }
727
728 static void init_rng(void)
729 {
730         int fd = open("/dev/urandom", O_RDONLY);
731         unsigned int foo;
732
733         if (fd > 0) {
734                 int ret = read(fd, &foo, sizeof(foo));
735
736                 if (ret < 0)
737                         srand(fd + foo);
738                 close(fd);
739         }
740
741         srand(foo);
742 }
743
744 int main_loop(void)
745 {
746         int fd;
747
748         /* listener is ready. */
749         fd = sock_connect_mptcp(cfg_host, cfg_port, cfg_sock_proto);
750         if (fd < 0)
751                 return 2;
752
753         check_getpeername_connect(fd);
754
755         if (cfg_rcvbuf)
756                 set_rcvbuf(fd, cfg_rcvbuf);
757         if (cfg_sndbuf)
758                 set_sndbuf(fd, cfg_sndbuf);
759
760         return copyfd_io(0, fd, 1);
761 }
762
763 int parse_proto(const char *proto)
764 {
765         if (!strcasecmp(proto, "MPTCP"))
766                 return IPPROTO_MPTCP;
767         if (!strcasecmp(proto, "TCP"))
768                 return IPPROTO_TCP;
769
770         fprintf(stderr, "Unknown protocol: %s\n.", proto);
771         die_usage();
772
773         /* silence compiler warning */
774         return 0;
775 }
776
777 int parse_mode(const char *mode)
778 {
779         if (!strcasecmp(mode, "poll"))
780                 return CFG_MODE_POLL;
781         if (!strcasecmp(mode, "mmap"))
782                 return CFG_MODE_MMAP;
783         if (!strcasecmp(mode, "sendfile"))
784                 return CFG_MODE_SENDFILE;
785
786         fprintf(stderr, "Unknown test mode: %s\n", mode);
787         fprintf(stderr, "Supported modes are:\n");
788         fprintf(stderr, "\t\t\"poll\" - interleaved read/write using poll()\n");
789         fprintf(stderr, "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n");
790         fprintf(stderr, "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n");
791
792         die_usage();
793
794         /* silence compiler warning */
795         return 0;
796 }
797
798 static int parse_int(const char *size)
799 {
800         unsigned long s;
801
802         errno = 0;
803
804         s = strtoul(size, NULL, 0);
805
806         if (errno) {
807                 fprintf(stderr, "Invalid sndbuf size %s (%s)\n",
808                         size, strerror(errno));
809                 die_usage();
810         }
811
812         if (s > INT_MAX) {
813                 fprintf(stderr, "Invalid sndbuf size %s (%s)\n",
814                         size, strerror(ERANGE));
815                 die_usage();
816         }
817
818         return (int)s;
819 }
820
821 static void parse_opts(int argc, char **argv)
822 {
823         int c;
824
825         while ((c = getopt(argc, argv, "6jlp:s:hut:m:S:R:w:")) != -1) {
826                 switch (c) {
827                 case 'j':
828                         cfg_join = true;
829                         cfg_mode = CFG_MODE_POLL;
830                         cfg_wait = 400000;
831                         break;
832                 case 'l':
833                         listen_mode = true;
834                         break;
835                 case 'p':
836                         cfg_port = optarg;
837                         break;
838                 case 's':
839                         cfg_sock_proto = parse_proto(optarg);
840                         break;
841                 case 'h':
842                         die_usage();
843                         break;
844                 case 'u':
845                         tcpulp_audit = true;
846                         break;
847                 case '6':
848                         pf = AF_INET6;
849                         break;
850                 case 't':
851                         poll_timeout = atoi(optarg) * 1000;
852                         if (poll_timeout <= 0)
853                                 poll_timeout = -1;
854                         break;
855                 case 'm':
856                         cfg_mode = parse_mode(optarg);
857                         break;
858                 case 'S':
859                         cfg_sndbuf = parse_int(optarg);
860                         break;
861                 case 'R':
862                         cfg_rcvbuf = parse_int(optarg);
863                         break;
864                 case 'w':
865                         cfg_wait = atoi(optarg)*1000000;
866                         break;
867                 }
868         }
869
870         if (optind + 1 != argc)
871                 die_usage();
872         cfg_host = argv[optind];
873
874         if (strchr(cfg_host, ':'))
875                 pf = AF_INET6;
876 }
877
878 int main(int argc, char *argv[])
879 {
880         init_rng();
881
882         signal(SIGUSR1, handle_signal);
883         parse_opts(argc, argv);
884
885         if (tcpulp_audit)
886                 return sock_test_tcpulp(cfg_host, cfg_port) ? 0 : 1;
887
888         if (listen_mode) {
889                 int fd = sock_listen_mptcp(cfg_host, cfg_port);
890
891                 if (fd < 0)
892                         return 1;
893
894                 if (cfg_rcvbuf)
895                         set_rcvbuf(fd, cfg_rcvbuf);
896                 if (cfg_sndbuf)
897                         set_sndbuf(fd, cfg_sndbuf);
898
899                 return main_loop_s(fd);
900         }
901
902         return main_loop();
903 }