tcp: propagate tcp_tw_isn via an extra parameter to ->route_req()
authorEric Dumazet <edumazet@google.com>
Sun, 7 Apr 2024 09:33:21 +0000 (09:33 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 9 Apr 2024 09:47:40 +0000 (11:47 +0200)
tcp_v6_init_req() reads TCP_SKB_CB(skb)->tcp_tw_isn to find
out if the request socket is created by a SYN hitting a TIMEWAIT socket.

This has been buggy for a decade, lets directly pass the information
from tcp_conn_request().

This is a preparatory patch to make the following one easier to review.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
include/net/tcp.h
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c
net/mptcp/subflow.c

index 9ab5b37e9d532cdf26dd423810b07912ef4abd75..fa0ab77acee23654b22e97615de983fc04eee319 100644 (file)
@@ -2284,7 +2284,8 @@ struct tcp_request_sock_ops {
        struct dst_entry *(*route_req)(const struct sock *sk,
                                       struct sk_buff *skb,
                                       struct flowi *fl,
-                                      struct request_sock *req);
+                                      struct request_sock *req,
+                                      u32 tw_isn);
        u32 (*init_seq)(const struct sk_buff *skb);
        u32 (*init_ts_off)(const struct net *net, const struct sk_buff *skb);
        int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
index 1f28a2561795cf48ee7dbf638c15c773c8b8c84c..48c275e6ef02bfc5dd98f0878c752841f949c714 100644 (file)
@@ -7160,7 +7160,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
        /* Note: tcp_v6_init_req() might override ir_iif for link locals */
        inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb);
 
-       dst = af_ops->route_req(sk, skb, &fl, req);
+       dst = af_ops->route_req(sk, skb, &fl, req, isn);
        if (!dst)
                goto drop_and_free;
 
index 52963c3bb8ca7380692f7be6e15d687c45e8673a..81e2f05c244d1671980a34bb756f528f3e6debcc 100644 (file)
@@ -1666,7 +1666,8 @@ static void tcp_v4_init_req(struct request_sock *req,
 static struct dst_entry *tcp_v4_route_req(const struct sock *sk,
                                          struct sk_buff *skb,
                                          struct flowi *fl,
-                                         struct request_sock *req)
+                                         struct request_sock *req,
+                                         u32 tw_isn)
 {
        tcp_v4_init_req(req, sk, skb);
 
index cffebaec66f1ab60f1dde00b8bd8cc7a595bdc91..5141f7033abd8bb03bc4e162066ca4befe343bdc 100644 (file)
@@ -793,7 +793,8 @@ clear_hash_nostart:
 
 static void tcp_v6_init_req(struct request_sock *req,
                            const struct sock *sk_listener,
-                           struct sk_buff *skb)
+                           struct sk_buff *skb,
+                           u32 tw_isn)
 {
        bool l3_slave = ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags);
        struct inet_request_sock *ireq = inet_rsk(req);
@@ -807,7 +808,7 @@ static void tcp_v6_init_req(struct request_sock *req,
            ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
                ireq->ir_iif = tcp_v6_iif(skb);
 
-       if (!TCP_SKB_CB(skb)->tcp_tw_isn &&
+       if (!tw_isn &&
            (ipv6_opt_accepted(sk_listener, skb, &TCP_SKB_CB(skb)->header.h6) ||
             np->rxopt.bits.rxinfo ||
             np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim ||
@@ -820,9 +821,10 @@ static void tcp_v6_init_req(struct request_sock *req,
 static struct dst_entry *tcp_v6_route_req(const struct sock *sk,
                                          struct sk_buff *skb,
                                          struct flowi *fl,
-                                         struct request_sock *req)
+                                         struct request_sock *req,
+                                         u32 tw_isn)
 {
-       tcp_v6_init_req(req, sk, skb);
+       tcp_v6_init_req(req, sk, skb, tw_isn);
 
        if (security_inet_conn_request(sk, skb, req))
                return NULL;
index 162b218d985883b5e9c2b7409f3cd7d8ea83f51a..b94d1dca1094f44a0ce292facefb56e4e6adf7a5 100644 (file)
@@ -289,7 +289,8 @@ EXPORT_SYMBOL_GPL(mptcp_subflow_init_cookie_req);
 static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
                                              struct sk_buff *skb,
                                              struct flowi *fl,
-                                             struct request_sock *req)
+                                             struct request_sock *req,
+                                             u32 tw_isn)
 {
        struct dst_entry *dst;
        int err;
@@ -297,7 +298,7 @@ static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
        tcp_rsk(req)->is_mptcp = 1;
        subflow_init_req(req, sk);
 
-       dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req);
+       dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req, tw_isn);
        if (!dst)
                return NULL;
 
@@ -356,7 +357,8 @@ static int subflow_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
 static struct dst_entry *subflow_v6_route_req(const struct sock *sk,
                                              struct sk_buff *skb,
                                              struct flowi *fl,
-                                             struct request_sock *req)
+                                             struct request_sock *req,
+                                             u32 tw_isn)
 {
        struct dst_entry *dst;
        int err;
@@ -364,7 +366,7 @@ static struct dst_entry *subflow_v6_route_req(const struct sock *sk,
        tcp_rsk(req)->is_mptcp = 1;
        subflow_init_req(req, sk);
 
-       dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req);
+       dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req, tw_isn);
        if (!dst)
                return NULL;