diff -NurpP linux-2.6.31.5-vs2.3.0.36.21/net/ipv4/inet_connection_sock.c linux-2.6.31.5-vs2.3.0.36.21.2/net/ipv4/inet_connection_sock.c --- linux-2.6.31.5-vs2.3.0.36.21/net/ipv4/inet_connection_sock.c 2009-09-10 16:11:43.000000000 +0200 +++ linux-2.6.31.5-vs2.3.0.36.21.2/net/ipv4/inet_connection_sock.c 2009-11-01 15:30:20.000000000 +0100 @@ -49,14 +49,9 @@ void inet_get_local_port_range(int *low, } EXPORT_SYMBOL(inet_get_local_port_range); -int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) +int ipv4_rcv_saddr_check(struct nx_info *sk1_nxi, const __be32 sk1_rcv_saddr, + struct nx_info *sk2_nxi, const __be32 sk2_rcv_saddr) { - __be32 sk1_rcv_saddr = inet_rcv_saddr(sk1), - sk2_rcv_saddr = inet_rcv_saddr(sk2); - - if (inet_v6_ipv6only(sk2)) - return 0; - if (sk1_rcv_saddr && sk2_rcv_saddr && sk1_rcv_saddr == sk2_rcv_saddr) @@ -64,25 +59,38 @@ int ipv4_rcv_saddr_equal(const struct so if (sk1_rcv_saddr && !sk2_rcv_saddr && - v4_addr_in_nx_info(sk2->sk_nx_info, sk1_rcv_saddr, NXA_MASK_BIND)) + v4_addr_in_nx_info(sk2_nxi, sk1_rcv_saddr, NXA_MASK_BIND)) return 1; if (sk2_rcv_saddr && !sk1_rcv_saddr && - v4_addr_in_nx_info(sk1->sk_nx_info, sk2_rcv_saddr, NXA_MASK_BIND)) + v4_addr_in_nx_info(sk1_nxi, sk2_rcv_saddr, NXA_MASK_BIND)) return 1; if (!sk1_rcv_saddr && !sk2_rcv_saddr && - nx_v4_addr_conflict(sk1->sk_nx_info, sk2->sk_nx_info)) + nx_v4_addr_conflict(sk1_nxi, sk2_nxi)) return 1; return 0; } +int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) +{ + const __be32 sk_rcv_saddr = inet_rcv_saddr(sk); + const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); + + if (inet_v6_ipv6only(sk2)) + return 0; + + return ipv4_rcv_saddr_check(sk->sk_nx_info, sk_rcv_saddr, + sk2->sk_nx_info, sk2_rcv_saddr); +} + int inet_csk_bind_conflict(const struct sock *sk, const struct inet_bind_bucket *tb) { + const __be32 sk_rcv_saddr = inet_rcv_saddr(sk); struct sock *sk2; struct hlist_node *node; int reuse = sk->sk_reuse; @@ -102,7 +110,9 @@ int inet_csk_bind_conflict(const struct sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { if (!reuse || !sk2->sk_reuse || sk2->sk_state == TCP_LISTEN) { - if (ipv4_rcv_saddr_equal(sk, sk2)) + const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); + if (ipv4_rcv_saddr_check(sk->sk_nx_info, sk_rcv_saddr, + sk2->sk_nx_info, sk2_rcv_saddr)) break; } } diff -NurpP linux-2.6.31.5-vs2.3.0.36.21/net/ipv4/udp.c linux-2.6.31.5-vs2.3.0.36.21.2/net/ipv4/udp.c --- linux-2.6.31.5-vs2.3.0.36.21/net/ipv4/udp.c 2009-09-10 17:17:40.000000000 +0200 +++ linux-2.6.31.5-vs2.3.0.36.21.2/net/ipv4/udp.c 2009-11-01 15:30:39.000000000 +0100 @@ -222,7 +222,7 @@ fail: return error; } -extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *); +extern int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2); int udp_v4_get_port(struct sock *sk, unsigned short snum) { diff -NurpP linux-2.6.31.5-vs2.3.0.36.21/net/ipv6/udp.c linux-2.6.31.5-vs2.3.0.36.21.2/net/ipv6/udp.c --- linux-2.6.31.5-vs2.3.0.36.21/net/ipv6/udp.c 2009-09-10 16:11:43.000000000 +0200 +++ linux-2.6.31.5-vs2.3.0.36.21.2/net/ipv6/udp.c 2009-11-01 15:33:46.000000000 +0100 @@ -50,6 +50,9 @@ #include #include "udp_impl.h" +extern int ipv4_rcv_saddr_check(struct nx_info *sk1_nxi, __be32 sk1_rcv_saddr, + struct nx_info *sk2_nxi, __be32 sk2_rcv_saddr); + int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) { const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; @@ -61,32 +64,11 @@ int ipv6_rcv_saddr_equal(const struct so int addr_type = ipv6_addr_type(sk_rcv_saddr6); int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; - if (sk2_ipv6only && !sk2_rcv_saddr6) - addr_type2 = IPV6_ADDR_ANY; - - /* if both are mapped or any, treat as IPv4 */ - if ((addr_type == IPV6_ADDR_MAPPED || (addr_type == IPV6_ADDR_ANY && !sk_ipv6only)) && - (addr_type2 == IPV6_ADDR_MAPPED || (addr_type2 == IPV6_ADDR_ANY && !sk2_ipv6only))) { - if (!sk_rcv_saddr && !sk2_rcv_saddr) { - if (nx_v4_addr_conflict(sk->sk_nx_info, sk2->sk_nx_info)) - return 1; - else if (addr_type != IPV6_ADDR_ANY && sk2_rcv_saddr6) - return 0; - /* remaining cases are at least one ANY */ - } else if (!sk_rcv_saddr) - return v4_addr_in_nx_info(sk->sk_nx_info, sk2_rcv_saddr, -1); - else if (!sk2_rcv_saddr) - return v4_addr_in_nx_info(sk2->sk_nx_info, sk_rcv_saddr, -1); - else - return (sk_rcv_saddr == sk2_rcv_saddr); - } - - if (!sk2_rcv_saddr6) - addr_type2 = IPV6_ADDR_ANY; - - /* both are IPv6 */ - if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY) - return nx_v6_addr_conflict(sk->sk_nx_info, sk2->sk_nx_info); + /* if both are mapped, treat as IPv4 */ + if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) + return (!sk2_ipv6only && + ipv4_rcv_saddr_check(sk->sk_nx_info, sk_rcv_saddr, + sk2->sk_nx_info, sk2_rcv_saddr)); if (addr_type == IPV6_ADDR_ANY) return v6_addr_in_nx_info(sk->sk_nx_info,