If SYN packet contains MP_CAPABLE option, keep it enabled. Syncokie validation and cookie-based socket creation is changed to instantiate an mptcp request sockets if the ACK contains an MPTCP connection request.
Signed-off-by: Florian Westphal <f...@strlen.de> --- net/ipv4/syncookies.c | 21 +++++++++++++++++---- net/ipv4/tcp_input.c | 3 --- net/ipv6/syncookies.c | 17 ++++++++++++++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index ee17f55401ef..5da49dc126f9 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -289,6 +289,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); const struct tcphdr *th = tcp_hdr(skb); __u32 cookie = ntohl(th->ack_seq) - 1; + const struct request_sock_ops *ops; struct sock *ret = sk; struct request_sock *req; int mss; @@ -326,12 +327,27 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) goto out; ret = NULL; - req = inet_reqsk_alloc(&tcp_request_sock_ops, sk, false); /* for safety */ + ops = &tcp_request_sock_ops; +#ifdef CONFIG_MPTCP + if (sk_is_mptcp(sk)) + ops = &mptcp_subflow_request_sock_ops; +#endif + + req = inet_reqsk_alloc(ops, sk, false); /* for safety */ if (!req) goto out; ireq = inet_rsk(req); treq = tcp_rsk(req); + treq->is_mptcp = sk_is_mptcp(sk); + + if (treq->is_mptcp) { + int err = mptcp_subflow_init_cookie_req(req, sk, skb); + + if (err) + goto out_free; + } + treq->rcv_isn = ntohl(th->seq) - 1; treq->snt_isn = cookie; treq->ts_off = 0; @@ -350,9 +366,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) treq->snt_synack = 0; treq->tfo_listener = false; - if (IS_ENABLED(CONFIG_MPTCP)) - treq->is_mptcp = 0; - if (IS_ENABLED(CONFIG_SMC)) ireq->smc_ok = 0; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 17aa1c29d11c..7f4c21bca3b5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6699,9 +6699,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, af_ops->init_req(req, sk, skb, want_cookie); - if (IS_ENABLED(CONFIG_MPTCP) && want_cookie) - tcp_rsk(req)->is_mptcp = 0; - if (security_inet_conn_request(sk, skb, req)) goto drop_and_free; diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 13235a012388..0a05c3c1e776 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -134,6 +134,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); const struct tcphdr *th = tcp_hdr(skb); __u32 cookie = ntohl(th->ack_seq) - 1; + const struct request_sock_ops *ops; struct sock *ret = sk; struct request_sock *req; int mss; @@ -170,7 +171,13 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) goto out; ret = NULL; - req = inet_reqsk_alloc(&tcp6_request_sock_ops, sk, false); + ops = &tcp6_request_sock_ops; +#ifdef CONFIG_MPTCP + if (sk_is_mptcp(sk)) + ops = &mptcp_subflow_request_sock_ops; +#endif + + req = inet_reqsk_alloc(ops, sk, false); if (!req) goto out; @@ -178,8 +185,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) treq = tcp_rsk(req); treq->tfo_listener = false; - if (IS_ENABLED(CONFIG_MPTCP)) - treq->is_mptcp = 0; + if (treq->is_mptcp) { + int err = mptcp_subflow_init_cookie_req(req, sk, skb); + + if (err) + goto out_free; + } if (security_inet_conn_request(sk, skb, req)) goto out_free; -- 2.26.2