inet: consolidate inet_csk_clone_lock()
authorEric Dumazet <edumazet@google.com>
Wed, 12 Feb 2025 13:13:28 +0000 (13:13 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 14 Feb 2025 21:40:33 +0000 (13:40 -0800)
Current inet_sock_set_state trace from inet_csk_clone_lock() is missing
many details :

... sock:inet_sock_set_state: family=AF_INET6 protocol=IPPROTO_TCP \
    sport=4901 dport=0 \
    saddr=127.0.0.6 daddr=0.0.0.0 \
    saddrv6=:: daddrv6=:: \
    oldstate=TCP_LISTEN newstate=TCP_SYN_RECV

Only the sport gives the listener port, no other parts of the n-tuple are correct.

In this patch, I initialize relevant fields of the new socket before
calling inet_sk_set_state(newsk, TCP_SYN_RECV).

We now have a trace including all the source/destination bits.

... sock:inet_sock_set_state: family=AF_INET6 protocol=IPPROTO_TCP \
    sport=4901 dport=47648 \
    saddr=127.0.0.6 daddr=127.0.0.6 \
    saddrv6=2002:a05:6830:1f85:: daddrv6=2001:4860:f803:65::3 \
    oldstate=TCP_LISTEN newstate=TCP_SYN_RECV

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250212131328.1514243-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ipv4/inet_connection_sock.c
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c

index be515ba..bfa529a 100644 (file)
@@ -426,9 +426,6 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
 
        newinet            = inet_sk(newsk);
        ireq               = inet_rsk(req);
-       sk_daddr_set(newsk, ireq->ir_rmt_addr);
-       sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
-       newinet->inet_saddr     = ireq->ir_loc_addr;
        RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt));
        newinet->mc_index  = inet_iif(skb);
        newinet->mc_ttl    = ip_hdr(skb)->ttl;
index d664924..39ae9d8 100644 (file)
@@ -365,6 +365,9 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        ireq = inet_rsk(req);
        ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
        ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
+       ireq->ir_rmt_addr = LOOPBACK4_IPV6;
+       ireq->ir_loc_addr = LOOPBACK4_IPV6;
+
        ireq->ireq_family = AF_INET6;
        ireq->ir_mark = inet_request_mark(sk, skb);
 
@@ -504,10 +507,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
 
        memcpy(newnp, np, sizeof(struct ipv6_pinfo));
 
-       newsk->sk_v6_daddr      = ireq->ir_v6_rmt_addr;
        newnp->saddr            = ireq->ir_v6_loc_addr;
-       newsk->sk_v6_rcv_saddr  = ireq->ir_v6_loc_addr;
-       newsk->sk_bound_dev_if  = ireq->ir_iif;
 
        /* Now IPv6 options...
 
@@ -546,9 +546,6 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
 
        dccp_sync_mss(newsk, dst_mtu(dst));
 
-       newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
-       newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
-
        if (__inet_inherit_port(sk, newsk) < 0) {
                inet_csk_prepare_forced_close(newsk);
                dccp_done(newsk);
index 1c00069..bf9ce0c 100644 (file)
@@ -1238,19 +1238,33 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
 {
        struct sock *newsk = sk_clone_lock(sk, priority);
        struct inet_connection_sock *newicsk;
+       struct inet_request_sock *ireq;
+       struct inet_sock *newinet;
 
        if (!newsk)
                return NULL;
 
        newicsk = inet_csk(newsk);
+       newinet = inet_sk(newsk);
+       ireq = inet_rsk(req);
 
-       inet_sk_set_state(newsk, TCP_SYN_RECV);
        newicsk->icsk_bind_hash = NULL;
        newicsk->icsk_bind2_hash = NULL;
 
-       inet_sk(newsk)->inet_dport = inet_rsk(req)->ir_rmt_port;
-       inet_sk(newsk)->inet_num = inet_rsk(req)->ir_num;
-       inet_sk(newsk)->inet_sport = htons(inet_rsk(req)->ir_num);
+       newinet->inet_dport = ireq->ir_rmt_port;
+       newinet->inet_num = ireq->ir_num;
+       newinet->inet_sport = htons(ireq->ir_num);
+
+       newsk->sk_bound_dev_if = ireq->ir_iif;
+
+       newsk->sk_daddr = ireq->ir_rmt_addr;
+       newsk->sk_rcv_saddr = ireq->ir_loc_addr;
+       newinet->inet_saddr = ireq->ir_loc_addr;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       newsk->sk_v6_daddr = ireq->ir_v6_rmt_addr;
+       newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr;
+#endif
 
        /* listeners have SOCK_RCU_FREE, not the children */
        sock_reset_flag(newsk, SOCK_RCU_FREE);
@@ -1270,6 +1284,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
        memset(&newicsk->icsk_accept_queue, 0,
               sizeof(newicsk->icsk_accept_queue));
 
+       inet_sk_set_state(newsk, TCP_SYN_RECV);
+
        inet_clone_ulp(req, newsk, priority);
 
        security_inet_csk_clone(newsk, req);
index 6245e24..f4a5e96 100644 (file)
@@ -1768,10 +1768,6 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
        newtp                 = tcp_sk(newsk);
        newinet               = inet_sk(newsk);
        ireq                  = inet_rsk(req);
-       sk_daddr_set(newsk, ireq->ir_rmt_addr);
-       sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
-       newsk->sk_bound_dev_if = ireq->ir_iif;
-       newinet->inet_saddr   = ireq->ir_loc_addr;
        inet_opt              = rcu_dereference(ireq->ireq_opt);
        RCU_INIT_POINTER(newinet->inet_opt, inet_opt);
        newinet->mc_index     = inet_iif(skb);
index 2debdf0..a806082 100644 (file)
@@ -798,6 +798,8 @@ static void tcp_v6_init_req(struct request_sock *req,
 
        ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
        ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
+       ireq->ir_rmt_addr = LOOPBACK4_IPV6;
+       ireq->ir_loc_addr = LOOPBACK4_IPV6;
 
        /* So that link locals have meaning */
        if ((!sk_listener->sk_bound_dev_if || l3_slave) &&
@@ -1451,10 +1453,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
 
        ip6_dst_store(newsk, dst, NULL, NULL);
 
-       newsk->sk_v6_daddr = ireq->ir_v6_rmt_addr;
        newnp->saddr = ireq->ir_v6_loc_addr;
-       newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr;
-       newsk->sk_bound_dev_if = ireq->ir_iif;
 
        /* Now IPv6 options...
 
@@ -1507,9 +1506,6 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
 
        tcp_initialize_rcv_mss(newsk);
 
-       newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
-       newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
-
 #ifdef CONFIG_TCP_MD5SIG
        l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif);