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)