summaryrefslogtreecommitdiff
path: root/net/mptcp
diff options
context:
space:
mode:
Diffstat (limited to 'net/mptcp')
-rw-r--r--net/mptcp/Kconfig6
-rw-r--r--net/mptcp/protocol.c56
-rw-r--r--net/mptcp/subflow.c13
3 files changed, 46 insertions, 29 deletions
diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig
index 5db56d2218c5..49f6054e7f4e 100644
--- a/net/mptcp/Kconfig
+++ b/net/mptcp/Kconfig
@@ -10,17 +10,19 @@ config MPTCP
uses the TCP protocol, and TCP options carry header information for
MPTCP.
+if MPTCP
+
config MPTCP_IPV6
bool "MPTCP: IPv6 support for Multipath TCP"
- depends on MPTCP
select IPV6
default y
config MPTCP_HMAC_TEST
bool "Tests for MPTCP HMAC implementation"
- default n
help
This option enable boot time self-test for the HMAC implementation
used by the MPTCP code
Say N if you are unsure.
+
+endif
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 39fdca79ce90..3bccee455688 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -28,7 +28,7 @@ static void __mptcp_close(struct sock *sk, long timeout);
static const struct proto_ops *tcp_proto_ops(struct sock *sk)
{
-#if IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
if (sk->sk_family == AF_INET6)
return &inet6_stream_ops;
#endif
@@ -644,19 +644,21 @@ static void __mptcp_close(struct sock *sk, long timeout)
{
struct mptcp_subflow_context *subflow, *tmp;
struct mptcp_sock *msk = mptcp_sk(sk);
+ LIST_HEAD(conn_list);
mptcp_token_destroy(msk->token);
inet_sk_state_store(sk, TCP_CLOSE);
- list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
+ list_splice_init(&msk->conn_list, &conn_list);
+
+ release_sock(sk);
+
+ list_for_each_entry_safe(subflow, tmp, &conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
__mptcp_close_ssk(sk, ssk, subflow, timeout);
}
- if (msk->cached_ext)
- __skb_ext_put(msk->cached_ext);
- release_sock(sk);
sk_common_release(sk);
}
@@ -776,18 +778,19 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
static void mptcp_destroy(struct sock *sk)
{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+
+ if (msk->cached_ext)
+ __skb_ext_put(msk->cached_ext);
}
static int mptcp_setsockopt(struct sock *sk, int level, int optname,
- char __user *uoptval, unsigned int optlen)
+ char __user *optval, unsigned int optlen)
{
struct mptcp_sock *msk = mptcp_sk(sk);
- char __kernel *optval;
int ret = -EOPNOTSUPP;
struct socket *ssock;
-
- /* will be treated as __user in tcp_setsockopt */
- optval = (char __kernel __force *)uoptval;
+ struct sock *ssk;
pr_debug("msk=%p", msk);
@@ -796,27 +799,28 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname,
*/
lock_sock(sk);
ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
- if (!IS_ERR(ssock)) {
- pr_debug("subflow=%p", ssock->sk);
- ret = kernel_setsockopt(ssock, level, optname, optval, optlen);
+ if (IS_ERR(ssock)) {
+ release_sock(sk);
+ return ret;
}
+
+ ssk = ssock->sk;
+ sock_hold(ssk);
release_sock(sk);
+ ret = tcp_setsockopt(ssk, level, optname, optval, optlen);
+ sock_put(ssk);
+
return ret;
}
static int mptcp_getsockopt(struct sock *sk, int level, int optname,
- char __user *uoptval, int __user *uoption)
+ char __user *optval, int __user *option)
{
struct mptcp_sock *msk = mptcp_sk(sk);
- char __kernel *optval;
int ret = -EOPNOTSUPP;
- int __kernel *option;
struct socket *ssock;
-
- /* will be treated as __user in tcp_getsockopt */
- optval = (char __kernel __force *)uoptval;
- option = (int __kernel __force *)uoption;
+ struct sock *ssk;
pr_debug("msk=%p", msk);
@@ -825,12 +829,18 @@ static int mptcp_getsockopt(struct sock *sk, int level, int optname,
*/
lock_sock(sk);
ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
- if (!IS_ERR(ssock)) {
- pr_debug("subflow=%p", ssock->sk);
- ret = kernel_getsockopt(ssock, level, optname, optval, option);
+ if (IS_ERR(ssock)) {
+ release_sock(sk);
+ return ret;
}
+
+ ssk = ssock->sk;
+ sock_hold(ssk);
release_sock(sk);
+ ret = tcp_getsockopt(ssk, level, optname, optval, option);
+ sock_put(ssk);
+
return ret;
}
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 1662e1178949..65122edf60aa 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -186,6 +186,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
+ if (tcp_rsk(req)->is_mptcp == 0)
+ goto create_child;
+
/* if the sk is MP_CAPABLE, we try to fetch the client key */
subflow_req = mptcp_subflow_rsk(req);
if (subflow_req->mp_capable) {
@@ -582,9 +585,9 @@ subflow_default_af_ops(struct sock *sk)
return &subflow_specific;
}
-void mptcp_handle_ipv6_mapped(struct sock *sk, bool mapped)
-{
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+void mptcpv6_handle_mapped(struct sock *sk, bool mapped)
+{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_connection_sock_af_ops *target;
@@ -599,8 +602,8 @@ void mptcp_handle_ipv6_mapped(struct sock *sk, bool mapped)
subflow->icsk_af_ops = icsk->icsk_af_ops;
icsk->icsk_af_ops = target;
-#endif
}
+#endif
int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
{
@@ -621,7 +624,9 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
*/
sf->sk->sk_net_refcnt = 1;
get_net(net);
+#ifdef CONFIG_PROC_FS
this_cpu_add(*net->core.sock_inuse, 1);
+#endif
err = tcp_set_ulp(sf->sk, "mptcp");
release_sock(sf->sk);
@@ -767,7 +772,7 @@ static void subflow_ulp_clone(const struct request_sock *req,
struct mptcp_subflow_context *old_ctx = mptcp_subflow_ctx(newsk);
struct mptcp_subflow_context *new_ctx;
- if (!subflow_req->mp_capable) {
+ if (!tcp_rsk(req)->is_mptcp || !subflow_req->mp_capable) {
subflow_ulp_fallback(newsk, old_ctx);
return;
}