Hi! On Thu, 2010-09-02 at 17:10:33 +0200, Andreas Henriksson wrote: > On Tue, Aug 31, 2010 at 02:42:36PM +0200, Mats Erik Andersson wrote: > > 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.
This is not longer the default in new Debian installations, since netbase 4.42. > > The source code for inetutils-inetd is written to work with the > > expected "net.ipv6.bindv6only=0", and there is no reason to expect > > upstream to change their views. This is not correct, inetutils-inetd works with any net.ipv6.bindv6only setting as it's always explicitly setting the IPV6_V6ONLY flag on IPv6 sockets. > > By the way, presently inetutils-1.8 is the valid release, so the > > Debian package is noticably lagging behind. Well, there's no valid or invalid release for what Debian concerns, I've just not packaged newer versions due to the regression in the man pages, which will be fixed in next upload. > > Now, a simple patch, which is included below, will alter the source > > to interpret "tcp", "udp" to imply a desire to open an IPv4 socket, > > as seems to be expected by some Debian users. The price to pay is > > that the service "inetutils-inetd" never will be able to open a > > dual stacked listen socket for any service. Instead, "tcp" and "tcp6" > > will both be needed to accomplish this. The patch in effect makes sure > > that "tcp" and "tcp4" are synonyms; likewise for "udp" and "udp4". The solution I implemented few days ago while preparing the next upload, is to make tcp and udp IPv4 only, which is what it should be, otherwise this breaks too many programs expectations, and this should be done in upstream too, I'll send the patch there. For reference all other inetd implementations out there I checked, currently alias tcp and udp to tcp4 and udp4, and the only difference is how they treat tcp6 and udp6, either as IPv6 only or supporting IPv4 mapping, and if they provide a mean to specify IPv6 only connections or mapped ones: Solaris: http://docs.sun.com/app/docs/doc/816-4554/6maoq023l?l=en&a=view OpenBSD: http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8 FreeBSD: http://www.freebsd.org/doc/handbook/network-inetd.html AIX: http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.cmds/doc/aixcmds3/inetd.htm HP-UX: http://docs.hp.com/en/B3921-90010/inetd.conf.4.html Irix: http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=man&fname=/usr/share/catman/a_man/cat1/inetd.z QNX: http://www.qnx.com/developers/docs/6.3.2/neutrino/utilities/i/inetd.conf.html Then I changed tcp6 and udp6 to be v4mapped, and added tcp6only and udp6only to be IPv6 only connections. This mimics the behaviour of other inetd implementations with IPv6 support, namely Solaris inetd. This will need to be discussed with upstream first though, as they might prefer a different behaviour, for example the FreeBSD one of making tcp6/udp6 IPv6 only and adding tcp46/udp46 for IPv4 mapped addresses. I also fixed the tcpmux service (which does not get activated anyway, but that's another bug fix and patch). Attached is the patch I'm tentatively including in the next upload, which I'll pass through upstream first. > > A negative side effect is that any administrator who is relying on > > inetutils-inetd to produce an IPv6 socket when using "tcp", he will > > have a broken configuration. That'd be a broken configuration anyway, if one wants an either IPv4 or IPv6 guaranteed socket, one should then use udp4/tcp4 or udp6/tcp6, udp/tcp point to the current default protocol, which might change in the future (once IPv6 adoption is way greater for example). > 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. This only fixes a bug present in 1.6, which was making the value for IPV6_V6ONLY be the reverse of what the program wanted through se_v4mapped. This should be pulled in, in case the release team end up not accepting the inetutils 1.8 basd upload. regards, guillem
diff --git a/src/inetd.c b/src/inetd.c index 6fe9adf..7fbfd41 100644 --- a/src/inetd.c +++ b/src/inetd.c @@ -563,8 +563,8 @@ setup (struct servtab *sep) if (sep->se_family == AF_INET6) { /* 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 + using `tcp6' as a protocol type all connections will be mapped + to IPv6, and with `tcp6only' they get mapped IPv4 mapped to IPv6. */ int val = sep->se_v4mapped ? 0 : 1; if (setsockopt (sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY, @@ -1002,10 +1003,9 @@ getconfigent (FILE *fconfig, const char *file, size_t *line) sep->se_proto = newstr (argv[INETD_PROTOCOL]); #ifdef IPV6 - /* We default to IPv6, in setup() we'll fall back to IPv4 if - it doesn't work. */ - sep->se_family = AF_INET6; - sep->se_v4mapped = 1; + /* We default to IPv4. */ + sep->se_family = AF_INET; + sep->se_v4mapped = 0; if ((strncmp (sep->se_proto, "tcp", 3) == 0) || (strncmp (sep->se_proto, "udp", 3) == 0)) @@ -1013,7 +1013,11 @@ getconfigent (FILE *fconfig, const char *file, size_t *line) if (sep->se_proto[3] == '6') { sep->se_family = AF_INET6; - sep->se_v4mapped = 0; + /* Check for tcp6only and udp6only. */ + if (strcmp (&sep->se_proto[3], "6only") == 0) + sep->se_v4mapped = 0; + else + sep->se_v4mapped = 1; } else if (sep->se_proto[3] == '4') { @@ -1208,7 +1228,6 @@ fix_tcpmux (void) serv.se_service = newstr ("tcpmux"); serv.se_socktype = SOCK_STREAM; - serv.se_proto = newstr ("tcp"); serv.se_checked = 1; serv.se_user = newstr ("root"); serv.se_bi = bi_lookup (&serv); @@ -1226,9 +1245,11 @@ fix_tcpmux (void) serv.se_fd = -1; serv.se_type = NORM_TYPE; #ifdef IPV6 + serv.se_proto = newstr ("tcp6"); serv.se_family = AF_INET6; serv.se_v4mapped = 1; #else + serv.se_proto = newstr ("tcp"); serv.se_family = AF_INET; #endif if (debug)