]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/udp.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / net / ipv6 / udp.c
index 84b1a296eecb3723cc0ddd79982aaf9ff1539f40..6842dd2edd5bc0a9552c4bfbd2f7b9fbed7480fe 100644 (file)
 #include <linux/seq_file.h>
 #include "udp_impl.h"
 
+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;
+       const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
+       int sk_ipv6only = ipv6_only_sock(sk);
+       int sk2_ipv6only = inet_v6_ipv6only(sk2);
+       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 both are mapped, treat as IPv4 */
+       if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED)
+               return ipv4_rcv_saddr_equal(sk, sk2);
+
+       if (addr_type2 == IPV6_ADDR_ANY &&
+           !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
+               return 1;
+
+       if (addr_type == IPV6_ADDR_ANY &&
+           !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
+               return 1;
+
+       if (sk2_rcv_saddr6 &&
+           ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6))
+               return 1;
+
+       return 0;
+}
+
 int udp_v6_get_port(struct sock *sk, unsigned short snum)
 {
        return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal);