Hi!

There's a release critical bug on Debian's inetutils, but the solution
implies changing the semantics of the protocol entries in inetd.conf,
and I'd like to know if my current approach is acceptable for
upstreaming so that I can go ahead with the fix for the next Debian
release, and ask for it to be accepted by the release team.

The bug makes lots of applications using inetutils-inetd not work as
they get a TCP over IPv6 socket with IPv4 mapped addresses by default
when using "tcp" as protocol (or "udp"), when they do not expect that.

The solution I've implemented is to make tcp and udp IPv4 only, which
is what it should be (for now, for compatibility reasons), otherwise
this breaks too many programs expectations.


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 means 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 (with the assumption that
any code prepared to handle IPv6 sockets should be able to handle dual
stack ones), and added tcp6only and udp6only to be IPv6 only connections.
This mimics the behaviour of other inetd implementations with IPv6
support, namely Solaris inetd. But you might prefer a different behaviour,
for example the FreeBSD one of making tcp6/udp6 IPv6 only and adding
tcp46/udp46 for IPv4 mapped addresses.


Attached is the current patch I've applied to inetutils 1.8-1 in
experimental.

thanks,
guillem
>From ee6ea58645a4db63f6ccad40566b37b23279797e Mon Sep 17 00:00:00 2001
From: Guillem Jover <[email protected]>
Date: Mon, 6 Sep 2010 10:52:27 +0200
Subject: [PATCH 3/3] inetd: Change protocol semantics in inetd.conf

* src/inetd.c (setup): Update comment.
(getconfigent) [IPV6]: Change default family to IPv4 for "tcp" and
"udp". Change "tcp6" and "udp6" to support IPv4 mapped addresses.
Add "tcp6only" and "udp6only" protocols for IPv6 only addresses.
(fix_tcpmux) [IPV6]: Set se_proto to "tcp6".
[!IPV6]: Set se_proto to "tcp".
---
 src/inetd.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/inetd.c b/src/inetd.c
index 1c51a51..0d3ff69 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 +1002,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 +1012,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')
 	    {
@@ -1221,7 +1224,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);
@@ -1239,9 +1241,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)
-- 
1.7.1

Reply via email to