From 63d9950b08184e6531adceb65f64b429909cc101 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 24 Mar 2009 16:24:50 +0000 Subject: [PATCH] ipv6: Make v4-mapped bindings consistent with IPv4 Binding to a v4-mapped address on an AF_INET6 socket should produce the same result as binding to an IPv4 address on AF_INET socket. The two are interchangable as v4-mapped address is really a portability aid. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 9b6a37d16fb0..61f55386a236 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -276,6 +276,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) /* Check if the address belongs to the host. */ if (addr_type == IPV6_ADDR_MAPPED) { + int chk_addr_ret; + /* Binding to v4-mapped address on a v6-only socket * makes no sense */ @@ -283,11 +285,17 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = -EINVAL; goto out; } + + /* Reproduce AF_INET checks to make the bindings consitant */ v4addr = addr->sin6_addr.s6_addr32[3]; - if (inet_addr_type(net, v4addr) != RTN_LOCAL) { - err = -EADDRNOTAVAIL; + chk_addr_ret = inet_addr_type(net, v4addr); + if (!sysctl_ip_nonlocal_bind && + !(inet->freebind || inet->transparent) && + v4addr != htonl(INADDR_ANY) && + chk_addr_ret != RTN_LOCAL && + chk_addr_ret != RTN_MULTICAST && + chk_addr_ret != RTN_BROADCAST) goto out; - } } else { if (addr_type != IPV6_ADDR_ANY) { struct net_device *dev = NULL; -- 2.30.2