connection.c revision 9ace9065
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>
774642e01fSmrg#include <X11/Xtrans/Xtransint.h>
7805b261ecSmrg#include <errno.h>
7905b261ecSmrg#include <signal.h>
8005b261ecSmrg#include <stdio.h>
8105b261ecSmrg#include <stdlib.h>
8205b261ecSmrg
8305b261ecSmrg#ifndef WIN32
8405b261ecSmrg#include <sys/socket.h>
8505b261ecSmrg
8605b261ecSmrg
8705b261ecSmrg
8805b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN)
8905b261ecSmrg# include <netinet/in.h>
9005b261ecSmrg# include <arpa/inet.h>
9105b261ecSmrg#  ifdef apollo
9205b261ecSmrg#   ifndef NO_TCP_H
9305b261ecSmrg#    include <netinet/tcp.h>
9405b261ecSmrg#   endif
9505b261ecSmrg#  else
9605b261ecSmrg#   ifdef CSRG_BASED
9705b261ecSmrg#    include <sys/param.h>
9805b261ecSmrg#   endif
9905b261ecSmrg#   include <netinet/tcp.h>
10005b261ecSmrg#  endif
10105b261ecSmrg# include <arpa/inet.h>
10205b261ecSmrg#endif
10305b261ecSmrg
10405b261ecSmrg#include <sys/uio.h>
1054642e01fSmrg
10605b261ecSmrg#endif /* WIN32 */
10705b261ecSmrg#include "misc.h"		/* for typedef of pointer */
10805b261ecSmrg#include "osdep.h"
10905b261ecSmrg#include <X11/Xpoll.h>
11005b261ecSmrg#include "opaque.h"
11105b261ecSmrg#include "dixstruct.h"
11205b261ecSmrg#include "xace.h"
11305b261ecSmrg
11405b261ecSmrg#define Pid_t pid_t
11505b261ecSmrg
11605b261ecSmrg
11705b261ecSmrg#ifdef HAS_GETPEERUCRED
11805b261ecSmrg# include <ucred.h>
11905b261ecSmrg# include <zone.h>
12005b261ecSmrg#endif
12105b261ecSmrg
12205b261ecSmrg#ifdef XSERVER_DTRACE
12305b261ecSmrg# include <sys/types.h>
12405b261ecSmrgtypedef const char *string;
12505b261ecSmrg# ifndef HAS_GETPEERUCRED
12605b261ecSmrg#  define zoneid_t int
12705b261ecSmrg# endif
12805b261ecSmrg# include "../dix/Xserver-dtrace.h"
12905b261ecSmrg#endif
13005b261ecSmrg
13105b261ecSmrgstatic int lastfdesc;		/* maximum file descriptor */
13205b261ecSmrg
13305b261ecSmrgfd_set WellKnownConnections;	/* Listener mask */
13405b261ecSmrgfd_set EnabledDevices;		/* mask for input devices that are on */
13505b261ecSmrgfd_set AllSockets;		/* select on this */
13605b261ecSmrgfd_set AllClients;		/* available clients */
13705b261ecSmrgfd_set LastSelectMask;		/* mask returned from last select call */
13805b261ecSmrgfd_set ClientsWithInput;	/* clients with FULL requests in buffer */
13905b261ecSmrgfd_set ClientsWriteBlocked;	/* clients who cannot receive output */
14005b261ecSmrgfd_set OutputPending;		/* clients with reply/event data ready to go */
14105b261ecSmrgint MaxClients = 0;
14205b261ecSmrgBool NewOutputPending;		/* not yet attempted to write some new output */
14305b261ecSmrgBool AnyClientsWriteBlocked;	/* true if some client blocked on write */
14405b261ecSmrg
14505b261ecSmrgstatic Bool RunFromSmartParent;	/* send SIGUSR1 to parent process */
1469ace9065SmrgBool RunFromSigStopParent;	/* send SIGSTOP to our own process; Upstart (or
1479ace9065Smrg				   equivalent) will send SIGCONT back. */
1486747b715SmrgBool PartialNetwork;	/* continue even if unable to bind all addrs */
14905b261ecSmrgstatic Pid_t ParentProcess;
15005b261ecSmrg
15105b261ecSmrgstatic Bool debug_conns = FALSE;
15205b261ecSmrg
15305b261ecSmrgfd_set IgnoredClientsWithInput;
15405b261ecSmrgstatic fd_set GrabImperviousClients;
15505b261ecSmrgstatic fd_set SavedAllClients;
15605b261ecSmrgstatic fd_set SavedAllSockets;
15705b261ecSmrgstatic fd_set SavedClientsWithInput;
1586747b715Smrgint GrabInProgress = 0;
15905b261ecSmrg
16005b261ecSmrg#if !defined(WIN32)
16105b261ecSmrgint *ConnectionTranslation = NULL;
16205b261ecSmrg#else
16305b261ecSmrg/*
16405b261ecSmrg * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
16505b261ecSmrg * not even a known maximum value, so use something quite arbitrary for now.
16605b261ecSmrg * Do storage is a hash table of size 256. Collisions are handled in a linked
16705b261ecSmrg * list.
16805b261ecSmrg */
16905b261ecSmrg
17005b261ecSmrg#undef MAXSOCKS
17105b261ecSmrg#define MAXSOCKS 500
17205b261ecSmrg#undef MAXSELECT
17305b261ecSmrg#define MAXSELECT 500
17405b261ecSmrg
17505b261ecSmrgstruct _ct_node {
17605b261ecSmrg    struct _ct_node *next;
17705b261ecSmrg    int key;
17805b261ecSmrg    int value;
17905b261ecSmrg};
18005b261ecSmrg
18105b261ecSmrgstruct _ct_node *ct_head[256];
18205b261ecSmrg
18305b261ecSmrgvoid InitConnectionTranslation(void)
18405b261ecSmrg{
1856747b715Smrg    memset(ct_head, 0, sizeof(ct_head));
18605b261ecSmrg}
18705b261ecSmrg
18805b261ecSmrgint GetConnectionTranslation(int conn)
18905b261ecSmrg{
19005b261ecSmrg    struct _ct_node *node = ct_head[conn & 0xff];
19105b261ecSmrg    while (node != NULL)
19205b261ecSmrg    {
19305b261ecSmrg        if (node->key == conn)
19405b261ecSmrg            return node->value;
19505b261ecSmrg        node = node->next;
19605b261ecSmrg    }
19705b261ecSmrg    return 0;
19805b261ecSmrg}
19905b261ecSmrg
20005b261ecSmrgvoid SetConnectionTranslation(int conn, int client)
20105b261ecSmrg{
20205b261ecSmrg    struct _ct_node **node = ct_head + (conn & 0xff);
20305b261ecSmrg    if (client == 0) /* remove entry */
20405b261ecSmrg    {
20505b261ecSmrg        while (*node != NULL)
20605b261ecSmrg        {
20705b261ecSmrg            if ((*node)->key == conn)
20805b261ecSmrg            {
20905b261ecSmrg                struct _ct_node *temp = *node;
21005b261ecSmrg                *node = (*node)->next;
21105b261ecSmrg                free(temp);
21205b261ecSmrg                return;
21305b261ecSmrg            }
21405b261ecSmrg            node = &((*node)->next);
21505b261ecSmrg        }
21605b261ecSmrg        return;
21705b261ecSmrg    } else
21805b261ecSmrg    {
21905b261ecSmrg        while (*node != NULL)
22005b261ecSmrg        {
22105b261ecSmrg            if ((*node)->key == conn)
22205b261ecSmrg            {
22305b261ecSmrg                (*node)->value = client;
22405b261ecSmrg                return;
22505b261ecSmrg            }
22605b261ecSmrg            node = &((*node)->next);
22705b261ecSmrg        }
2286747b715Smrg        *node = malloc(sizeof(struct _ct_node));
22905b261ecSmrg        (*node)->next = NULL;
23005b261ecSmrg        (*node)->key = conn;
23105b261ecSmrg        (*node)->value = client;
23205b261ecSmrg        return;
23305b261ecSmrg    }
23405b261ecSmrg}
23505b261ecSmrg
23605b261ecSmrgvoid ClearConnectionTranslation(void)
23705b261ecSmrg{
23805b261ecSmrg    unsigned i;
23905b261ecSmrg    for (i = 0; i < 256; i++)
24005b261ecSmrg    {
24105b261ecSmrg        struct _ct_node *node = ct_head[i];
24205b261ecSmrg        while (node != NULL)
24305b261ecSmrg        {
24405b261ecSmrg            struct _ct_node *temp = node;
24505b261ecSmrg            node = node->next;
2466747b715Smrg            free(temp);
24705b261ecSmrg        }
24805b261ecSmrg    }
24905b261ecSmrg}
25005b261ecSmrg#endif
25105b261ecSmrg
25205b261ecSmrgstatic XtransConnInfo 	*ListenTransConns = NULL;
25305b261ecSmrgstatic int	       	*ListenTransFds = NULL;
25405b261ecSmrgstatic int		ListenTransCount;
25505b261ecSmrg
25605b261ecSmrgstatic void ErrorConnMax(XtransConnInfo /* trans_conn */);
25705b261ecSmrg
25805b261ecSmrgstatic XtransConnInfo
25905b261ecSmrglookup_trans_conn (int fd)
26005b261ecSmrg{
26105b261ecSmrg    if (ListenTransFds)
26205b261ecSmrg    {
26305b261ecSmrg	int i;
26405b261ecSmrg	for (i = 0; i < ListenTransCount; i++)
26505b261ecSmrg	    if (ListenTransFds[i] == fd)
26605b261ecSmrg		return ListenTransConns[i];
26705b261ecSmrg    }
26805b261ecSmrg
2696747b715Smrg    return NULL;
27005b261ecSmrg}
27105b261ecSmrg
27205b261ecSmrg/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
27305b261ecSmrg
27405b261ecSmrgvoid
27505b261ecSmrgInitConnectionLimits(void)
27605b261ecSmrg{
27705b261ecSmrg    lastfdesc = -1;
27805b261ecSmrg
27905b261ecSmrg#ifndef __CYGWIN__
28005b261ecSmrg
28105b261ecSmrg#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
28205b261ecSmrg    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
28305b261ecSmrg#endif
28405b261ecSmrg
28505b261ecSmrg#ifdef HAS_GETDTABLESIZE
28605b261ecSmrg    if (lastfdesc < 0)
28705b261ecSmrg	lastfdesc = getdtablesize() - 1;
28805b261ecSmrg#endif
28905b261ecSmrg
29005b261ecSmrg#ifdef _NFILE
29105b261ecSmrg    if (lastfdesc < 0)
29205b261ecSmrg	lastfdesc = _NFILE - 1;
29305b261ecSmrg#endif
29405b261ecSmrg
29505b261ecSmrg#endif /* __CYGWIN__ */
29605b261ecSmrg
29705b261ecSmrg    /* This is the fallback */
29805b261ecSmrg    if (lastfdesc < 0)
29905b261ecSmrg	lastfdesc = MAXSOCKS;
30005b261ecSmrg
30105b261ecSmrg    if (lastfdesc > MAXSELECT)
30205b261ecSmrg	lastfdesc = MAXSELECT;
30305b261ecSmrg
30405b261ecSmrg    if (lastfdesc > MAXCLIENTS)
30505b261ecSmrg    {
30605b261ecSmrg	lastfdesc = MAXCLIENTS;
30705b261ecSmrg	if (debug_conns)
30805b261ecSmrg	    ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
30905b261ecSmrg    }
31005b261ecSmrg    MaxClients = lastfdesc;
31105b261ecSmrg
31205b261ecSmrg#ifdef DEBUG
31305b261ecSmrg    ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
31405b261ecSmrg#endif
31505b261ecSmrg
31605b261ecSmrg#if !defined(WIN32)
31705b261ecSmrg    if (!ConnectionTranslation)
31805b261ecSmrg        ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
31905b261ecSmrg#else
32005b261ecSmrg    InitConnectionTranslation();
32105b261ecSmrg#endif
32205b261ecSmrg}
32305b261ecSmrg
3244642e01fSmrg/*
3254642e01fSmrg * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
3264642e01fSmrg *
3274642e01fSmrg *  a- The parent process is ignoring SIGUSR1
3284642e01fSmrg *
3294642e01fSmrg * or
3304642e01fSmrg *
3314642e01fSmrg *  b- The parent process is expecting a SIGUSR1
3324642e01fSmrg *     when the server is ready to accept connections
3334642e01fSmrg *
3344642e01fSmrg * In the first case, the signal will be harmless, in the second case,
3354642e01fSmrg * the signal will be quite useful.
3364642e01fSmrg */
3374642e01fSmrgstatic void
3384642e01fSmrgInitParentProcess(void)
3394642e01fSmrg{
3404642e01fSmrg#if !defined(WIN32)
3414642e01fSmrg    OsSigHandlerPtr handler;
3424642e01fSmrg    handler = OsSignal (SIGUSR1, SIG_IGN);
3434642e01fSmrg    if ( handler == SIG_IGN)
3444642e01fSmrg	RunFromSmartParent = TRUE;
3454642e01fSmrg    OsSignal(SIGUSR1, handler);
3464642e01fSmrg    ParentProcess = getppid ();
3474642e01fSmrg#endif
3484642e01fSmrg}
3494642e01fSmrg
3504642e01fSmrgvoid
3514642e01fSmrgNotifyParentProcess(void)
3524642e01fSmrg{
3534642e01fSmrg#if !defined(WIN32)
3544642e01fSmrg    if (RunFromSmartParent) {
3554642e01fSmrg	if (ParentProcess > 1) {
3564642e01fSmrg	    kill (ParentProcess, SIGUSR1);
3574642e01fSmrg	}
3584642e01fSmrg    }
3599ace9065Smrg    if (RunFromSigStopParent)
3609ace9065Smrg	raise (SIGSTOP);
3614642e01fSmrg#endif
3624642e01fSmrg}
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
37605b261ecSmrg    FD_ZERO(&AllSockets);
37705b261ecSmrg    FD_ZERO(&AllClients);
37805b261ecSmrg    FD_ZERO(&LastSelectMask);
37905b261ecSmrg    FD_ZERO(&ClientsWithInput);
38005b261ecSmrg
38105b261ecSmrg#if !defined(WIN32)
38205b261ecSmrg    for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
38305b261ecSmrg#else
38405b261ecSmrg    ClearConnectionTranslation();
38505b261ecSmrg#endif
38605b261ecSmrg
38705b261ecSmrg    FD_ZERO (&WellKnownConnections);
38805b261ecSmrg
38905b261ecSmrg    sprintf (port, "%d", atoi (display));
39005b261ecSmrg
39105b261ecSmrg    if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
39205b261ecSmrg	&ListenTransCount, &ListenTransConns) >= 0) &&
39305b261ecSmrg	(ListenTransCount >= 1))
39405b261ecSmrg    {
39505b261ecSmrg	if (!PartialNetwork && partial)
39605b261ecSmrg	{
39705b261ecSmrg	    FatalError ("Failed to establish all listening sockets");
39805b261ecSmrg	}
39905b261ecSmrg	else
40005b261ecSmrg	{
4016747b715Smrg	    ListenTransFds = malloc(ListenTransCount * sizeof (int));
40205b261ecSmrg
40305b261ecSmrg	    for (i = 0; i < ListenTransCount; i++)
40405b261ecSmrg	    {
40505b261ecSmrg		int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
40605b261ecSmrg
40705b261ecSmrg		ListenTransFds[i] = fd;
40805b261ecSmrg		FD_SET (fd, &WellKnownConnections);
40905b261ecSmrg
41005b261ecSmrg		if (!_XSERVTransIsLocal (ListenTransConns[i]))
41105b261ecSmrg		{
41205b261ecSmrg		    DefineSelf (fd);
41305b261ecSmrg		}
41405b261ecSmrg	    }
41505b261ecSmrg	}
41605b261ecSmrg    }
41705b261ecSmrg
41805b261ecSmrg    if (!XFD_ANYSET (&WellKnownConnections))
41905b261ecSmrg        FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
42005b261ecSmrg#if !defined(WIN32)
42105b261ecSmrg    OsSignal (SIGPIPE, SIG_IGN);
42205b261ecSmrg    OsSignal (SIGHUP, AutoResetServer);
42305b261ecSmrg#endif
42405b261ecSmrg    OsSignal (SIGINT, GiveUp);
42505b261ecSmrg    OsSignal (SIGTERM, GiveUp);
42605b261ecSmrg    XFD_COPYSET (&WellKnownConnections, &AllSockets);
42705b261ecSmrg    ResetHosts(display);
4284642e01fSmrg
4294642e01fSmrg    InitParentProcess();
4304642e01fSmrg
43105b261ecSmrg#ifdef XDMCP
43205b261ecSmrg    XdmcpInit ();
43305b261ecSmrg#endif
43405b261ecSmrg}
43505b261ecSmrg
43605b261ecSmrgvoid
43705b261ecSmrgResetWellKnownSockets (void)
43805b261ecSmrg{
43905b261ecSmrg    int i;
44005b261ecSmrg
44105b261ecSmrg    ResetOsBuffers();
44205b261ecSmrg
44305b261ecSmrg    for (i = 0; i < ListenTransCount; i++)
44405b261ecSmrg    {
44505b261ecSmrg	int status = _XSERVTransResetListener (ListenTransConns[i]);
44605b261ecSmrg
44705b261ecSmrg	if (status != TRANS_RESET_NOOP)
44805b261ecSmrg	{
44905b261ecSmrg	    if (status == TRANS_RESET_FAILURE)
45005b261ecSmrg	    {
45105b261ecSmrg		/*
45205b261ecSmrg		 * ListenTransConns[i] freed by xtrans.
45305b261ecSmrg		 * Remove it from out list.
45405b261ecSmrg		 */
45505b261ecSmrg
45605b261ecSmrg		FD_CLR (ListenTransFds[i], &WellKnownConnections);
45705b261ecSmrg		ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
45805b261ecSmrg		ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
45905b261ecSmrg		ListenTransCount -= 1;
46005b261ecSmrg		i -= 1;
46105b261ecSmrg	    }
46205b261ecSmrg	    else if (status == TRANS_RESET_NEW_FD)
46305b261ecSmrg	    {
46405b261ecSmrg		/*
46505b261ecSmrg		 * A new file descriptor was allocated (the old one was closed)
46605b261ecSmrg		 */
46705b261ecSmrg
46805b261ecSmrg		int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
46905b261ecSmrg
47005b261ecSmrg		FD_CLR (ListenTransFds[i], &WellKnownConnections);
47105b261ecSmrg		ListenTransFds[i] = newfd;
47205b261ecSmrg		FD_SET(newfd, &WellKnownConnections);
47305b261ecSmrg	    }
47405b261ecSmrg	}
47505b261ecSmrg    }
47605b261ecSmrg
47705b261ecSmrg    ResetAuthorization ();
47805b261ecSmrg    ResetHosts(display);
47905b261ecSmrg    /*
48005b261ecSmrg     * restart XDMCP
48105b261ecSmrg     */
48205b261ecSmrg#ifdef XDMCP
48305b261ecSmrg    XdmcpReset ();
48405b261ecSmrg#endif
48505b261ecSmrg}
48605b261ecSmrg
48705b261ecSmrgvoid
48805b261ecSmrgCloseWellKnownConnections(void)
48905b261ecSmrg{
49005b261ecSmrg    int i;
49105b261ecSmrg
49205b261ecSmrg    for (i = 0; i < ListenTransCount; i++)
49305b261ecSmrg	_XSERVTransClose (ListenTransConns[i]);
49405b261ecSmrg}
49505b261ecSmrg
49605b261ecSmrgstatic void
49705b261ecSmrgAuthAudit (ClientPtr client, Bool letin,
49805b261ecSmrg    struct sockaddr *saddr, int len,
49905b261ecSmrg    unsigned int proto_n, char *auth_proto, int auth_id)
50005b261ecSmrg{
50105b261ecSmrg    char addr[128];
50205b261ecSmrg    char *out = addr;
50305b261ecSmrg    char client_uid_string[64];
5044642e01fSmrg    LocalClientCredRec *lcc;
5054642e01fSmrg#ifdef XSERVER_DTRACE
50605b261ecSmrg    pid_t client_pid = -1;
50705b261ecSmrg    zoneid_t client_zid = -1;
50805b261ecSmrg#endif
50905b261ecSmrg
51005b261ecSmrg    if (!len)
51105b261ecSmrg        strcpy(out, "local host");
51205b261ecSmrg    else
51305b261ecSmrg	switch (saddr->sa_family)
51405b261ecSmrg	{
51505b261ecSmrg	case AF_UNSPEC:
51605b261ecSmrg#if defined(UNIXCONN) || defined(LOCALCONN)
51705b261ecSmrg	case AF_UNIX:
51805b261ecSmrg#endif
51905b261ecSmrg	    strcpy(out, "local host");
52005b261ecSmrg	    break;
5219ace9065Smrg#if defined(TCPCONN) || defined(STREAMSCONN)
52205b261ecSmrg	case AF_INET:
52305b261ecSmrg	    sprintf(out, "IP %s",
52405b261ecSmrg		inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
52505b261ecSmrg	    break;
52605b261ecSmrg#if defined(IPv6) && defined(AF_INET6)
52705b261ecSmrg	case AF_INET6: {
52805b261ecSmrg	    char ipaddr[INET6_ADDRSTRLEN];
52905b261ecSmrg	    inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
53005b261ecSmrg	      ipaddr, sizeof(ipaddr));
53105b261ecSmrg	    sprintf(out, "IP %s", ipaddr);
53205b261ecSmrg	}
53305b261ecSmrg	    break;
53405b261ecSmrg#endif
53505b261ecSmrg#endif
53605b261ecSmrg	default:
53705b261ecSmrg	    strcpy(out, "unknown address");
53805b261ecSmrg	}
53905b261ecSmrg
5404642e01fSmrg    if (GetLocalClientCreds(client, &lcc) != -1) {
5414642e01fSmrg	int slen; /* length written to client_uid_string */
5424642e01fSmrg
5434642e01fSmrg	strcpy(client_uid_string, " ( ");
5444642e01fSmrg	slen = 3;
5454642e01fSmrg
5464642e01fSmrg	if (lcc->fieldsSet & LCC_UID_SET) {
5474642e01fSmrg	    snprintf(client_uid_string + slen,
5484642e01fSmrg		     sizeof(client_uid_string) - slen,
5494642e01fSmrg		     "uid=%ld ", (long) lcc->euid);
5504642e01fSmrg	    slen = strlen(client_uid_string);
5514642e01fSmrg	}
5524642e01fSmrg
5534642e01fSmrg	if (lcc->fieldsSet & LCC_GID_SET) {
5544642e01fSmrg	    snprintf(client_uid_string + slen,
5554642e01fSmrg		     sizeof(client_uid_string) - slen,
5564642e01fSmrg		     "gid=%ld ", (long) lcc->egid);
5574642e01fSmrg	    slen = strlen(client_uid_string);
5584642e01fSmrg	}
5594642e01fSmrg
5604642e01fSmrg	if (lcc->fieldsSet & LCC_PID_SET) {
5614642e01fSmrg#ifdef XSERVER_DTRACE
5624642e01fSmrg	    client_pid = lcc->pid;
56305b261ecSmrg#endif
5644642e01fSmrg	    snprintf(client_uid_string + slen,
5654642e01fSmrg		     sizeof(client_uid_string) - slen,
5664642e01fSmrg		     "pid=%ld ", (long) lcc->pid);
5674642e01fSmrg	    slen = strlen(client_uid_string);
5684642e01fSmrg	}
5694642e01fSmrg
5704642e01fSmrg	if (lcc->fieldsSet & LCC_ZID_SET) {
5714642e01fSmrg#ifdef XSERVER_DTRACE
5724642e01fSmrg	    client_zid = lcc->zoneid;
5734642e01fSmrg#endif
5744642e01fSmrg	    snprintf(client_uid_string + slen,
5754642e01fSmrg		     sizeof(client_uid_string) - slen,
5764642e01fSmrg		     "zoneid=%ld ", (long) lcc->zoneid);
5774642e01fSmrg	    slen = strlen(client_uid_string);
5784642e01fSmrg	}
5794642e01fSmrg
5804642e01fSmrg	snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
5814642e01fSmrg		 ")");
5824642e01fSmrg	FreeLocalClientCreds(lcc);
5834642e01fSmrg    }
58405b261ecSmrg    else {
58505b261ecSmrg	client_uid_string[0] = '\0';
58605b261ecSmrg    }
58705b261ecSmrg
58805b261ecSmrg#ifdef XSERVER_DTRACE
58905b261ecSmrg    XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
59005b261ecSmrg#endif
5914642e01fSmrg    if (auditTrailLevel > 1) {
59205b261ecSmrg      if (proto_n)
59305b261ecSmrg	AuditF("client %d %s from %s%s\n  Auth name: %.*s ID: %d\n",
59405b261ecSmrg	       client->index, letin ? "connected" : "rejected", addr,
59505b261ecSmrg	       client_uid_string, (int)proto_n, auth_proto, auth_id);
59605b261ecSmrg      else
59705b261ecSmrg	AuditF("client %d %s from %s%s\n",
59805b261ecSmrg	       client->index, letin ? "connected" : "rejected", addr,
59905b261ecSmrg	       client_uid_string);
60005b261ecSmrg
60105b261ecSmrg    }
60205b261ecSmrg}
60305b261ecSmrg
60405b261ecSmrgXID
60505b261ecSmrgAuthorizationIDOfClient(ClientPtr client)
60605b261ecSmrg{
60705b261ecSmrg    if (client->osPrivate)
60805b261ecSmrg	return ((OsCommPtr)client->osPrivate)->auth_id;
60905b261ecSmrg    else
61005b261ecSmrg	return None;
61105b261ecSmrg}
61205b261ecSmrg
61305b261ecSmrg
61405b261ecSmrg/*****************************************************************
61505b261ecSmrg * ClientAuthorized
61605b261ecSmrg *
61705b261ecSmrg *    Sent by the client at connection setup:
61805b261ecSmrg *                typedef struct _xConnClientPrefix {
61905b261ecSmrg *                   CARD8	byteOrder;
62005b261ecSmrg *                   BYTE	pad;
62105b261ecSmrg *                   CARD16	majorVersion, minorVersion;
62205b261ecSmrg *                   CARD16	nbytesAuthProto;
62305b261ecSmrg *                   CARD16	nbytesAuthString;
62405b261ecSmrg *                 } xConnClientPrefix;
62505b261ecSmrg *
62605b261ecSmrg *     	It is hoped that eventually one protocol will be agreed upon.  In the
62705b261ecSmrg *        mean time, a server that implements a different protocol than the
62805b261ecSmrg *        client expects, or a server that only implements the host-based
62905b261ecSmrg *        mechanism, will simply ignore this information.
63005b261ecSmrg *
63105b261ecSmrg *****************************************************************/
63205b261ecSmrg
6336747b715Smrgchar *
63405b261ecSmrgClientAuthorized(ClientPtr client,
63505b261ecSmrg    unsigned int proto_n, char *auth_proto,
63605b261ecSmrg    unsigned int string_n, char *auth_string)
63705b261ecSmrg{
63805b261ecSmrg    OsCommPtr 		priv;
63905b261ecSmrg    Xtransaddr		*from = NULL;
64005b261ecSmrg    int 		family;
64105b261ecSmrg    int			fromlen;
64205b261ecSmrg    XID	 		auth_id;
64305b261ecSmrg    char	 	*reason = NULL;
64405b261ecSmrg    XtransConnInfo	trans_conn;
64505b261ecSmrg
64605b261ecSmrg    priv = (OsCommPtr)client->osPrivate;
64705b261ecSmrg    trans_conn = priv->trans_conn;
64805b261ecSmrg
6494642e01fSmrg    /* Allow any client to connect without authorization on a launchd socket,
6504642e01fSmrg       because it is securely created -- this prevents a race condition on launch */
6514642e01fSmrg    if(trans_conn->flags & TRANS_NOXAUTH) {
6524642e01fSmrg        auth_id = (XID) 0L;
6534642e01fSmrg    } else {
6544642e01fSmrg        auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
6554642e01fSmrg    }
65605b261ecSmrg
65705b261ecSmrg    if (auth_id == (XID) ~0L)
65805b261ecSmrg    {
6594642e01fSmrg	if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
66005b261ecSmrg	{
66105b261ecSmrg	    if (InvalidHost ((struct sockaddr *) from, fromlen, client))
66205b261ecSmrg		AuthAudit(client, FALSE, (struct sockaddr *) from,
66305b261ecSmrg			  fromlen, proto_n, auth_proto, auth_id);
66405b261ecSmrg	    else
66505b261ecSmrg	    {
66605b261ecSmrg		auth_id = (XID) 0;
66705b261ecSmrg#ifdef XSERVER_DTRACE
66805b261ecSmrg		if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
66905b261ecSmrg#else
67005b261ecSmrg		if (auditTrailLevel > 1)
67105b261ecSmrg#endif
67205b261ecSmrg		    AuthAudit(client, TRUE,
67305b261ecSmrg			(struct sockaddr *) from, fromlen,
67405b261ecSmrg			proto_n, auth_proto, auth_id);
67505b261ecSmrg	    }
67605b261ecSmrg
6776747b715Smrg	    free(from);
67805b261ecSmrg	}
67905b261ecSmrg
68005b261ecSmrg	if (auth_id == (XID) ~0L) {
68105b261ecSmrg	    if (reason)
68205b261ecSmrg		return reason;
68305b261ecSmrg	    else
68405b261ecSmrg		return "Client is not authorized to connect to Server";
68505b261ecSmrg	}
68605b261ecSmrg    }
68705b261ecSmrg#ifdef XSERVER_DTRACE
68805b261ecSmrg    else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
68905b261ecSmrg#else
69005b261ecSmrg    else if (auditTrailLevel > 1)
69105b261ecSmrg#endif
69205b261ecSmrg    {
69305b261ecSmrg	if (_XSERVTransGetPeerAddr (trans_conn,
69405b261ecSmrg	    &family, &fromlen, &from) != -1)
69505b261ecSmrg	{
69605b261ecSmrg	    AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
69705b261ecSmrg		      proto_n, auth_proto, auth_id);
69805b261ecSmrg
6996747b715Smrg	    free(from);
70005b261ecSmrg	}
70105b261ecSmrg    }
70205b261ecSmrg    priv->auth_id = auth_id;
70305b261ecSmrg    priv->conn_time = 0;
70405b261ecSmrg
70505b261ecSmrg#ifdef XDMCP
70605b261ecSmrg    /* indicate to Xdmcp protocol that we've opened new client */
70705b261ecSmrg    XdmcpOpenDisplay(priv->fd);
70805b261ecSmrg#endif /* XDMCP */
70905b261ecSmrg
71005b261ecSmrg    XaceHook(XACE_AUTH_AVAIL, client, auth_id);
71105b261ecSmrg
71205b261ecSmrg    /* At this point, if the client is authorized to change the access control
71305b261ecSmrg     * list, we should getpeername() information, and add the client to
71405b261ecSmrg     * the selfhosts list.  It's not really the host machine, but the
71505b261ecSmrg     * true purpose of the selfhosts list is to see who may change the
71605b261ecSmrg     * access control list.
71705b261ecSmrg     */
71805b261ecSmrg    return((char *)NULL);
71905b261ecSmrg}
72005b261ecSmrg
72105b261ecSmrgstatic ClientPtr
72205b261ecSmrgAllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
72305b261ecSmrg{
72405b261ecSmrg    OsCommPtr	oc;
72505b261ecSmrg    ClientPtr	client;
72605b261ecSmrg
72705b261ecSmrg    if (
72805b261ecSmrg#ifndef WIN32
72905b261ecSmrg	fd >= lastfdesc
73005b261ecSmrg#else
73105b261ecSmrg	XFD_SETCOUNT(&AllClients) >= MaxClients
73205b261ecSmrg#endif
73305b261ecSmrg	)
73405b261ecSmrg	return NullClient;
7356747b715Smrg    oc = malloc(sizeof(OsCommRec));
73605b261ecSmrg    if (!oc)
73705b261ecSmrg	return NullClient;
73805b261ecSmrg    oc->trans_conn = trans_conn;
73905b261ecSmrg    oc->fd = fd;
74005b261ecSmrg    oc->input = (ConnectionInputPtr)NULL;
74105b261ecSmrg    oc->output = (ConnectionOutputPtr)NULL;
74205b261ecSmrg    oc->auth_id = None;
74305b261ecSmrg    oc->conn_time = conn_time;
74405b261ecSmrg    if (!(client = NextAvailableClient((pointer)oc)))
74505b261ecSmrg    {
7466747b715Smrg	free(oc);
74705b261ecSmrg	return NullClient;
74805b261ecSmrg    }
7499ace9065Smrg    oc->local_client = ComputeLocalClient(client);
75005b261ecSmrg#if !defined(WIN32)
75105b261ecSmrg    ConnectionTranslation[fd] = client->index;
75205b261ecSmrg#else
75305b261ecSmrg    SetConnectionTranslation(fd, client->index);
75405b261ecSmrg#endif
75505b261ecSmrg    if (GrabInProgress)
75605b261ecSmrg    {
75705b261ecSmrg        FD_SET(fd, &SavedAllClients);
75805b261ecSmrg        FD_SET(fd, &SavedAllSockets);
75905b261ecSmrg    }
76005b261ecSmrg    else
76105b261ecSmrg    {
76205b261ecSmrg        FD_SET(fd, &AllClients);
76305b261ecSmrg        FD_SET(fd, &AllSockets);
76405b261ecSmrg    }
76505b261ecSmrg
76605b261ecSmrg#ifdef DEBUG
76705b261ecSmrg    ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
76805b261ecSmrg	   client->index, fd);
76905b261ecSmrg#endif
77005b261ecSmrg#ifdef XSERVER_DTRACE
77105b261ecSmrg    XSERVER_CLIENT_CONNECT(client->index, fd);
77205b261ecSmrg#endif
77305b261ecSmrg
77405b261ecSmrg    return client;
77505b261ecSmrg}
77605b261ecSmrg
77705b261ecSmrg/*****************
77805b261ecSmrg * EstablishNewConnections
77905b261ecSmrg *    If anyone is waiting on listened sockets, accept them.
78005b261ecSmrg *    Returns a mask with indices of new clients.  Updates AllClients
78105b261ecSmrg *    and AllSockets.
78205b261ecSmrg *****************/
78305b261ecSmrg
78405b261ecSmrg/*ARGSUSED*/
78505b261ecSmrgBool
78605b261ecSmrgEstablishNewConnections(ClientPtr clientUnused, pointer closure)
78705b261ecSmrg{
78805b261ecSmrg    fd_set  readyconnections;     /* set of listeners that are ready */
78905b261ecSmrg    int curconn;                  /* fd of listener that's ready */
79005b261ecSmrg    register int newconn;         /* fd of new client */
79105b261ecSmrg    CARD32 connect_time;
79205b261ecSmrg    register int i;
79305b261ecSmrg    register ClientPtr client;
79405b261ecSmrg    register OsCommPtr oc;
79505b261ecSmrg    fd_set tmask;
79605b261ecSmrg
79705b261ecSmrg    XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
79805b261ecSmrg    XFD_COPYSET(&tmask, &readyconnections);
79905b261ecSmrg    if (!XFD_ANYSET(&readyconnections))
80005b261ecSmrg	return TRUE;
80105b261ecSmrg    connect_time = GetTimeInMillis();
80205b261ecSmrg    /* kill off stragglers */
80305b261ecSmrg    for (i=1; i<currentMaxClients; i++)
80405b261ecSmrg    {
80505b261ecSmrg	if ((client = clients[i]))
80605b261ecSmrg	{
80705b261ecSmrg	    oc = (OsCommPtr)(client->osPrivate);
80805b261ecSmrg	    if ((oc && (oc->conn_time != 0) &&
80905b261ecSmrg		(connect_time - oc->conn_time) >= TimeOutValue) ||
81005b261ecSmrg		(client->noClientException != Success && !client->clientGone))
81105b261ecSmrg		CloseDownClient(client);
81205b261ecSmrg	}
81305b261ecSmrg    }
81405b261ecSmrg#ifndef WIN32
81505b261ecSmrg    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
81605b261ecSmrg    {
81705b261ecSmrg      while (readyconnections.fds_bits[i])
81805b261ecSmrg#else
81905b261ecSmrg      for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
82005b261ecSmrg#endif
82105b261ecSmrg      {
82205b261ecSmrg	XtransConnInfo trans_conn, new_trans_conn;
82305b261ecSmrg	int status;
82405b261ecSmrg
82505b261ecSmrg#ifndef WIN32
8266747b715Smrg	curconn = mffs (readyconnections.fds_bits[i]) - 1;
82705b261ecSmrg	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
82805b261ecSmrg	curconn += (i * (sizeof(fd_mask)*8));
82905b261ecSmrg#else
83005b261ecSmrg	curconn = XFD_FD(&readyconnections, i);
83105b261ecSmrg#endif
83205b261ecSmrg
83305b261ecSmrg	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
83405b261ecSmrg	    continue;
83505b261ecSmrg
83605b261ecSmrg	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
83705b261ecSmrg	    continue;
83805b261ecSmrg
83905b261ecSmrg	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
84005b261ecSmrg
84105b261ecSmrg	if (newconn < lastfdesc)
84205b261ecSmrg	{
84305b261ecSmrg		int clientid;
84405b261ecSmrg#if !defined(WIN32)
84505b261ecSmrg  		clientid = ConnectionTranslation[newconn];
84605b261ecSmrg#else
84705b261ecSmrg  		clientid = GetConnectionTranslation(newconn);
84805b261ecSmrg#endif
84905b261ecSmrg		if(clientid && (client = clients[clientid]))
85005b261ecSmrg 			CloseDownClient(client);
85105b261ecSmrg	}
85205b261ecSmrg
85305b261ecSmrg	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
85405b261ecSmrg
85505b261ecSmrg	if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
85605b261ecSmrg	{
85705b261ecSmrg	    ErrorConnMax(new_trans_conn);
85805b261ecSmrg	    _XSERVTransClose(new_trans_conn);
85905b261ecSmrg	}
8604642e01fSmrg
8614642e01fSmrg	if(trans_conn->flags & TRANS_NOXAUTH)
8624642e01fSmrg	    new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
8634642e01fSmrg
86405b261ecSmrg      }
86505b261ecSmrg#ifndef WIN32
86605b261ecSmrg    }
86705b261ecSmrg#endif
86805b261ecSmrg    return TRUE;
86905b261ecSmrg}
87005b261ecSmrg
87105b261ecSmrg#define NOROOM "Maximum number of clients reached"
87205b261ecSmrg
87305b261ecSmrg/************
87405b261ecSmrg *   ErrorConnMax
87505b261ecSmrg *     Fail a connection due to lack of client or file descriptor space
87605b261ecSmrg ************/
87705b261ecSmrg
87805b261ecSmrgstatic void
87905b261ecSmrgErrorConnMax(XtransConnInfo trans_conn)
88005b261ecSmrg{
88105b261ecSmrg    int fd = _XSERVTransGetConnectionNumber (trans_conn);
88205b261ecSmrg    xConnSetupPrefix csp;
88305b261ecSmrg    char pad[3];
88405b261ecSmrg    struct iovec iov[3];
88505b261ecSmrg    char byteOrder = 0;
88605b261ecSmrg    int whichbyte = 1;
88705b261ecSmrg    struct timeval waittime;
88805b261ecSmrg    fd_set mask;
88905b261ecSmrg
89005b261ecSmrg    /* if these seems like a lot of trouble to go to, it probably is */
89105b261ecSmrg    waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
89205b261ecSmrg    waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
89305b261ecSmrg		       (1000000 / MILLI_PER_SECOND);
89405b261ecSmrg    FD_ZERO(&mask);
89505b261ecSmrg    FD_SET(fd, &mask);
89605b261ecSmrg    (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
89705b261ecSmrg    /* try to read the byte-order of the connection */
89805b261ecSmrg    (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
89905b261ecSmrg    if ((byteOrder == 'l') || (byteOrder == 'B'))
90005b261ecSmrg    {
90105b261ecSmrg	csp.success = xFalse;
90205b261ecSmrg	csp.lengthReason = sizeof(NOROOM) - 1;
90305b261ecSmrg	csp.length = (sizeof(NOROOM) + 2) >> 2;
90405b261ecSmrg	csp.majorVersion = X_PROTOCOL;
90505b261ecSmrg	csp.minorVersion = X_PROTOCOL_REVISION;
90605b261ecSmrg	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
90705b261ecSmrg	    (!(*(char *) &whichbyte) && (byteOrder == 'l')))
90805b261ecSmrg	{
90905b261ecSmrg	    swaps(&csp.majorVersion, whichbyte);
91005b261ecSmrg	    swaps(&csp.minorVersion, whichbyte);
91105b261ecSmrg	    swaps(&csp.length, whichbyte);
91205b261ecSmrg	}
91305b261ecSmrg	iov[0].iov_len = sz_xConnSetupPrefix;
91405b261ecSmrg	iov[0].iov_base = (char *) &csp;
91505b261ecSmrg	iov[1].iov_len = csp.lengthReason;
91605b261ecSmrg	iov[1].iov_base = NOROOM;
91705b261ecSmrg	iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
91805b261ecSmrg	iov[2].iov_base = pad;
91905b261ecSmrg	(void)_XSERVTransWritev(trans_conn, iov, 3);
92005b261ecSmrg    }
92105b261ecSmrg}
92205b261ecSmrg
92305b261ecSmrg/************
92405b261ecSmrg *   CloseDownFileDescriptor:
92505b261ecSmrg *     Remove this file descriptor and it's I/O buffers, etc.
92605b261ecSmrg ************/
92705b261ecSmrg
92805b261ecSmrgstatic void
92905b261ecSmrgCloseDownFileDescriptor(OsCommPtr oc)
93005b261ecSmrg{
93105b261ecSmrg    int connection = oc->fd;
93205b261ecSmrg
93305b261ecSmrg    if (oc->trans_conn) {
93405b261ecSmrg	_XSERVTransDisconnect(oc->trans_conn);
93505b261ecSmrg	_XSERVTransClose(oc->trans_conn);
93605b261ecSmrg    }
93705b261ecSmrg#ifndef WIN32
93805b261ecSmrg    ConnectionTranslation[connection] = 0;
93905b261ecSmrg#else
94005b261ecSmrg    SetConnectionTranslation(connection, 0);
94105b261ecSmrg#endif
94205b261ecSmrg    FD_CLR(connection, &AllSockets);
94305b261ecSmrg    FD_CLR(connection, &AllClients);
94405b261ecSmrg    FD_CLR(connection, &ClientsWithInput);
94505b261ecSmrg    FD_CLR(connection, &GrabImperviousClients);
94605b261ecSmrg    if (GrabInProgress)
94705b261ecSmrg    {
94805b261ecSmrg	FD_CLR(connection, &SavedAllSockets);
94905b261ecSmrg	FD_CLR(connection, &SavedAllClients);
95005b261ecSmrg	FD_CLR(connection, &SavedClientsWithInput);
95105b261ecSmrg    }
95205b261ecSmrg    FD_CLR(connection, &ClientsWriteBlocked);
95305b261ecSmrg    if (!XFD_ANYSET(&ClientsWriteBlocked))
95405b261ecSmrg    	AnyClientsWriteBlocked = FALSE;
95505b261ecSmrg    FD_CLR(connection, &OutputPending);
95605b261ecSmrg}
95705b261ecSmrg
95805b261ecSmrg/*****************
95905b261ecSmrg * CheckConnections
96005b261ecSmrg *    Some connection has died, go find which one and shut it down
96105b261ecSmrg *    The file descriptor has been closed, but is still in AllClients.
96205b261ecSmrg *    If would truly be wonderful if select() would put the bogus
96305b261ecSmrg *    file descriptors in the exception mask, but nooooo.  So we have
96405b261ecSmrg *    to check each and every socket individually.
96505b261ecSmrg *****************/
96605b261ecSmrg
96705b261ecSmrgvoid
96805b261ecSmrgCheckConnections(void)
96905b261ecSmrg{
97005b261ecSmrg#ifndef WIN32
97105b261ecSmrg    fd_mask		mask;
97205b261ecSmrg#endif
97305b261ecSmrg    fd_set		tmask;
97405b261ecSmrg    int			curclient, curoff;
97505b261ecSmrg    int			i;
97605b261ecSmrg    struct timeval	notime;
97705b261ecSmrg    int r;
97805b261ecSmrg#ifdef WIN32
97905b261ecSmrg    fd_set savedAllClients;
98005b261ecSmrg#endif
98105b261ecSmrg
98205b261ecSmrg    notime.tv_sec = 0;
98305b261ecSmrg    notime.tv_usec = 0;
98405b261ecSmrg
98505b261ecSmrg#ifndef WIN32
98605b261ecSmrg    for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
98705b261ecSmrg    {
98805b261ecSmrg	mask = AllClients.fds_bits[i];
98905b261ecSmrg        while (mask)
99005b261ecSmrg    	{
9916747b715Smrg	    curoff = mffs (mask) - 1;
99205b261ecSmrg	    curclient = curoff + (i * (sizeof(fd_mask)*8));
99305b261ecSmrg            FD_ZERO(&tmask);
99405b261ecSmrg            FD_SET(curclient, &tmask);
99505b261ecSmrg            do {
99605b261ecSmrg                r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
99705b261ecSmrg            } while (r < 0 && (errno == EINTR || errno == EAGAIN));
99805b261ecSmrg            if (r < 0)
99905b261ecSmrg                if (ConnectionTranslation[curclient] > 0)
100005b261ecSmrg                    CloseDownClient(clients[ConnectionTranslation[curclient]]);
100105b261ecSmrg	    mask &= ~((fd_mask)1 << curoff);
100205b261ecSmrg	}
100305b261ecSmrg    }
100405b261ecSmrg#else
100505b261ecSmrg    XFD_COPYSET(&AllClients, &savedAllClients);
100605b261ecSmrg    for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
100705b261ecSmrg    {
100805b261ecSmrg	curclient = XFD_FD(&savedAllClients, i);
100905b261ecSmrg	FD_ZERO(&tmask);
101005b261ecSmrg	FD_SET(curclient, &tmask);
101105b261ecSmrg        do {
101205b261ecSmrg            r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
101305b261ecSmrg        } while (r < 0 && (errno == EINTR || errno == EAGAIN));
101405b261ecSmrg	if (r < 0)
101505b261ecSmrg            if (GetConnectionTranslation(curclient) > 0)
101605b261ecSmrg                CloseDownClient(clients[GetConnectionTranslation(curclient)]);
101705b261ecSmrg    }
101805b261ecSmrg#endif
101905b261ecSmrg}
102005b261ecSmrg
102105b261ecSmrg
102205b261ecSmrg/*****************
102305b261ecSmrg * CloseDownConnection
102405b261ecSmrg *    Delete client from AllClients and free resources
102505b261ecSmrg *****************/
102605b261ecSmrg
102705b261ecSmrgvoid
102805b261ecSmrgCloseDownConnection(ClientPtr client)
102905b261ecSmrg{
103005b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
103105b261ecSmrg
10326747b715Smrg    if (FlushCallback)
10336747b715Smrg	CallCallbacks(&FlushCallback, NULL);
10346747b715Smrg
103505b261ecSmrg    if (oc->output && oc->output->count)
103605b261ecSmrg	FlushClient(client, oc, (char *)NULL, 0);
103705b261ecSmrg#ifdef XDMCP
103805b261ecSmrg    XdmcpCloseDisplay(oc->fd);
103905b261ecSmrg#endif
104005b261ecSmrg    CloseDownFileDescriptor(oc);
104105b261ecSmrg    FreeOsBuffers(oc);
10426747b715Smrg    free(client->osPrivate);
104305b261ecSmrg    client->osPrivate = (pointer)NULL;
104405b261ecSmrg    if (auditTrailLevel > 1)
104505b261ecSmrg	AuditF("client %d disconnected\n", client->index);
104605b261ecSmrg}
104705b261ecSmrg
10486747b715Smrgvoid
104905b261ecSmrgAddGeneralSocket(int fd)
105005b261ecSmrg{
105105b261ecSmrg    FD_SET(fd, &AllSockets);
105205b261ecSmrg    if (GrabInProgress)
105305b261ecSmrg	FD_SET(fd, &SavedAllSockets);
105405b261ecSmrg}
105505b261ecSmrg
10566747b715Smrgvoid
105705b261ecSmrgAddEnabledDevice(int fd)
105805b261ecSmrg{
105905b261ecSmrg    FD_SET(fd, &EnabledDevices);
106005b261ecSmrg    AddGeneralSocket(fd);
106105b261ecSmrg}
106205b261ecSmrg
10636747b715Smrgvoid
106405b261ecSmrgRemoveGeneralSocket(int fd)
106505b261ecSmrg{
106605b261ecSmrg    FD_CLR(fd, &AllSockets);
106705b261ecSmrg    if (GrabInProgress)
106805b261ecSmrg	FD_CLR(fd, &SavedAllSockets);
106905b261ecSmrg}
107005b261ecSmrg
10716747b715Smrgvoid
107205b261ecSmrgRemoveEnabledDevice(int fd)
107305b261ecSmrg{
107405b261ecSmrg    FD_CLR(fd, &EnabledDevices);
107505b261ecSmrg    RemoveGeneralSocket(fd);
107605b261ecSmrg}
107705b261ecSmrg
107805b261ecSmrg/*****************
107905b261ecSmrg * OnlyListenToOneClient:
108005b261ecSmrg *    Only accept requests from  one client.  Continue to handle new
108105b261ecSmrg *    connections, but don't take any protocol requests from the new
108205b261ecSmrg *    ones.  Note that if GrabInProgress is set, EstablishNewConnections
108305b261ecSmrg *    needs to put new clients into SavedAllSockets and SavedAllClients.
108405b261ecSmrg *    Note also that there is no timeout for this in the protocol.
108505b261ecSmrg *    This routine is "undone" by ListenToAllClients()
108605b261ecSmrg *****************/
108705b261ecSmrg
10884642e01fSmrgint
108905b261ecSmrgOnlyListenToOneClient(ClientPtr client)
109005b261ecSmrg{
109105b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
10924642e01fSmrg    int rc, connection = oc->fd;
10934642e01fSmrg
10944642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
10954642e01fSmrg    if (rc != Success)
10964642e01fSmrg	return rc;
109705b261ecSmrg
109805b261ecSmrg    if (! GrabInProgress)
109905b261ecSmrg    {
110005b261ecSmrg	XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
110105b261ecSmrg	XFD_ANDSET(&ClientsWithInput,
110205b261ecSmrg		       &ClientsWithInput, &GrabImperviousClients);
110305b261ecSmrg	if (FD_ISSET(connection, &SavedClientsWithInput))
110405b261ecSmrg	{
110505b261ecSmrg	    FD_CLR(connection, &SavedClientsWithInput);
110605b261ecSmrg	    FD_SET(connection, &ClientsWithInput);
110705b261ecSmrg	}
110805b261ecSmrg	XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
110905b261ecSmrg	XFD_COPYSET(&AllSockets, &SavedAllSockets);
111005b261ecSmrg	XFD_COPYSET(&AllClients, &SavedAllClients);
111105b261ecSmrg	XFD_UNSET(&AllSockets, &AllClients);
111205b261ecSmrg	XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
111305b261ecSmrg	FD_SET(connection, &AllClients);
111405b261ecSmrg	XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
111505b261ecSmrg	GrabInProgress = client->index;
111605b261ecSmrg    }
11174642e01fSmrg    return rc;
111805b261ecSmrg}
111905b261ecSmrg
112005b261ecSmrg/****************
112105b261ecSmrg * ListenToAllClients:
112205b261ecSmrg *    Undoes OnlyListentToOneClient()
112305b261ecSmrg ****************/
112405b261ecSmrg
112505b261ecSmrgvoid
112605b261ecSmrgListenToAllClients(void)
112705b261ecSmrg{
112805b261ecSmrg    if (GrabInProgress)
112905b261ecSmrg    {
113005b261ecSmrg	XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
113105b261ecSmrg	XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
113205b261ecSmrg	XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
113305b261ecSmrg	GrabInProgress = 0;
113405b261ecSmrg    }
113505b261ecSmrg}
113605b261ecSmrg
113705b261ecSmrg/****************
113805b261ecSmrg * IgnoreClient
113905b261ecSmrg *    Removes one client from input masks.
114005b261ecSmrg *    Must have cooresponding call to AttendClient.
114105b261ecSmrg ****************/
114205b261ecSmrg
11436747b715Smrgvoid
114405b261ecSmrgIgnoreClient (ClientPtr client)
114505b261ecSmrg{
114605b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
114705b261ecSmrg    int connection = oc->fd;
114805b261ecSmrg
11496747b715Smrg    client->ignoreCount++;
11506747b715Smrg    if (client->ignoreCount > 1)
11516747b715Smrg	return;
11526747b715Smrg
115305b261ecSmrg    isItTimeToYield = TRUE;
115405b261ecSmrg    if (!GrabInProgress || FD_ISSET(connection, &AllClients))
115505b261ecSmrg    {
115605b261ecSmrg    	if (FD_ISSET (connection, &ClientsWithInput))
115705b261ecSmrg	    FD_SET(connection, &IgnoredClientsWithInput);
115805b261ecSmrg    	else
115905b261ecSmrg	    FD_CLR(connection, &IgnoredClientsWithInput);
116005b261ecSmrg    	FD_CLR(connection, &ClientsWithInput);
116105b261ecSmrg    	FD_CLR(connection, &AllSockets);
116205b261ecSmrg    	FD_CLR(connection, &AllClients);
116305b261ecSmrg	FD_CLR(connection, &LastSelectMask);
116405b261ecSmrg    }
116505b261ecSmrg    else
116605b261ecSmrg    {
116705b261ecSmrg    	if (FD_ISSET (connection, &SavedClientsWithInput))
116805b261ecSmrg	    FD_SET(connection, &IgnoredClientsWithInput);
116905b261ecSmrg    	else
117005b261ecSmrg	    FD_CLR(connection, &IgnoredClientsWithInput);
117105b261ecSmrg	FD_CLR(connection, &SavedClientsWithInput);
117205b261ecSmrg	FD_CLR(connection, &SavedAllSockets);
117305b261ecSmrg	FD_CLR(connection, &SavedAllClients);
117405b261ecSmrg    }
117505b261ecSmrg}
117605b261ecSmrg
117705b261ecSmrg/****************
117805b261ecSmrg * AttendClient
117905b261ecSmrg *    Adds one client back into the input masks.
118005b261ecSmrg ****************/
118105b261ecSmrg
11826747b715Smrgvoid
118305b261ecSmrgAttendClient (ClientPtr client)
118405b261ecSmrg{
118505b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
118605b261ecSmrg    int connection = oc->fd;
11876747b715Smrg
11886747b715Smrg    client->ignoreCount--;
11896747b715Smrg    if (client->ignoreCount)
11906747b715Smrg	return;
11916747b715Smrg
119205b261ecSmrg    if (!GrabInProgress || GrabInProgress == client->index ||
119305b261ecSmrg	FD_ISSET(connection, &GrabImperviousClients))
119405b261ecSmrg    {
119505b261ecSmrg    	FD_SET(connection, &AllClients);
119605b261ecSmrg    	FD_SET(connection, &AllSockets);
119705b261ecSmrg	FD_SET(connection, &LastSelectMask);
119805b261ecSmrg    	if (FD_ISSET (connection, &IgnoredClientsWithInput))
119905b261ecSmrg	    FD_SET(connection, &ClientsWithInput);
120005b261ecSmrg    }
120105b261ecSmrg    else
120205b261ecSmrg    {
120305b261ecSmrg	FD_SET(connection, &SavedAllClients);
120405b261ecSmrg	FD_SET(connection, &SavedAllSockets);
120505b261ecSmrg	if (FD_ISSET(connection, &IgnoredClientsWithInput))
120605b261ecSmrg	    FD_SET(connection, &SavedClientsWithInput);
120705b261ecSmrg    }
120805b261ecSmrg}
120905b261ecSmrg
121005b261ecSmrg/* make client impervious to grabs; assume only executing client calls this */
121105b261ecSmrg
12124642e01fSmrgvoid
121305b261ecSmrgMakeClientGrabImpervious(ClientPtr client)
121405b261ecSmrg{
121505b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
121605b261ecSmrg    int connection = oc->fd;
121705b261ecSmrg
121805b261ecSmrg    FD_SET(connection, &GrabImperviousClients);
121905b261ecSmrg
122005b261ecSmrg    if (ServerGrabCallback)
122105b261ecSmrg    {
122205b261ecSmrg	ServerGrabInfoRec grabinfo;
122305b261ecSmrg	grabinfo.client = client;
122405b261ecSmrg	grabinfo.grabstate  = CLIENT_IMPERVIOUS;
122505b261ecSmrg	CallCallbacks(&ServerGrabCallback, &grabinfo);
122605b261ecSmrg    }
122705b261ecSmrg}
122805b261ecSmrg
122905b261ecSmrg/* make client pervious to grabs; assume only executing client calls this */
123005b261ecSmrg
12314642e01fSmrgvoid
123205b261ecSmrgMakeClientGrabPervious(ClientPtr client)
123305b261ecSmrg{
123405b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
123505b261ecSmrg    int connection = oc->fd;
123605b261ecSmrg
123705b261ecSmrg    FD_CLR(connection, &GrabImperviousClients);
123805b261ecSmrg    if (GrabInProgress && (GrabInProgress != client->index))
123905b261ecSmrg    {
124005b261ecSmrg	if (FD_ISSET(connection, &ClientsWithInput))
124105b261ecSmrg	{
124205b261ecSmrg	    FD_SET(connection, &SavedClientsWithInput);
124305b261ecSmrg	    FD_CLR(connection, &ClientsWithInput);
124405b261ecSmrg	}
124505b261ecSmrg	FD_CLR(connection, &AllSockets);
124605b261ecSmrg	FD_CLR(connection, &AllClients);
124705b261ecSmrg	isItTimeToYield = TRUE;
124805b261ecSmrg    }
124905b261ecSmrg
125005b261ecSmrg    if (ServerGrabCallback)
125105b261ecSmrg    {
125205b261ecSmrg	ServerGrabInfoRec grabinfo;
125305b261ecSmrg	grabinfo.client = client;
125405b261ecSmrg	grabinfo.grabstate  = CLIENT_PERVIOUS;
125505b261ecSmrg	CallCallbacks(&ServerGrabCallback, &grabinfo);
125605b261ecSmrg    }
125705b261ecSmrg}
125805b261ecSmrg
12594642e01fSmrg#ifdef XQUARTZ
12604642e01fSmrg/* Add a fd (from launchd) to our listeners */
12616747b715Smrgvoid ListenOnOpenFD(int fd, int noxauth) {
12624642e01fSmrg    char port[256];
12634642e01fSmrg    XtransConnInfo ciptr;
12646747b715Smrg    const char *display_env = getenv("DISPLAY");
12654642e01fSmrg
12666747b715Smrg    if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
12674642e01fSmrg        /* Make the path the launchd socket if our DISPLAY is set right */
12686747b715Smrg        strcpy(port, display_env);
12694642e01fSmrg    } else {
12704642e01fSmrg        /* Just some default so things don't break and die. */
12714642e01fSmrg        sprintf(port, ":%d", atoi(display));
12724642e01fSmrg    }
12734642e01fSmrg
12744642e01fSmrg    /* Make our XtransConnInfo
12754642e01fSmrg     * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
12764642e01fSmrg     */
12774642e01fSmrg    ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
12784642e01fSmrg    if(ciptr == NULL) {
12794642e01fSmrg        ErrorF("Got NULL while trying to Reopen launchd port.\n");
12804642e01fSmrg        return;
12814642e01fSmrg    }
12824642e01fSmrg
12834642e01fSmrg    if(noxauth)
12844642e01fSmrg        ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
12854642e01fSmrg
12864642e01fSmrg    /* Allocate space to store it */
12876747b715Smrg    ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
12886747b715Smrg    ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
12894642e01fSmrg
12904642e01fSmrg    /* Store it */
12914642e01fSmrg    ListenTransConns[ListenTransCount] = ciptr;
12924642e01fSmrg    ListenTransFds[ListenTransCount] = fd;
12934642e01fSmrg
12944642e01fSmrg    FD_SET(fd, &WellKnownConnections);
12954642e01fSmrg    FD_SET(fd, &AllSockets);
12964642e01fSmrg
12974642e01fSmrg    /* Increment the count */
12984642e01fSmrg    ListenTransCount++;
12994642e01fSmrg
13004642e01fSmrg    /* This *might* not be needed... /shrug */
13014642e01fSmrg    ResetAuthorization();
13024642e01fSmrg    ResetHosts(display);
13034642e01fSmrg#ifdef XDMCP
13044642e01fSmrg    XdmcpReset();
13054642e01fSmrg#endif
13064642e01fSmrg}
13074642e01fSmrg
13084642e01fSmrg#endif
1309