diff options
author | Neal Cardwell <ncardwell@google.com> | 2012-08-18 23:30:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-20 06:03:33 -0400 |
commit | fae6ef87faeb8853896920c68ee703d715799d28 (patch) | |
tree | 67a31066d1ad0a6f2f997ee64dd4eb78b05b9a19 /net/ipv6/tcp_ipv6.c | |
parent | 3de7a37b02f607716753dc669c1dca4f71db08fc (diff) |
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>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index bb9ce2b2f377..a3e60cc04a8a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -94,6 +94,18 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
94 | } | 94 | } |
95 | #endif | 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 | static void tcp_v6_hash(struct sock *sk) | 109 | static void tcp_v6_hash(struct sock *sk) |
98 | { | 110 | { |
99 | if (sk->sk_state != TCP_CLOSE) { | 111 | if (sk->sk_state != TCP_CLOSE) { |
@@ -1270,6 +1282,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1270 | 1282 | ||
1271 | newsk->sk_gso_type = SKB_GSO_TCPV6; | 1283 | newsk->sk_gso_type = SKB_GSO_TCPV6; |
1272 | __ip6_dst_store(newsk, dst, NULL, NULL); | 1284 | __ip6_dst_store(newsk, dst, NULL, NULL); |
1285 | inet6_sk_rx_dst_set(newsk, skb); | ||
1273 | 1286 | ||
1274 | newtcp6sk = (struct tcp6_sock *)newsk; | 1287 | newtcp6sk = (struct tcp6_sock *)newsk; |
1275 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; | 1288 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; |
@@ -1729,18 +1742,6 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { | |||
1729 | .twsk_destructor= tcp_twsk_destructor, | 1742 | .twsk_destructor= tcp_twsk_destructor, |
1730 | }; | 1743 | }; |
1731 | 1744 | ||
1732 | static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | ||
1733 | { | ||
1734 | struct dst_entry *dst = skb_dst(skb); | ||
1735 | const struct rt6_info *rt = (const struct rt6_info *)dst; | ||
1736 | |||
1737 | dst_hold(dst); | ||
1738 | sk->sk_rx_dst = dst; | ||
1739 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | ||
1740 | if (rt->rt6i_node) | ||
1741 | inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; | ||
1742 | } | ||
1743 | |||
1744 | static const struct inet_connection_sock_af_ops ipv6_specific = { | 1745 | static const struct inet_connection_sock_af_ops ipv6_specific = { |
1745 | .queue_xmit = inet6_csk_xmit, | 1746 | .queue_xmit = inet6_csk_xmit, |
1746 | .send_check = tcp_v6_send_check, | 1747 | .send_check = tcp_v6_send_check, |