connection.c revision 05b261ec
105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrg
2605b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
3605b261ecSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg******************************************************************/
4705b261ecSmrg/*****************************************************************
4805b261ecSmrg *  Stuff to create connections --- OS dependent
4905b261ecSmrg *
5005b261ecSmrg *      EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
5105b261ecSmrg *      CloseDownConnection, CheckConnections, AddEnabledDevice,
5205b261ecSmrg *	RemoveEnabledDevice, OnlyListToOneClient,
5305b261ecSmrg *      ListenToAllClients,
5405b261ecSmrg *
5505b261ecSmrg *      (WaitForSomething is in its own file)
5605b261ecSmrg *
5705b261ecSmrg *      In this implementation, a client socket table is not kept.
5805b261ecSmrg *      Instead, what would be the index into the table is just the
5905b261ecSmrg *      file descriptor of the socket.  This won't work for if the
6005b261ecSmrg *      socket ids aren't small nums (0 - 2^8)
6105b261ecSmrg *
6205b261ecSmrg *****************************************************************/
6305b261ecSmrg
6405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
6505b261ecSmrg#include <dix-config.h>
6605b261ecSmrg#endif
6705b261ecSmrg
6805b261ecSmrg#ifdef WIN32
6905b261ecSmrg#include <X11/Xwinsock.h>
7005b261ecSmrg#endif
7105b261ecSmrg#include <X11/X.h>
7205b261ecSmrg#include <X11/Xproto.h>
7305b261ecSmrg#define XSERV_t
7405b261ecSmrg#define TRANS_SERVER
7505b261ecSmrg#define TRANS_REOPEN
7605b261ecSmrg#include <X11/Xtrans/Xtrans.h>
7705b261ecSmrg#include <errno.h>
7805b261ecSmrg#include <signal.h>
7905b261ecSmrg#include <stdio.h>
8005b261ecSmrg#include <stdlib.h>
8105b261ecSmrg
8205b261ecSmrg#ifndef WIN32
8305b261ecSmrg#if defined(Lynx)
8405b261ecSmrg#include <socket.h>
8505b261ecSmrg#else
8605b261ecSmrg#include <sys/socket.h>
8705b261ecSmrg#endif
8805b261ecSmrg
8905b261ecSmrg#ifdef hpux
9005b261ecSmrg#include <sys/utsname.h>
9105b261ecSmrg#include <sys/ioctl.h>
9205b261ecSmrg#endif
9305b261ecSmrg
9405b261ecSmrg#if defined(DGUX)
9505b261ecSmrg#include <sys/ioctl.h>
9605b261ecSmrg#include <sys/utsname.h>
9705b261ecSmrg#include <sys/socket.h>
9805b261ecSmrg#include <sys/uio.h>
9905b261ecSmrg#include <netinet/in.h>
10005b261ecSmrg#include <netinet/tcp.h>
10105b261ecSmrg#include <sys/param.h>
10205b261ecSmrg#include <unistd.h>
10305b261ecSmrg#endif
10405b261ecSmrg
10505b261ecSmrg
10605b261ecSmrg#ifdef AIXV3
10705b261ecSmrg#include <sys/ioctl.h>
10805b261ecSmrg#endif
10905b261ecSmrg
11005b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN)
11105b261ecSmrg# include <netinet/in.h>
11205b261ecSmrg# include <arpa/inet.h>
11305b261ecSmrg# if !defined(hpux)
11405b261ecSmrg#  ifdef apollo
11505b261ecSmrg#   ifndef NO_TCP_H
11605b261ecSmrg#    include <netinet/tcp.h>
11705b261ecSmrg#   endif
11805b261ecSmrg#  else
11905b261ecSmrg#   ifdef CSRG_BASED
12005b261ecSmrg#    include <sys/param.h>
12105b261ecSmrg#   endif
12205b261ecSmrg#   include <netinet/tcp.h>
12305b261ecSmrg#  endif
12405b261ecSmrg# endif
12505b261ecSmrg# include <arpa/inet.h>
12605b261ecSmrg#endif
12705b261ecSmrg
12805b261ecSmrg#ifndef Lynx
12905b261ecSmrg#include <sys/uio.h>
13005b261ecSmrg#else
13105b261ecSmrg#include <uio.h>
13205b261ecSmrg#endif
13305b261ecSmrg#endif /* WIN32 */
13405b261ecSmrg#include "misc.h"		/* for typedef of pointer */
13505b261ecSmrg#include "osdep.h"
13605b261ecSmrg#include <X11/Xpoll.h>
13705b261ecSmrg#include "opaque.h"
13805b261ecSmrg#include "dixstruct.h"
13905b261ecSmrg#ifdef XAPPGROUP
14005b261ecSmrg#include "appgroup.h"
14105b261ecSmrg#endif
14205b261ecSmrg#include "xace.h"
14305b261ecSmrg#ifdef XCSECURITY
14405b261ecSmrg#include "securitysrv.h"
14505b261ecSmrg#endif
14605b261ecSmrg
14705b261ecSmrg#ifdef X_NOT_POSIX
14805b261ecSmrg#define Pid_t int
14905b261ecSmrg#else
15005b261ecSmrg#define Pid_t pid_t
15105b261ecSmrg#endif
15205b261ecSmrg
15305b261ecSmrg#ifdef DNETCONN
15405b261ecSmrg#include <netdnet/dn.h>
15505b261ecSmrg#endif /* DNETCONN */
15605b261ecSmrg
15705b261ecSmrg#ifdef HAS_GETPEERUCRED
15805b261ecSmrg# include <ucred.h>
15905b261ecSmrg# include <zone.h>
16005b261ecSmrg#endif
16105b261ecSmrg
16205b261ecSmrg#ifdef XSERVER_DTRACE
16305b261ecSmrg# include <sys/types.h>
16405b261ecSmrgtypedef const char *string;
16505b261ecSmrg# ifndef HAS_GETPEERUCRED
16605b261ecSmrg#  define zoneid_t int
16705b261ecSmrg# endif
16805b261ecSmrg# include "../dix/Xserver-dtrace.h"
16905b261ecSmrg#endif
17005b261ecSmrg
17105b261ecSmrgstatic int lastfdesc;		/* maximum file descriptor */
17205b261ecSmrg
17305b261ecSmrgfd_set WellKnownConnections;	/* Listener mask */
17405b261ecSmrgfd_set EnabledDevices;		/* mask for input devices that are on */
17505b261ecSmrgfd_set AllSockets;		/* select on this */
17605b261ecSmrgfd_set AllClients;		/* available clients */
17705b261ecSmrgfd_set LastSelectMask;		/* mask returned from last select call */
17805b261ecSmrgfd_set ClientsWithInput;	/* clients with FULL requests in buffer */
17905b261ecSmrgfd_set ClientsWriteBlocked;	/* clients who cannot receive output */
18005b261ecSmrgfd_set OutputPending;		/* clients with reply/event data ready to go */
18105b261ecSmrgint MaxClients = 0;
18205b261ecSmrgBool NewOutputPending;		/* not yet attempted to write some new output */
18305b261ecSmrgBool AnyClientsWriteBlocked;	/* true if some client blocked on write */
18405b261ecSmrg
18505b261ecSmrgstatic Bool RunFromSmartParent;	/* send SIGUSR1 to parent process */
18605b261ecSmrgBool PartialNetwork;		/* continue even if unable to bind all addrs */
18705b261ecSmrgstatic Pid_t ParentProcess;
18805b261ecSmrg
18905b261ecSmrgstatic Bool debug_conns = FALSE;
19005b261ecSmrg
19105b261ecSmrgfd_set IgnoredClientsWithInput;
19205b261ecSmrgstatic fd_set GrabImperviousClients;
19305b261ecSmrgstatic fd_set SavedAllClients;
19405b261ecSmrgstatic fd_set SavedAllSockets;
19505b261ecSmrgstatic fd_set SavedClientsWithInput;
19605b261ecSmrg_X_EXPORT int GrabInProgress = 0;
19705b261ecSmrg
19805b261ecSmrg#if !defined(WIN32)
19905b261ecSmrgint *ConnectionTranslation = NULL;
20005b261ecSmrg#else
20105b261ecSmrg/*
20205b261ecSmrg * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
20305b261ecSmrg * not even a known maximum value, so use something quite arbitrary for now.
20405b261ecSmrg * Do storage is a hash table of size 256. Collisions are handled in a linked
20505b261ecSmrg * list.
20605b261ecSmrg */
20705b261ecSmrg
20805b261ecSmrg#undef MAXSOCKS
20905b261ecSmrg#define MAXSOCKS 500
21005b261ecSmrg#undef MAXSELECT
21105b261ecSmrg#define MAXSELECT 500
21205b261ecSmrg#define MAXFD 500
21305b261ecSmrg
21405b261ecSmrgstruct _ct_node {
21505b261ecSmrg    struct _ct_node *next;
21605b261ecSmrg    int key;
21705b261ecSmrg    int value;
21805b261ecSmrg};
21905b261ecSmrg
22005b261ecSmrgstruct _ct_node *ct_head[256];
22105b261ecSmrg
22205b261ecSmrgvoid InitConnectionTranslation(void)
22305b261ecSmrg{
22405b261ecSmrg    bzero(ct_head, sizeof(ct_head));
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrgint GetConnectionTranslation(int conn)
22805b261ecSmrg{
22905b261ecSmrg    struct _ct_node *node = ct_head[conn & 0xff];
23005b261ecSmrg    while (node != NULL)
23105b261ecSmrg    {
23205b261ecSmrg        if (node->key == conn)
23305b261ecSmrg            return node->value;
23405b261ecSmrg        node = node->next;
23505b261ecSmrg    }
23605b261ecSmrg    return 0;
23705b261ecSmrg}
23805b261ecSmrg
23905b261ecSmrgvoid SetConnectionTranslation(int conn, int client)
24005b261ecSmrg{
24105b261ecSmrg    struct _ct_node **node = ct_head + (conn & 0xff);
24205b261ecSmrg    if (client == 0) /* remove entry */
24305b261ecSmrg    {
24405b261ecSmrg        while (*node != NULL)
24505b261ecSmrg        {
24605b261ecSmrg            if ((*node)->key == conn)
24705b261ecSmrg            {
24805b261ecSmrg                struct _ct_node *temp = *node;
24905b261ecSmrg                *node = (*node)->next;
25005b261ecSmrg                free(temp);
25105b261ecSmrg                return;
25205b261ecSmrg            }
25305b261ecSmrg            node = &((*node)->next);
25405b261ecSmrg        }
25505b261ecSmrg        return;
25605b261ecSmrg    } else
25705b261ecSmrg    {
25805b261ecSmrg        while (*node != NULL)
25905b261ecSmrg        {
26005b261ecSmrg            if ((*node)->key == conn)
26105b261ecSmrg            {
26205b261ecSmrg                (*node)->value = client;
26305b261ecSmrg                return;
26405b261ecSmrg            }
26505b261ecSmrg            node = &((*node)->next);
26605b261ecSmrg        }
26705b261ecSmrg        *node = (struct _ct_node*)xalloc(sizeof(struct _ct_node));
26805b261ecSmrg        (*node)->next = NULL;
26905b261ecSmrg        (*node)->key = conn;
27005b261ecSmrg        (*node)->value = client;
27105b261ecSmrg        return;
27205b261ecSmrg    }
27305b261ecSmrg}
27405b261ecSmrg
27505b261ecSmrgvoid ClearConnectionTranslation(void)
27605b261ecSmrg{
27705b261ecSmrg    unsigned i;
27805b261ecSmrg    for (i = 0; i < 256; i++)
27905b261ecSmrg    {
28005b261ecSmrg        struct _ct_node *node = ct_head[i];
28105b261ecSmrg        while (node != NULL)
28205b261ecSmrg        {
28305b261ecSmrg            struct _ct_node *temp = node;
28405b261ecSmrg            node = node->next;
28505b261ecSmrg            xfree(temp);
28605b261ecSmrg        }
28705b261ecSmrg    }
28805b261ecSmrg}
28905b261ecSmrg#endif
29005b261ecSmrg
29105b261ecSmrgstatic XtransConnInfo 	*ListenTransConns = NULL;
29205b261ecSmrgstatic int	       	*ListenTransFds = NULL;
29305b261ecSmrgstatic int		ListenTransCount;
29405b261ecSmrg
29505b261ecSmrgstatic void ErrorConnMax(XtransConnInfo /* trans_conn */);
29605b261ecSmrg
29705b261ecSmrgstatic XtransConnInfo
29805b261ecSmrglookup_trans_conn (int fd)
29905b261ecSmrg{
30005b261ecSmrg    if (ListenTransFds)
30105b261ecSmrg    {
30205b261ecSmrg	int i;
30305b261ecSmrg	for (i = 0; i < ListenTransCount; i++)
30405b261ecSmrg	    if (ListenTransFds[i] == fd)
30505b261ecSmrg		return ListenTransConns[i];
30605b261ecSmrg    }
30705b261ecSmrg
30805b261ecSmrg    return (NULL);
30905b261ecSmrg}
31005b261ecSmrg
31105b261ecSmrg/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
31205b261ecSmrg
31305b261ecSmrgvoid
31405b261ecSmrgInitConnectionLimits(void)
31505b261ecSmrg{
31605b261ecSmrg    lastfdesc = -1;
31705b261ecSmrg
31805b261ecSmrg#ifndef __CYGWIN__
31905b261ecSmrg
32005b261ecSmrg#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
32105b261ecSmrg    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
32205b261ecSmrg#endif
32305b261ecSmrg
32405b261ecSmrg#ifdef HAS_GETDTABLESIZE
32505b261ecSmrg    if (lastfdesc < 0)
32605b261ecSmrg	lastfdesc = getdtablesize() - 1;
32705b261ecSmrg#endif
32805b261ecSmrg
32905b261ecSmrg#ifdef _NFILE
33005b261ecSmrg    if (lastfdesc < 0)
33105b261ecSmrg	lastfdesc = _NFILE - 1;
33205b261ecSmrg#endif
33305b261ecSmrg
33405b261ecSmrg#endif /* __CYGWIN__ */
33505b261ecSmrg
33605b261ecSmrg    /* This is the fallback */
33705b261ecSmrg    if (lastfdesc < 0)
33805b261ecSmrg	lastfdesc = MAXSOCKS;
33905b261ecSmrg
34005b261ecSmrg    if (lastfdesc > MAXSELECT)
34105b261ecSmrg	lastfdesc = MAXSELECT;
34205b261ecSmrg
34305b261ecSmrg    if (lastfdesc > MAXCLIENTS)
34405b261ecSmrg    {
34505b261ecSmrg	lastfdesc = MAXCLIENTS;
34605b261ecSmrg	if (debug_conns)
34705b261ecSmrg	    ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
34805b261ecSmrg    }
34905b261ecSmrg    MaxClients = lastfdesc;
35005b261ecSmrg
35105b261ecSmrg#ifdef DEBUG
35205b261ecSmrg    ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
35305b261ecSmrg#endif
35405b261ecSmrg
35505b261ecSmrg#if !defined(WIN32)
35605b261ecSmrg    if (!ConnectionTranslation)
35705b261ecSmrg        ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
35805b261ecSmrg#else
35905b261ecSmrg    InitConnectionTranslation();
36005b261ecSmrg#endif
36105b261ecSmrg}
36205b261ecSmrg
36305b261ecSmrg
36405b261ecSmrg/*****************
36505b261ecSmrg * CreateWellKnownSockets
36605b261ecSmrg *    At initialization, create the sockets to listen on for new clients.
36705b261ecSmrg *****************/
36805b261ecSmrg
36905b261ecSmrgvoid
37005b261ecSmrgCreateWellKnownSockets(void)
37105b261ecSmrg{
37205b261ecSmrg    int		i;
37305b261ecSmrg    int		partial;
37405b261ecSmrg    char 	port[20];
37505b261ecSmrg    OsSigHandlerPtr handler;
37605b261ecSmrg
37705b261ecSmrg    FD_ZERO(&AllSockets);
37805b261ecSmrg    FD_ZERO(&AllClients);
37905b261ecSmrg    FD_ZERO(&LastSelectMask);
38005b261ecSmrg    FD_ZERO(&ClientsWithInput);
38105b261ecSmrg
38205b261ecSmrg#if !defined(WIN32)
38305b261ecSmrg    for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
38405b261ecSmrg#else
38505b261ecSmrg    ClearConnectionTranslation();
38605b261ecSmrg#endif
38705b261ecSmrg
38805b261ecSmrg    FD_ZERO (&WellKnownConnections);
38905b261ecSmrg
39005b261ecSmrg    sprintf (port, "%d", atoi (display));
39105b261ecSmrg
39205b261ecSmrg    if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
39305b261ecSmrg	&ListenTransCount, &ListenTransConns) >= 0) &&
39405b261ecSmrg	(ListenTransCount >= 1))
39505b261ecSmrg    {
39605b261ecSmrg	if (!PartialNetwork && partial)
39705b261ecSmrg	{
39805b261ecSmrg	    FatalError ("Failed to establish all listening sockets");
39905b261ecSmrg	}
40005b261ecSmrg	else
40105b261ecSmrg	{
40205b261ecSmrg	    ListenTransFds = (int *) xalloc (ListenTransCount * sizeof (int));
40305b261ecSmrg
40405b261ecSmrg	    for (i = 0; i < ListenTransCount; i++)
40505b261ecSmrg	    {
40605b261ecSmrg		int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
40705b261ecSmrg
40805b261ecSmrg		ListenTransFds[i] = fd;
40905b261ecSmrg		FD_SET (fd, &WellKnownConnections);
41005b261ecSmrg
41105b261ecSmrg		if (!_XSERVTransIsLocal (ListenTransConns[i]))
41205b261ecSmrg		{
41305b261ecSmrg		    DefineSelf (fd);
41405b261ecSmrg		}
41505b261ecSmrg	    }
41605b261ecSmrg	}
41705b261ecSmrg    }
41805b261ecSmrg
41905b261ecSmrg    if (!XFD_ANYSET (&WellKnownConnections))
42005b261ecSmrg        FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
42105b261ecSmrg#if !defined(WIN32)
42205b261ecSmrg    OsSignal (SIGPIPE, SIG_IGN);
42305b261ecSmrg    OsSignal (SIGHUP, AutoResetServer);
42405b261ecSmrg#endif
42505b261ecSmrg    OsSignal (SIGINT, GiveUp);
42605b261ecSmrg    OsSignal (SIGTERM, GiveUp);
42705b261ecSmrg    XFD_COPYSET (&WellKnownConnections, &AllSockets);
42805b261ecSmrg    ResetHosts(display);
42905b261ecSmrg    /*
43005b261ecSmrg     * Magic:  If SIGUSR1 was set to SIG_IGN when
43105b261ecSmrg     * the server started, assume that either
43205b261ecSmrg     *
43305b261ecSmrg     *  a- The parent process is ignoring SIGUSR1
43405b261ecSmrg     *
43505b261ecSmrg     * or
43605b261ecSmrg     *
43705b261ecSmrg     *  b- The parent process is expecting a SIGUSR1
43805b261ecSmrg     *     when the server is ready to accept connections
43905b261ecSmrg     *
44005b261ecSmrg     * In the first case, the signal will be harmless,
44105b261ecSmrg     * in the second case, the signal will be quite
44205b261ecSmrg     * useful
44305b261ecSmrg     */
44405b261ecSmrg#if !defined(WIN32)
44505b261ecSmrg    handler = OsSignal (SIGUSR1, SIG_IGN);
44605b261ecSmrg    if ( handler == SIG_IGN)
44705b261ecSmrg	RunFromSmartParent = TRUE;
44805b261ecSmrg    OsSignal(SIGUSR1, handler);
44905b261ecSmrg    ParentProcess = getppid ();
45005b261ecSmrg    if (RunFromSmartParent) {
45105b261ecSmrg	if (ParentProcess > 1) {
45205b261ecSmrg	    kill (ParentProcess, SIGUSR1);
45305b261ecSmrg	}
45405b261ecSmrg    }
45505b261ecSmrg#endif
45605b261ecSmrg#ifdef XDMCP
45705b261ecSmrg    XdmcpInit ();
45805b261ecSmrg#endif
45905b261ecSmrg}
46005b261ecSmrg
46105b261ecSmrgvoid
46205b261ecSmrgResetWellKnownSockets (void)
46305b261ecSmrg{
46405b261ecSmrg    int i;
46505b261ecSmrg
46605b261ecSmrg    ResetOsBuffers();
46705b261ecSmrg
46805b261ecSmrg    for (i = 0; i < ListenTransCount; i++)
46905b261ecSmrg    {
47005b261ecSmrg	int status = _XSERVTransResetListener (ListenTransConns[i]);
47105b261ecSmrg
47205b261ecSmrg	if (status != TRANS_RESET_NOOP)
47305b261ecSmrg	{
47405b261ecSmrg	    if (status == TRANS_RESET_FAILURE)
47505b261ecSmrg	    {
47605b261ecSmrg		/*
47705b261ecSmrg		 * ListenTransConns[i] freed by xtrans.
47805b261ecSmrg		 * Remove it from out list.
47905b261ecSmrg		 */
48005b261ecSmrg
48105b261ecSmrg		FD_CLR (ListenTransFds[i], &WellKnownConnections);
48205b261ecSmrg		ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
48305b261ecSmrg		ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
48405b261ecSmrg		ListenTransCount -= 1;
48505b261ecSmrg		i -= 1;
48605b261ecSmrg	    }
48705b261ecSmrg	    else if (status == TRANS_RESET_NEW_FD)
48805b261ecSmrg	    {
48905b261ecSmrg		/*
49005b261ecSmrg		 * A new file descriptor was allocated (the old one was closed)
49105b261ecSmrg		 */
49205b261ecSmrg
49305b261ecSmrg		int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
49405b261ecSmrg
49505b261ecSmrg		FD_CLR (ListenTransFds[i], &WellKnownConnections);
49605b261ecSmrg		ListenTransFds[i] = newfd;
49705b261ecSmrg		FD_SET(newfd, &WellKnownConnections);
49805b261ecSmrg	    }
49905b261ecSmrg	}
50005b261ecSmrg    }
50105b261ecSmrg
50205b261ecSmrg    ResetAuthorization ();
50305b261ecSmrg    ResetHosts(display);
50405b261ecSmrg    /*
50505b261ecSmrg     * See above in CreateWellKnownSockets about SIGUSR1
50605b261ecSmrg     */
50705b261ecSmrg#if !defined(WIN32)
50805b261ecSmrg    if (RunFromSmartParent) {
50905b261ecSmrg	if (ParentProcess > 1) {
51005b261ecSmrg	    kill (ParentProcess, SIGUSR1);
51105b261ecSmrg	}
51205b261ecSmrg    }
51305b261ecSmrg#endif
51405b261ecSmrg    /*
51505b261ecSmrg     * restart XDMCP
51605b261ecSmrg     */
51705b261ecSmrg#ifdef XDMCP
51805b261ecSmrg    XdmcpReset ();
51905b261ecSmrg#endif
52005b261ecSmrg}
52105b261ecSmrg
52205b261ecSmrgvoid
52305b261ecSmrgCloseWellKnownConnections(void)
52405b261ecSmrg{
52505b261ecSmrg    int i;
52605b261ecSmrg
52705b261ecSmrg    for (i = 0; i < ListenTransCount; i++)
52805b261ecSmrg	_XSERVTransClose (ListenTransConns[i]);
52905b261ecSmrg}
53005b261ecSmrg
53105b261ecSmrgstatic void
53205b261ecSmrgAuthAudit (ClientPtr client, Bool letin,
53305b261ecSmrg    struct sockaddr *saddr, int len,
53405b261ecSmrg    unsigned int proto_n, char *auth_proto, int auth_id)
53505b261ecSmrg{
53605b261ecSmrg    char addr[128];
53705b261ecSmrg    char *out = addr;
53805b261ecSmrg    int client_uid;
53905b261ecSmrg    char client_uid_string[64];
54005b261ecSmrg#ifdef HAS_GETPEERUCRED
54105b261ecSmrg    ucred_t *peercred = NULL;
54205b261ecSmrg#endif
54305b261ecSmrg#if defined(HAS_GETPEERUCRED) || defined(XSERVER_DTRACE)
54405b261ecSmrg    pid_t client_pid = -1;
54505b261ecSmrg    zoneid_t client_zid = -1;
54605b261ecSmrg#endif
54705b261ecSmrg
54805b261ecSmrg    if (!len)
54905b261ecSmrg        strcpy(out, "local host");
55005b261ecSmrg    else
55105b261ecSmrg	switch (saddr->sa_family)
55205b261ecSmrg	{
55305b261ecSmrg	case AF_UNSPEC:
55405b261ecSmrg#if defined(UNIXCONN) || defined(LOCALCONN)
55505b261ecSmrg	case AF_UNIX:
55605b261ecSmrg#endif
55705b261ecSmrg	    strcpy(out, "local host");
55805b261ecSmrg	    break;
55905b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
56005b261ecSmrg	case AF_INET:
56105b261ecSmrg	    sprintf(out, "IP %s",
56205b261ecSmrg		inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
56305b261ecSmrg	    break;
56405b261ecSmrg#if defined(IPv6) && defined(AF_INET6)
56505b261ecSmrg	case AF_INET6: {
56605b261ecSmrg	    char ipaddr[INET6_ADDRSTRLEN];
56705b261ecSmrg	    inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
56805b261ecSmrg	      ipaddr, sizeof(ipaddr));
56905b261ecSmrg	    sprintf(out, "IP %s", ipaddr);
57005b261ecSmrg	}
57105b261ecSmrg	    break;
57205b261ecSmrg#endif
57305b261ecSmrg#endif
57405b261ecSmrg#ifdef DNETCONN
57505b261ecSmrg	case AF_DECnet:
57605b261ecSmrg	    sprintf(out, "DN %s",
57705b261ecSmrg		    dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add));
57805b261ecSmrg	    break;
57905b261ecSmrg#endif
58005b261ecSmrg	default:
58105b261ecSmrg	    strcpy(out, "unknown address");
58205b261ecSmrg	}
58305b261ecSmrg
58405b261ecSmrg#ifdef HAS_GETPEERUCRED
58505b261ecSmrg    if (getpeerucred(((OsCommPtr)client->osPrivate)->fd, &peercred) >= 0) {
58605b261ecSmrg	client_uid = ucred_geteuid(peercred);
58705b261ecSmrg	client_pid = ucred_getpid(peercred);
58805b261ecSmrg	client_zid = ucred_getzoneid(peercred);
58905b261ecSmrg
59005b261ecSmrg	ucred_free(peercred);
59105b261ecSmrg	snprintf(client_uid_string, sizeof(client_uid_string),
59205b261ecSmrg		 " (uid %ld, pid %ld, zone %ld)",
59305b261ecSmrg		 (long) client_uid, (long) client_pid, (long) client_zid);
59405b261ecSmrg    }
59505b261ecSmrg#else
59605b261ecSmrg    if (LocalClientCred(client, &client_uid, NULL) != -1) {
59705b261ecSmrg	snprintf(client_uid_string, sizeof(client_uid_string),
59805b261ecSmrg		 " (uid %d)", client_uid);
59905b261ecSmrg    }
60005b261ecSmrg#endif
60105b261ecSmrg    else {
60205b261ecSmrg	client_uid_string[0] = '\0';
60305b261ecSmrg    }
60405b261ecSmrg
60505b261ecSmrg#ifdef XSERVER_DTRACE
60605b261ecSmrg    XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
60705b261ecSmrg    if (auditTrailLevel > 1) {
60805b261ecSmrg#endif
60905b261ecSmrg      if (proto_n)
61005b261ecSmrg	AuditF("client %d %s from %s%s\n  Auth name: %.*s ID: %d\n",
61105b261ecSmrg	       client->index, letin ? "connected" : "rejected", addr,
61205b261ecSmrg	       client_uid_string, (int)proto_n, auth_proto, auth_id);
61305b261ecSmrg      else
61405b261ecSmrg	AuditF("client %d %s from %s%s\n",
61505b261ecSmrg	       client->index, letin ? "connected" : "rejected", addr,
61605b261ecSmrg	       client_uid_string);
61705b261ecSmrg
61805b261ecSmrg#ifdef XSERVER_DTRACE
61905b261ecSmrg    }
62005b261ecSmrg#endif
62105b261ecSmrg}
62205b261ecSmrg
62305b261ecSmrgXID
62405b261ecSmrgAuthorizationIDOfClient(ClientPtr client)
62505b261ecSmrg{
62605b261ecSmrg    if (client->osPrivate)
62705b261ecSmrg	return ((OsCommPtr)client->osPrivate)->auth_id;
62805b261ecSmrg    else
62905b261ecSmrg	return None;
63005b261ecSmrg}
63105b261ecSmrg
63205b261ecSmrg
63305b261ecSmrg/*****************************************************************
63405b261ecSmrg * ClientAuthorized
63505b261ecSmrg *
63605b261ecSmrg *    Sent by the client at connection setup:
63705b261ecSmrg *                typedef struct _xConnClientPrefix {
63805b261ecSmrg *                   CARD8	byteOrder;
63905b261ecSmrg *                   BYTE	pad;
64005b261ecSmrg *                   CARD16	majorVersion, minorVersion;
64105b261ecSmrg *                   CARD16	nbytesAuthProto;
64205b261ecSmrg *                   CARD16	nbytesAuthString;
64305b261ecSmrg *                 } xConnClientPrefix;
64405b261ecSmrg *
64505b261ecSmrg *     	It is hoped that eventually one protocol will be agreed upon.  In the
64605b261ecSmrg *        mean time, a server that implements a different protocol than the
64705b261ecSmrg *        client expects, or a server that only implements the host-based
64805b261ecSmrg *        mechanism, will simply ignore this information.
64905b261ecSmrg *
65005b261ecSmrg *****************************************************************/
65105b261ecSmrg
65205b261ecSmrgchar *
65305b261ecSmrgClientAuthorized(ClientPtr client,
65405b261ecSmrg    unsigned int proto_n, char *auth_proto,
65505b261ecSmrg    unsigned int string_n, char *auth_string)
65605b261ecSmrg{
65705b261ecSmrg    OsCommPtr 		priv;
65805b261ecSmrg    Xtransaddr		*from = NULL;
65905b261ecSmrg    int 		family;
66005b261ecSmrg    int			fromlen;
66105b261ecSmrg    XID	 		auth_id;
66205b261ecSmrg    char	 	*reason = NULL;
66305b261ecSmrg    XtransConnInfo	trans_conn;
66405b261ecSmrg
66505b261ecSmrg    priv = (OsCommPtr)client->osPrivate;
66605b261ecSmrg    trans_conn = priv->trans_conn;
66705b261ecSmrg
66805b261ecSmrg    auth_id = CheckAuthorization (proto_n, auth_proto,
66905b261ecSmrg				  string_n, auth_string, client, &reason);
67005b261ecSmrg
67105b261ecSmrg    if (auth_id == (XID) ~0L)
67205b261ecSmrg    {
67305b261ecSmrg	if (
67405b261ecSmrg#ifdef XCSECURITY
67505b261ecSmrg	    (proto_n == 0 ||
67605b261ecSmrg	    strncmp (auth_proto, XSecurityAuthorizationName, proto_n) != 0) &&
67705b261ecSmrg#endif
67805b261ecSmrg	    _XSERVTransGetPeerAddr (trans_conn,
67905b261ecSmrg	        &family, &fromlen, &from) != -1)
68005b261ecSmrg	{
68105b261ecSmrg	    if (InvalidHost ((struct sockaddr *) from, fromlen, client))
68205b261ecSmrg		AuthAudit(client, FALSE, (struct sockaddr *) from,
68305b261ecSmrg			  fromlen, proto_n, auth_proto, auth_id);
68405b261ecSmrg	    else
68505b261ecSmrg	    {
68605b261ecSmrg		auth_id = (XID) 0;
68705b261ecSmrg#ifdef XSERVER_DTRACE
68805b261ecSmrg		if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
68905b261ecSmrg#else
69005b261ecSmrg		if (auditTrailLevel > 1)
69105b261ecSmrg#endif
69205b261ecSmrg		    AuthAudit(client, TRUE,
69305b261ecSmrg			(struct sockaddr *) from, fromlen,
69405b261ecSmrg			proto_n, auth_proto, auth_id);
69505b261ecSmrg	    }
69605b261ecSmrg
69705b261ecSmrg	    xfree ((char *) from);
69805b261ecSmrg	}
69905b261ecSmrg
70005b261ecSmrg	if (auth_id == (XID) ~0L) {
70105b261ecSmrg	    if (reason)
70205b261ecSmrg		return reason;
70305b261ecSmrg	    else
70405b261ecSmrg		return "Client is not authorized to connect to Server";
70505b261ecSmrg	}
70605b261ecSmrg    }
70705b261ecSmrg#ifdef XSERVER_DTRACE
70805b261ecSmrg    else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
70905b261ecSmrg#else
71005b261ecSmrg    else if (auditTrailLevel > 1)
71105b261ecSmrg#endif
71205b261ecSmrg    {
71305b261ecSmrg	if (_XSERVTransGetPeerAddr (trans_conn,
71405b261ecSmrg	    &family, &fromlen, &from) != -1)
71505b261ecSmrg	{
71605b261ecSmrg	    AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
71705b261ecSmrg		      proto_n, auth_proto, auth_id);
71805b261ecSmrg
71905b261ecSmrg	    xfree ((char *) from);
72005b261ecSmrg	}
72105b261ecSmrg    }
72205b261ecSmrg    priv->auth_id = auth_id;
72305b261ecSmrg    priv->conn_time = 0;
72405b261ecSmrg
72505b261ecSmrg#ifdef XDMCP
72605b261ecSmrg    /* indicate to Xdmcp protocol that we've opened new client */
72705b261ecSmrg    XdmcpOpenDisplay(priv->fd);
72805b261ecSmrg#endif /* XDMCP */
72905b261ecSmrg
73005b261ecSmrg    XaceHook(XACE_AUTH_AVAIL, client, auth_id);
73105b261ecSmrg
73205b261ecSmrg    /* At this point, if the client is authorized to change the access control
73305b261ecSmrg     * list, we should getpeername() information, and add the client to
73405b261ecSmrg     * the selfhosts list.  It's not really the host machine, but the
73505b261ecSmrg     * true purpose of the selfhosts list is to see who may change the
73605b261ecSmrg     * access control list.
73705b261ecSmrg     */
73805b261ecSmrg    return((char *)NULL);
73905b261ecSmrg}
74005b261ecSmrg
74105b261ecSmrgstatic ClientPtr
74205b261ecSmrgAllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
74305b261ecSmrg{
74405b261ecSmrg    OsCommPtr	oc;
74505b261ecSmrg    ClientPtr	client;
74605b261ecSmrg
74705b261ecSmrg    if (
74805b261ecSmrg#ifndef WIN32
74905b261ecSmrg	fd >= lastfdesc
75005b261ecSmrg#else
75105b261ecSmrg	XFD_SETCOUNT(&AllClients) >= MaxClients
75205b261ecSmrg#endif
75305b261ecSmrg	)
75405b261ecSmrg	return NullClient;
75505b261ecSmrg    oc = (OsCommPtr)xalloc(sizeof(OsCommRec));
75605b261ecSmrg    if (!oc)
75705b261ecSmrg	return NullClient;
75805b261ecSmrg    oc->trans_conn = trans_conn;
75905b261ecSmrg    oc->fd = fd;
76005b261ecSmrg    oc->input = (ConnectionInputPtr)NULL;
76105b261ecSmrg    oc->output = (ConnectionOutputPtr)NULL;
76205b261ecSmrg    oc->auth_id = None;
76305b261ecSmrg    oc->conn_time = conn_time;
76405b261ecSmrg    if (!(client = NextAvailableClient((pointer)oc)))
76505b261ecSmrg    {
76605b261ecSmrg	xfree (oc);
76705b261ecSmrg	return NullClient;
76805b261ecSmrg    }
76905b261ecSmrg#if !defined(WIN32)
77005b261ecSmrg    ConnectionTranslation[fd] = client->index;
77105b261ecSmrg#else
77205b261ecSmrg    SetConnectionTranslation(fd, client->index);
77305b261ecSmrg#endif
77405b261ecSmrg    if (GrabInProgress)
77505b261ecSmrg    {
77605b261ecSmrg        FD_SET(fd, &SavedAllClients);
77705b261ecSmrg        FD_SET(fd, &SavedAllSockets);
77805b261ecSmrg    }
77905b261ecSmrg    else
78005b261ecSmrg    {
78105b261ecSmrg        FD_SET(fd, &AllClients);
78205b261ecSmrg        FD_SET(fd, &AllSockets);
78305b261ecSmrg    }
78405b261ecSmrg
78505b261ecSmrg#ifdef DEBUG
78605b261ecSmrg    ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
78705b261ecSmrg	   client->index, fd);
78805b261ecSmrg#endif
78905b261ecSmrg#ifdef XSERVER_DTRACE
79005b261ecSmrg    XSERVER_CLIENT_CONNECT(client->index, fd);
79105b261ecSmrg#endif
79205b261ecSmrg
79305b261ecSmrg    return client;
79405b261ecSmrg}
79505b261ecSmrg
79605b261ecSmrg/*****************
79705b261ecSmrg * EstablishNewConnections
79805b261ecSmrg *    If anyone is waiting on listened sockets, accept them.
79905b261ecSmrg *    Returns a mask with indices of new clients.  Updates AllClients
80005b261ecSmrg *    and AllSockets.
80105b261ecSmrg *****************/
80205b261ecSmrg
80305b261ecSmrg/*ARGSUSED*/
80405b261ecSmrgBool
80505b261ecSmrgEstablishNewConnections(ClientPtr clientUnused, pointer closure)
80605b261ecSmrg{
80705b261ecSmrg    fd_set  readyconnections;     /* set of listeners that are ready */
80805b261ecSmrg    int curconn;                  /* fd of listener that's ready */
80905b261ecSmrg    register int newconn;         /* fd of new client */
81005b261ecSmrg    CARD32 connect_time;
81105b261ecSmrg    register int i;
81205b261ecSmrg    register ClientPtr client;
81305b261ecSmrg    register OsCommPtr oc;
81405b261ecSmrg    fd_set tmask;
81505b261ecSmrg
81605b261ecSmrg    XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
81705b261ecSmrg    XFD_COPYSET(&tmask, &readyconnections);
81805b261ecSmrg    if (!XFD_ANYSET(&readyconnections))
81905b261ecSmrg	return TRUE;
82005b261ecSmrg    connect_time = GetTimeInMillis();
82105b261ecSmrg    /* kill off stragglers */
82205b261ecSmrg    for (i=1; i<currentMaxClients; i++)
82305b261ecSmrg    {
82405b261ecSmrg	if ((client = clients[i]))
82505b261ecSmrg	{
82605b261ecSmrg	    oc = (OsCommPtr)(client->osPrivate);
82705b261ecSmrg	    if ((oc && (oc->conn_time != 0) &&
82805b261ecSmrg		(connect_time - oc->conn_time) >= TimeOutValue) ||
82905b261ecSmrg		(client->noClientException != Success && !client->clientGone))
83005b261ecSmrg		CloseDownClient(client);
83105b261ecSmrg	}
83205b261ecSmrg    }
83305b261ecSmrg#ifndef WIN32
83405b261ecSmrg    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
83505b261ecSmrg    {
83605b261ecSmrg      while (readyconnections.fds_bits[i])
83705b261ecSmrg#else
83805b261ecSmrg      for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
83905b261ecSmrg#endif
84005b261ecSmrg      {
84105b261ecSmrg	XtransConnInfo trans_conn, new_trans_conn;
84205b261ecSmrg	int status;
84305b261ecSmrg
84405b261ecSmrg#ifndef WIN32
84505b261ecSmrg	curconn = ffs (readyconnections.fds_bits[i]) - 1;
84605b261ecSmrg	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
84705b261ecSmrg	curconn += (i * (sizeof(fd_mask)*8));
84805b261ecSmrg#else
84905b261ecSmrg	curconn = XFD_FD(&readyconnections, i);
85005b261ecSmrg#endif
85105b261ecSmrg
85205b261ecSmrg	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
85305b261ecSmrg	    continue;
85405b261ecSmrg
85505b261ecSmrg	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
85605b261ecSmrg	    continue;
85705b261ecSmrg
85805b261ecSmrg	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
85905b261ecSmrg
86005b261ecSmrg	if (newconn < lastfdesc)
86105b261ecSmrg	{
86205b261ecSmrg		int clientid;
86305b261ecSmrg#if !defined(WIN32)
86405b261ecSmrg  		clientid = ConnectionTranslation[newconn];
86505b261ecSmrg#else
86605b261ecSmrg  		clientid = GetConnectionTranslation(newconn);
86705b261ecSmrg#endif
86805b261ecSmrg		if(clientid && (client = clients[clientid]))
86905b261ecSmrg 			CloseDownClient(client);
87005b261ecSmrg	}
87105b261ecSmrg
87205b261ecSmrg	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
87305b261ecSmrg
87405b261ecSmrg	if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
87505b261ecSmrg	{
87605b261ecSmrg	    ErrorConnMax(new_trans_conn);
87705b261ecSmrg	    _XSERVTransClose(new_trans_conn);
87805b261ecSmrg	}
87905b261ecSmrg      }
88005b261ecSmrg#ifndef WIN32
88105b261ecSmrg    }
88205b261ecSmrg#endif
88305b261ecSmrg    return TRUE;
88405b261ecSmrg}
88505b261ecSmrg
88605b261ecSmrg#define NOROOM "Maximum number of clients reached"
88705b261ecSmrg
88805b261ecSmrg/************
88905b261ecSmrg *   ErrorConnMax
89005b261ecSmrg *     Fail a connection due to lack of client or file descriptor space
89105b261ecSmrg ************/
89205b261ecSmrg
89305b261ecSmrgstatic void
89405b261ecSmrgErrorConnMax(XtransConnInfo trans_conn)
89505b261ecSmrg{
89605b261ecSmrg    int fd = _XSERVTransGetConnectionNumber (trans_conn);
89705b261ecSmrg    xConnSetupPrefix csp;
89805b261ecSmrg    char pad[3];
89905b261ecSmrg    struct iovec iov[3];
90005b261ecSmrg    char byteOrder = 0;
90105b261ecSmrg    int whichbyte = 1;
90205b261ecSmrg    struct timeval waittime;
90305b261ecSmrg    fd_set mask;
90405b261ecSmrg
90505b261ecSmrg    /* if these seems like a lot of trouble to go to, it probably is */
90605b261ecSmrg    waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
90705b261ecSmrg    waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
90805b261ecSmrg		       (1000000 / MILLI_PER_SECOND);
90905b261ecSmrg    FD_ZERO(&mask);
91005b261ecSmrg    FD_SET(fd, &mask);
91105b261ecSmrg    (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
91205b261ecSmrg    /* try to read the byte-order of the connection */
91305b261ecSmrg    (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
91405b261ecSmrg    if ((byteOrder == 'l') || (byteOrder == 'B'))
91505b261ecSmrg    {
91605b261ecSmrg	csp.success = xFalse;
91705b261ecSmrg	csp.lengthReason = sizeof(NOROOM) - 1;
91805b261ecSmrg	csp.length = (sizeof(NOROOM) + 2) >> 2;
91905b261ecSmrg	csp.majorVersion = X_PROTOCOL;
92005b261ecSmrg	csp.minorVersion = X_PROTOCOL_REVISION;
92105b261ecSmrg	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
92205b261ecSmrg	    (!(*(char *) &whichbyte) && (byteOrder == 'l')))
92305b261ecSmrg	{
92405b261ecSmrg	    swaps(&csp.majorVersion, whichbyte);
92505b261ecSmrg	    swaps(&csp.minorVersion, whichbyte);
92605b261ecSmrg	    swaps(&csp.length, whichbyte);
92705b261ecSmrg	}
92805b261ecSmrg	iov[0].iov_len = sz_xConnSetupPrefix;
92905b261ecSmrg	iov[0].iov_base = (char *) &csp;
93005b261ecSmrg	iov[1].iov_len = csp.lengthReason;
93105b261ecSmrg	iov[1].iov_base = NOROOM;
93205b261ecSmrg	iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
93305b261ecSmrg	iov[2].iov_base = pad;
93405b261ecSmrg	(void)_XSERVTransWritev(trans_conn, iov, 3);
93505b261ecSmrg    }
93605b261ecSmrg}
93705b261ecSmrg
93805b261ecSmrg/************
93905b261ecSmrg *   CloseDownFileDescriptor:
94005b261ecSmrg *     Remove this file descriptor and it's I/O buffers, etc.
94105b261ecSmrg ************/
94205b261ecSmrg
94305b261ecSmrgstatic void
94405b261ecSmrgCloseDownFileDescriptor(OsCommPtr oc)
94505b261ecSmrg{
94605b261ecSmrg    int connection = oc->fd;
94705b261ecSmrg
94805b261ecSmrg    if (oc->trans_conn) {
94905b261ecSmrg	_XSERVTransDisconnect(oc->trans_conn);
95005b261ecSmrg	_XSERVTransClose(oc->trans_conn);
95105b261ecSmrg    }
95205b261ecSmrg#ifndef WIN32
95305b261ecSmrg    ConnectionTranslation[connection] = 0;
95405b261ecSmrg#else
95505b261ecSmrg    SetConnectionTranslation(connection, 0);
95605b261ecSmrg#endif
95705b261ecSmrg    FD_CLR(connection, &AllSockets);
95805b261ecSmrg    FD_CLR(connection, &AllClients);
95905b261ecSmrg    FD_CLR(connection, &ClientsWithInput);
96005b261ecSmrg    FD_CLR(connection, &GrabImperviousClients);
96105b261ecSmrg    if (GrabInProgress)
96205b261ecSmrg    {
96305b261ecSmrg	FD_CLR(connection, &SavedAllSockets);
96405b261ecSmrg	FD_CLR(connection, &SavedAllClients);
96505b261ecSmrg	FD_CLR(connection, &SavedClientsWithInput);
96605b261ecSmrg    }
96705b261ecSmrg    FD_CLR(connection, &ClientsWriteBlocked);
96805b261ecSmrg    if (!XFD_ANYSET(&ClientsWriteBlocked))
96905b261ecSmrg    	AnyClientsWriteBlocked = FALSE;
97005b261ecSmrg    FD_CLR(connection, &OutputPending);
97105b261ecSmrg}
97205b261ecSmrg
97305b261ecSmrg/*****************
97405b261ecSmrg * CheckConnections
97505b261ecSmrg *    Some connection has died, go find which one and shut it down
97605b261ecSmrg *    The file descriptor has been closed, but is still in AllClients.
97705b261ecSmrg *    If would truly be wonderful if select() would put the bogus
97805b261ecSmrg *    file descriptors in the exception mask, but nooooo.  So we have
97905b261ecSmrg *    to check each and every socket individually.
98005b261ecSmrg *****************/
98105b261ecSmrg
98205b261ecSmrgvoid
98305b261ecSmrgCheckConnections(void)
98405b261ecSmrg{
98505b261ecSmrg#ifndef WIN32
98605b261ecSmrg    fd_mask		mask;
98705b261ecSmrg#endif
98805b261ecSmrg    fd_set		tmask;
98905b261ecSmrg    int			curclient, curoff;
99005b261ecSmrg    int			i;
99105b261ecSmrg    struct timeval	notime;
99205b261ecSmrg    int r;
99305b261ecSmrg#ifdef WIN32
99405b261ecSmrg    fd_set savedAllClients;
99505b261ecSmrg#endif
99605b261ecSmrg
99705b261ecSmrg    notime.tv_sec = 0;
99805b261ecSmrg    notime.tv_usec = 0;
99905b261ecSmrg
100005b261ecSmrg#ifndef WIN32
100105b261ecSmrg    for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
100205b261ecSmrg    {
100305b261ecSmrg	mask = AllClients.fds_bits[i];
100405b261ecSmrg        while (mask)
100505b261ecSmrg    	{
100605b261ecSmrg	    curoff = ffs (mask) - 1;
100705b261ecSmrg	    curclient = curoff + (i * (sizeof(fd_mask)*8));
100805b261ecSmrg            FD_ZERO(&tmask);
100905b261ecSmrg            FD_SET(curclient, &tmask);
101005b261ecSmrg            do {
101105b261ecSmrg                r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
101205b261ecSmrg            } while (r < 0 && (errno == EINTR || errno == EAGAIN));
101305b261ecSmrg            if (r < 0)
101405b261ecSmrg                if (ConnectionTranslation[curclient] > 0)
101505b261ecSmrg                    CloseDownClient(clients[ConnectionTranslation[curclient]]);
101605b261ecSmrg	    mask &= ~((fd_mask)1 << curoff);
101705b261ecSmrg	}
101805b261ecSmrg    }
101905b261ecSmrg#else
102005b261ecSmrg    XFD_COPYSET(&AllClients, &savedAllClients);
102105b261ecSmrg    for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
102205b261ecSmrg    {
102305b261ecSmrg	curclient = XFD_FD(&savedAllClients, i);
102405b261ecSmrg	FD_ZERO(&tmask);
102505b261ecSmrg	FD_SET(curclient, &tmask);
102605b261ecSmrg        do {
102705b261ecSmrg            r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
102805b261ecSmrg        } while (r < 0 && (errno == EINTR || errno == EAGAIN));
102905b261ecSmrg	if (r < 0)
103005b261ecSmrg            if (GetConnectionTranslation(curclient) > 0)
103105b261ecSmrg                CloseDownClient(clients[GetConnectionTranslation(curclient)]);
103205b261ecSmrg    }
103305b261ecSmrg#endif
103405b261ecSmrg}
103505b261ecSmrg
103605b261ecSmrg
103705b261ecSmrg/*****************
103805b261ecSmrg * CloseDownConnection
103905b261ecSmrg *    Delete client from AllClients and free resources
104005b261ecSmrg *****************/
104105b261ecSmrg
104205b261ecSmrgvoid
104305b261ecSmrgCloseDownConnection(ClientPtr client)
104405b261ecSmrg{
104505b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
104605b261ecSmrg
104705b261ecSmrg    if (oc->output && oc->output->count)
104805b261ecSmrg	FlushClient(client, oc, (char *)NULL, 0);
104905b261ecSmrg#ifdef XDMCP
105005b261ecSmrg    XdmcpCloseDisplay(oc->fd);
105105b261ecSmrg#endif
105205b261ecSmrg    CloseDownFileDescriptor(oc);
105305b261ecSmrg    FreeOsBuffers(oc);
105405b261ecSmrg    xfree(client->osPrivate);
105505b261ecSmrg    client->osPrivate = (pointer)NULL;
105605b261ecSmrg    if (auditTrailLevel > 1)
105705b261ecSmrg	AuditF("client %d disconnected\n", client->index);
105805b261ecSmrg}
105905b261ecSmrg
106005b261ecSmrg_X_EXPORT void
106105b261ecSmrgAddGeneralSocket(int fd)
106205b261ecSmrg{
106305b261ecSmrg    FD_SET(fd, &AllSockets);
106405b261ecSmrg    if (GrabInProgress)
106505b261ecSmrg	FD_SET(fd, &SavedAllSockets);
106605b261ecSmrg}
106705b261ecSmrg
106805b261ecSmrg_X_EXPORT void
106905b261ecSmrgAddEnabledDevice(int fd)
107005b261ecSmrg{
107105b261ecSmrg    FD_SET(fd, &EnabledDevices);
107205b261ecSmrg    AddGeneralSocket(fd);
107305b261ecSmrg}
107405b261ecSmrg
107505b261ecSmrg_X_EXPORT void
107605b261ecSmrgRemoveGeneralSocket(int fd)
107705b261ecSmrg{
107805b261ecSmrg    FD_CLR(fd, &AllSockets);
107905b261ecSmrg    if (GrabInProgress)
108005b261ecSmrg	FD_CLR(fd, &SavedAllSockets);
108105b261ecSmrg}
108205b261ecSmrg
108305b261ecSmrg_X_EXPORT void
108405b261ecSmrgRemoveEnabledDevice(int fd)
108505b261ecSmrg{
108605b261ecSmrg    FD_CLR(fd, &EnabledDevices);
108705b261ecSmrg    RemoveGeneralSocket(fd);
108805b261ecSmrg}
108905b261ecSmrg
109005b261ecSmrg/*****************
109105b261ecSmrg * OnlyListenToOneClient:
109205b261ecSmrg *    Only accept requests from  one client.  Continue to handle new
109305b261ecSmrg *    connections, but don't take any protocol requests from the new
109405b261ecSmrg *    ones.  Note that if GrabInProgress is set, EstablishNewConnections
109505b261ecSmrg *    needs to put new clients into SavedAllSockets and SavedAllClients.
109605b261ecSmrg *    Note also that there is no timeout for this in the protocol.
109705b261ecSmrg *    This routine is "undone" by ListenToAllClients()
109805b261ecSmrg *****************/
109905b261ecSmrg
110005b261ecSmrgvoid
110105b261ecSmrgOnlyListenToOneClient(ClientPtr client)
110205b261ecSmrg{
110305b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
110405b261ecSmrg    int connection = oc->fd;
110505b261ecSmrg
110605b261ecSmrg    if (! GrabInProgress)
110705b261ecSmrg    {
110805b261ecSmrg	XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
110905b261ecSmrg	XFD_ANDSET(&ClientsWithInput,
111005b261ecSmrg		       &ClientsWithInput, &GrabImperviousClients);
111105b261ecSmrg	if (FD_ISSET(connection, &SavedClientsWithInput))
111205b261ecSmrg	{
111305b261ecSmrg	    FD_CLR(connection, &SavedClientsWithInput);
111405b261ecSmrg	    FD_SET(connection, &ClientsWithInput);
111505b261ecSmrg	}
111605b261ecSmrg	XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
111705b261ecSmrg	XFD_COPYSET(&AllSockets, &SavedAllSockets);
111805b261ecSmrg	XFD_COPYSET(&AllClients, &SavedAllClients);
111905b261ecSmrg	XFD_UNSET(&AllSockets, &AllClients);
112005b261ecSmrg	XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
112105b261ecSmrg	FD_SET(connection, &AllClients);
112205b261ecSmrg	XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
112305b261ecSmrg	GrabInProgress = client->index;
112405b261ecSmrg    }
112505b261ecSmrg}
112605b261ecSmrg
112705b261ecSmrg/****************
112805b261ecSmrg * ListenToAllClients:
112905b261ecSmrg *    Undoes OnlyListentToOneClient()
113005b261ecSmrg ****************/
113105b261ecSmrg
113205b261ecSmrgvoid
113305b261ecSmrgListenToAllClients(void)
113405b261ecSmrg{
113505b261ecSmrg    if (GrabInProgress)
113605b261ecSmrg    {
113705b261ecSmrg	XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
113805b261ecSmrg	XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
113905b261ecSmrg	XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
114005b261ecSmrg	GrabInProgress = 0;
114105b261ecSmrg    }
114205b261ecSmrg}
114305b261ecSmrg
114405b261ecSmrg/****************
114505b261ecSmrg * IgnoreClient
114605b261ecSmrg *    Removes one client from input masks.
114705b261ecSmrg *    Must have cooresponding call to AttendClient.
114805b261ecSmrg ****************/
114905b261ecSmrg
115005b261ecSmrg_X_EXPORT void
115105b261ecSmrgIgnoreClient (ClientPtr client)
115205b261ecSmrg{
115305b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
115405b261ecSmrg    int connection = oc->fd;
115505b261ecSmrg
115605b261ecSmrg    isItTimeToYield = TRUE;
115705b261ecSmrg    if (!GrabInProgress || FD_ISSET(connection, &AllClients))
115805b261ecSmrg    {
115905b261ecSmrg    	if (FD_ISSET (connection, &ClientsWithInput))
116005b261ecSmrg	    FD_SET(connection, &IgnoredClientsWithInput);
116105b261ecSmrg    	else
116205b261ecSmrg	    FD_CLR(connection, &IgnoredClientsWithInput);
116305b261ecSmrg    	FD_CLR(connection, &ClientsWithInput);
116405b261ecSmrg    	FD_CLR(connection, &AllSockets);
116505b261ecSmrg    	FD_CLR(connection, &AllClients);
116605b261ecSmrg	FD_CLR(connection, &LastSelectMask);
116705b261ecSmrg    }
116805b261ecSmrg    else
116905b261ecSmrg    {
117005b261ecSmrg    	if (FD_ISSET (connection, &SavedClientsWithInput))
117105b261ecSmrg	    FD_SET(connection, &IgnoredClientsWithInput);
117205b261ecSmrg    	else
117305b261ecSmrg	    FD_CLR(connection, &IgnoredClientsWithInput);
117405b261ecSmrg	FD_CLR(connection, &SavedClientsWithInput);
117505b261ecSmrg	FD_CLR(connection, &SavedAllSockets);
117605b261ecSmrg	FD_CLR(connection, &SavedAllClients);
117705b261ecSmrg    }
117805b261ecSmrg}
117905b261ecSmrg
118005b261ecSmrg/****************
118105b261ecSmrg * AttendClient
118205b261ecSmrg *    Adds one client back into the input masks.
118305b261ecSmrg ****************/
118405b261ecSmrg
118505b261ecSmrg_X_EXPORT void
118605b261ecSmrgAttendClient (ClientPtr client)
118705b261ecSmrg{
118805b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
118905b261ecSmrg    int connection = oc->fd;
119005b261ecSmrg    if (!GrabInProgress || GrabInProgress == client->index ||
119105b261ecSmrg	FD_ISSET(connection, &GrabImperviousClients))
119205b261ecSmrg    {
119305b261ecSmrg    	FD_SET(connection, &AllClients);
119405b261ecSmrg    	FD_SET(connection, &AllSockets);
119505b261ecSmrg	FD_SET(connection, &LastSelectMask);
119605b261ecSmrg    	if (FD_ISSET (connection, &IgnoredClientsWithInput))
119705b261ecSmrg	    FD_SET(connection, &ClientsWithInput);
119805b261ecSmrg    }
119905b261ecSmrg    else
120005b261ecSmrg    {
120105b261ecSmrg	FD_SET(connection, &SavedAllClients);
120205b261ecSmrg	FD_SET(connection, &SavedAllSockets);
120305b261ecSmrg	if (FD_ISSET(connection, &IgnoredClientsWithInput))
120405b261ecSmrg	    FD_SET(connection, &SavedClientsWithInput);
120505b261ecSmrg    }
120605b261ecSmrg}
120705b261ecSmrg
120805b261ecSmrg/* make client impervious to grabs; assume only executing client calls this */
120905b261ecSmrg
121005b261ecSmrg_X_EXPORT void
121105b261ecSmrgMakeClientGrabImpervious(ClientPtr client)
121205b261ecSmrg{
121305b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
121405b261ecSmrg    int connection = oc->fd;
121505b261ecSmrg
121605b261ecSmrg    FD_SET(connection, &GrabImperviousClients);
121705b261ecSmrg
121805b261ecSmrg    if (ServerGrabCallback)
121905b261ecSmrg    {
122005b261ecSmrg	ServerGrabInfoRec grabinfo;
122105b261ecSmrg	grabinfo.client = client;
122205b261ecSmrg	grabinfo.grabstate  = CLIENT_IMPERVIOUS;
122305b261ecSmrg	CallCallbacks(&ServerGrabCallback, &grabinfo);
122405b261ecSmrg    }
122505b261ecSmrg}
122605b261ecSmrg
122705b261ecSmrg/* make client pervious to grabs; assume only executing client calls this */
122805b261ecSmrg
122905b261ecSmrg_X_EXPORT void
123005b261ecSmrgMakeClientGrabPervious(ClientPtr client)
123105b261ecSmrg{
123205b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
123305b261ecSmrg    int connection = oc->fd;
123405b261ecSmrg
123505b261ecSmrg    FD_CLR(connection, &GrabImperviousClients);
123605b261ecSmrg    if (GrabInProgress && (GrabInProgress != client->index))
123705b261ecSmrg    {
123805b261ecSmrg	if (FD_ISSET(connection, &ClientsWithInput))
123905b261ecSmrg	{
124005b261ecSmrg	    FD_SET(connection, &SavedClientsWithInput);
124105b261ecSmrg	    FD_CLR(connection, &ClientsWithInput);
124205b261ecSmrg	}
124305b261ecSmrg	FD_CLR(connection, &AllSockets);
124405b261ecSmrg	FD_CLR(connection, &AllClients);
124505b261ecSmrg	isItTimeToYield = TRUE;
124605b261ecSmrg    }
124705b261ecSmrg
124805b261ecSmrg    if (ServerGrabCallback)
124905b261ecSmrg    {
125005b261ecSmrg	ServerGrabInfoRec grabinfo;
125105b261ecSmrg	grabinfo.client = client;
125205b261ecSmrg	grabinfo.grabstate  = CLIENT_PERVIOUS;
125305b261ecSmrg	CallCallbacks(&ServerGrabCallback, &grabinfo);
125405b261ecSmrg    }
125505b261ecSmrg}
125605b261ecSmrg
1257