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",