mptcp: relax check on MPC passive fallback
[platform/kernel/linux-starfive.git] / net / mptcp / subflow.c
index 9c1f8d1..d3c5ecf 100644 (file)
@@ -157,8 +157,8 @@ static int subflow_check_req(struct request_sock *req,
 
        mptcp_get_options(skb, &mp_opt);
 
-       opt_mp_capable = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPC);
-       opt_mp_join = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ);
+       opt_mp_capable = !!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYN);
+       opt_mp_join = !!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYN);
        if (opt_mp_capable) {
                SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
 
@@ -254,8 +254,8 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,
        subflow_init_req(req, sk_listener);
        mptcp_get_options(skb, &mp_opt);
 
-       opt_mp_capable = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPC);
-       opt_mp_join = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ);
+       opt_mp_capable = !!(mp_opt.suboptions & OPTION_MPTCP_MPC_ACK);
+       opt_mp_join = !!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK);
        if (opt_mp_capable && opt_mp_join)
                return -EINVAL;
 
@@ -419,21 +419,28 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc
        return inet_sk(sk)->inet_dport != inet_sk((struct sock *)msk)->inet_dport;
 }
 
-void __mptcp_set_connected(struct sock *sk)
+void __mptcp_sync_state(struct sock *sk, int state)
 {
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
+       __mptcp_propagate_sndbuf(sk, msk->first);
        if (sk->sk_state == TCP_SYN_SENT) {
-               inet_sk_state_store(sk, TCP_ESTABLISHED);
+               inet_sk_state_store(sk, state);
                sk->sk_state_change(sk);
        }
 }
 
-static void mptcp_set_connected(struct sock *sk)
+static void mptcp_propagate_state(struct sock *sk, struct sock *ssk)
 {
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
        mptcp_data_lock(sk);
-       if (!sock_owned_by_user(sk))
-               __mptcp_set_connected(sk);
-       else
-               __set_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->cb_flags);
+       if (!sock_owned_by_user(sk)) {
+               __mptcp_sync_state(sk, ssk->sk_state);
+       } else {
+               msk->pending_state = ssk->sk_state;
+               __set_bit(MPTCP_SYNC_STATE, &msk->cb_flags);
+       }
        mptcp_data_unlock(sk);
 }
 
@@ -472,7 +479,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
                return;
 
        msk = mptcp_sk(parent);
-       mptcp_propagate_sndbuf(parent, sk);
        subflow->rel_write_seq = 1;
        subflow->conn_finished = 1;
        subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
@@ -480,7 +486,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 
        mptcp_get_options(skb, &mp_opt);
        if (subflow->request_mptcp) {
-               if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) {
+               if (!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYNACK)) {
                        MPTCP_INC_STATS(sock_net(sk),
                                        MPTCP_MIB_MPCAPABLEACTIVEFALLBACK);
                        mptcp_do_fallback(sk);
@@ -496,11 +502,11 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
                subflow_set_remote_key(msk, subflow, &mp_opt);
                MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK);
                mptcp_finish_connect(sk);
-               mptcp_set_connected(parent);
+               mptcp_propagate_state(parent, sk);
        } else if (subflow->request_join) {
                u8 hmac[SHA256_DIGEST_SIZE];
 
-               if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ)) {
+               if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYNACK)) {
                        subflow->reset_reason = MPTCP_RST_EMPTCP;
                        goto do_reset;
                }
@@ -540,7 +546,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
        } else if (mptcp_check_fallback(sk)) {
 fallback:
                mptcp_rcv_space_init(msk, sk);
-               mptcp_set_connected(parent);
+               mptcp_propagate_state(parent, sk);
        }
        return;
 
@@ -777,12 +783,13 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
                 * options.
                 */
                mptcp_get_options(skb, &mp_opt);
-               if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC))
+               if (!(mp_opt.suboptions &
+                     (OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_ACK)))
                        fallback = true;
 
        } else if (subflow_req->mp_join) {
                mptcp_get_options(skb, &mp_opt);
-               if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ) ||
+               if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) ||
                    !subflow_hmac_valid(req, &mp_opt) ||
                    !mptcp_can_accept_new_subflow(subflow_req->msk)) {
                        SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
@@ -1728,12 +1735,11 @@ static void subflow_state_change(struct sock *sk)
 
        msk = mptcp_sk(parent);
        if (subflow_simultaneous_connect(sk)) {
-               mptcp_propagate_sndbuf(parent, sk);
                mptcp_do_fallback(sk);
                mptcp_rcv_space_init(msk, sk);
                pr_fallback(msk);
                subflow->conn_finished = 1;
-               mptcp_set_connected(parent);
+               mptcp_propagate_state(parent, sk);
        }
 
        /* as recvmsg() does not acquire the subflow socket for ssk selection
@@ -1969,6 +1975,17 @@ static void tcp_release_cb_override(struct sock *ssk)
        tcp_release_cb(ssk);
 }
 
+static int tcp_abort_override(struct sock *ssk, int err)
+{
+       /* closing a listener subflow requires a great deal of care.
+        * keep it simple and just prevent such operation
+        */
+       if (inet_sk_state_load(ssk) == TCP_LISTEN)
+               return -EINVAL;
+
+       return tcp_abort(ssk, err);
+}
+
 static struct tcp_ulp_ops subflow_ulp_ops __read_mostly = {
        .name           = "mptcp",
        .owner          = THIS_MODULE,
@@ -2013,6 +2030,7 @@ void __init mptcp_subflow_init(void)
 
        tcp_prot_override = tcp_prot;
        tcp_prot_override.release_cb = tcp_release_cb_override;
+       tcp_prot_override.diag_destroy = tcp_abort_override;
 
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
        /* In struct mptcp_subflow_request_sock, we assume the TCP request sock
@@ -2049,6 +2067,7 @@ void __init mptcp_subflow_init(void)
 
        tcpv6_prot_override = tcpv6_prot;
        tcpv6_prot_override.release_cb = tcp_release_cb_override;
+       tcpv6_prot_override.diag_destroy = tcp_abort_override;
 #endif
 
        mptcp_diag_subflow_init(&subflow_ulp_ops);