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