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-m [MPTCP|TCP] -- use tcp or mptcp sockets\n");
69 	fprintf(stderr, "\t-s [mmap|poll] -- use poll (default) or mmap\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
410 				 */
411 				if (cfg_join)
412 					usleep(400000);
413 				shutdown(peerfd, SHUT_WR);
414 			} else {
415 				if (errno == EINTR)
416 					continue;
417 				perror("read");
418 				return 4;
419 			}
420 		}
421 
422 		if (fds.revents & (POLLERR | POLLNVAL)) {
423 			fprintf(stderr, "Unexpected revents: "
424 				"POLLERR/POLLNVAL(%x)\n", fds.revents);
425 			return 5;
426 		}
427 	}
428 
429 	/* leave some time for late join/announce */
430 	if (cfg_wait)
431 		usleep(cfg_wait);
432 
433 	close(peerfd);
434 	return 0;
435 }
436 
437 static int do_recvfile(int infd, int outfd)
438 {
439 	ssize_t r;
440 
441 	do {
442 		char buf[16384];
443 
444 		r = do_rnd_read(infd, buf, sizeof(buf));
445 		if (r > 0) {
446 			if (write(outfd, buf, r) != r)
447 				break;
448 		} else if (r < 0) {
449 			perror("read");
450 		}
451 	} while (r > 0);
452 
453 	return (int)r;
454 }
455 
456 static int do_mmap(int infd, int outfd, unsigned int size)
457 {
458 	char *inbuf = mmap(NULL, size, PROT_READ, MAP_SHARED, infd, 0);
459 	ssize_t ret = 0, off = 0;
460 	size_t rem;
461 
462 	if (inbuf == MAP_FAILED) {
463 		perror("mmap");
464 		return 1;
465 	}
466 
467 	rem = size;
468 
469 	while (rem > 0) {
470 		ret = write(outfd, inbuf + off, rem);
471 
472 		if (ret < 0) {
473 			perror("write");
474 			break;
475 		}
476 
477 		off += ret;
478 		rem -= ret;
479 	}
480 
481 	munmap(inbuf, size);
482 	return rem;
483 }
484 
485 static int get_infd_size(int fd)
486 {
487 	struct stat sb;
488 	ssize_t count;
489 	int err;
490 
491 	err = fstat(fd, &sb);
492 	if (err < 0) {
493 		perror("fstat");
494 		return -1;
495 	}
496 
497 	if ((sb.st_mode & S_IFMT) != S_IFREG) {
498 		fprintf(stderr, "%s: stdin is not a regular file\n", __func__);
499 		return -2;
500 	}
501 
502 	count = sb.st_size;
503 	if (count > INT_MAX) {
504 		fprintf(stderr, "File too large: %zu\n", count);
505 		return -3;
506 	}
507 
508 	return (int)count;
509 }
510 
511 static int do_sendfile(int infd, int outfd, unsigned int count)
512 {
513 	while (count > 0) {
514 		ssize_t r;
515 
516 		r = sendfile(outfd, infd, NULL, count);
517 		if (r < 0) {
518 			perror("sendfile");
519 			return 3;
520 		}
521 
522 		count -= r;
523 	}
524 
525 	return 0;
526 }
527 
528 static int copyfd_io_mmap(int infd, int peerfd, int outfd,
529 			  unsigned int size)
530 {
531 	int err;
532 
533 	if (listen_mode) {
534 		err = do_recvfile(peerfd, outfd);
535 		if (err)
536 			return err;
537 
538 		err = do_mmap(infd, peerfd, size);
539 	} else {
540 		err = do_mmap(infd, peerfd, size);
541 		if (err)
542 			return err;
543 
544 		shutdown(peerfd, SHUT_WR);
545 
546 		err = do_recvfile(peerfd, outfd);
547 	}
548 
549 	return err;
550 }
551 
552 static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
553 			      unsigned int size)
554 {
555 	int err;
556 
557 	if (listen_mode) {
558 		err = do_recvfile(peerfd, outfd);
559 		if (err)
560 			return err;
561 
562 		err = do_sendfile(infd, peerfd, size);
563 	} else {
564 		err = do_sendfile(infd, peerfd, size);
565 		if (err)
566 			return err;
567 		err = do_recvfile(peerfd, outfd);
568 	}
569 
570 	return err;
571 }
572 
573 static int copyfd_io(int infd, int peerfd, int outfd)
574 {
575 	int file_size;
576 
577 	switch (cfg_mode) {
578 	case CFG_MODE_POLL:
579 		return copyfd_io_poll(infd, peerfd, outfd);
580 	case CFG_MODE_MMAP:
581 		file_size = get_infd_size(infd);
582 		if (file_size < 0)
583 			return file_size;
584 		return copyfd_io_mmap(infd, peerfd, outfd, file_size);
585 	case CFG_MODE_SENDFILE:
586 		file_size = get_infd_size(infd);
587 		if (file_size < 0)
588 			return file_size;
589 		return copyfd_io_sendfile(infd, peerfd, outfd, file_size);
590 	}
591 
592 	fprintf(stderr, "Invalid mode %d\n", cfg_mode);
593 
594 	die_usage();
595 	return 1;
596 }
597 
598 static void check_sockaddr(int pf, struct sockaddr_storage *ss,
599 			   socklen_t salen)
600 {
601 	struct sockaddr_in6 *sin6;
602 	struct sockaddr_in *sin;
603 	socklen_t wanted_size = 0;
604 
605 	switch (pf) {
606 	case AF_INET:
607 		wanted_size = sizeof(*sin);
608 		sin = (void *)ss;
609 		if (!sin->sin_port)
610 			fprintf(stderr, "accept: something wrong: ip connection from port 0");
611 		break;
612 	case AF_INET6:
613 		wanted_size = sizeof(*sin6);
614 		sin6 = (void *)ss;
615 		if (!sin6->sin6_port)
616 			fprintf(stderr, "accept: something wrong: ipv6 connection from port 0");
617 		break;
618 	default:
619 		fprintf(stderr, "accept: Unknown pf %d, salen %u\n", pf, salen);
620 		return;
621 	}
622 
623 	if (salen != wanted_size)
624 		fprintf(stderr, "accept: size mismatch, got %d expected %d\n",
625 			(int)salen, wanted_size);
626 
627 	if (ss->ss_family != pf)
628 		fprintf(stderr, "accept: pf mismatch, expect %d, ss_family is %d\n",
629 			(int)ss->ss_family, pf);
630 }
631 
632 static void check_getpeername(int fd, struct sockaddr_storage *ss, socklen_t salen)
633 {
634 	struct sockaddr_storage peerss;
635 	socklen_t peersalen = sizeof(peerss);
636 
637 	if (getpeername(fd, (struct sockaddr *)&peerss, &peersalen) < 0) {
638 		perror("getpeername");
639 		return;
640 	}
641 
642 	if (peersalen != salen) {
643 		fprintf(stderr, "%s: %d vs %d\n", __func__, peersalen, salen);
644 		return;
645 	}
646 
647 	if (memcmp(ss, &peerss, peersalen)) {
648 		char a[INET6_ADDRSTRLEN];
649 		char b[INET6_ADDRSTRLEN];
650 		char c[INET6_ADDRSTRLEN];
651 		char d[INET6_ADDRSTRLEN];
652 
653 		xgetnameinfo((struct sockaddr *)ss, salen,
654 			     a, sizeof(a), b, sizeof(b));
655 
656 		xgetnameinfo((struct sockaddr *)&peerss, peersalen,
657 			     c, sizeof(c), d, sizeof(d));
658 
659 		fprintf(stderr, "%s: memcmp failure: accept %s vs peername %s, %s vs %s salen %d vs %d\n",
660 			__func__, a, c, b, d, peersalen, salen);
661 	}
662 }
663 
664 static void check_getpeername_connect(int fd)
665 {
666 	struct sockaddr_storage ss;
667 	socklen_t salen = sizeof(ss);
668 	char a[INET6_ADDRSTRLEN];
669 	char b[INET6_ADDRSTRLEN];
670 
671 	if (getpeername(fd, (struct sockaddr *)&ss, &salen) < 0) {
672 		perror("getpeername");
673 		return;
674 	}
675 
676 	xgetnameinfo((struct sockaddr *)&ss, salen,
677 		     a, sizeof(a), b, sizeof(b));
678 
679 	if (strcmp(cfg_host, a) || strcmp(cfg_port, b))
680 		fprintf(stderr, "%s: %s vs %s, %s vs %s\n", __func__,
681 			cfg_host, a, cfg_port, b);
682 }
683 
684 static void maybe_close(int fd)
685 {
686 	unsigned int r = rand();
687 
688 	if (!cfg_join && (r & 1))
689 		close(fd);
690 }
691 
692 int main_loop_s(int listensock)
693 {
694 	struct sockaddr_storage ss;
695 	struct pollfd polls;
696 	socklen_t salen;
697 	int remotesock;
698 
699 	polls.fd = listensock;
700 	polls.events = POLLIN;
701 
702 	switch (poll(&polls, 1, poll_timeout)) {
703 	case -1:
704 		perror("poll");
705 		return 1;
706 	case 0:
707 		fprintf(stderr, "%s: timed out\n", __func__);
708 		close(listensock);
709 		return 2;
710 	}
711 
712 	salen = sizeof(ss);
713 	remotesock = accept(listensock, (struct sockaddr *)&ss, &salen);
714 	if (remotesock >= 0) {
715 		maybe_close(listensock);
716 		check_sockaddr(pf, &ss, salen);
717 		check_getpeername(remotesock, &ss, salen);
718 
719 		return copyfd_io(0, remotesock, 1);
720 	}
721 
722 	perror("accept");
723 
724 	return 1;
725 }
726 
727 static void init_rng(void)
728 {
729 	int fd = open("/dev/urandom", O_RDONLY);
730 	unsigned int foo;
731 
732 	if (fd > 0) {
733 		int ret = read(fd, &foo, sizeof(foo));
734 
735 		if (ret < 0)
736 			srand(fd + foo);
737 		close(fd);
738 	}
739 
740 	srand(foo);
741 }
742 
743 int main_loop(void)
744 {
745 	int fd;
746 
747 	/* listener is ready. */
748 	fd = sock_connect_mptcp(cfg_host, cfg_port, cfg_sock_proto);
749 	if (fd < 0)
750 		return 2;
751 
752 	check_getpeername_connect(fd);
753 
754 	if (cfg_rcvbuf)
755 		set_rcvbuf(fd, cfg_rcvbuf);
756 	if (cfg_sndbuf)
757 		set_sndbuf(fd, cfg_sndbuf);
758 
759 	return copyfd_io(0, fd, 1);
760 }
761 
762 int parse_proto(const char *proto)
763 {
764 	if (!strcasecmp(proto, "MPTCP"))
765 		return IPPROTO_MPTCP;
766 	if (!strcasecmp(proto, "TCP"))
767 		return IPPROTO_TCP;
768 
769 	fprintf(stderr, "Unknown protocol: %s\n.", proto);
770 	die_usage();
771 
772 	/* silence compiler warning */
773 	return 0;
774 }
775 
776 int parse_mode(const char *mode)
777 {
778 	if (!strcasecmp(mode, "poll"))
779 		return CFG_MODE_POLL;
780 	if (!strcasecmp(mode, "mmap"))
781 		return CFG_MODE_MMAP;
782 	if (!strcasecmp(mode, "sendfile"))
783 		return CFG_MODE_SENDFILE;
784 
785 	fprintf(stderr, "Unknown test mode: %s\n", mode);
786 	fprintf(stderr, "Supported modes are:\n");
787 	fprintf(stderr, "\t\t\"poll\" - interleaved read/write using poll()\n");
788 	fprintf(stderr, "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n");
789 	fprintf(stderr, "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n");
790 
791 	die_usage();
792 
793 	/* silence compiler warning */
794 	return 0;
795 }
796 
797 static int parse_int(const char *size)
798 {
799 	unsigned long s;
800 
801 	errno = 0;
802 
803 	s = strtoul(size, NULL, 0);
804 
805 	if (errno) {
806 		fprintf(stderr, "Invalid sndbuf size %s (%s)\n",
807 			size, strerror(errno));
808 		die_usage();
809 	}
810 
811 	if (s > INT_MAX) {
812 		fprintf(stderr, "Invalid sndbuf size %s (%s)\n",
813 			size, strerror(ERANGE));
814 		die_usage();
815 	}
816 
817 	return (int)s;
818 }
819 
820 static void parse_opts(int argc, char **argv)
821 {
822 	int c;
823 
824 	while ((c = getopt(argc, argv, "6jlp:s:hut:m:S:R:w:")) != -1) {
825 		switch (c) {
826 		case 'j':
827 			cfg_join = true;
828 			cfg_mode = CFG_MODE_POLL;
829 			cfg_wait = 400000;
830 			break;
831 		case 'l':
832 			listen_mode = true;
833 			break;
834 		case 'p':
835 			cfg_port = optarg;
836 			break;
837 		case 's':
838 			cfg_sock_proto = parse_proto(optarg);
839 			break;
840 		case 'h':
841 			die_usage();
842 			break;
843 		case 'u':
844 			tcpulp_audit = true;
845 			break;
846 		case '6':
847 			pf = AF_INET6;
848 			break;
849 		case 't':
850 			poll_timeout = atoi(optarg) * 1000;
851 			if (poll_timeout <= 0)
852 				poll_timeout = -1;
853 			break;
854 		case 'm':
855 			cfg_mode = parse_mode(optarg);
856 			break;
857 		case 'S':
858 			cfg_sndbuf = parse_int(optarg);
859 			break;
860 		case 'R':
861 			cfg_rcvbuf = parse_int(optarg);
862 			break;
863 		case 'w':
864 			cfg_wait = atoi(optarg)*1000000;
865 			break;
866 		}
867 	}
868 
869 	if (optind + 1 != argc)
870 		die_usage();
871 	cfg_host = argv[optind];
872 
873 	if (strchr(cfg_host, ':'))
874 		pf = AF_INET6;
875 }
876 
877 int main(int argc, char *argv[])
878 {
879 	init_rng();
880 
881 	signal(SIGUSR1, handle_signal);
882 	parse_opts(argc, argv);
883 
884 	if (tcpulp_audit)
885 		return sock_test_tcpulp(cfg_host, cfg_port) ? 0 : 1;
886 
887 	if (listen_mode) {
888 		int fd = sock_listen_mptcp(cfg_host, cfg_port);
889 
890 		if (fd < 0)
891 			return 1;
892 
893 		if (cfg_rcvbuf)
894 			set_rcvbuf(fd, cfg_rcvbuf);
895 		if (cfg_sndbuf)
896 			set_sndbuf(fd, cfg_sndbuf);
897 
898 		return main_loop_s(fd);
899 	}
900 
901 	return main_loop();
902 }
903