diff options
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 3516e6fe2e5..3a4d92b5a83 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -17,6 +17,7 @@ #include <linux/in6.h> #include <linux/ipv6.h> #include <linux/jhash.h> +#include <linux/slab.h> #include <net/addrconf.h> #include <net/inet_connection_sock.h> @@ -41,11 +42,16 @@ int inet6_csk_bind_conflict(const struct sock *sk, if (sk != sk2 && (!sk->sk_bound_dev_if || !sk2->sk_bound_dev_if || - sk->sk_bound_dev_if == sk2->sk_bound_dev_if) && - (!sk->sk_reuse || !sk2->sk_reuse || - sk2->sk_state == TCP_LISTEN) && - ipv6_rcv_saddr_equal(sk, sk2)) - break; + sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { + if ((!sk->sk_reuse || !sk2->sk_reuse || + sk2->sk_state == TCP_LISTEN) && + ipv6_rcv_saddr_equal(sk, sk2)) + break; + else if (sk->sk_reuse && sk2->sk_reuse && + !ipv6_addr_any(inet6_rcv_saddr(sk)) && + ipv6_rcv_saddr_equal(sk, sk2)) + break; + } } return node != NULL; |