12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028 |
- /***********************************************************
- Copyright 1987, 1989, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Digital not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ******************************************************************/
- /*****************************************************************
- * Stuff to create connections --- OS dependent
- *
- * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
- * CloseDownConnection, CheckConnections, AddEnabledDevice,
- * RemoveEnabledDevice, OnlyListToOneClient,
- * ListenToAllClients,
- *
- * (WaitForSomething is in its own file)
- *
- * In this implementation, a client socket table is not kept.
- * Instead, what would be the index into the table is just the
- * file descriptor of the socket. This won't work for if the
- * socket ids aren't small nums (0 - 2^8)
- *
- *****************************************************************/
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <X11/X.h>
- #include <X11/Xproto.h>
- #define XSERV_t
- #define TRANS_SERVER
- #define TRANS_REOPEN
- #include <X11/Xtrans/Xtrans.h>
- #include <errno.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #if defined(TCPCONN)
- # include <netinet/in.h>
- # include <arpa/inet.h>
- # ifdef CSRG_BASED
- # include <sys/param.h>
- # endif
- # include <netinet/tcp.h>
- # include <arpa/inet.h>
- #endif
- #include <sys/uio.h>
- #include "misc.h" /* for typedef of pointer */
- #include "osdep.h"
- #include <X11/Xpoll.h>
- #include "opaque.h"
- #include "dixstruct.h"
- #define Pid_t pid_t
- #ifdef HAS_GETPEERUCRED
- # include <ucred.h>
- # include <zone.h>
- #endif
- int lastfdesc; /* maximum file descriptor */
- fd_set WellKnownConnections; /* Listener mask */
- fd_set EnabledDevices; /* mask for input devices that are on */
- fd_set AllSockets; /* select on this */
- fd_set AllClients; /* available clients */
- fd_set LastSelectMask; /* mask returned from last select call */
- fd_set ClientsWithInput; /* clients with FULL requests in buffer */
- fd_set ClientsWriteBlocked; /* clients who cannot receive output */
- fd_set OutputPending; /* clients with reply/event data ready to go */
- int MaxClients = 0;
- Bool NewOutputPending; /* not yet attempted to write some new output */
- Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
- Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
- Bool PartialNetwork; /* continue even if unable to bind all addrs */
- static Pid_t ParentProcess;
- static Bool debug_conns = FALSE;
- fd_set IgnoredClientsWithInput;
- static fd_set GrabImperviousClients;
- static fd_set SavedAllClients;
- static fd_set SavedAllSockets;
- static fd_set SavedClientsWithInput;
- _X_EXPORT int GrabInProgress = 0;
- int *ConnectionTranslation = NULL;
- XtransConnInfo *ListenTransConns = NULL;
- int *ListenTransFds = NULL;
- int ListenTransCount;
- static void ErrorConnMax(XtransConnInfo /* trans_conn */);
- static XtransConnInfo
- lookup_trans_conn (int fd)
- {
- if (ListenTransFds)
- {
- int i;
- for (i = 0; i < ListenTransCount; i++)
- if (ListenTransFds[i] == fd)
- return ListenTransConns[i];
- }
- return (NULL);
- }
- /* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
- void
- InitConnectionLimits(void)
- {
- lastfdesc = -1;
- #if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
- lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
- #endif
- #ifdef HAS_GETDTABLESIZE
- if (lastfdesc < 0)
- lastfdesc = getdtablesize() - 1;
- #endif
- #ifdef _NFILE
- if (lastfdesc < 0)
- lastfdesc = _NFILE - 1;
- #endif
- /* This is the fallback */
- if (lastfdesc < 0)
- lastfdesc = MAXSOCKS;
- if (lastfdesc > MAXSELECT)
- lastfdesc = MAXSELECT;
- if (lastfdesc > MAXCLIENTS)
- {
- lastfdesc = MAXCLIENTS;
- if (debug_conns)
- ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
- }
- MaxClients = lastfdesc;
- #ifdef DEBUG
- ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
- #endif
- ConnectionTranslation = (int *)malloc(sizeof(int)*(lastfdesc + 1));
- }
- /*****************
- * CreateWellKnownSockets
- * At initialization, create the sockets to listen on for new clients.
- *****************/
- void
- CreateWellKnownSockets(void)
- {
- int i;
- int partial;
- char port[20];
- OsSigHandlerPtr handler;
- FD_ZERO(&AllSockets);
- FD_ZERO(&AllClients);
- FD_ZERO(&LastSelectMask);
- FD_ZERO(&ClientsWithInput);
- for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
- FD_ZERO (&WellKnownConnections);
- sprintf (port, "%d", atoi (display));
- if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
- &ListenTransCount, &ListenTransConns) >= 0) &&
- (ListenTransCount >= 1))
- {
- if (!PartialNetwork && partial)
- {
- FatalError ("Failed to establish all listening sockets");
- }
- else
- {
- ListenTransFds = malloc(ListenTransCount * sizeof (int));
- for (i = 0; i < ListenTransCount; i++)
- {
- int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
- ListenTransFds[i] = fd;
- FD_SET (fd, &WellKnownConnections);
- if (!_XSERVTransIsLocal (ListenTransConns[i]))
- {
- DefineSelf (fd);
- }
- }
- }
- }
- if (!XFD_ANYSET (&WellKnownConnections))
- FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
- OsSignal (SIGPIPE, SIG_IGN);
- OsSignal (SIGHUP, AutoResetServer);
- OsSignal (SIGINT, GiveUp);
- OsSignal (SIGTERM, GiveUp);
- XFD_COPYSET (&WellKnownConnections, &AllSockets);
- ResetHosts(display);
- /*
- * Magic: If SIGUSR1 was set to SIG_IGN when
- * the server started, assume that either
- *
- * a- The parent process is ignoring SIGUSR1
- *
- * or
- *
- * b- The parent process is expecting a SIGUSR1
- * when the server is ready to accept connections
- *
- * In the first case, the signal will be harmless,
- * in the second case, the signal will be quite
- * useful
- */
- handler = OsSignal (SIGUSR1, SIG_IGN);
- if ( handler == SIG_IGN)
- RunFromSmartParent = TRUE;
- OsSignal(SIGUSR1, handler);
- ParentProcess = getppid ();
- if (RunFromSmartParent) {
- if (ParentProcess > 1) {
- kill (ParentProcess, SIGUSR1);
- }
- }
- #ifdef XDMCP
- XdmcpInit ();
- #endif
- }
- void
- ResetWellKnownSockets (void)
- {
- int i;
- ResetOsBuffers();
- for (i = 0; i < ListenTransCount; i++)
- {
- int status = _XSERVTransResetListener (ListenTransConns[i]);
- if (status != TRANS_RESET_NOOP)
- {
- if (status == TRANS_RESET_FAILURE)
- {
- /*
- * ListenTransConns[i] freed by xtrans.
- * Remove it from out list.
- */
- FD_CLR (ListenTransFds[i], &WellKnownConnections);
- ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
- ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
- ListenTransCount -= 1;
- i -= 1;
- }
- else if (status == TRANS_RESET_NEW_FD)
- {
- /*
- * A new file descriptor was allocated (the old one was closed)
- */
- int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
- FD_CLR (ListenTransFds[i], &WellKnownConnections);
- ListenTransFds[i] = newfd;
- FD_SET(newfd, &WellKnownConnections);
- }
- }
- }
- ResetAuthorization ();
- ResetHosts(display);
- /*
- * See above in CreateWellKnownSockets about SIGUSR1
- */
- if (RunFromSmartParent) {
- if (ParentProcess > 1) {
- kill (ParentProcess, SIGUSR1);
- }
- }
- /*
- * restart XDMCP
- */
- #ifdef XDMCP
- XdmcpReset ();
- #endif
- }
- void
- CloseWellKnownConnections(void)
- {
- int i;
- for (i = 0; i < ListenTransCount; i++)
- _XSERVTransClose (ListenTransConns[i]);
- }
- static void
- AuthAudit (ClientPtr client, Bool letin,
- struct sockaddr *saddr, int len,
- unsigned int proto_n, char *auth_proto, int auth_id)
- {
- char addr[128];
- char *out = addr;
- int client_uid;
- char client_uid_string[64];
- #ifdef HAS_GETPEERUCRED
- ucred_t *peercred = NULL;
- pid_t client_pid = -1;
- zoneid_t client_zid = -1;
- #endif
- if (!len)
- strcpy(out, "local host");
- else
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
- #if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
- #endif
- strcpy(out, "local host");
- break;
- #if defined(TCPCONN)
- case AF_INET:
- sprintf(out, "IP %s",
- inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
- break;
- #if defined(IPv6) && defined(AF_INET6)
- case AF_INET6: {
- char ipaddr[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
- ipaddr, sizeof(ipaddr));
- sprintf(out, "IP %s", ipaddr);
- }
- break;
- #endif
- #endif
- default:
- strcpy(out, "unknown address");
- }
- #ifdef HAS_GETPEERUCRED
- if (getpeerucred(((OsCommPtr)client->osPrivate)->fd, &peercred) >= 0) {
- client_uid = ucred_geteuid(peercred);
- client_pid = ucred_getpid(peercred);
- client_zid = ucred_getzoneid(peercred);
- ucred_free(peercred);
- snprintf(client_uid_string, sizeof(client_uid_string),
- " (uid %ld, pid %ld, zone %ld)",
- (long) client_uid, (long) client_pid, (long) client_zid);
- }
- #else
- if (LocalClientCred(client, &client_uid, NULL) != -1) {
- snprintf(client_uid_string, sizeof(client_uid_string),
- " (uid %d)", client_uid);
- }
- #endif
- else {
- client_uid_string[0] = '\0';
- }
- if (proto_n)
- AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
- client->index, letin ? "connected" : "rejected", addr,
- client_uid_string, (int)proto_n, auth_proto, auth_id);
- else
- AuditF("client %d %s from %s%s\n",
- client->index, letin ? "connected" : "rejected", addr,
- client_uid_string);
- }
- /*****************************************************************
- * ClientAuthorized
- *
- * Sent by the client at connection setup:
- * typedef struct _xConnClientPrefix {
- * CARD8 byteOrder;
- * BYTE pad;
- * CARD16 majorVersion, minorVersion;
- * CARD16 nbytesAuthProto;
- * CARD16 nbytesAuthString;
- * } xConnClientPrefix;
- *
- * It is hoped that eventually one protocol will be agreed upon. In the
- * mean time, a server that implements a different protocol than the
- * client expects, or a server that only implements the host-based
- * mechanism, will simply ignore this information.
- *
- *****************************************************************/
- const char *
- ClientAuthorized(ClientPtr client,
- unsigned int proto_n, char *auth_proto,
- unsigned int string_n, char *auth_string)
- {
- OsCommPtr priv;
- Xtransaddr *from = NULL;
- int family;
- int fromlen;
- XID auth_id;
- const char *reason = NULL;
- XtransConnInfo trans_conn;
- priv = (OsCommPtr)client->osPrivate;
- trans_conn = priv->trans_conn;
- auth_id = CheckAuthorization (proto_n, auth_proto,
- string_n, auth_string, client, &reason);
- if (auth_id == (XID) ~0L)
- {
- if (
- _XSERVTransGetPeerAddr (trans_conn,
- &family, &fromlen, &from) != -1)
- {
- if (InvalidHost ((struct sockaddr *) from, fromlen, client))
- AuthAudit(client, FALSE, (struct sockaddr *) from,
- fromlen, proto_n, auth_proto, auth_id);
- else
- {
- auth_id = (XID) 0;
- if (auditTrailLevel > 1)
- AuthAudit(client, TRUE,
- (struct sockaddr *) from, fromlen,
- proto_n, auth_proto, auth_id);
- }
- free((char *) from);
- }
- if (auth_id == (XID) ~0L) {
- if (reason)
- return reason;
- else
- return "Client is not authorized to connect to Server";
- }
- }
- else if (auditTrailLevel > 1)
- {
- if (_XSERVTransGetPeerAddr (trans_conn,
- &family, &fromlen, &from) != -1)
- {
- AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
- proto_n, auth_proto, auth_id);
- free((char *) from);
- }
- }
- priv->auth_id = auth_id;
- priv->conn_time = 0;
- #ifdef XDMCP
- /* indicate to Xdmcp protocol that we've opened new client */
- XdmcpOpenDisplay(priv->fd);
- #endif /* XDMCP */
- /* At this point, if the client is authorized to change the access control
- * list, we should getpeername() information, and add the client to
- * the selfhosts list. It's not really the host machine, but the
- * true purpose of the selfhosts list is to see who may change the
- * access control list.
- */
- return((char *)NULL);
- }
- static ClientPtr
- AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
- {
- OsCommPtr oc;
- ClientPtr client;
- if (
- fd >= lastfdesc
- )
- return NullClient;
- oc = (OsCommPtr)malloc(sizeof(OsCommRec));
- if (!oc)
- return NullClient;
- oc->trans_conn = trans_conn;
- oc->fd = fd;
- oc->input = (ConnectionInputPtr)NULL;
- oc->output = (ConnectionOutputPtr)NULL;
- oc->auth_id = None;
- oc->conn_time = conn_time;
- if (!(client = NextAvailableClient((pointer)oc)))
- {
- free(oc);
- return NullClient;
- }
- ConnectionTranslation[fd] = client->index;
- if (GrabInProgress)
- {
- FD_SET(fd, &SavedAllClients);
- FD_SET(fd, &SavedAllSockets);
- }
- else
- {
- FD_SET(fd, &AllClients);
- FD_SET(fd, &AllSockets);
- }
- #ifdef DEBUG
- ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
- client->index, fd);
- #endif
- return client;
- }
- /*****************
- * EstablishNewConnections
- * If anyone is waiting on listened sockets, accept them.
- * Returns a mask with indices of new clients. Updates AllClients
- * and AllSockets.
- *****************/
- /*ARGSUSED*/
- Bool
- EstablishNewConnections(ClientPtr clientUnused, pointer closure)
- {
- fd_set readyconnections; /* set of listeners that are ready */
- int curconn; /* fd of listener that's ready */
- int newconn; /* fd of new client */
- CARD32 connect_time;
- int i;
- ClientPtr client;
- OsCommPtr oc;
- fd_set tmask;
- XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
- XFD_COPYSET(&tmask, &readyconnections);
- if (!XFD_ANYSET(&readyconnections))
- return TRUE;
- connect_time = GetTimeInMillis();
- /* kill off stragglers */
- for (i=1; i<currentMaxClients; i++)
- {
- if ((client = clients[i]))
- {
- oc = (OsCommPtr)(client->osPrivate);
- if ((oc && (oc->conn_time != 0) &&
- (connect_time - oc->conn_time) >= TimeOutValue) ||
- (client->noClientException != Success && !client->clientGone))
- CloseDownClient(client);
- }
- }
- for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- while (readyconnections.fds_bits[i])
- {
- XtransConnInfo trans_conn, new_trans_conn;
- int status;
- curconn = ffs (readyconnections.fds_bits[i]) - 1;
- readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
- curconn += (i * (sizeof(fd_mask)*8));
- if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
- continue;
- if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
- continue;
- newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
- if (newconn < lastfdesc)
- {
- int clientid;
- clientid = ConnectionTranslation[newconn];
- if(clientid && (client = clients[clientid]))
- CloseDownClient(client);
- }
- _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
- if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
- {
- ErrorConnMax(new_trans_conn);
- _XSERVTransClose(new_trans_conn);
- }
- }
- }
- return TRUE;
- }
- #define NOROOM "Maximum number of clients reached"
- /************
- * ErrorConnMax
- * Fail a connection due to lack of client or file descriptor space
- ************/
- static void
- ErrorConnMax(XtransConnInfo trans_conn)
- {
- int fd = _XSERVTransGetConnectionNumber (trans_conn);
- xConnSetupPrefix csp;
- char pad[3];
- struct iovec iov[3];
- char byteOrder = 0;
- int whichbyte = 1;
- struct timeval waittime;
- fd_set mask;
- /* if these seems like a lot of trouble to go to, it probably is */
- waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
- waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
- (1000000 / MILLI_PER_SECOND);
- FD_ZERO(&mask);
- FD_SET(fd, &mask);
- (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
- /* try to read the byte-order of the connection */
- (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
- if ((byteOrder == 'l') || (byteOrder == 'B'))
- {
- csp.success = xFalse;
- csp.lengthReason = sizeof(NOROOM) - 1;
- csp.length = (sizeof(NOROOM) + 2) >> 2;
- csp.majorVersion = X_PROTOCOL;
- csp.minorVersion = X_PROTOCOL_REVISION;
- if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
- (!(*(char *) &whichbyte) && (byteOrder == 'l')))
- {
- swaps(&csp.majorVersion);
- swaps(&csp.minorVersion);
- swaps(&csp.length);
- }
- iov[0].iov_len = sz_xConnSetupPrefix;
- iov[0].iov_base = (char *) &csp;
- iov[1].iov_len = csp.lengthReason;
- iov[1].iov_base = NOROOM;
- iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
- iov[2].iov_base = pad;
- (void)_XSERVTransWritev(trans_conn, iov, 3);
- }
- }
- /************
- * CloseDownFileDescriptor:
- * Remove this file descriptor and it's I/O buffers, etc.
- ************/
- static void
- CloseDownFileDescriptor(OsCommPtr oc)
- {
- int connection = oc->fd;
- if (oc->trans_conn) {
- _XSERVTransDisconnect(oc->trans_conn);
- _XSERVTransClose(oc->trans_conn);
- }
- ConnectionTranslation[connection] = 0;
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- FD_CLR(connection, &ClientsWithInput);
- FD_CLR(connection, &GrabImperviousClients);
- if (GrabInProgress)
- {
- FD_CLR(connection, &SavedAllSockets);
- FD_CLR(connection, &SavedAllClients);
- FD_CLR(connection, &SavedClientsWithInput);
- }
- FD_CLR(connection, &ClientsWriteBlocked);
- if (!XFD_ANYSET(&ClientsWriteBlocked))
- AnyClientsWriteBlocked = FALSE;
- FD_CLR(connection, &OutputPending);
- }
- /*****************
- * CheckConnections
- * Some connection has died, go find which one and shut it down
- * The file descriptor has been closed, but is still in AllClients.
- * If would truly be wonderful if select() would put the bogus
- * file descriptors in the exception mask, but nooooo. So we have
- * to check each and every socket individually.
- *****************/
- void
- CheckConnections(void)
- {
- fd_mask mask;
- fd_set tmask;
- int curclient, curoff;
- int i;
- struct timeval notime;
- int r;
- notime.tv_sec = 0;
- notime.tv_usec = 0;
- for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- mask = AllClients.fds_bits[i];
- while (mask)
- {
- curoff = ffs (mask) - 1;
- curclient = curoff + (i * (sizeof(fd_mask)*8));
- FD_ZERO(&tmask);
- FD_SET(curclient, &tmask);
- r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
- if (r < 0)
- CloseDownClient(clients[ConnectionTranslation[curclient]]);
- mask &= ~((fd_mask)1 << curoff);
- }
- }
- }
- static void FreeOsBuffers(OsCommPtr oc) {
- ConnectionInputPtr oci;
- ConnectionOutputPtr oco;
- if (AvailableInput == oc)
- AvailableInput = (OsCommPtr)NULL;
- if ((oci = oc->input)) {
- if (FreeInputs) {
- free(oci->buffer);
- free(oci);
- } else {
- FreeInputs = oci;
- oci->next = (ConnectionInputPtr)NULL;
- oci->bufptr = oci->buffer;
- oci->bufcnt = 0;
- oci->lenLastReq = 0;
- }
- }
- if ((oco = oc->output)) {
- if (FreeOutputs) {
- free(oco->buf);
- free(oco);
- } else {
- FreeOutputs = oco;
- oco->next = (ConnectionOutputPtr)NULL;
- oco->count = 0;
- }
- }
- }
- /*****************
- * CloseDownConnection
- * Delete client from AllClients and free resources
- *****************/
- void
- CloseDownConnection(ClientPtr client)
- {
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- if (oc->output && oc->output->count)
- FlushClient(client, oc, (char *)NULL, 0);
- #ifdef XDMCP
- XdmcpCloseDisplay(oc->fd);
- #endif
- CloseDownFileDescriptor(oc);
- FreeOsBuffers(oc);
- client->osPrivate = (pointer)NULL;
- if (auditTrailLevel > 1)
- AuditF("client %d disconnected\n", client->index);
- free(oc);
- }
- _X_EXPORT void
- AddGeneralSocket(int fd)
- {
- FD_SET(fd, &AllSockets);
- if (GrabInProgress)
- FD_SET(fd, &SavedAllSockets);
- }
- _X_EXPORT void
- AddEnabledDevice(int fd)
- {
- FD_SET(fd, &EnabledDevices);
- AddGeneralSocket(fd);
- }
- _X_EXPORT void
- RemoveGeneralSocket(int fd)
- {
- FD_CLR(fd, &AllSockets);
- if (GrabInProgress)
- FD_CLR(fd, &SavedAllSockets);
- }
- _X_EXPORT void
- RemoveEnabledDevice(int fd)
- {
- FD_CLR(fd, &EnabledDevices);
- RemoveGeneralSocket(fd);
- }
- /*****************
- * OnlyListenToOneClient:
- * Only accept requests from one client. Continue to handle new
- * connections, but don't take any protocol requests from the new
- * ones. Note that if GrabInProgress is set, EstablishNewConnections
- * needs to put new clients into SavedAllSockets and SavedAllClients.
- * Note also that there is no timeout for this in the protocol.
- * This routine is "undone" by ListenToAllClients()
- *****************/
- void
- OnlyListenToOneClient(ClientPtr client)
- {
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
- if (! GrabInProgress)
- {
- XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
- XFD_ANDSET(&ClientsWithInput,
- &ClientsWithInput, &GrabImperviousClients);
- if (FD_ISSET(connection, &SavedClientsWithInput))
- {
- FD_CLR(connection, &SavedClientsWithInput);
- FD_SET(connection, &ClientsWithInput);
- }
- XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
- XFD_COPYSET(&AllSockets, &SavedAllSockets);
- XFD_COPYSET(&AllClients, &SavedAllClients);
- XFD_UNSET(&AllSockets, &AllClients);
- XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
- FD_SET(connection, &AllClients);
- XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
- GrabInProgress = client->index;
- }
- }
- /****************
- * ListenToAllClients:
- * Undoes OnlyListentToOneClient()
- ****************/
- void
- ListenToAllClients(void)
- {
- if (GrabInProgress)
- {
- XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
- XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
- XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
- GrabInProgress = 0;
- }
- }
- /****************
- * IgnoreClient
- * Removes one client from input masks.
- * Must have cooresponding call to AttendClient.
- ****************/
- _X_EXPORT void
- IgnoreClient (ClientPtr client)
- {
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
- isItTimeToYield = TRUE;
- if (!GrabInProgress || FD_ISSET(connection, &AllClients))
- {
- if (FD_ISSET (connection, &ClientsWithInput))
- FD_SET(connection, &IgnoredClientsWithInput);
- else
- FD_CLR(connection, &IgnoredClientsWithInput);
- FD_CLR(connection, &ClientsWithInput);
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- FD_CLR(connection, &LastSelectMask);
- }
- else
- {
- if (FD_ISSET (connection, &SavedClientsWithInput))
- FD_SET(connection, &IgnoredClientsWithInput);
- else
- FD_CLR(connection, &IgnoredClientsWithInput);
- FD_CLR(connection, &SavedClientsWithInput);
- FD_CLR(connection, &SavedAllSockets);
- FD_CLR(connection, &SavedAllClients);
- }
- }
- /****************
- * AttendClient
- * Adds one client back into the input masks.
- ****************/
- _X_EXPORT void
- AttendClient (ClientPtr client)
- {
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
- if (!GrabInProgress || GrabInProgress == client->index ||
- FD_ISSET(connection, &GrabImperviousClients))
- {
- FD_SET(connection, &AllClients);
- FD_SET(connection, &AllSockets);
- FD_SET(connection, &LastSelectMask);
- if (FD_ISSET (connection, &IgnoredClientsWithInput))
- FD_SET(connection, &ClientsWithInput);
- }
- else
- {
- FD_SET(connection, &SavedAllClients);
- FD_SET(connection, &SavedAllSockets);
- if (FD_ISSET(connection, &IgnoredClientsWithInput))
- FD_SET(connection, &SavedClientsWithInput);
- }
- }
- /* make client impervious to grabs; assume only executing client calls this */
- _X_EXPORT void
- MakeClientGrabImpervious(ClientPtr client)
- {
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
- FD_SET(connection, &GrabImperviousClients);
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = CLIENT_IMPERVIOUS;
- CallCallbacks(&ServerGrabCallback, &grabinfo);
- }
- }
- /* make client pervious to grabs; assume only executing client calls this */
- _X_EXPORT void
- MakeClientGrabPervious(ClientPtr client)
- {
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
- FD_CLR(connection, &GrabImperviousClients);
- if (GrabInProgress && (GrabInProgress != client->index))
- {
- if (FD_ISSET(connection, &ClientsWithInput))
- {
- FD_SET(connection, &SavedClientsWithInput);
- FD_CLR(connection, &ClientsWithInput);
- }
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- isItTimeToYield = TRUE;
- }
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = CLIENT_PERVIOUS;
- CallCallbacks(&ServerGrabCallback, &grabinfo);
- }
- }
|