tcp: Don't nuke connections for the wrong protocol
Currently, calling tcp_nuke_addr to reset IPv6 connections resets IPv4 connections as well, because all Android framework sockets are dual-stack (i.e., IPv6) sockets, and we don't check the source address to see if the connection was in fact an IPv4 connection. Fix this by checking the source address and not resetting the connection if it's a mapped address. Also slightly tweak the IPv4 code path, which doesn't check for mapped addresses either. This was not causing any problems because tcp_is_local normally always returns true for LOOPBACK4_IPV6 (127.0.0.6), because the loopback interface is configured as as 127.0.0.0/8. However, checking explicitly for LOOPBACK4_IPV6 makes the code a bit more robust. Bug: 5535055 Change-Id: I4d6ed3497c5b8643c864783cf681f088cf6b8d2a Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
This commit is contained in:
@@ -273,6 +273,8 @@
|
|||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
#include <net/ip.h>
|
#include <net/ip.h>
|
||||||
#include <net/ip6_route.h>
|
#include <net/ip6_route.h>
|
||||||
|
#include <net/ipv6.h>
|
||||||
|
#include <net/transp_v6.h>
|
||||||
#include <net/netdma.h>
|
#include <net/netdma.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
||||||
@@ -3374,8 +3376,16 @@ restart:
|
|||||||
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
|
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
struct inet_sock *inet = inet_sk(sk);
|
||||||
|
|
||||||
|
if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
|
||||||
|
continue;
|
||||||
|
if (sock_flag(sk, SOCK_DEAD))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (family == AF_INET) {
|
if (family == AF_INET) {
|
||||||
__be32 s4 = inet->inet_rcv_saddr;
|
__be32 s4 = inet->inet_rcv_saddr;
|
||||||
|
if (s4 == LOOPBACK4_IPV6)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (in->s_addr != s4 &&
|
if (in->s_addr != s4 &&
|
||||||
!(in->s_addr == INADDR_ANY &&
|
!(in->s_addr == INADDR_ANY &&
|
||||||
!tcp_is_local(net, s4)))
|
!tcp_is_local(net, s4)))
|
||||||
@@ -3387,7 +3397,11 @@ restart:
|
|||||||
struct in6_addr *s6;
|
struct in6_addr *s6;
|
||||||
if (!inet->pinet6)
|
if (!inet->pinet6)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
s6 = &inet->pinet6->rcv_saddr;
|
s6 = &inet->pinet6->rcv_saddr;
|
||||||
|
if (ipv6_addr_type(s6) == IPV6_ADDR_MAPPED)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!ipv6_addr_equal(in6, s6) &&
|
if (!ipv6_addr_equal(in6, s6) &&
|
||||||
!(ipv6_addr_equal(in6, &in6addr_any) &&
|
!(ipv6_addr_equal(in6, &in6addr_any) &&
|
||||||
!tcp_is_local6(net, s6)))
|
!tcp_is_local6(net, s6)))
|
||||||
@@ -3395,11 +3409,6 @@ restart:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
|
|
||||||
continue;
|
|
||||||
if (sock_flag(sk, SOCK_DEAD))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sock_hold(sk);
|
sock_hold(sk);
|
||||||
spin_unlock_bh(lock);
|
spin_unlock_bh(lock);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user