[vserver] [Patch, RFC] Merge of ipv6_rcv_saddr_equal() for 2.6.30.x

From: Bruno Prémont <bonbons_at_linux-vserver.org>
Date: Sat 22 Aug 2009 - 11:34:00 BST
Message-ID: <20090822123400.455fbdf9@neptune.home>

This patch works for me according to below tests:

None of the guests share IP addresses, guests 2,3 have IPv4 and IPv6
addresses, guest1 only IPv4.

host_vt1# nc -6 -l -p 10000 -s :: -v => OK
host_vt2# nc -6 -l -p 10000 -s :: -v => INUSE
host_vt1# # stop nc
host_vt2# # stop nc

guest1# nc -4 -l -p 10000 -s 0.0.0.0 -v => OK
guest2# nc -6 -l -p 10000 -s :: -v => OK
guest3# nc -6 -l -p 10000 -s :: -v => OK
host_vt1# nc -6 -l -p 10000 -s :: -v => INUSE

Please test and report back, if anyone has a testnet.sh script or
similar please mention and run it against this patch!

Signed-off-by: <bonbons@linux-vserver.org>

---
--- linux-2.6.30.5-vs2.3.0.36.14-pre5.orig/net/ipv6/af_inet6.c	2009-08-22 00:44:21.295614269 +0200
+++ linux-2.6.30.5-vs2.3.0.36.14-pre5/net/ipv6/af_inet6.c	2009-08-22 01:26:24.711662351 +0200
@@ -306,8 +306,14 @@ int inet6_bind(struct socket *sock, stru
 		    v4addr != htonl(INADDR_ANY) &&
 		    chk_addr_ret != RTN_LOCAL &&
 		    chk_addr_ret != RTN_MULTICAST &&
-		    chk_addr_ret != RTN_BROADCAST)
+		    chk_addr_ret != RTN_BROADCAST) {
+			err = -EADDRNOTAVAIL;
 			goto out;
+		}
+		if (!v4_addr_in_nx_info(sk->sk_nx_info, v4addr, NXA_MASK_BIND)) {
+			err = -EADDRNOTAVAIL;
+			goto out;
+		}
 	} else {
 		if (addr_type != IPV6_ADDR_ANY) {
 			struct net_device *dev = NULL;
--- linux-2.6.30.5-vs2.3.0.36.14-pre5.orig/net/ipv6/udp.c	2009-08-21 22:38:58.139614225 +0200
+++ linux-2.6.30.5-vs2.3.0.36.14-pre5/net/ipv6/udp.c	2009-08-22 00:39:40.947661415 +0200
@@ -61,25 +61,44 @@ 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 both are mapped, treat as IPv4 */
-	if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED)
-		return (!sk2_ipv6only &&
-			(!sk_rcv_saddr || !sk2_rcv_saddr ||
-			  sk_rcv_saddr == sk2_rcv_saddr));
+	if (sk2_ipv6only && !sk2_rcv_saddr6)
+		addr_type2 = IPV6_ADDR_ANY;
 
-	if (addr_type2 == IPV6_ADDR_ANY &&
-	    !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
-		return 1;
+	/* 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 (addr_type == IPV6_ADDR_ANY &&
-	    !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
-		return 1;
+	if (!sk2_rcv_saddr6)
+		addr_type2 = IPV6_ADDR_ANY;
 
-	if (sk2_rcv_saddr6 &&
-	    ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6))
-		return 1;
+	/* 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);
 
-	return 0;
+	if (addr_type == IPV6_ADDR_ANY) {
+		const struct in6_addr in6_any = {
+			.s6_addr32 = { 0, 0, 0, 0}
+		};
+		return v6_addr_in_nx_info(sk->sk_nx_info, sk2_rcv_saddr6 ? sk2_rcv_saddr6 : &in6_any, -1);
+	}
+
+	if (addr_type2 == IPV6_ADDR_ANY)
+		return v6_addr_in_nx_info(sk2->sk_nx_info, sk_rcv_saddr6, -1);
+
+	return ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6);
 }
 
 int udp_v6_get_port(struct sock *sk, unsigned short snum)
Received on Sat Aug 22 12:11:07 2009
[Next/Previous Months] [Main vserver Project Homepage] [Howto Subscribe/Unsubscribe] [Paul Sladen's vserver stuff]
Generated on Sat 22 Aug 2009 - 12:11:11 BST by hypermail 2.1.8