I've made the patch below which takes care of the problem for me.
I have tried several different versions, I didn't really like any
of them. 
This code is one of the rare pieces of code that is rather well
structured and relatively free of any ugly hacks. This fix makes
it a lot uglier, what I particularly don't like is that it now
depends on the order in which the listeners for the different 
protocols are created.

I've tried several different solutions including the use if
getaddrinfo(), everything made this code more ugly.

Any better solutions are welcome. If there are none, I'll commit this
code.

Egbert.

Index: Xtrans.c
===================================================================
RCS file: /home/x-cvs/xc/lib/xtrans/Xtrans.c,v
retrieving revision 3.31
diff -u -w -r3.31 Xtrans.c
--- Xtrans.c    20 Jul 2003 16:12:15 -0000      3.31
+++ Xtrans.c    23 Jul 2003 13:35:40 -0000
@@ -90,10 +90,10 @@
 #endif /* STREAMSCONN */
 #if defined(TCPCONN)
     { &TRANS(SocketTCPFuncs),  TRANS_SOCKET_TCP_INDEX },
-    { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX },
 #if defined(IPv6) && defined(AF_INET6)
     { &TRANS(SocketINET6Funcs),        TRANS_SOCKET_INET6_INDEX },
 #endif /* IPv6 */
+    { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX },
 #endif /* TCPCONN */
 #if defined(DNETCONN)
     { &TRANS(DNETFuncs),       TRANS_DNET_INDEX },
@@ -768,10 +768,10 @@
 #ifdef TRANS_SERVER
 
 int
-TRANS(CreateListener) (XtransConnInfo ciptr, char *port)
+TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
 
 {
-    return ciptr->transptr->CreateListener (ciptr, port);
+    return ciptr->transptr->CreateListener (ciptr, port, flags);
 }
 
 int
@@ -1037,6 +1037,9 @@
     char               buffer[256]; /* ??? What size ?? */
     XtransConnInfo     ciptr, temp_ciptrs[NUMTRANS];
     int                        status, i, j;
+#if defined (linux) && defined(IPv6) && defined(AF_INET6)
+    Bool               ipv6_succ = FALSE;
+#endif
 
     PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n",
           port ? port : "NULL", ciptrs_ret, 0);
@@ -1046,6 +1049,7 @@
     for (i = 0; i < NUMTRANS; i++)
     {
        Xtransport *trans = Xtransports[i].transport;
+       unsigned int flags = 0;
 
        if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
            continue;
@@ -1065,8 +1069,13 @@
                  trans->TransName, 0, 0);
            continue;
        }
+#if defined (linux) && defined(IPv6) && defined(AF_INET6)
+               if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
+                    && ipv6_succ))
+                   flags |= ADDR_IN_USE_ALLOWED;
+#endif
 
-       if ((status = TRANS(CreateListener (ciptr, port))) < 0)
+       if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
        {
            if (status == TRANS_ADDR_IN_USE)
            {
@@ -1098,6 +1107,11 @@
            }
        }
 
+#if defined (linux) && defined(IPv6) && defined(AF_INET6)
+       if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
+           ipv6_succ = TRUE;
+#endif
+       
        PRMSG (5,
              "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
              trans->TransName, ciptr->fd, 0);
@@ -1165,7 +1179,7 @@
            continue;
        }
 
-       if ((status = TRANS(CreateListener (ciptr, port))) < 0)
+       if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
        {
            if (status == TRANS_ADDR_IN_USE)
            {
Index: Xtrans.h
===================================================================
RCS file: /home/x-cvs/xc/lib/xtrans/Xtrans.h,v
retrieving revision 3.21
diff -u -w -r3.21 Xtrans.h
--- Xtrans.h    20 Jul 2003 16:12:15 -0000      3.21
+++ Xtrans.h    23 Jul 2003 13:35:41 -0000
@@ -339,7 +339,8 @@
 
 int TRANS(CreateListener)(
     XtransConnInfo,    /* ciptr */
-    char *             /* port */
+    char *,            /* port */
+    unsigned int       /* flags */
 );
 
 int TRANS(NoListen) (
Index: Xtransint.h
===================================================================
RCS file: /home/x-cvs/xc/lib/xtrans/Xtransint.h,v
retrieving revision 3.35
diff -u -w -r3.35 Xtransint.h
--- Xtransint.h 26 Nov 2002 01:12:30 -0000      3.35
+++ Xtransint.h 23 Jul 2003 13:35:41 -0000
@@ -26,7 +26,7 @@
 from The Open Group.
 
 */
-/* $XFree86: xc/lib/xtrans/Xtransint.h,v 3.35 2002/11/26 01:12:30 dawes Exp $ */
+/* $XFree86: xc/lib/xtrans/Xtransint.h,v 3.34 2002/11/20 23:00:36 dawes Exp $ */
 
 /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
  *
@@ -283,10 +283,13 @@
     );
 
 #ifdef TRANS_SERVER
+/* Flags */
+# define ADDR_IN_USE_ALLOWED   1
 
     int        (*CreateListener)(
        XtransConnInfo,         /* connection */
-       char *                  /* port */
+       char *,                 /* port */
+       unsigned int            /* flags */
     );
 
     int        (*ResetListener)(
Index: Xtranssock.c
===================================================================
RCS file: /home/x-cvs/xc/lib/xtrans/Xtranssock.c,v
retrieving revision 3.59
diff -u -w -r3.59 Xtranssock.c
--- Xtranssock.c        18 Jul 2003 15:39:48 -0000      3.59
+++ Xtranssock.c        23 Jul 2003 13:35:41 -0000
@@ -783,7 +783,8 @@
 
 static int
 TRANS(SocketCreateListener) (XtransConnInfo ciptr, 
-                            struct sockaddr *sockname, int socknamelen)
+                            struct sockaddr *sockname,
+                            int socknamelen, unsigned int flags)
 
 {
     int        namelen = socknamelen;
@@ -803,7 +804,10 @@
 
     while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
     {
-       if (errno == EADDRINUSE)
+       if (errno == EADDRINUSE) {
+           if (flags & ADDR_IN_USE_ALLOWED)
+               break;
+       } else
            return TRANS_ADDR_IN_USE;
 
        if (retry-- == 0) {
@@ -853,7 +857,7 @@
 
 #ifdef TCPCONN
 static int
-TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port)
+TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
 
 {
 #if defined(IPv6) && defined(AF_INET6)
@@ -958,7 +962,7 @@
 #endif
 
     if ((status = TRANS(SocketCreateListener) (ciptr,
-       (struct sockaddr *) &sockname, namelen)) < 0)
+       (struct sockaddr *) &sockname, namelen, flags)) < 0)
     {
        PRMSG (1,
     "SocketINETCreateListener: ...SocketCreateListener() failed\n",
@@ -983,7 +987,8 @@
 #ifdef UNIXCONN
 
 static int
-TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port)
+TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
+                                unsigned int flags)
 
 {
     struct sockaddr_un sockname;
@@ -1034,7 +1039,7 @@
     unlink (sockname.sun_path);
 
     if ((status = TRANS(SocketCreateListener) (ciptr,
-       (struct sockaddr *) &sockname, namelen)) < 0)
+       (struct sockaddr *) &sockname, namelen, flags)) < 0)
     {
        PRMSG (1,
     "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",

Reply via email to