Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: tcp: move sk_rx_dst_set call after tcp_create_openreq_child()

This commit removes the sk_rx_dst_set calls from
tcp_create_openreq_child(), because at that point the icsk_af_ops
field of ipv6_mapped TCP sockets has not been set to its proper final
value.

Instead, to make sure we get the right sk_rx_dst_set variant
appropriate for the address family of the new connection, we have
tcp_v{4,6}_syn_recv_sock() directly call the appropriate function
shortly after the call to tcp_create_openreq_child() returns.

This also moves inet6_sk_rx_dst_set() to avoid a forward declaration
with the new approach.

Signed-off-by: Neal Cardwell <ncardwell@google.com>
Reported-by: Artem Savkov <artem.savkov@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Neal Cardwell and committed by
David S. Miller
fae6ef87 3de7a37b

+14 -14
+1
net/ipv4/tcp_ipv4.c
··· 1462 1462 goto exit_nonewsk; 1463 1463 1464 1464 newsk->sk_gso_type = SKB_GSO_TCPV4; 1465 + inet_sk_rx_dst_set(newsk, skb); 1465 1466 1466 1467 newtp = tcp_sk(newsk); 1467 1468 newinet = inet_sk(newsk);
-2
net/ipv4/tcp_minisocks.c
··· 387 387 struct tcp_sock *oldtp = tcp_sk(sk); 388 388 struct tcp_cookie_values *oldcvp = oldtp->cookie_values; 389 389 390 - newicsk->icsk_af_ops->sk_rx_dst_set(newsk, skb); 391 - 392 390 /* TCP Cookie Transactions require space for the cookie pair, 393 391 * as it differs for each connection. There is no need to 394 392 * copy any s_data_payload stored at the original socket.
+13 -12
net/ipv6/tcp_ipv6.c
··· 94 94 } 95 95 #endif 96 96 97 + static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) 98 + { 99 + struct dst_entry *dst = skb_dst(skb); 100 + const struct rt6_info *rt = (const struct rt6_info *)dst; 101 + 102 + dst_hold(dst); 103 + sk->sk_rx_dst = dst; 104 + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; 105 + if (rt->rt6i_node) 106 + inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; 107 + } 108 + 97 109 static void tcp_v6_hash(struct sock *sk) 98 110 { 99 111 if (sk->sk_state != TCP_CLOSE) { ··· 1282 1270 1283 1271 newsk->sk_gso_type = SKB_GSO_TCPV6; 1284 1272 __ip6_dst_store(newsk, dst, NULL, NULL); 1273 + inet6_sk_rx_dst_set(newsk, skb); 1285 1274 1286 1275 newtcp6sk = (struct tcp6_sock *)newsk; 1287 1276 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; ··· 1741 1728 .twsk_unique = tcp_twsk_unique, 1742 1729 .twsk_destructor= tcp_twsk_destructor, 1743 1730 }; 1744 - 1745 - static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) 1746 - { 1747 - struct dst_entry *dst = skb_dst(skb); 1748 - const struct rt6_info *rt = (const struct rt6_info *)dst; 1749 - 1750 - dst_hold(dst); 1751 - sk->sk_rx_dst = dst; 1752 - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; 1753 - if (rt->rt6i_node) 1754 - inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; 1755 - } 1756 1731 1757 1732 static const struct inet_connection_sock_af_ops ipv6_specific = { 1758 1733 .queue_xmit = inet6_csk_xmit,