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, ¬ime); 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, ¬ime); 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