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