diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-03-24 12:24:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-24 22:49:10 -0400 |
commit | 63d9950b08184e6531adceb65f64b429909cc101 (patch) | |
tree | 2933add2118119824305ffbff647dbd6c606e020 /net/ipv6/af_inet6.c | |
parent | 0f8d3c7ac3693d7b6c731bf2159273a59bf70e12 (diff) |
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 <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r-- | net/ipv6/af_inet6.c | 14 |
1 files 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) | |||
276 | 276 | ||
277 | /* Check if the address belongs to the host. */ | 277 | /* Check if the address belongs to the host. */ |
278 | if (addr_type == IPV6_ADDR_MAPPED) { | 278 | if (addr_type == IPV6_ADDR_MAPPED) { |
279 | int chk_addr_ret; | ||
280 | |||
279 | /* Binding to v4-mapped address on a v6-only socket | 281 | /* Binding to v4-mapped address on a v6-only socket |
280 | * makes no sense | 282 | * makes no sense |
281 | */ | 283 | */ |
@@ -283,11 +285,17 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
283 | err = -EINVAL; | 285 | err = -EINVAL; |
284 | goto out; | 286 | goto out; |
285 | } | 287 | } |
288 | |||
289 | /* Reproduce AF_INET checks to make the bindings consitant */ | ||
286 | v4addr = addr->sin6_addr.s6_addr32[3]; | 290 | v4addr = addr->sin6_addr.s6_addr32[3]; |
287 | if (inet_addr_type(net, v4addr) != RTN_LOCAL) { | 291 | chk_addr_ret = inet_addr_type(net, v4addr); |
288 | err = -EADDRNOTAVAIL; | 292 | if (!sysctl_ip_nonlocal_bind && |
293 | !(inet->freebind || inet->transparent) && | ||
294 | v4addr != htonl(INADDR_ANY) && | ||
295 | chk_addr_ret != RTN_LOCAL && | ||
296 | chk_addr_ret != RTN_MULTICAST && | ||
297 | chk_addr_ret != RTN_BROADCAST) | ||
289 | goto out; | 298 | goto out; |
290 | } | ||
291 | } else { | 299 | } else { |
292 | if (addr_type != IPV6_ADDR_ANY) { | 300 | if (addr_type != IPV6_ADDR_ANY) { |
293 | struct net_device *dev = NULL; | 301 | struct net_device *dev = NULL; |