From: Geliang Tang <tanggeliang@kylinos.cn>
Supporting TCP_MD5 socket option is required when MPTCP is used by
default when creating a socket, to keep the same behaviour as with
TCP. TCP_MD5 is not compatible with MPTCP, and it will cause a
fallback to TCP at the connection request, if MPTCP was requested.
This then fixes a "regression" compared to TCP.
This patch adds setsockopt support for TCP_MD5SIG and TCP_MD5SIG_EXT
options. The implementation:
- Allow setting these options (getsockopt remains unsupported)
- Apply them only to the first subflow
- Trigger fallback to TCP to maintain MD5 compatibility
- Check if fallback has already occurred in subflow_check_req(). If so,
return immediately
Note that getsockopt for these options remains unsupported, consistent
with TCP.
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/575
Fixes: d9e4c1291810 ("mptcp: only admit explicitly supported sockopt")
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/sockopt.c | 14 ++++++++++++--
net/mptcp/subflow.c | 3 +++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index b264185b810d..f2f0b475c8d6 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -13,6 +13,7 @@
#include <net/tcp.h>
#include <net/mptcp.h>
#include "protocol.h"
+#include "mib.h"
#define MIN_INFO_OPTLEN_SIZE 16
#define MIN_FULL_INFO_OPTLEN_SIZE 40
@@ -567,11 +568,12 @@ static bool mptcp_supported_sockopt(int level, int optname)
case TCP_FASTOPEN_CONNECT:
case TCP_FASTOPEN_KEY:
case TCP_FASTOPEN_NO_COOKIE:
+ /* MD5 will force a fallback to TCP: OK to set while not connected */
+ case TCP_MD5SIG:
+ case TCP_MD5SIG_EXT:
return true;
}
- /* TCP_MD5SIG, TCP_MD5SIG_EXT are not supported, MD5 is not compatible with MPTCP */
-
/* TCP_REPAIR, TCP_REPAIR_QUEUE, TCP_QUEUE_SEQ, TCP_REPAIR_OPTIONS,
* TCP_REPAIR_WINDOW are not supported, better avoid this mess
*/
@@ -836,6 +838,14 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
case TCP_FASTOPEN_NO_COOKIE:
return mptcp_setsockopt_first_sf_only(msk, SOL_TCP, optname,
optval, optlen);
+ case TCP_MD5SIG:
+ case TCP_MD5SIG_EXT:
+ ret = mptcp_setsockopt_first_sf_only(msk, SOL_TCP, optname,
+ optval, optlen);
+ if (ret == 0)
+ WARN_ON_ONCE(!__mptcp_try_fallback(msk,
+ MPTCP_MIB_MD5SIGFALLBACK));
+ return ret;
}
ret = mptcp_get_int_option(msk, optval, optlen, &val);
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 3f1b62a9fe88..3c8bbd5d8bf5 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -155,6 +155,9 @@ static int subflow_check_req(struct request_sock *req,
pr_debug("subflow_req=%p, listener=%p\n", subflow_req, listener);
+ if (__mptcp_check_fallback(mptcp_sk(listener->conn)))
+ return 0;
+
#ifdef CONFIG_TCP_MD5SIG
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
* TCP option space.
--
2.48.1