Re: socket api problem: can't bind an ipv6 socket to ::ffff:0.0.0.0

Previous thread: [PATCH] tipc: fix non-const printf format arguments by Stephen Hemminger on Tuesday, March 17, 2009 - 11:28 am. (2 messages)

Next thread: pull request: wireless-next-2.6 2009-03-17 by John W. Linville on Tuesday, March 17, 2009 - 12:21 pm. (3 messages)
From: Brian Haley
Date: Tuesday, March 17, 2009 - 12:21 pm

Top-posting so others can see your off-list rant in full.  I see no reason to
help you any further, even though I did have a patch that would change this
behavior for you.  Good luck with your "biggest noncommercial Internet messaging
infrastructure" in the world.

-Brian

--

From: David Miller
Date: Tuesday, March 17, 2009 - 12:31 pm

From: Brian Haley <brian.haley@hp.com>

What a jerk.  Brian, don't help him any more, you were being
very reasonable in your email to him.  His response was way
out of line.

--

From: Vlad Yasevich
Date: Tuesday, March 17, 2009 - 2:05 pm

Hi David

Regardless of how we may feel about this thread, it did make me run
the BSD bindtest utility and look at the results.  What I found was
rather surprising.

There were multiple tests that one would exptect to succeed, but they
were failing.

Things that I consider broken:
  1) We can bind to a v4-mapped IPv6 address on a v6-only socket.
  2) We conflict IPv4 wildcrads with explicit IPv6 addresses and vice-versa
  3) We inconsitently treat V4 address and v4-mapped addresses.  As an example,
     try binging to 0.1.2.3. (This also kind of goes to binding
     ::ffff:0.0.0.0).

The following 4 RFC patches attempt to fix this.  I've run bindtest tool and
am currently analizing the results.  They look a heck of a lot better.

Thanks
-vlad

--

From: Vlad Yasevich
Date: Tuesday, March 17, 2009 - 2:06 pm

The IPv4 wildcard (0.0.0.0) address does not intersect
in any way with explicit IPv6 addresses.  These two should
be permitted, but the IPv4 conflict code checks the ipv6only
bit as part of the test.  Since binding to an explicit IPv6
address restricts the socket to only that IPv6 address, the
side-effect is that the socket behaves as v6-only.  By
explicitely setting ipv6only in this case, allows the 2 binds
to succeed.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
 net/ipv6/af_inet6.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 07b9f3c..0adce8e 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -346,8 +346,11 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 		goto out;
 	}
 
-	if (addr_type != IPV6_ADDR_ANY)
+	if (addr_type != IPV6_ADDR_ANY) {
 		sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
+		if (addr_type != IPV6_ADDR_MAPPED)
+			np->ipv6only = 1;
+	}
 	if (snum)
 		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
 	inet->sport = htons(inet->num);
-- 
1.5.4.3

--

From: Vlad Yasevich
Date: Tuesday, March 17, 2009 - 2:05 pm

A socket marked v6-only, can not receive or send traffic to v4-mapped
addresses.  Thus allowing binding to v4-mapped address on such a
socket makes no sense.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
 net/ipv6/af_inet6.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 3e2ddfa..07b9f3c 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -276,6 +276,13 @@ 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) {
+		/* Binding to v4-mapped address on a v6-only socket
+		 * makes no sense
+		 */
+		if (np->ipv6only) {
+			err = -EINVAL;
+			goto out;
+		}
 		v4addr = addr->sin6_addr.s6_addr32[3];
 		if (inet_addr_type(net, v4addr) != RTN_LOCAL) {
 			err = -EADDRNOTAVAIL;
-- 
1.5.4.3

--

From: Vlad Yasevich
Date: Tuesday, March 17, 2009 - 2:06 pm

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>
---
 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 0adce8e..274cc89 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;
-- 
1.5.4.3

--

From: Vlad Yasevich
Date: Tuesday, March 17, 2009 - 2:06 pm

The ipv6 version of bind_conflict code calls ipv6_rcv_saddr_equal()
which at times wrongly identified intersections between addresses.
It particularly broke down under a few instances and caused erroneouse
bind conflicts.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
 include/net/addrconf.h |    4 ++--
 include/net/udp.h      |    2 ++
 net/ipv4/udp.c         |    3 ++-
 net/ipv6/addrconf.c    |   34 ----------------------------------
 net/ipv6/udp.c         |   30 ++++++++++++++++++++++++++++++
 5 files changed, 36 insertions(+), 37 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index c216de5..7b55ab2 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -88,8 +88,8 @@ extern int			ipv6_dev_get_saddr(struct net *net,
 extern int			ipv6_get_lladdr(struct net_device *dev,
 						struct in6_addr *addr,
 						unsigned char banned_flags);
-extern int			ipv6_rcv_saddr_equal(const struct sock *sk, 
-						      const struct sock *sk2);
+extern int 			ipv6_rcv_saddr_equal(const struct sock *sk,
+						    const struct sock *sk2);
 extern void			addrconf_join_solict(struct net_device *dev,
 					struct in6_addr *addr);
 extern void			addrconf_leave_solict(struct inet6_dev *idev,
diff --git a/include/net/udp.h b/include/net/udp.h
index 90e6ce5..93dbe29 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -124,6 +124,8 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
 	sk_common_release(sk);
 }
 
+extern int	ipv4_rcv_saddr_equal(const struct sock *sk1,
+				    const struct sock *sk2);
 extern int	udp_lib_get_port(struct sock *sk, unsigned short snum,
 		int (*)(const struct sock*,const struct sock*));
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4bd178a..ce64e4d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -222,7 +222,7 @@ fail:
 	return error;
 }
 
-static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+int ipv4_rcv_saddr_equal(const struct sock ...
From: Jarek Poplawski
Date: Wednesday, March 18, 2009 - 2:13 am

Do you mean he got that joke wrong? Otherwise I think he is right. We
shouln't advise him how to do the things right, but, since what he
wants looks like legal and acceptable elsewhere, try to do this the
least invasive way.

Jarek P.
--

From: David Miller
Date: Wednesday, March 18, 2009 - 2:36 pm

From: Jarek Poplawski <jarkao2@gmail.com>

First of all, no matter if we allow that kind of bind() he wants or
not, he cannot use it in his application unless he wants his
application to be useless of most people's machines for at least a
year.

That's why the "make Linux be compatible with X other systems" is
always a joke argument.  Application wise, one still has to be
compatible with all existing Linux systems which is a much larger
issue.

And yes we should advise people what is an appropriate way to
accomplish some task.  If we aren't the experts on such a topic,
then who the hell is?
--

From: Jarek Poplawski
Date: Wednesday, March 18, 2009 - 2:53 pm

On Wed, Mar 18, 2009 at 02:36:35PM -0700, David Miller wrote:

Only if sb. is looking for advice; otherwise it's not very nice,
especially if repeated many times.

Jarek P.
--

From: David Miller
Date: Wednesday, March 18, 2009 - 5:32 pm

From: Jarek Poplawski <jarkao2@gmail.com>

If the purpose of the query was to suggest that Linux should behave a
certain way, it should be no surprise to anyone that if we should
disagree with that suggestion we would suggest what we consider more
desriable alternatives for the application developer.

I don't even think this is worth the time we are spending to discuss
it, it seems so straightforward.
--

Previous thread: [PATCH] tipc: fix non-const printf format arguments by Stephen Hemminger on Tuesday, March 17, 2009 - 11:28 am. (2 messages)

Next thread: pull request: wireless-next-2.6 2009-03-17 by John W. Linville on Tuesday, March 17, 2009 - 12:21 pm. (3 messages)