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