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