diff options
author | Neal Cardwell <ncardwell@google.com> | 2014-08-14 12:40:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-14 17:38:54 -0400 |
commit | 4fab9071950c2021d846e18351e0f46a1cffd67b (patch) | |
tree | f7538ee4e32315a32ab45f3e7bb00e9c6a919bfa | |
parent | bc8fc7b8f825ef17a0fb9e68c18ce94fa66ab337 (diff) |
tcp: fix tcp_release_cb() to dispatch via address family for mtu_reduced()
Make sure we use the correct address-family-specific function for
handling MTU reductions from within tcp_release_cb().
Previously AF_INET6 sockets were incorrectly always using the IPv6
code path when sometimes they were handling IPv4 traffic and thus had
an IPv4 dst.
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Diagnosed-by: Willem de Bruijn <willemb@google.com>
Fixes: 563d34d057862 ("tcp: dont drop MTU reduction indications")
Reviewed-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/inet_connection_sock.h | 1 | ||||
-rw-r--r-- | include/net/sock.h | 1 | ||||
-rw-r--r-- | include/net/tcp.h | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 3 |
6 files changed, 8 insertions, 5 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 7a4313887568..5fbe6568c3cf 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h | |||
@@ -62,6 +62,7 @@ struct inet_connection_sock_af_ops { | |||
62 | void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); | 62 | void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); |
63 | int (*bind_conflict)(const struct sock *sk, | 63 | int (*bind_conflict)(const struct sock *sk, |
64 | const struct inet_bind_bucket *tb, bool relax); | 64 | const struct inet_bind_bucket *tb, bool relax); |
65 | void (*mtu_reduced)(struct sock *sk); | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | /** inet_connection_sock - INET connection oriented sock | 68 | /** inet_connection_sock - INET connection oriented sock |
diff --git a/include/net/sock.h b/include/net/sock.h index 38805fa02e48..7f2ab72f321a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -987,7 +987,6 @@ struct proto { | |||
987 | struct sk_buff *skb); | 987 | struct sk_buff *skb); |
988 | 988 | ||
989 | void (*release_cb)(struct sock *sk); | 989 | void (*release_cb)(struct sock *sk); |
990 | void (*mtu_reduced)(struct sock *sk); | ||
991 | 990 | ||
992 | /* Keeping track of sk's, looking them up, and port selection methods. */ | 991 | /* Keeping track of sk's, looking them up, and port selection methods. */ |
993 | void (*hash)(struct sock *sk); | 992 | void (*hash)(struct sock *sk); |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 36f55254573f..e337e05035be 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -448,6 +448,7 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); | |||
448 | */ | 448 | */ |
449 | 449 | ||
450 | void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); | 450 | void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); |
451 | void tcp_v4_mtu_reduced(struct sock *sk); | ||
451 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); | 452 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); |
452 | struct sock *tcp_create_openreq_child(struct sock *sk, | 453 | struct sock *tcp_create_openreq_child(struct sock *sk, |
453 | struct request_sock *req, | 454 | struct request_sock *req, |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index dceff5fe8e66..cd17f009aede 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -271,7 +271,7 @@ EXPORT_SYMBOL(tcp_v4_connect); | |||
271 | * It can be called through tcp_release_cb() if socket was owned by user | 271 | * It can be called through tcp_release_cb() if socket was owned by user |
272 | * at the time tcp_v4_err() was called to handle ICMP message. | 272 | * at the time tcp_v4_err() was called to handle ICMP message. |
273 | */ | 273 | */ |
274 | static void tcp_v4_mtu_reduced(struct sock *sk) | 274 | void tcp_v4_mtu_reduced(struct sock *sk) |
275 | { | 275 | { |
276 | struct dst_entry *dst; | 276 | struct dst_entry *dst; |
277 | struct inet_sock *inet = inet_sk(sk); | 277 | struct inet_sock *inet = inet_sk(sk); |
@@ -302,6 +302,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk) | |||
302 | tcp_simple_retransmit(sk); | 302 | tcp_simple_retransmit(sk); |
303 | } /* else let the usual retransmit timer handle it */ | 303 | } /* else let the usual retransmit timer handle it */ |
304 | } | 304 | } |
305 | EXPORT_SYMBOL(tcp_v4_mtu_reduced); | ||
305 | 306 | ||
306 | static void do_redirect(struct sk_buff *skb, struct sock *sk) | 307 | static void do_redirect(struct sk_buff *skb, struct sock *sk) |
307 | { | 308 | { |
@@ -1787,6 +1788,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { | |||
1787 | .compat_setsockopt = compat_ip_setsockopt, | 1788 | .compat_setsockopt = compat_ip_setsockopt, |
1788 | .compat_getsockopt = compat_ip_getsockopt, | 1789 | .compat_getsockopt = compat_ip_getsockopt, |
1789 | #endif | 1790 | #endif |
1791 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
1790 | }; | 1792 | }; |
1791 | EXPORT_SYMBOL(ipv4_specific); | 1793 | EXPORT_SYMBOL(ipv4_specific); |
1792 | 1794 | ||
@@ -2406,7 +2408,6 @@ struct proto tcp_prot = { | |||
2406 | .sendpage = tcp_sendpage, | 2408 | .sendpage = tcp_sendpage, |
2407 | .backlog_rcv = tcp_v4_do_rcv, | 2409 | .backlog_rcv = tcp_v4_do_rcv, |
2408 | .release_cb = tcp_release_cb, | 2410 | .release_cb = tcp_release_cb, |
2409 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
2410 | .hash = inet_hash, | 2411 | .hash = inet_hash, |
2411 | .unhash = inet_unhash, | 2412 | .unhash = inet_unhash, |
2412 | .get_port = inet_csk_get_port, | 2413 | .get_port = inet_csk_get_port, |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ff3f0f75cc6c..5a7c41fbc6d3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -800,7 +800,7 @@ void tcp_release_cb(struct sock *sk) | |||
800 | __sock_put(sk); | 800 | __sock_put(sk); |
801 | } | 801 | } |
802 | if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { | 802 | if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { |
803 | sk->sk_prot->mtu_reduced(sk); | 803 | inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); |
804 | __sock_put(sk); | 804 | __sock_put(sk); |
805 | } | 805 | } |
806 | } | 806 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f2ce95502392..29964c3d363c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1595,6 +1595,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { | |||
1595 | .compat_setsockopt = compat_ipv6_setsockopt, | 1595 | .compat_setsockopt = compat_ipv6_setsockopt, |
1596 | .compat_getsockopt = compat_ipv6_getsockopt, | 1596 | .compat_getsockopt = compat_ipv6_getsockopt, |
1597 | #endif | 1597 | #endif |
1598 | .mtu_reduced = tcp_v6_mtu_reduced, | ||
1598 | }; | 1599 | }; |
1599 | 1600 | ||
1600 | #ifdef CONFIG_TCP_MD5SIG | 1601 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1625,6 +1626,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1625 | .compat_setsockopt = compat_ipv6_setsockopt, | 1626 | .compat_setsockopt = compat_ipv6_setsockopt, |
1626 | .compat_getsockopt = compat_ipv6_getsockopt, | 1627 | .compat_getsockopt = compat_ipv6_getsockopt, |
1627 | #endif | 1628 | #endif |
1629 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
1628 | }; | 1630 | }; |
1629 | 1631 | ||
1630 | #ifdef CONFIG_TCP_MD5SIG | 1632 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1864,7 +1866,6 @@ struct proto tcpv6_prot = { | |||
1864 | .sendpage = tcp_sendpage, | 1866 | .sendpage = tcp_sendpage, |
1865 | .backlog_rcv = tcp_v6_do_rcv, | 1867 | .backlog_rcv = tcp_v6_do_rcv, |
1866 | .release_cb = tcp_release_cb, | 1868 | .release_cb = tcp_release_cb, |
1867 | .mtu_reduced = tcp_v6_mtu_reduced, | ||
1868 | .hash = tcp_v6_hash, | 1869 | .hash = tcp_v6_hash, |
1869 | .unhash = inet_unhash, | 1870 | .unhash = inet_unhash, |
1870 | .get_port = inet_csk_get_port, | 1871 | .get_port = inet_csk_get_port, |