1 // SPDX-License-Identifier: GPL-2.0
19 #include <sys/ioctl.h>
21 #include <sys/random.h>
22 #include <sys/sendfile.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
28 #include <arpa/inet.h>
31 #include <netinet/in.h>
33 #include <linux/tcp.h>
34 #include <linux/time_types.h>
35 #include <linux/sockios.h>
40 #define IPPROTO_MPTCP 262
46 static int poll_timeout
= 10 * 1000;
47 static bool listen_mode
;
62 static enum cfg_mode cfg_mode
= CFG_MODE_POLL
;
63 static enum cfg_peek cfg_peek
= CFG_NONE_PEEK
;
64 static const char *cfg_host
;
65 static const char *cfg_port
= "12000";
66 static int cfg_sock_proto
= IPPROTO_MPTCP
;
67 static int pf
= AF_INET
;
68 static int cfg_sndbuf
;
69 static int cfg_rcvbuf
;
71 static bool cfg_remove
;
72 static unsigned int cfg_time
;
73 static unsigned int cfg_do_w
;
75 static uint32_t cfg_mark
;
76 static char *cfg_input
;
77 static int cfg_repeat
= 1;
78 static int cfg_truncate
;
79 static int cfg_rcv_trunc
;
81 struct cfg_cmsg_types
{
82 unsigned int cmsg_enabled
:1;
83 unsigned int timestampns
:1;
84 unsigned int tcp_inq
:1;
87 struct cfg_sockopt_types
{
88 unsigned int transparent
:1;
92 struct tcp_inq_state
{
101 unsigned int total_len
;
104 static struct tcp_inq_state tcp_inq
;
106 static struct cfg_cmsg_types cfg_cmsg_types
;
107 static struct cfg_sockopt_types cfg_sockopt_types
;
109 static void die_usage(void)
111 fprintf(stderr
, "Usage: mptcp_connect [-6] [-c cmsg] [-f offset] [-i file] [-I num] [-j] [-l] "
112 "[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-r num] [-R num] "
113 "[-s MPTCP|TCP] [-S num] [-t num] [-T num] [-w sec] connect_address\n");
114 fprintf(stderr
, "\t-6 use ipv6\n");
115 fprintf(stderr
, "\t-c cmsg -- test cmsg type <cmsg>\n");
116 fprintf(stderr
, "\t-f offset -- stop the I/O after receiving and sending the specified amount "
117 "of bytes. If there are unread bytes in the receive queue, that will cause a MPTCP "
118 "fastclose at close/shutdown. If offset is negative, expect the peer to close before "
119 "all the local data as been sent, thus toleration errors on write and EPIPE signals\n");
120 fprintf(stderr
, "\t-i file -- read the data to send from the given file instead of stdin");
121 fprintf(stderr
, "\t-I num -- repeat the transfer 'num' times. In listen mode accepts num "
122 "incoming connections, in client mode, disconnect and reconnect to the server\n");
123 fprintf(stderr
, "\t-j -- add additional sleep at connection start and tear down "
124 "-- for MPJ tests\n");
125 fprintf(stderr
, "\t-l -- listens mode, accepts incoming connection\n");
126 fprintf(stderr
, "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n");
127 fprintf(stderr
, "\t-M mark -- set socket packet mark\n");
128 fprintf(stderr
, "\t-o option -- test sockopt <option>\n");
129 fprintf(stderr
, "\t-p num -- use port num\n");
131 "\t-P [saveWithPeek|saveAfterPeek] -- save data with/after MSG_PEEK form tcp socket\n");
132 fprintf(stderr
, "\t-r num -- enable slow mode, limiting each write to num bytes "
133 "-- for remove addr tests\n");
134 fprintf(stderr
, "\t-R num -- set SO_RCVBUF to num\n");
135 fprintf(stderr
, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\n");
136 fprintf(stderr
, "\t-S num -- set SO_SNDBUF to num\n");
137 fprintf(stderr
, "\t-t num -- set poll timeout to num\n");
138 fprintf(stderr
, "\t-T num -- set expected runtime to num ms\n");
139 fprintf(stderr
, "\t-w num -- wait num sec before closing the socket\n");
143 static void xerror(const char *fmt
, ...)
148 vfprintf(stderr
, fmt
, ap
);
153 static void handle_signal(int nr
)
158 static const char *getxinfo_strerr(int err
)
160 if (err
== EAI_SYSTEM
)
161 return strerror(errno
);
163 return gai_strerror(err
);
166 static void xgetnameinfo(const struct sockaddr
*addr
, socklen_t addrlen
,
167 char *host
, socklen_t hostlen
,
168 char *serv
, socklen_t servlen
)
170 int flags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
171 int err
= getnameinfo(addr
, addrlen
, host
, hostlen
, serv
, servlen
,
175 const char *errstr
= getxinfo_strerr(err
);
177 fprintf(stderr
, "Fatal: getnameinfo: %s\n", errstr
);
182 static void xgetaddrinfo(const char *node
, const char *service
,
183 const struct addrinfo
*hints
,
184 struct addrinfo
**res
)
186 int err
= getaddrinfo(node
, service
, hints
, res
);
189 const char *errstr
= getxinfo_strerr(err
);
191 fprintf(stderr
, "Fatal: getaddrinfo(%s:%s): %s\n",
192 node
? node
: "", service
? service
: "", errstr
);
197 static void set_rcvbuf(int fd
, unsigned int size
)
201 err
= setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &size
, sizeof(size
));
203 perror("set SO_RCVBUF");
208 static void set_sndbuf(int fd
, unsigned int size
)
212 err
= setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &size
, sizeof(size
));
214 perror("set SO_SNDBUF");
219 static void set_mark(int fd
, uint32_t mark
)
223 err
= setsockopt(fd
, SOL_SOCKET
, SO_MARK
, &mark
, sizeof(mark
));
225 perror("set SO_MARK");
230 static void set_transparent(int fd
, int pf
)
236 if (-1 == setsockopt(fd
, SOL_IP
, IP_TRANSPARENT
, &one
, sizeof(one
)))
237 perror("IP_TRANSPARENT");
240 if (-1 == setsockopt(fd
, IPPROTO_IPV6
, IPV6_TRANSPARENT
, &one
, sizeof(one
)))
241 perror("IPV6_TRANSPARENT");
246 static void set_mptfo(int fd
, int pf
)
250 if (setsockopt(fd
, IPPROTO_TCP
, TCP_FASTOPEN
, &qlen
, sizeof(qlen
)) == -1)
251 perror("TCP_FASTOPEN");
254 static int do_ulp_so(int sock
, const char *name
)
256 return setsockopt(sock
, IPPROTO_TCP
, TCP_ULP
, name
, strlen(name
));
259 #define X(m) xerror("%s:%u: %s: failed for proto %d at line %u", __FILE__, __LINE__, (m), proto, line)
260 static void sock_test_tcpulp(int sock
, int proto
, unsigned int line
)
262 socklen_t buflen
= 8;
264 int ret
= getsockopt(sock
, IPPROTO_TCP
, TCP_ULP
, buf
, &buflen
);
270 if (strcmp(buf
, "mptcp") != 0)
271 xerror("unexpected ULP '%s' for proto %d at line %u", buf
, proto
, line
);
272 ret
= do_ulp_so(sock
, "tls");
275 } else if (proto
== IPPROTO_MPTCP
) {
276 ret
= do_ulp_so(sock
, "tls");
281 ret
= do_ulp_so(sock
, "mptcp");
288 #define SOCK_TEST_TCPULP(s, p) sock_test_tcpulp((s), (p), __LINE__)
290 static int sock_listen_mptcp(const char * const listenaddr
,
291 const char * const port
)
294 struct addrinfo hints
= {
295 .ai_protocol
= IPPROTO_TCP
,
296 .ai_socktype
= SOCK_STREAM
,
297 .ai_flags
= AI_PASSIVE
| AI_NUMERICHOST
300 hints
.ai_family
= pf
;
302 struct addrinfo
*a
, *addr
;
305 xgetaddrinfo(listenaddr
, port
, &hints
, &addr
);
306 hints
.ai_family
= pf
;
308 for (a
= addr
; a
; a
= a
->ai_next
) {
309 sock
= socket(a
->ai_family
, a
->ai_socktype
, cfg_sock_proto
);
313 SOCK_TEST_TCPULP(sock
, cfg_sock_proto
);
315 if (-1 == setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &one
,
317 perror("setsockopt");
319 if (cfg_sockopt_types
.transparent
)
320 set_transparent(sock
, pf
);
322 if (cfg_sockopt_types
.mptfo
)
325 if (bind(sock
, a
->ai_addr
, a
->ai_addrlen
) == 0)
336 fprintf(stderr
, "Could not create listen socket\n");
340 SOCK_TEST_TCPULP(sock
, cfg_sock_proto
);
342 if (listen(sock
, 20)) {
348 SOCK_TEST_TCPULP(sock
, cfg_sock_proto
);
353 static int sock_connect_mptcp(const char * const remoteaddr
,
354 const char * const port
, int proto
,
355 struct addrinfo
**peer
,
356 int infd
, struct wstate
*winfo
)
358 struct addrinfo hints
= {
359 .ai_protocol
= IPPROTO_TCP
,
360 .ai_socktype
= SOCK_STREAM
,
362 struct addrinfo
*a
, *addr
;
366 hints
.ai_family
= pf
;
368 xgetaddrinfo(remoteaddr
, port
, &hints
, &addr
);
369 for (a
= addr
; a
; a
= a
->ai_next
) {
370 sock
= socket(a
->ai_family
, a
->ai_socktype
, proto
);
376 SOCK_TEST_TCPULP(sock
, proto
);
379 set_mark(sock
, cfg_mark
);
381 if (cfg_sockopt_types
.mptfo
) {
382 if (!winfo
->total_len
)
383 winfo
->total_len
= winfo
->len
= read(infd
, winfo
->buf
,
386 syn_copied
= sendto(sock
, winfo
->buf
, winfo
->len
, MSG_FASTOPEN
,
387 a
->ai_addr
, a
->ai_addrlen
);
388 if (syn_copied
>= 0) {
389 winfo
->off
= syn_copied
;
390 winfo
->len
-= syn_copied
;
395 if (connect(sock
, a
->ai_addr
, a
->ai_addrlen
) == 0) {
400 if (cfg_sockopt_types
.mptfo
) {
413 SOCK_TEST_TCPULP(sock
, proto
);
417 static size_t do_rnd_write(const int fd
, char *buf
, const size_t len
)
419 static bool first
= true;
423 do_w
= rand() & 0xffff;
424 if (do_w
== 0 || do_w
> len
)
427 if (cfg_join
&& first
&& do_w
> 100)
430 if (cfg_remove
&& do_w
> cfg_do_w
)
433 bw
= write(fd
, buf
, do_w
);
437 /* let the join handshake complete, before going on */
438 if (cfg_join
&& first
) {
449 static size_t do_write(const int fd
, char *buf
, const size_t len
)
453 while (offset
< len
) {
457 bw
= write(fd
, buf
+ offset
, len
- offset
);
463 written
= (size_t)bw
;
470 static void process_cmsg(struct msghdr
*msgh
)
472 struct __kernel_timespec ts
;
473 bool inq_found
= false;
474 bool ts_found
= false;
475 unsigned int inq
= 0;
476 struct cmsghdr
*cmsg
;
478 for (cmsg
= CMSG_FIRSTHDR(msgh
); cmsg
; cmsg
= CMSG_NXTHDR(msgh
, cmsg
)) {
479 if (cmsg
->cmsg_level
== SOL_SOCKET
&& cmsg
->cmsg_type
== SO_TIMESTAMPNS_NEW
) {
480 memcpy(&ts
, CMSG_DATA(cmsg
), sizeof(ts
));
484 if (cmsg
->cmsg_level
== IPPROTO_TCP
&& cmsg
->cmsg_type
== TCP_CM_INQ
) {
485 memcpy(&inq
, CMSG_DATA(cmsg
), sizeof(inq
));
492 if (cfg_cmsg_types
.timestampns
) {
494 xerror("TIMESTAMPNS not present\n");
497 if (cfg_cmsg_types
.tcp_inq
) {
499 xerror("TCP_INQ not present\n");
502 xerror("tcp_inq %u is larger than one kbyte\n", inq
);
507 static ssize_t
do_recvmsg_cmsg(const int fd
, char *buf
, const size_t len
)
514 struct msghdr msg
= {
517 .msg_control
= msg_buf
,
518 .msg_controllen
= sizeof(msg_buf
),
521 unsigned int last_hint
= tcp_inq
.last
;
522 int ret
= recvmsg(fd
, &msg
, flags
);
525 if (ret
== 0 && tcp_inq
.expect_eof
)
528 if (ret
== 0 && cfg_cmsg_types
.tcp_inq
)
529 if (last_hint
!= 1 && last_hint
!= 0)
530 xerror("EOF but last tcp_inq hint was %u\n", last_hint
);
535 if (tcp_inq
.expect_eof
)
536 xerror("expected EOF, last_hint %u, now %u\n",
537 last_hint
, tcp_inq
.last
);
539 if (msg
.msg_controllen
&& !cfg_cmsg_types
.cmsg_enabled
)
540 xerror("got %lu bytes of cmsg data, expected 0\n",
541 (unsigned long)msg
.msg_controllen
);
543 if (msg
.msg_controllen
== 0 && cfg_cmsg_types
.cmsg_enabled
)
544 xerror("%s\n", "got no cmsg data");
546 if (msg
.msg_controllen
)
549 if (cfg_cmsg_types
.tcp_inq
) {
550 if ((size_t)ret
< len
&& last_hint
> (unsigned int)ret
) {
551 if (ret
+ 1 != (int)last_hint
) {
552 int next
= read(fd
, msg_buf
, sizeof(msg_buf
));
554 xerror("read %u of %u, last_hint was %u tcp_inq hint now %u next_read returned %d/%m\n",
555 ret
, (unsigned int)len
, last_hint
, tcp_inq
.last
, next
);
557 tcp_inq
.expect_eof
= true;
565 static ssize_t
do_rnd_read(const int fd
, char *buf
, const size_t len
)
578 if (cfg_peek
== CFG_WITH_PEEK
) {
579 ret
= recv(fd
, buf
, cap
, MSG_PEEK
);
580 ret
= (ret
< 0) ? ret
: read(fd
, tmp
, ret
);
581 } else if (cfg_peek
== CFG_AFTER_PEEK
) {
582 ret
= recv(fd
, buf
, cap
, MSG_PEEK
);
583 ret
= (ret
< 0) ? ret
: read(fd
, buf
, cap
);
584 } else if (cfg_cmsg_types
.cmsg_enabled
) {
585 ret
= do_recvmsg_cmsg(fd
, buf
, cap
);
587 ret
= read(fd
, buf
, cap
);
593 static void set_nonblock(int fd
, bool nonblock
)
595 int flags
= fcntl(fd
, F_GETFL
);
601 fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
);
603 fcntl(fd
, F_SETFL
, flags
& ~O_NONBLOCK
);
606 static void shut_wr(int fd
)
608 /* Close our write side, ev. give some time
609 * for address notification and/or checking
615 shutdown(fd
, SHUT_WR
);
618 static int copyfd_io_poll(int infd
, int peerfd
, int outfd
,
619 bool *in_closed_after_out
, struct wstate
*winfo
)
621 struct pollfd fds
= {
623 .events
= POLLIN
| POLLOUT
,
625 unsigned int total_wlen
= 0, total_rlen
= 0;
627 set_nonblock(peerfd
, true);
633 if (fds
.events
== 0 || quit
)
636 switch (poll(&fds
, 1, poll_timeout
)) {
643 fprintf(stderr
, "%s: poll timed out (events: "
644 "POLLIN %u, POLLOUT %u)\n", __func__
,
645 fds
.events
& POLLIN
, fds
.events
& POLLOUT
);
649 if (fds
.revents
& POLLIN
) {
650 ssize_t rb
= sizeof(rbuf
);
652 /* limit the total amount of read data to the trunc value*/
653 if (cfg_truncate
> 0) {
654 if (rb
+ total_rlen
> cfg_truncate
)
655 rb
= cfg_truncate
- total_rlen
;
656 len
= read(peerfd
, rbuf
, rb
);
658 len
= do_rnd_read(peerfd
, rbuf
, sizeof(rbuf
));
661 /* no more data to receive:
662 * peer has closed its write side
664 fds
.events
&= ~POLLIN
;
666 if ((fds
.events
& POLLOUT
) == 0) {
667 *in_closed_after_out
= true;
668 /* and nothing more to send */
672 /* Else, still have data to transmit */
673 } else if (len
< 0) {
681 do_write(outfd
, rbuf
, len
);
684 if (fds
.revents
& POLLOUT
) {
685 if (winfo
->len
== 0) {
687 winfo
->len
= read(infd
, winfo
->buf
, sizeof(winfo
->buf
));
690 if (winfo
->len
> 0) {
693 /* limit the total amount of written data to the trunc value */
694 if (cfg_truncate
> 0 && winfo
->len
+ total_wlen
> cfg_truncate
)
695 winfo
->len
= cfg_truncate
- total_wlen
;
697 bw
= do_rnd_write(peerfd
, winfo
->buf
+ winfo
->off
, winfo
->len
);
708 } else if (winfo
->len
== 0) {
709 /* We have no more data to send. */
710 fds
.events
&= ~POLLOUT
;
712 if ((fds
.events
& POLLIN
) == 0)
713 /* ... and peer also closed already */
725 if (fds
.revents
& (POLLERR
| POLLNVAL
)) {
728 fprintf(stderr
, "Unexpected revents: "
729 "POLLERR/POLLNVAL(%x)\n", fds
.revents
);
733 if (cfg_truncate
> 0 && total_wlen
>= cfg_truncate
&&
734 total_rlen
>= cfg_truncate
)
738 /* leave some time for late join/announce */
739 if (cfg_remove
&& !quit
)
745 static int do_recvfile(int infd
, int outfd
)
752 r
= do_rnd_read(infd
, buf
, sizeof(buf
));
754 if (write(outfd
, buf
, r
) != r
)
764 static int spool_buf(int fd
, struct wstate
*winfo
)
767 int ret
= write(fd
, winfo
->buf
+ winfo
->off
, winfo
->len
);
779 static int do_mmap(int infd
, int outfd
, unsigned int size
,
780 struct wstate
*winfo
)
782 char *inbuf
= mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, infd
, 0);
783 ssize_t ret
= 0, off
= winfo
->total_len
;
786 if (inbuf
== MAP_FAILED
) {
791 ret
= spool_buf(outfd
, winfo
);
795 rem
= size
- winfo
->total_len
;
798 ret
= write(outfd
, inbuf
+ off
, rem
);
813 static int get_infd_size(int fd
)
819 err
= fstat(fd
, &sb
);
825 if ((sb
.st_mode
& S_IFMT
) != S_IFREG
) {
826 fprintf(stderr
, "%s: stdin is not a regular file\n", __func__
);
831 if (count
> INT_MAX
) {
832 fprintf(stderr
, "File too large: %zu\n", count
);
839 static int do_sendfile(int infd
, int outfd
, unsigned int count
,
840 struct wstate
*winfo
)
842 int ret
= spool_buf(outfd
, winfo
);
847 count
-= winfo
->total_len
;
852 r
= sendfile(outfd
, infd
, NULL
, count
);
864 static int copyfd_io_mmap(int infd
, int peerfd
, int outfd
,
865 unsigned int size
, bool *in_closed_after_out
,
866 struct wstate
*winfo
)
871 err
= do_recvfile(peerfd
, outfd
);
875 err
= do_mmap(infd
, peerfd
, size
, winfo
);
877 err
= do_mmap(infd
, peerfd
, size
, winfo
);
883 err
= do_recvfile(peerfd
, outfd
);
884 *in_closed_after_out
= true;
890 static int copyfd_io_sendfile(int infd
, int peerfd
, int outfd
,
891 unsigned int size
, bool *in_closed_after_out
, struct wstate
*winfo
)
896 err
= do_recvfile(peerfd
, outfd
);
900 err
= do_sendfile(infd
, peerfd
, size
, winfo
);
902 err
= do_sendfile(infd
, peerfd
, size
, winfo
);
908 err
= do_recvfile(peerfd
, outfd
);
909 *in_closed_after_out
= true;
915 static int copyfd_io(int infd
, int peerfd
, int outfd
, bool close_peerfd
, struct wstate
*winfo
)
917 bool in_closed_after_out
= false;
918 struct timespec start
, end
;
922 if (cfg_time
&& (clock_gettime(CLOCK_MONOTONIC
, &start
) < 0))
923 xerror("can not fetch start time %d", errno
);
927 ret
= copyfd_io_poll(infd
, peerfd
, outfd
, &in_closed_after_out
,
932 file_size
= get_infd_size(infd
);
935 ret
= copyfd_io_mmap(infd
, peerfd
, outfd
, file_size
,
936 &in_closed_after_out
, winfo
);
939 case CFG_MODE_SENDFILE
:
940 file_size
= get_infd_size(infd
);
943 ret
= copyfd_io_sendfile(infd
, peerfd
, outfd
, file_size
,
944 &in_closed_after_out
, winfo
);
948 fprintf(stderr
, "Invalid mode %d\n", cfg_mode
);
961 unsigned int delta_ms
;
963 if (clock_gettime(CLOCK_MONOTONIC
, &end
) < 0)
964 xerror("can not fetch end time %d", errno
);
965 delta_ms
= (end
.tv_sec
- start
.tv_sec
) * 1000 + (end
.tv_nsec
- start
.tv_nsec
) / 1000000;
966 if (delta_ms
> cfg_time
) {
967 xerror("transfer slower than expected! runtime %d ms, expected %d ms",
971 /* show the runtime only if this end shutdown(wr) before receiving the EOF,
972 * (that is, if this end got the longer runtime)
974 if (in_closed_after_out
)
975 fprintf(stderr
, "%d", delta_ms
);
981 static void check_sockaddr(int pf
, struct sockaddr_storage
*ss
,
984 struct sockaddr_in6
*sin6
;
985 struct sockaddr_in
*sin
;
986 socklen_t wanted_size
= 0;
990 wanted_size
= sizeof(*sin
);
993 fprintf(stderr
, "accept: something wrong: ip connection from port 0");
996 wanted_size
= sizeof(*sin6
);
998 if (!sin6
->sin6_port
)
999 fprintf(stderr
, "accept: something wrong: ipv6 connection from port 0");
1002 fprintf(stderr
, "accept: Unknown pf %d, salen %u\n", pf
, salen
);
1006 if (salen
!= wanted_size
)
1007 fprintf(stderr
, "accept: size mismatch, got %d expected %d\n",
1008 (int)salen
, wanted_size
);
1010 if (ss
->ss_family
!= pf
)
1011 fprintf(stderr
, "accept: pf mismatch, expect %d, ss_family is %d\n",
1012 (int)ss
->ss_family
, pf
);
1015 static void check_getpeername(int fd
, struct sockaddr_storage
*ss
, socklen_t salen
)
1017 struct sockaddr_storage peerss
;
1018 socklen_t peersalen
= sizeof(peerss
);
1020 if (getpeername(fd
, (struct sockaddr
*)&peerss
, &peersalen
) < 0) {
1021 perror("getpeername");
1025 if (peersalen
!= salen
) {
1026 fprintf(stderr
, "%s: %d vs %d\n", __func__
, peersalen
, salen
);
1030 if (memcmp(ss
, &peerss
, peersalen
)) {
1031 char a
[INET6_ADDRSTRLEN
];
1032 char b
[INET6_ADDRSTRLEN
];
1033 char c
[INET6_ADDRSTRLEN
];
1034 char d
[INET6_ADDRSTRLEN
];
1036 xgetnameinfo((struct sockaddr
*)ss
, salen
,
1037 a
, sizeof(a
), b
, sizeof(b
));
1039 xgetnameinfo((struct sockaddr
*)&peerss
, peersalen
,
1040 c
, sizeof(c
), d
, sizeof(d
));
1042 fprintf(stderr
, "%s: memcmp failure: accept %s vs peername %s, %s vs %s salen %d vs %d\n",
1043 __func__
, a
, c
, b
, d
, peersalen
, salen
);
1047 static void check_getpeername_connect(int fd
)
1049 struct sockaddr_storage ss
;
1050 socklen_t salen
= sizeof(ss
);
1051 char a
[INET6_ADDRSTRLEN
];
1052 char b
[INET6_ADDRSTRLEN
];
1054 if (getpeername(fd
, (struct sockaddr
*)&ss
, &salen
) < 0) {
1055 perror("getpeername");
1059 xgetnameinfo((struct sockaddr
*)&ss
, salen
,
1060 a
, sizeof(a
), b
, sizeof(b
));
1062 if (strcmp(cfg_host
, a
) || strcmp(cfg_port
, b
))
1063 fprintf(stderr
, "%s: %s vs %s, %s vs %s\n", __func__
,
1064 cfg_host
, a
, cfg_port
, b
);
1067 static void maybe_close(int fd
)
1069 unsigned int r
= rand();
1071 if (!(cfg_join
|| cfg_remove
|| cfg_repeat
> 1) && (r
& 1))
1075 int main_loop_s(int listensock
)
1077 struct sockaddr_storage ss
;
1078 struct wstate winfo
;
1079 struct pollfd polls
;
1085 polls
.fd
= listensock
;
1086 polls
.events
= POLLIN
;
1088 switch (poll(&polls
, 1, poll_timeout
)) {
1093 fprintf(stderr
, "%s: timed out\n", __func__
);
1099 remotesock
= accept(listensock
, (struct sockaddr
*)&ss
, &salen
);
1100 if (remotesock
>= 0) {
1101 maybe_close(listensock
);
1102 check_sockaddr(pf
, &ss
, salen
);
1103 check_getpeername(remotesock
, &ss
, salen
);
1106 fd
= open(cfg_input
, O_RDONLY
);
1108 xerror("can't open %s: %d", cfg_input
, errno
);
1111 SOCK_TEST_TCPULP(remotesock
, 0);
1113 memset(&winfo
, 0, sizeof(winfo
));
1114 copyfd_io(fd
, remotesock
, 1, true, &winfo
);
1123 if (--cfg_repeat
> 0)
1129 static void init_rng(void)
1133 if (getrandom(&foo
, sizeof(foo
), 0) == -1) {
1134 perror("getrandom");
1141 static void xsetsockopt(int fd
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1145 err
= setsockopt(fd
, level
, optname
, optval
, optlen
);
1147 perror("setsockopt");
1152 static void apply_cmsg_types(int fd
, const struct cfg_cmsg_types
*cmsg
)
1154 static const unsigned int on
= 1;
1156 if (cmsg
->timestampns
)
1157 xsetsockopt(fd
, SOL_SOCKET
, SO_TIMESTAMPNS_NEW
, &on
, sizeof(on
));
1159 xsetsockopt(fd
, IPPROTO_TCP
, TCP_INQ
, &on
, sizeof(on
));
1162 static void parse_cmsg_types(const char *type
)
1164 char *next
= strchr(type
, ',');
1165 unsigned int len
= 0;
1167 cfg_cmsg_types
.cmsg_enabled
= 1;
1170 parse_cmsg_types(next
+ 1);
1176 if (strncmp(type
, "TIMESTAMPNS", len
) == 0) {
1177 cfg_cmsg_types
.timestampns
= 1;
1181 if (strncmp(type
, "TCPINQ", len
) == 0) {
1182 cfg_cmsg_types
.tcp_inq
= 1;
1186 fprintf(stderr
, "Unrecognized cmsg option %s\n", type
);
1190 static void parse_setsock_options(const char *name
)
1192 char *next
= strchr(name
, ',');
1193 unsigned int len
= 0;
1196 parse_setsock_options(next
+ 1);
1202 if (strncmp(name
, "TRANSPARENT", len
) == 0) {
1203 cfg_sockopt_types
.transparent
= 1;
1207 if (strncmp(name
, "MPTFO", len
) == 0) {
1208 cfg_sockopt_types
.mptfo
= 1;
1212 fprintf(stderr
, "Unrecognized setsockopt option %s\n", name
);
1216 void xdisconnect(int fd
)
1218 socklen_t addrlen
= sizeof(struct sockaddr_storage
);
1219 struct sockaddr_storage addr
, empty
;
1220 int msec_sleep
= 10;
1225 /* get the local address and convert it to string */
1226 if (getsockname(fd
, (struct sockaddr
*)&addr
, &addrlen
) < 0)
1227 xerror("getsockname");
1229 if (addr
.ss_family
== AF_INET
)
1230 raw_addr
= &(((struct sockaddr_in
*)&addr
)->sin_addr
);
1231 else if (addr
.ss_family
== AF_INET6
)
1232 raw_addr
= &(((struct sockaddr_in6
*)&addr
)->sin6_addr
);
1234 xerror("bad family");
1236 strcpy(cmd
, "ss -M | grep -q ");
1237 cmdlen
= strlen(cmd
);
1238 if (!inet_ntop(addr
.ss_family
, raw_addr
, &cmd
[cmdlen
],
1239 sizeof(cmd
) - cmdlen
))
1240 xerror("inet_ntop");
1242 shutdown(fd
, SHUT_WR
);
1245 * wait until the pending data is completely flushed and all
1246 * the MPTCP sockets reached the closed status.
1247 * disconnect will bypass/ignore/drop any pending data.
1249 for (i
= 0; ; i
+= msec_sleep
) {
1250 /* closed socket are not listed by 'ss' */
1251 if (system(cmd
) != 0)
1254 if (i
> poll_timeout
)
1255 xerror("timeout while waiting for spool to complete");
1256 usleep(msec_sleep
* 1000);
1259 memset(&empty
, 0, sizeof(empty
));
1260 empty
.ss_family
= AF_UNSPEC
;
1261 if (connect(fd
, (struct sockaddr
*)&empty
, addrlen
) < 0)
1262 xerror("can't disconnect: %d", errno
);
1267 int fd
= 0, ret
, fd_in
= 0;
1268 struct addrinfo
*peer
;
1269 struct wstate winfo
;
1271 if (cfg_input
&& cfg_sockopt_types
.mptfo
) {
1272 fd_in
= open(cfg_input
, O_RDONLY
);
1274 xerror("can't open %s:%d", cfg_input
, errno
);
1277 memset(&winfo
, 0, sizeof(winfo
));
1278 fd
= sock_connect_mptcp(cfg_host
, cfg_port
, cfg_sock_proto
, &peer
, fd_in
, &winfo
);
1283 check_getpeername_connect(fd
);
1285 SOCK_TEST_TCPULP(fd
, cfg_sock_proto
);
1288 set_rcvbuf(fd
, cfg_rcvbuf
);
1290 set_sndbuf(fd
, cfg_sndbuf
);
1291 if (cfg_cmsg_types
.cmsg_enabled
)
1292 apply_cmsg_types(fd
, &cfg_cmsg_types
);
1294 if (cfg_input
&& !cfg_sockopt_types
.mptfo
) {
1295 fd_in
= open(cfg_input
, O_RDONLY
);
1297 xerror("can't open %s:%d", cfg_input
, errno
);
1300 ret
= copyfd_io(fd_in
, fd
, 1, 0, &winfo
);
1304 if (cfg_truncate
> 0) {
1306 } else if (--cfg_repeat
> 0) {
1309 /* the socket could be unblocking at this point, we need the
1310 * connect to be blocking
1312 set_nonblock(fd
, false);
1313 if (connect(fd
, peer
->ai_addr
, peer
->ai_addrlen
))
1314 xerror("can't reconnect: %d", errno
);
1317 memset(&winfo
, 0, sizeof(winfo
));
1326 int parse_proto(const char *proto
)
1328 if (!strcasecmp(proto
, "MPTCP"))
1329 return IPPROTO_MPTCP
;
1330 if (!strcasecmp(proto
, "TCP"))
1333 fprintf(stderr
, "Unknown protocol: %s\n.", proto
);
1336 /* silence compiler warning */
1340 int parse_mode(const char *mode
)
1342 if (!strcasecmp(mode
, "poll"))
1343 return CFG_MODE_POLL
;
1344 if (!strcasecmp(mode
, "mmap"))
1345 return CFG_MODE_MMAP
;
1346 if (!strcasecmp(mode
, "sendfile"))
1347 return CFG_MODE_SENDFILE
;
1349 fprintf(stderr
, "Unknown test mode: %s\n", mode
);
1350 fprintf(stderr
, "Supported modes are:\n");
1351 fprintf(stderr
, "\t\t\"poll\" - interleaved read/write using poll()\n");
1352 fprintf(stderr
, "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n");
1353 fprintf(stderr
, "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n");
1357 /* silence compiler warning */
1361 int parse_peek(const char *mode
)
1363 if (!strcasecmp(mode
, "saveWithPeek"))
1364 return CFG_WITH_PEEK
;
1365 if (!strcasecmp(mode
, "saveAfterPeek"))
1366 return CFG_AFTER_PEEK
;
1368 fprintf(stderr
, "Unknown: %s\n", mode
);
1369 fprintf(stderr
, "Supported MSG_PEEK mode are:\n");
1371 "\t\t\"saveWithPeek\" - recv data with flags 'MSG_PEEK' and save the peek data into file\n");
1373 "\t\t\"saveAfterPeek\" - read and save data into file after recv with flags 'MSG_PEEK'\n");
1377 /* silence compiler warning */
1381 static int parse_int(const char *size
)
1387 s
= strtoul(size
, NULL
, 0);
1390 fprintf(stderr
, "Invalid sndbuf size %s (%s)\n",
1391 size
, strerror(errno
));
1396 fprintf(stderr
, "Invalid sndbuf size %s (%s)\n",
1397 size
, strerror(ERANGE
));
1404 static void parse_opts(int argc
, char **argv
)
1408 while ((c
= getopt(argc
, argv
, "6c:f:hi:I:jlm:M:o:p:P:r:R:s:S:t:T:w:")) != -1) {
1411 cfg_truncate
= atoi(optarg
);
1413 /* when receiving a fastclose, ignore PIPE signals and
1414 * all the I/O errors later in the code
1416 if (cfg_truncate
< 0) {
1417 cfg_rcv_trunc
= true;
1418 signal(SIGPIPE
, handle_signal
);
1423 cfg_mode
= CFG_MODE_POLL
;
1427 cfg_mode
= CFG_MODE_POLL
;
1429 cfg_do_w
= atoi(optarg
);
1437 cfg_repeat
= atoi(optarg
);
1446 cfg_sock_proto
= parse_proto(optarg
);
1455 poll_timeout
= atoi(optarg
) * 1000;
1456 if (poll_timeout
<= 0)
1460 cfg_time
= atoi(optarg
);
1463 cfg_mode
= parse_mode(optarg
);
1466 cfg_sndbuf
= parse_int(optarg
);
1469 cfg_rcvbuf
= parse_int(optarg
);
1472 cfg_wait
= atoi(optarg
)*1000000;
1475 cfg_mark
= strtol(optarg
, NULL
, 0);
1478 cfg_peek
= parse_peek(optarg
);
1481 parse_cmsg_types(optarg
);
1484 parse_setsock_options(optarg
);
1489 if (optind
+ 1 != argc
)
1491 cfg_host
= argv
[optind
];
1493 if (strchr(cfg_host
, ':'))
1497 int main(int argc
, char *argv
[])
1501 signal(SIGUSR1
, handle_signal
);
1502 parse_opts(argc
, argv
);
1505 int fd
= sock_listen_mptcp(cfg_host
, cfg_port
);
1511 set_rcvbuf(fd
, cfg_rcvbuf
);
1513 set_sndbuf(fd
, cfg_sndbuf
);
1515 set_mark(fd
, cfg_mark
);
1516 if (cfg_cmsg_types
.cmsg_enabled
)
1517 apply_cmsg_types(fd
, &cfg_cmsg_types
);
1519 return main_loop_s(fd
);