On Tue, Aug 31, 2010 at 02:42:36PM +0200, Mats Erik Andersson wrote:
> Let me contribute an observation on this bug.
> 
> The main cause of this bug is the setting "net.ipv6.bindv6only=1",
> which is enforced by Debian in contradiction to the statement
> made in the man page ipv6(7), the section about socket options
> and IPV6_V6ONLY, as seen from the perspective of glibc.
> 
> The source code for inetutils-inetd is written to work with the
> expected "net.ipv6.bindv6only=0", and there is no reason to expect
[...]

When I saw the discussion of this bug I thought about the
non-standard bindv6only in debian, just like you.

I wondered to myself why you didn't suggest the solution
of just (re)setting BIND_V6ONLY to 0 using setsockopt.

After diffing 1.6 and the new upstream 1.8 release, I found this
little change which might solve the issue. It seems like
the setsockopt call simply reversed the on/off value of v6only.

Please see (and test?) attachment.

-- 
Andreas Henriksson
Patch extracted from changes between inetutils 1.6 -> 1.8.

--- inetutils-1.6/inetd/inetd.c	2008-12-27 19:50:35.000000000 +0100
+++ inetutils-1.8/src/inetd.c	2010-05-15 13:48:38.000000000 +0200
@@ -584,24 +564,28 @@
 #ifdef IPV6
   if (sep->se_family == AF_INET6)
     {
-      int val = sep->se_v4mapped;
+      /* Reverse the value of SEP->se_v4mapped, since otherwise if
+	 using `tcp' as a protocol type all connections will be mapped
+	 to IPv6, and with `tcp6' they get mapped IPv4 mapped to
+	 IPv6.  */
+      int val = sep->se_v4mapped ? 0 : 1;
       if (setsockopt (sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY,
 		      (char *) &val, sizeof (val)) < 0)
 	syslog (LOG_ERR, "setsockopt (IPV6_V6ONLY): %m");
     }
 #endif      
   if (strncmp (sep->se_proto, "tcp", 3) == 0 && (options & SO_DEBUG))
     {
       if (setsockopt (sep->se_fd, SOL_SOCKET, SO_DEBUG,
 		      (char *) &on, sizeof (on)) < 0)
 	syslog (LOG_ERR, "setsockopt (SO_DEBUG): %m");
     }
   
   err = setsockopt (sep->se_fd, SOL_SOCKET, SO_REUSEADDR,
 		    (char *) &on, sizeof (on));
   if (err < 0)
     syslog (LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
       
   err = bind (sep->se_fd, (struct sockaddr *) &sep->se_ctrladdr,
 	      sizeof (sep->se_ctrladdr));
   if (err < 0)

Reply via email to