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