selftests: mptcp: try to set mptcp ulp mode in different sk states

The kernel will crash without
'mptcp: clear 'kern' flag from fallback sockets' change.

Since this doesn't slow down testing in a noticeable way,
run this unconditionally.

The explicit test did not catch this, because the check was done
for tcp socket returned by 'socket(.. IPPROTO_TCP) rather than a
tcp socket returned by accept() on a mptcp listen fd.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Florian Westphal 2021-12-17 15:37:01 -08:00 committed by Jakub Kicinski
parent 3ce0852c86
commit f730b65c9d
2 changed files with 51 additions and 66 deletions

View File

@ -59,7 +59,6 @@ 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 bool tcpulp_audit;
static int pf = AF_INET;
static int cfg_sndbuf;
static int cfg_rcvbuf;
@ -103,7 +102,6 @@ static void die_usage(void)
fprintf(stderr, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\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-u -- check mptcp ulp\n");
fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
fprintf(stderr, "\t-o option -- test sockopt <option>\n");
@ -215,6 +213,42 @@ static void set_transparent(int fd, int pf)
}
}
static int do_ulp_so(int sock, const char *name)
{
return setsockopt(sock, IPPROTO_TCP, TCP_ULP, name, strlen(name));
}
#define X(m) xerror("%s:%u: %s: failed for proto %d at line %u", __FILE__, __LINE__, (m), proto, line)
static void sock_test_tcpulp(int sock, int proto, unsigned int line)
{
socklen_t buflen = 8;
char buf[8] = "";
int ret = getsockopt(sock, IPPROTO_TCP, TCP_ULP, buf, &buflen);
if (ret != 0)
X("getsockopt");
if (buflen > 0) {
if (strcmp(buf, "mptcp") != 0)
xerror("unexpected ULP '%s' for proto %d at line %u", buf, proto, line);
ret = do_ulp_so(sock, "tls");
if (ret == 0)
X("setsockopt");
} else if (proto == IPPROTO_MPTCP) {
ret = do_ulp_so(sock, "tls");
if (ret != -1)
X("setsockopt");
}
ret = do_ulp_so(sock, "mptcp");
if (ret != -1)
X("setsockopt");
#undef X
}
#define SOCK_TEST_TCPULP(s, p) sock_test_tcpulp((s), (p), __LINE__)
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
@ -238,6 +272,8 @@ static int sock_listen_mptcp(const char * const listenaddr,
if (sock < 0)
continue;
SOCK_TEST_TCPULP(sock, cfg_sock_proto);
if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
sizeof(one)))
perror("setsockopt");
@ -260,52 +296,19 @@ static int sock_listen_mptcp(const char * const listenaddr,
return sock;
}
SOCK_TEST_TCPULP(sock, cfg_sock_proto);
if (listen(sock, 20)) {
perror("listen");
close(sock);
return -1;
}
SOCK_TEST_TCPULP(sock, cfg_sock_proto);
return sock;
}
static bool sock_test_tcpulp(const char * const remoteaddr,
const char * const port)
{
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *a, *addr;
int sock = -1, ret = 0;
bool test_pass = false;
hints.ai_family = AF_INET;
xgetaddrinfo(remoteaddr, port, &hints, &addr);
for (a = addr; a; a = a->ai_next) {
sock = socket(a->ai_family, a->ai_socktype, IPPROTO_TCP);
if (sock < 0) {
perror("socket");
continue;
}
ret = setsockopt(sock, IPPROTO_TCP, TCP_ULP, "mptcp",
sizeof("mptcp"));
if (ret == -1 && errno == EOPNOTSUPP)
test_pass = true;
close(sock);
if (test_pass)
break;
if (!ret)
fprintf(stderr,
"setsockopt(TCP_ULP) returned 0\n");
else
perror("setsockopt(TCP_ULP)");
}
return test_pass;
}
static int sock_connect_mptcp(const char * const remoteaddr,
const char * const port, int proto)
{
@ -326,6 +329,8 @@ static int sock_connect_mptcp(const char * const remoteaddr,
continue;
}
SOCK_TEST_TCPULP(sock, proto);
if (cfg_mark)
set_mark(sock, cfg_mark);
@ -338,6 +343,8 @@ static int sock_connect_mptcp(const char * const remoteaddr,
}
freeaddrinfo(addr);
if (sock != -1)
SOCK_TEST_TCPULP(sock, proto);
return sock;
}
@ -954,6 +961,8 @@ int main_loop_s(int listensock)
check_sockaddr(pf, &ss, salen);
check_getpeername(remotesock, &ss, salen);
SOCK_TEST_TCPULP(remotesock, 0);
return copyfd_io(0, remotesock, 1);
}
@ -1059,6 +1068,8 @@ int main_loop(void)
check_getpeername_connect(fd);
SOCK_TEST_TCPULP(fd, cfg_sock_proto);
if (cfg_rcvbuf)
set_rcvbuf(fd, cfg_rcvbuf);
if (cfg_sndbuf)
@ -1151,7 +1162,7 @@ static void parse_opts(int argc, char **argv)
{
int c;
while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:o:")) != -1) {
while ((c = getopt(argc, argv, "6jr:lp:s:ht:T:m:S:R:w:M:P:c:o:")) != -1) {
switch (c) {
case 'j':
cfg_join = true;
@ -1177,9 +1188,6 @@ static void parse_opts(int argc, char **argv)
case 'h':
die_usage();
break;
case 'u':
tcpulp_audit = true;
break;
case '6':
pf = AF_INET6;
break;
@ -1233,9 +1241,6 @@ int main(int argc, char *argv[])
signal(SIGUSR1, handle_signal);
parse_opts(argc, argv);
if (tcpulp_audit)
return sock_test_tcpulp(cfg_host, cfg_port) ? 0 : 1;
if (listen_mode) {
int fd = sock_listen_mptcp(cfg_host, cfg_port);

View File

@ -296,24 +296,6 @@ check_mptcp_disabled()
return 0
}
check_mptcp_ulp_setsockopt()
{
local t retval
t="ns_ulp-$sech-$(mktemp -u XXXXXX)"
ip netns add ${t} || exit $ksft_skip
if ! ip netns exec ${t} ./mptcp_connect -u -p 10000 -s TCP 127.0.0.1 2>&1; then
printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) allowed\t[ FAIL ]\n"
retval=1
ret=$retval
else
printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) blocked\t[ OK ]\n"
retval=0
fi
ip netns del ${t}
return $retval
}
# $1: IP address
is_v6()
{
@ -780,8 +762,6 @@ make_file "$sin" "server"
check_mptcp_disabled
check_mptcp_ulp_setsockopt
stop_if_error "The kernel configuration is not valid for MPTCP"
echo "INFO: validating network environment with pings"