// SPDX-License-Identifier: GPL-2.0 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int optind; #ifndef IPPROTO_MPTCP #define IPPROTO_MPTCP 262 #endif #ifndef TCP_ULP #define TCP_ULP 31 #endif static int poll_timeout = 10 * 1000; static bool listen_mode; static bool quit; enum cfg_mode { CFG_MODE_POLL, CFG_MODE_MMAP, CFG_MODE_SENDFILE, }; enum cfg_peek { CFG_NONE_PEEK, CFG_WITH_PEEK, CFG_AFTER_PEEK, }; static enum cfg_mode cfg_mode = CFG_MODE_POLL; static enum cfg_peek cfg_peek = CFG_NONE_PEEK; static const char *cfg_host; static const char *cfg_port = "12000"; static int cfg_sock_proto = IPPROTO_MPTCP; static int pf = AF_INET; static int cfg_sndbuf; static int cfg_rcvbuf; static bool cfg_join; static bool cfg_remove; static unsigned int cfg_time; static unsigned int cfg_do_w; static int cfg_wait; static uint32_t cfg_mark; static char *cfg_input; static int cfg_repeat = 1; static int cfg_truncate; static int cfg_rcv_trunc; struct cfg_cmsg_types { unsigned int cmsg_enabled:1; unsigned int timestampns:1; unsigned int tcp_inq:1; }; struct cfg_sockopt_types { unsigned int transparent:1; unsigned int mptfo:1; }; struct tcp_inq_state { unsigned int last; bool expect_eof; }; struct wstate { char buf[8192]; unsigned int len; unsigned int off; unsigned int total_len; }; static struct tcp_inq_state tcp_inq; static struct cfg_cmsg_types cfg_cmsg_types; static struct cfg_sockopt_types cfg_sockopt_types; static void die_usage(void) { fprintf(stderr, "Usage: mptcp_connect [-6] [-c cmsg] [-f offset] [-i file] [-I num] [-j] [-l] " "[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-r num] [-R num] " "[-s MPTCP|TCP] [-S num] [-t num] [-T num] [-w sec] connect_address\n"); fprintf(stderr, "\t-6 use ipv6\n"); fprintf(stderr, "\t-c cmsg -- test cmsg type \n"); fprintf(stderr, "\t-f offset -- stop the I/O after receiving and sending the specified amount " "of bytes. If there are unread bytes in the receive queue, that will cause a MPTCP " "fastclose at close/shutdown. If offset is negative, expect the peer to close before " "all the local data as been sent, thus toleration errors on write and EPIPE signals\n"); fprintf(stderr, "\t-i file -- read the data to send from the given file instead of stdin"); fprintf(stderr, "\t-I num -- repeat the transfer 'num' times. In listen mode accepts num " "incoming connections, in client mode, disconnect and reconnect to the server\n"); fprintf(stderr, "\t-j -- add additional sleep at connection start and tear down " "-- for MPJ tests\n"); fprintf(stderr, "\t-l -- listens mode, accepts incoming connection\n"); fprintf(stderr, "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n"); fprintf(stderr, "\t-M mark -- set socket packet mark\n"); fprintf(stderr, "\t-o option -- test sockopt