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)