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