connection.c revision 4e185dc0
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 2505b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 29f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its 30f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 32f7df2e56Smrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 35f7df2e56Smrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg******************************************************************/ 4605b261ecSmrg/***************************************************************** 4705b261ecSmrg * Stuff to create connections --- OS dependent 4805b261ecSmrg * 4905b261ecSmrg * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets, 507e31ba66Smrg * CloseDownConnection, 517e31ba66Smrg * OnlyListToOneClient, 5205b261ecSmrg * ListenToAllClients, 5305b261ecSmrg * 5405b261ecSmrg * (WaitForSomething is in its own file) 5505b261ecSmrg * 5605b261ecSmrg * In this implementation, a client socket table is not kept. 5705b261ecSmrg * Instead, what would be the index into the table is just the 5805b261ecSmrg * file descriptor of the socket. This won't work for if the 5905b261ecSmrg * socket ids aren't small nums (0 - 2^8) 6005b261ecSmrg * 6105b261ecSmrg *****************************************************************/ 6205b261ecSmrg 635bd42952Smrg#include <X11/Xpoll.h> 645bd42952Smrg 6505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 6605b261ecSmrg#include <dix-config.h> 6705b261ecSmrg#endif 6805b261ecSmrg 6905b261ecSmrg#ifdef WIN32 7005b261ecSmrg#include <X11/Xwinsock.h> 7105b261ecSmrg#endif 7205b261ecSmrg#include <X11/X.h> 7305b261ecSmrg#include <X11/Xproto.h> 7405b261ecSmrg#define XSERV_t 7505b261ecSmrg#define TRANS_SERVER 7605b261ecSmrg#define TRANS_REOPEN 7705b261ecSmrg#include <X11/Xtrans/Xtrans.h> 784642e01fSmrg#include <X11/Xtrans/Xtransint.h> 7905b261ecSmrg#include <errno.h> 8005b261ecSmrg#include <signal.h> 8105b261ecSmrg#include <stdio.h> 8205b261ecSmrg#include <stdlib.h> 8305b261ecSmrg 8405b261ecSmrg#ifndef WIN32 8505b261ecSmrg#include <sys/socket.h> 8605b261ecSmrg 877e31ba66Smrg#if defined(TCPCONN) 88f7df2e56Smrg#include <netinet/in.h> 89f7df2e56Smrg#include <arpa/inet.h> 90f7df2e56Smrg#ifdef apollo 91f7df2e56Smrg#ifndef NO_TCP_H 92f7df2e56Smrg#include <netinet/tcp.h> 93f7df2e56Smrg#endif 94f7df2e56Smrg#else 95f7df2e56Smrg#ifdef CSRG_BASED 96f7df2e56Smrg#include <sys/param.h> 97f7df2e56Smrg#endif 98f7df2e56Smrg#include <netinet/tcp.h> 99f7df2e56Smrg#endif 100f7df2e56Smrg#include <arpa/inet.h> 10105b261ecSmrg#endif 10205b261ecSmrg 10305b261ecSmrg#include <sys/uio.h> 1044642e01fSmrg 105f7df2e56Smrg#endif /* WIN32 */ 106f7df2e56Smrg#include "misc.h" /* for typedef of pointer */ 10705b261ecSmrg#include "osdep.h" 10805b261ecSmrg#include "opaque.h" 10905b261ecSmrg#include "dixstruct.h" 11005b261ecSmrg#include "xace.h" 11105b261ecSmrg 11205b261ecSmrg#define Pid_t pid_t 11305b261ecSmrg 114f7df2e56Smrg#ifdef HAVE_GETPEERUCRED 115f7df2e56Smrg#include <ucred.h> 116f7df2e56Smrg#include <zone.h> 117f7df2e56Smrg#else 118f7df2e56Smrg#define zoneid_t int 11905b261ecSmrg#endif 12005b261ecSmrg 121f7df2e56Smrg#include "probes.h" 12205b261ecSmrg 1237e31ba66Smrgstruct ospoll *server_poll; 12405b261ecSmrg 12505b261ecSmrgint MaxClients = 0; 126f7df2e56SmrgBool NewOutputPending; /* not yet attempted to write some new output */ 127f7df2e56SmrgBool NoListenAll; /* Don't establish any listening sockets */ 128f7df2e56Smrg 129f7df2e56Smrgstatic Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ 130f7df2e56SmrgBool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or 131f7df2e56Smrg equivalent) will send SIGCONT back. */ 132f7df2e56Smrgstatic char dynamic_display[7]; /* display name */ 133f7df2e56SmrgBool PartialNetwork; /* continue even if unable to bind all addrs */ 13405b261ecSmrgstatic Pid_t ParentProcess; 13505b261ecSmrg 1366747b715Smrgint GrabInProgress = 0; 13705b261ecSmrg 1387e31ba66Smrgstatic void 1397e31ba66SmrgQueueNewConnections(int curconn, int ready, void *data); 140f7df2e56Smrg 1417e31ba66Smrgstatic void 1427e31ba66Smrgset_poll_client(ClientPtr client); 143f7df2e56Smrg 1447e31ba66Smrgstatic void 1457e31ba66Smrgset_poll_clients(void); 14605b261ecSmrg 147f7df2e56Smrgstatic XtransConnInfo *ListenTransConns = NULL; 148f7df2e56Smrgstatic int *ListenTransFds = NULL; 149f7df2e56Smrgstatic int ListenTransCount; 15005b261ecSmrg 151f7df2e56Smrgstatic void ErrorConnMax(XtransConnInfo /* trans_conn */ ); 15205b261ecSmrg 15305b261ecSmrgstatic XtransConnInfo 154f7df2e56Smrglookup_trans_conn(int fd) 15505b261ecSmrg{ 156f7df2e56Smrg if (ListenTransFds) { 157f7df2e56Smrg int i; 158f7df2e56Smrg 159f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) 160f7df2e56Smrg if (ListenTransFds[i] == fd) 161f7df2e56Smrg return ListenTransConns[i]; 16205b261ecSmrg } 16305b261ecSmrg 1646747b715Smrg return NULL; 16505b261ecSmrg} 16605b261ecSmrg 1677e31ba66Smrg/* Set MaxClients */ 16805b261ecSmrg 16905b261ecSmrgvoid 17005b261ecSmrgInitConnectionLimits(void) 17105b261ecSmrg{ 1727e31ba66Smrg MaxClients = MAXCLIENTS; 17305b261ecSmrg 17405b261ecSmrg#ifdef DEBUG 17505b261ecSmrg ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients); 17605b261ecSmrg#endif 17705b261ecSmrg} 17805b261ecSmrg 1794642e01fSmrg/* 1804642e01fSmrg * If SIGUSR1 was set to SIG_IGN when the server started, assume that either 1814642e01fSmrg * 1824642e01fSmrg * a- The parent process is ignoring SIGUSR1 1834642e01fSmrg * 1844642e01fSmrg * or 1854642e01fSmrg * 1864642e01fSmrg * b- The parent process is expecting a SIGUSR1 1874642e01fSmrg * when the server is ready to accept connections 1884642e01fSmrg * 1894642e01fSmrg * In the first case, the signal will be harmless, in the second case, 1904642e01fSmrg * the signal will be quite useful. 1914642e01fSmrg */ 1924642e01fSmrgstatic void 1934642e01fSmrgInitParentProcess(void) 1944642e01fSmrg{ 1954642e01fSmrg#if !defined(WIN32) 1964642e01fSmrg OsSigHandlerPtr handler; 197f7df2e56Smrg 198f7df2e56Smrg handler = OsSignal(SIGUSR1, SIG_IGN); 199f7df2e56Smrg if (handler == SIG_IGN) 200f7df2e56Smrg RunFromSmartParent = TRUE; 2014642e01fSmrg OsSignal(SIGUSR1, handler); 202f7df2e56Smrg ParentProcess = getppid(); 2034642e01fSmrg#endif 2044642e01fSmrg} 2054642e01fSmrg 2064642e01fSmrgvoid 2074642e01fSmrgNotifyParentProcess(void) 2084642e01fSmrg{ 2094642e01fSmrg#if !defined(WIN32) 210f7df2e56Smrg if (displayfd >= 0) { 211f7df2e56Smrg if (write(displayfd, display, strlen(display)) != strlen(display)) 212f7df2e56Smrg FatalError("Cannot write display number to fd %d\n", displayfd); 213f7df2e56Smrg if (write(displayfd, "\n", 1) != 1) 214f7df2e56Smrg FatalError("Cannot write display number to fd %d\n", displayfd); 215f7df2e56Smrg close(displayfd); 216f7df2e56Smrg displayfd = -1; 217f7df2e56Smrg } 2184642e01fSmrg if (RunFromSmartParent) { 219f7df2e56Smrg if (ParentProcess > 1) { 220f7df2e56Smrg kill(ParentProcess, SIGUSR1); 221f7df2e56Smrg } 2224642e01fSmrg } 2239ace9065Smrg if (RunFromSigStopParent) 224f7df2e56Smrg raise(SIGSTOP); 2254642e01fSmrg#endif 2264642e01fSmrg} 22705b261ecSmrg 228f7df2e56Smrgstatic Bool 229f7df2e56SmrgTryCreateSocket(int num, int *partial) 230f7df2e56Smrg{ 231f7df2e56Smrg char port[20]; 232f7df2e56Smrg 233f7df2e56Smrg snprintf(port, sizeof(port), "%d", num); 234f7df2e56Smrg 235f7df2e56Smrg return (_XSERVTransMakeAllCOTSServerListeners(port, partial, 236f7df2e56Smrg &ListenTransCount, 237f7df2e56Smrg &ListenTransConns) >= 0); 238f7df2e56Smrg} 239f7df2e56Smrg 24005b261ecSmrg/***************** 24105b261ecSmrg * CreateWellKnownSockets 24205b261ecSmrg * At initialization, create the sockets to listen on for new clients. 24305b261ecSmrg *****************/ 24405b261ecSmrg 24505b261ecSmrgvoid 24605b261ecSmrgCreateWellKnownSockets(void) 24705b261ecSmrg{ 248f7df2e56Smrg int i; 249f7df2e56Smrg int partial; 25005b261ecSmrg 251f7df2e56Smrg /* display is initialized to "0" by main(). It is then set to the display 252f7df2e56Smrg * number if specified on the command line. */ 25305b261ecSmrg 254f7df2e56Smrg if (NoListenAll) { 255f7df2e56Smrg ListenTransCount = 0; 256f7df2e56Smrg } 257f7df2e56Smrg else if ((displayfd < 0) || explicit_display) { 258f7df2e56Smrg if (TryCreateSocket(atoi(display), &partial) && 259f7df2e56Smrg ListenTransCount >= 1) 260f7df2e56Smrg if (!PartialNetwork && partial) 261f7df2e56Smrg FatalError ("Failed to establish all listening sockets"); 262f7df2e56Smrg } 263f7df2e56Smrg else { /* -displayfd and no explicit display number */ 264f7df2e56Smrg Bool found = 0; 265f7df2e56Smrg for (i = 0; i < 65536 - X_TCP_PORT; i++) { 266f7df2e56Smrg if (TryCreateSocket(i, &partial) && !partial) { 267f7df2e56Smrg found = 1; 268f7df2e56Smrg break; 269f7df2e56Smrg } 270f7df2e56Smrg else 271f7df2e56Smrg CloseWellKnownConnections(); 272f7df2e56Smrg } 273f7df2e56Smrg if (!found) 274f7df2e56Smrg FatalError("Failed to find a socket to listen on"); 275f7df2e56Smrg snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); 276f7df2e56Smrg display = dynamic_display; 277f7df2e56Smrg LogSetDisplay(); 278f7df2e56Smrg } 279f7df2e56Smrg 280f7df2e56Smrg ListenTransFds = xallocarray(ListenTransCount, sizeof (int)); 281f7df2e56Smrg if (ListenTransFds == NULL) 282f7df2e56Smrg FatalError ("Failed to create listening socket array"); 283f7df2e56Smrg 284f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 285f7df2e56Smrg int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); 286f7df2e56Smrg 287f7df2e56Smrg ListenTransFds[i] = fd; 2887e31ba66Smrg SetNotifyFd(fd, QueueNewConnections, X_NOTIFY_READ, NULL); 289f7df2e56Smrg 290f7df2e56Smrg if (!_XSERVTransIsLocal(ListenTransConns[i])) 291f7df2e56Smrg DefineSelf (fd); 29205b261ecSmrg } 29305b261ecSmrg 2947e31ba66Smrg if (ListenTransCount == 0 && !NoListenAll) 295f7df2e56Smrg FatalError 296f7df2e56Smrg ("Cannot establish any listening sockets - Make sure an X server isn't already running"); 297f7df2e56Smrg 29805b261ecSmrg#if !defined(WIN32) 299f7df2e56Smrg OsSignal(SIGPIPE, SIG_IGN); 300f7df2e56Smrg OsSignal(SIGHUP, AutoResetServer); 30105b261ecSmrg#endif 302f7df2e56Smrg OsSignal(SIGINT, GiveUp); 303f7df2e56Smrg OsSignal(SIGTERM, GiveUp); 30405b261ecSmrg ResetHosts(display); 3054642e01fSmrg 3064642e01fSmrg InitParentProcess(); 3074642e01fSmrg 30805b261ecSmrg#ifdef XDMCP 309f7df2e56Smrg XdmcpInit(); 31005b261ecSmrg#endif 31105b261ecSmrg} 31205b261ecSmrg 31305b261ecSmrgvoid 314f7df2e56SmrgResetWellKnownSockets(void) 31505b261ecSmrg{ 31605b261ecSmrg int i; 31705b261ecSmrg 31805b261ecSmrg ResetOsBuffers(); 31905b261ecSmrg 320f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 321f7df2e56Smrg int status = _XSERVTransResetListener(ListenTransConns[i]); 322f7df2e56Smrg 323f7df2e56Smrg if (status != TRANS_RESET_NOOP) { 324f7df2e56Smrg if (status == TRANS_RESET_FAILURE) { 325f7df2e56Smrg /* 326f7df2e56Smrg * ListenTransConns[i] freed by xtrans. 327f7df2e56Smrg * Remove it from out list. 328f7df2e56Smrg */ 329f7df2e56Smrg 3307e31ba66Smrg RemoveNotifyFd(ListenTransFds[i]); 331f7df2e56Smrg ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; 332f7df2e56Smrg ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; 333f7df2e56Smrg ListenTransCount -= 1; 334f7df2e56Smrg i -= 1; 335f7df2e56Smrg } 336f7df2e56Smrg else if (status == TRANS_RESET_NEW_FD) { 337f7df2e56Smrg /* 338f7df2e56Smrg * A new file descriptor was allocated (the old one was closed) 339f7df2e56Smrg */ 340f7df2e56Smrg 341f7df2e56Smrg int newfd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); 342f7df2e56Smrg 343f7df2e56Smrg ListenTransFds[i] = newfd; 344f7df2e56Smrg } 345f7df2e56Smrg } 34605b261ecSmrg } 3477e31ba66Smrg for (i = 0; i < ListenTransCount; i++) 3487e31ba66Smrg SetNotifyFd(ListenTransFds[i], QueueNewConnections, X_NOTIFY_READ, NULL); 34905b261ecSmrg 350f7df2e56Smrg ResetAuthorization(); 35105b261ecSmrg ResetHosts(display); 35205b261ecSmrg /* 35305b261ecSmrg * restart XDMCP 35405b261ecSmrg */ 35505b261ecSmrg#ifdef XDMCP 356f7df2e56Smrg XdmcpReset(); 35705b261ecSmrg#endif 35805b261ecSmrg} 35905b261ecSmrg 36005b261ecSmrgvoid 36105b261ecSmrgCloseWellKnownConnections(void) 36205b261ecSmrg{ 36305b261ecSmrg int i; 36405b261ecSmrg 365f7df2e56Smrg for (i = 0; i < ListenTransCount; i++) { 366f7df2e56Smrg if (ListenTransConns[i] != NULL) { 367f7df2e56Smrg _XSERVTransClose(ListenTransConns[i]); 368f7df2e56Smrg ListenTransConns[i] = NULL; 3697e31ba66Smrg if (ListenTransFds != NULL) 3707e31ba66Smrg RemoveNotifyFd(ListenTransFds[i]); 371f7df2e56Smrg } 372f7df2e56Smrg } 373f7df2e56Smrg ListenTransCount = 0; 37405b261ecSmrg} 37505b261ecSmrg 37605b261ecSmrgstatic void 377f7df2e56SmrgAuthAudit(ClientPtr client, Bool letin, 378f7df2e56Smrg struct sockaddr *saddr, int len, 379f7df2e56Smrg unsigned int proto_n, char *auth_proto, int auth_id) 38005b261ecSmrg{ 38105b261ecSmrg char addr[128]; 38205b261ecSmrg char client_uid_string[64]; 3834642e01fSmrg LocalClientCredRec *lcc; 384f7df2e56Smrg 3854642e01fSmrg#ifdef XSERVER_DTRACE 38605b261ecSmrg pid_t client_pid = -1; 38705b261ecSmrg zoneid_t client_zid = -1; 38805b261ecSmrg#endif 38905b261ecSmrg 39005b261ecSmrg if (!len) 391f7df2e56Smrg strlcpy(addr, "local host", sizeof(addr)); 39205b261ecSmrg else 393f7df2e56Smrg switch (saddr->sa_family) { 394f7df2e56Smrg case AF_UNSPEC: 39505b261ecSmrg#if defined(UNIXCONN) || defined(LOCALCONN) 396f7df2e56Smrg case AF_UNIX: 39705b261ecSmrg#endif 398f7df2e56Smrg strlcpy(addr, "local host", sizeof(addr)); 399f7df2e56Smrg break; 4007e31ba66Smrg#if defined(TCPCONN) 401f7df2e56Smrg case AF_INET: 402f7df2e56Smrg snprintf(addr, sizeof(addr), "IP %s", 403f7df2e56Smrg inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); 404f7df2e56Smrg break; 40505b261ecSmrg#if defined(IPv6) && defined(AF_INET6) 406f7df2e56Smrg case AF_INET6:{ 407f7df2e56Smrg char ipaddr[INET6_ADDRSTRLEN]; 408f7df2e56Smrg 409f7df2e56Smrg inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, 410f7df2e56Smrg ipaddr, sizeof(ipaddr)); 411f7df2e56Smrg snprintf(addr, sizeof(addr), "IP %s", ipaddr); 412f7df2e56Smrg } 413f7df2e56Smrg break; 41405b261ecSmrg#endif 41505b261ecSmrg#endif 416f7df2e56Smrg default: 417f7df2e56Smrg strlcpy(addr, "unknown address", sizeof(addr)); 418f7df2e56Smrg } 41905b261ecSmrg 4204642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 421f7df2e56Smrg int slen; /* length written to client_uid_string */ 422f7df2e56Smrg 423f7df2e56Smrg strcpy(client_uid_string, " ( "); 424f7df2e56Smrg slen = 3; 425f7df2e56Smrg 426f7df2e56Smrg if (lcc->fieldsSet & LCC_UID_SET) { 427f7df2e56Smrg snprintf(client_uid_string + slen, 428f7df2e56Smrg sizeof(client_uid_string) - slen, 429f7df2e56Smrg "uid=%ld ", (long) lcc->euid); 430f7df2e56Smrg slen = strlen(client_uid_string); 431f7df2e56Smrg } 432f7df2e56Smrg 433f7df2e56Smrg if (lcc->fieldsSet & LCC_GID_SET) { 434f7df2e56Smrg snprintf(client_uid_string + slen, 435f7df2e56Smrg sizeof(client_uid_string) - slen, 436f7df2e56Smrg "gid=%ld ", (long) lcc->egid); 437f7df2e56Smrg slen = strlen(client_uid_string); 438f7df2e56Smrg } 439f7df2e56Smrg 440f7df2e56Smrg if (lcc->fieldsSet & LCC_PID_SET) { 441f7df2e56Smrg#ifdef XSERVER_DTRACE 442f7df2e56Smrg client_pid = lcc->pid; 44305b261ecSmrg#endif 444f7df2e56Smrg snprintf(client_uid_string + slen, 445f7df2e56Smrg sizeof(client_uid_string) - slen, 446f7df2e56Smrg "pid=%ld ", (long) lcc->pid); 447f7df2e56Smrg slen = strlen(client_uid_string); 448f7df2e56Smrg } 449f7df2e56Smrg 450f7df2e56Smrg if (lcc->fieldsSet & LCC_ZID_SET) { 4514642e01fSmrg#ifdef XSERVER_DTRACE 452f7df2e56Smrg client_zid = lcc->zoneid; 453f7df2e56Smrg#endif 454f7df2e56Smrg snprintf(client_uid_string + slen, 455f7df2e56Smrg sizeof(client_uid_string) - slen, 456f7df2e56Smrg "zoneid=%ld ", (long) lcc->zoneid); 457f7df2e56Smrg slen = strlen(client_uid_string); 458f7df2e56Smrg } 459f7df2e56Smrg 460f7df2e56Smrg snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, 461f7df2e56Smrg ")"); 462f7df2e56Smrg FreeLocalClientCreds(lcc); 4634642e01fSmrg } 46405b261ecSmrg else { 465f7df2e56Smrg client_uid_string[0] = '\0'; 46605b261ecSmrg } 467f7df2e56Smrg 46805b261ecSmrg#ifdef XSERVER_DTRACE 46905b261ecSmrg XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid); 47005b261ecSmrg#endif 4714642e01fSmrg if (auditTrailLevel > 1) { 472f7df2e56Smrg if (proto_n) 473f7df2e56Smrg AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", 474f7df2e56Smrg client->index, letin ? "connected" : "rejected", addr, 475f7df2e56Smrg client_uid_string, (int) proto_n, auth_proto, auth_id); 476f7df2e56Smrg else 477f7df2e56Smrg AuditF("client %d %s from %s%s\n", 478f7df2e56Smrg client->index, letin ? "connected" : "rejected", addr, 479f7df2e56Smrg client_uid_string); 48005b261ecSmrg 48105b261ecSmrg } 48205b261ecSmrg} 48305b261ecSmrg 48405b261ecSmrgXID 48505b261ecSmrgAuthorizationIDOfClient(ClientPtr client) 48605b261ecSmrg{ 48705b261ecSmrg if (client->osPrivate) 488f7df2e56Smrg return ((OsCommPtr) client->osPrivate)->auth_id; 48905b261ecSmrg else 490f7df2e56Smrg return None; 49105b261ecSmrg} 49205b261ecSmrg 49305b261ecSmrg/***************************************************************** 49405b261ecSmrg * ClientAuthorized 49505b261ecSmrg * 49605b261ecSmrg * Sent by the client at connection setup: 49705b261ecSmrg * typedef struct _xConnClientPrefix { 49805b261ecSmrg * CARD8 byteOrder; 49905b261ecSmrg * BYTE pad; 50005b261ecSmrg * CARD16 majorVersion, minorVersion; 501f7df2e56Smrg * CARD16 nbytesAuthProto; 502f7df2e56Smrg * CARD16 nbytesAuthString; 50305b261ecSmrg * } xConnClientPrefix; 50405b261ecSmrg * 50505b261ecSmrg * It is hoped that eventually one protocol will be agreed upon. In the 50605b261ecSmrg * mean time, a server that implements a different protocol than the 50705b261ecSmrg * client expects, or a server that only implements the host-based 50805b261ecSmrg * mechanism, will simply ignore this information. 50905b261ecSmrg * 51005b261ecSmrg *****************************************************************/ 51105b261ecSmrg 512f7df2e56Smrgconst char * 513f7df2e56SmrgClientAuthorized(ClientPtr client, 514f7df2e56Smrg unsigned int proto_n, char *auth_proto, 515f7df2e56Smrg unsigned int string_n, char *auth_string) 51605b261ecSmrg{ 517f7df2e56Smrg OsCommPtr priv; 518f7df2e56Smrg Xtransaddr *from = NULL; 519f7df2e56Smrg int family; 520f7df2e56Smrg int fromlen; 521f7df2e56Smrg XID auth_id; 522f7df2e56Smrg const char *reason = NULL; 523f7df2e56Smrg XtransConnInfo trans_conn; 524f7df2e56Smrg 525f7df2e56Smrg priv = (OsCommPtr) client->osPrivate; 52605b261ecSmrg trans_conn = priv->trans_conn; 52705b261ecSmrg 5284642e01fSmrg /* Allow any client to connect without authorization on a launchd socket, 5294642e01fSmrg because it is securely created -- this prevents a race condition on launch */ 530f7df2e56Smrg if (trans_conn->flags & TRANS_NOXAUTH) { 5314642e01fSmrg auth_id = (XID) 0L; 532f7df2e56Smrg } 533f7df2e56Smrg else { 534f7df2e56Smrg auth_id = 535f7df2e56Smrg CheckAuthorization(proto_n, auth_proto, string_n, auth_string, 536f7df2e56Smrg client, &reason); 5374642e01fSmrg } 53805b261ecSmrg 539f7df2e56Smrg if (auth_id == (XID) ~0L) { 540f7df2e56Smrg if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) { 541f7df2e56Smrg if (InvalidHost((struct sockaddr *) from, fromlen, client)) 542f7df2e56Smrg AuthAudit(client, FALSE, (struct sockaddr *) from, 543f7df2e56Smrg fromlen, proto_n, auth_proto, auth_id); 544f7df2e56Smrg else { 545f7df2e56Smrg auth_id = (XID) 0; 54605b261ecSmrg#ifdef XSERVER_DTRACE 547f7df2e56Smrg if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) 54805b261ecSmrg#else 549f7df2e56Smrg if (auditTrailLevel > 1) 55005b261ecSmrg#endif 551f7df2e56Smrg AuthAudit(client, TRUE, 552f7df2e56Smrg (struct sockaddr *) from, fromlen, 553f7df2e56Smrg proto_n, auth_proto, auth_id); 554f7df2e56Smrg } 555f7df2e56Smrg 556f7df2e56Smrg free(from); 557f7df2e56Smrg } 558f7df2e56Smrg 559f7df2e56Smrg if (auth_id == (XID) ~0L) { 560f7df2e56Smrg if (reason) 561f7df2e56Smrg return reason; 562f7df2e56Smrg else 563f7df2e56Smrg return "Client is not authorized to connect to Server"; 564f7df2e56Smrg } 56505b261ecSmrg } 56605b261ecSmrg#ifdef XSERVER_DTRACE 56705b261ecSmrg else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) 56805b261ecSmrg#else 56905b261ecSmrg else if (auditTrailLevel > 1) 57005b261ecSmrg#endif 57105b261ecSmrg { 572f7df2e56Smrg if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) { 573f7df2e56Smrg AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, 574f7df2e56Smrg proto_n, auth_proto, auth_id); 575f7df2e56Smrg 576f7df2e56Smrg free(from); 577f7df2e56Smrg } 57805b261ecSmrg } 57905b261ecSmrg priv->auth_id = auth_id; 58005b261ecSmrg priv->conn_time = 0; 58105b261ecSmrg 58205b261ecSmrg#ifdef XDMCP 58305b261ecSmrg /* indicate to Xdmcp protocol that we've opened new client */ 58405b261ecSmrg XdmcpOpenDisplay(priv->fd); 585f7df2e56Smrg#endif /* XDMCP */ 58605b261ecSmrg 58705b261ecSmrg XaceHook(XACE_AUTH_AVAIL, client, auth_id); 58805b261ecSmrg 58905b261ecSmrg /* At this point, if the client is authorized to change the access control 59005b261ecSmrg * list, we should getpeername() information, and add the client to 59105b261ecSmrg * the selfhosts list. It's not really the host machine, but the 59205b261ecSmrg * true purpose of the selfhosts list is to see who may change the 59305b261ecSmrg * access control list. 59405b261ecSmrg */ 595f7df2e56Smrg return ((char *) NULL); 59605b261ecSmrg} 59705b261ecSmrg 5987e31ba66Smrgstatic void 5997e31ba66SmrgClientReady(int fd, int xevents, void *data) 6007e31ba66Smrg{ 6017e31ba66Smrg ClientPtr client = data; 6027e31ba66Smrg 6037e31ba66Smrg if (xevents & X_NOTIFY_ERROR) { 6047e31ba66Smrg CloseDownClient(client); 6057e31ba66Smrg return; 6067e31ba66Smrg } 6077e31ba66Smrg if (xevents & X_NOTIFY_READ) 6087e31ba66Smrg mark_client_ready(client); 6097e31ba66Smrg if (xevents & X_NOTIFY_WRITE) { 6107e31ba66Smrg ospoll_mute(server_poll, fd, X_NOTIFY_WRITE); 6117e31ba66Smrg NewOutputPending = TRUE; 6127e31ba66Smrg } 6137e31ba66Smrg} 6147e31ba66Smrg 61505b261ecSmrgstatic ClientPtr 616f7df2e56SmrgAllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) 61705b261ecSmrg{ 618f7df2e56Smrg OsCommPtr oc; 619f7df2e56Smrg ClientPtr client; 620f7df2e56Smrg 6216747b715Smrg oc = malloc(sizeof(OsCommRec)); 62205b261ecSmrg if (!oc) 623f7df2e56Smrg return NullClient; 62405b261ecSmrg oc->trans_conn = trans_conn; 62505b261ecSmrg oc->fd = fd; 626f7df2e56Smrg oc->input = (ConnectionInputPtr) NULL; 627f7df2e56Smrg oc->output = (ConnectionOutputPtr) NULL; 62805b261ecSmrg oc->auth_id = None; 62905b261ecSmrg oc->conn_time = conn_time; 6307e31ba66Smrg oc->flags = 0; 631f7df2e56Smrg if (!(client = NextAvailableClient((void *) oc))) { 632f7df2e56Smrg free(oc); 633f7df2e56Smrg return NullClient; 63405b261ecSmrg } 635f7df2e56Smrg client->local = ComputeLocalClient(client); 6367e31ba66Smrg ospoll_add(server_poll, fd, 6377e31ba66Smrg ospoll_trigger_edge, 6387e31ba66Smrg ClientReady, 6397e31ba66Smrg client); 6407e31ba66Smrg set_poll_client(client); 64105b261ecSmrg 64205b261ecSmrg#ifdef DEBUG 64305b261ecSmrg ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n", 644f7df2e56Smrg client->index, fd); 64505b261ecSmrg#endif 64605b261ecSmrg#ifdef XSERVER_DTRACE 64705b261ecSmrg XSERVER_CLIENT_CONNECT(client->index, fd); 648f7df2e56Smrg#endif 64905b261ecSmrg 65005b261ecSmrg return client; 65105b261ecSmrg} 65205b261ecSmrg 65305b261ecSmrg/***************** 65405b261ecSmrg * EstablishNewConnections 65505b261ecSmrg * If anyone is waiting on listened sockets, accept them. 65605b261ecSmrg * Returns a mask with indices of new clients. Updates AllClients 65705b261ecSmrg * and AllSockets. 65805b261ecSmrg *****************/ 65905b261ecSmrg 6607e31ba66Smrgstatic Bool 661f7df2e56SmrgEstablishNewConnections(ClientPtr clientUnused, void *closure) 66205b261ecSmrg{ 6637e31ba66Smrg int curconn = (int) (intptr_t) closure; 6647e31ba66Smrg int newconn; /* fd of new client */ 66505b261ecSmrg CARD32 connect_time; 6667e31ba66Smrg int i; 6677e31ba66Smrg ClientPtr client; 6687e31ba66Smrg OsCommPtr oc; 6697e31ba66Smrg XtransConnInfo trans_conn, new_trans_conn; 6707e31ba66Smrg int status; 6717e31ba66Smrg 67205b261ecSmrg connect_time = GetTimeInMillis(); 67305b261ecSmrg /* kill off stragglers */ 674f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) { 675f7df2e56Smrg if ((client = clients[i])) { 676f7df2e56Smrg oc = (OsCommPtr) (client->osPrivate); 677f7df2e56Smrg if ((oc && (oc->conn_time != 0) && 678f7df2e56Smrg (connect_time - oc->conn_time) >= TimeOutValue) || 679f7df2e56Smrg (client->noClientException != Success && !client->clientGone)) 680f7df2e56Smrg CloseDownClient(client); 681f7df2e56Smrg } 68205b261ecSmrg } 68305b261ecSmrg 6847e31ba66Smrg if ((trans_conn = lookup_trans_conn(curconn)) == NULL) 6857e31ba66Smrg return TRUE; 686f7df2e56Smrg 6877e31ba66Smrg if ((new_trans_conn = _XSERVTransAccept(trans_conn, &status)) == NULL) 6887e31ba66Smrg return TRUE; 68905b261ecSmrg 6907e31ba66Smrg newconn = _XSERVTransGetConnectionNumber(new_trans_conn); 69105b261ecSmrg 6927e31ba66Smrg _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); 6934642e01fSmrg 6947e31ba66Smrg if (trans_conn->flags & TRANS_NOXAUTH) 6957e31ba66Smrg new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; 6964642e01fSmrg 6977e31ba66Smrg if (!AllocNewConnection(new_trans_conn, newconn, connect_time)) { 6987e31ba66Smrg ErrorConnMax(new_trans_conn); 69905b261ecSmrg } 7007e31ba66Smrg return TRUE; 701f7df2e56Smrg} 7027e31ba66Smrg 7037e31ba66Smrgstatic void 7047e31ba66SmrgQueueNewConnections(int fd, int ready, void *data) 7057e31ba66Smrg{ 7067e31ba66Smrg QueueWorkProc(EstablishNewConnections, NULL, (void *) (intptr_t) fd); 70705b261ecSmrg} 70805b261ecSmrg 70905b261ecSmrg#define NOROOM "Maximum number of clients reached" 71005b261ecSmrg 71105b261ecSmrg/************ 71205b261ecSmrg * ErrorConnMax 71305b261ecSmrg * Fail a connection due to lack of client or file descriptor space 71405b261ecSmrg ************/ 71505b261ecSmrg 71605b261ecSmrgstatic void 7177e31ba66SmrgConnMaxNotify(int fd, int events, void *data) 71805b261ecSmrg{ 7197e31ba66Smrg XtransConnInfo trans_conn = data; 720f7df2e56Smrg char order = 0; 7217e31ba66Smrg 72205b261ecSmrg /* try to read the byte-order of the connection */ 723f7df2e56Smrg (void) _XSERVTransRead(trans_conn, &order, 1); 724f7df2e56Smrg if (order == 'l' || order == 'B' || order == 'r' || order == 'R') { 7257e31ba66Smrg xConnSetupPrefix csp; 7267e31ba66Smrg char pad[3] = { 0, 0, 0 }; 7277e31ba66Smrg int whichbyte = 1; 7287e31ba66Smrg struct iovec iov[3]; 7297e31ba66Smrg 730f7df2e56Smrg csp.success = xFalse; 731f7df2e56Smrg csp.lengthReason = sizeof(NOROOM) - 1; 732f7df2e56Smrg csp.length = (sizeof(NOROOM) + 2) >> 2; 733f7df2e56Smrg csp.majorVersion = X_PROTOCOL; 734f7df2e56Smrg csp.minorVersion = X_PROTOCOL_REVISION; 7357e31ba66Smrg if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || 7367e31ba66Smrg (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { 737f7df2e56Smrg swaps(&csp.majorVersion); 738f7df2e56Smrg swaps(&csp.minorVersion); 739f7df2e56Smrg swaps(&csp.length); 740f7df2e56Smrg } 741f7df2e56Smrg iov[0].iov_len = sz_xConnSetupPrefix; 742f7df2e56Smrg iov[0].iov_base = (char *) &csp; 743f7df2e56Smrg iov[1].iov_len = csp.lengthReason; 744f7df2e56Smrg iov[1].iov_base = (void *) NOROOM; 745f7df2e56Smrg iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; 746f7df2e56Smrg iov[2].iov_base = pad; 747f7df2e56Smrg (void) _XSERVTransWritev(trans_conn, iov, 3); 74805b261ecSmrg } 7497e31ba66Smrg RemoveNotifyFd(trans_conn->fd); 7507e31ba66Smrg _XSERVTransClose(trans_conn); 7517e31ba66Smrg} 7527e31ba66Smrg 7537e31ba66Smrgstatic void 7547e31ba66SmrgErrorConnMax(XtransConnInfo trans_conn) 7557e31ba66Smrg{ 7567e31ba66Smrg if (!SetNotifyFd(trans_conn->fd, ConnMaxNotify, X_NOTIFY_READ, trans_conn)) 7577e31ba66Smrg _XSERVTransClose(trans_conn); 75805b261ecSmrg} 75905b261ecSmrg 76005b261ecSmrg/************ 76105b261ecSmrg * CloseDownFileDescriptor: 7627e31ba66Smrg * Remove this file descriptor 76305b261ecSmrg ************/ 76405b261ecSmrg 7657e31ba66Smrgvoid 76605b261ecSmrgCloseDownFileDescriptor(OsCommPtr oc) 76705b261ecSmrg{ 76805b261ecSmrg if (oc->trans_conn) { 7697e31ba66Smrg int connection = oc->fd; 7707e31ba66Smrg#ifdef XDMCP 7717e31ba66Smrg XdmcpCloseDisplay(connection); 7727e31ba66Smrg#endif 7737e31ba66Smrg ospoll_remove(server_poll, connection); 774f7df2e56Smrg _XSERVTransDisconnect(oc->trans_conn); 775f7df2e56Smrg _XSERVTransClose(oc->trans_conn); 7767e31ba66Smrg oc->trans_conn = NULL; 7777e31ba66Smrg oc->fd = -1; 77805b261ecSmrg } 77905b261ecSmrg} 78005b261ecSmrg 78105b261ecSmrg/***************** 78205b261ecSmrg * CloseDownConnection 783f7df2e56Smrg * Delete client from AllClients and free resources 78405b261ecSmrg *****************/ 78505b261ecSmrg 78605b261ecSmrgvoid 78705b261ecSmrgCloseDownConnection(ClientPtr client) 78805b261ecSmrg{ 789f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 79005b261ecSmrg 7916747b715Smrg if (FlushCallback) 7927e31ba66Smrg CallCallbacks(&FlushCallback, client); 7936747b715Smrg 794f7df2e56Smrg if (oc->output) 795f7df2e56Smrg FlushClient(client, oc, (char *) NULL, 0); 79605b261ecSmrg CloseDownFileDescriptor(oc); 79705b261ecSmrg FreeOsBuffers(oc); 7986747b715Smrg free(client->osPrivate); 799f7df2e56Smrg client->osPrivate = (void *) NULL; 80005b261ecSmrg if (auditTrailLevel > 1) 801f7df2e56Smrg AuditF("client %d disconnected\n", client->index); 80205b261ecSmrg} 80305b261ecSmrg 8047e31ba66Smrgstruct notify_fd { 8057e31ba66Smrg int mask; 8067e31ba66Smrg NotifyFdProcPtr notify; 8077e31ba66Smrg void *data; 8087e31ba66Smrg}; 80905b261ecSmrg 8107e31ba66Smrg/***************** 8117e31ba66Smrg * HandleNotifyFd 8127e31ba66Smrg * A poll callback to be called when the registered 8137e31ba66Smrg * file descriptor is ready. 8147e31ba66Smrg *****************/ 81505b261ecSmrg 8167e31ba66Smrgstatic void 8177e31ba66SmrgHandleNotifyFd(int fd, int xevents, void *data) 81805b261ecSmrg{ 8197e31ba66Smrg struct notify_fd *n = data; 8207e31ba66Smrg n->notify(fd, xevents, n->data); 82105b261ecSmrg} 82205b261ecSmrg 8237e31ba66Smrg/***************** 8247e31ba66Smrg * SetNotifyFd 8257e31ba66Smrg * Registers a callback to be invoked when the specified 8267e31ba66Smrg * file descriptor becomes readable. 8277e31ba66Smrg *****************/ 8287e31ba66Smrg 8297e31ba66SmrgBool 8307e31ba66SmrgSetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data) 83105b261ecSmrg{ 8327e31ba66Smrg struct notify_fd *n; 8337e31ba66Smrg 8347e31ba66Smrg n = ospoll_data(server_poll, fd); 8357e31ba66Smrg if (!n) { 8367e31ba66Smrg if (mask == 0) 8377e31ba66Smrg return TRUE; 8387e31ba66Smrg 8397e31ba66Smrg n = calloc(1, sizeof (struct notify_fd)); 8407e31ba66Smrg if (!n) 8417e31ba66Smrg return FALSE; 8427e31ba66Smrg ospoll_add(server_poll, fd, 8437e31ba66Smrg ospoll_trigger_level, 8447e31ba66Smrg HandleNotifyFd, 8457e31ba66Smrg n); 8467e31ba66Smrg } 8477e31ba66Smrg 8487e31ba66Smrg if (mask == 0) { 8497e31ba66Smrg ospoll_remove(server_poll, fd); 8507e31ba66Smrg free(n); 8517e31ba66Smrg } else { 8527e31ba66Smrg int listen = mask & ~n->mask; 8537e31ba66Smrg int mute = n->mask & ~mask; 8547e31ba66Smrg 8557e31ba66Smrg if (listen) 8567e31ba66Smrg ospoll_listen(server_poll, fd, listen); 8577e31ba66Smrg if (mute) 8587e31ba66Smrg ospoll_mute(server_poll, fd, mute); 8597e31ba66Smrg n->mask = mask; 8607e31ba66Smrg n->data = data; 8617e31ba66Smrg n->notify = notify; 8627e31ba66Smrg } 8637e31ba66Smrg 8647e31ba66Smrg return TRUE; 86505b261ecSmrg} 86605b261ecSmrg 86705b261ecSmrg/***************** 86805b261ecSmrg * OnlyListenToOneClient: 86905b261ecSmrg * Only accept requests from one client. Continue to handle new 87005b261ecSmrg * connections, but don't take any protocol requests from the new 87105b261ecSmrg * ones. Note that if GrabInProgress is set, EstablishNewConnections 87205b261ecSmrg * needs to put new clients into SavedAllSockets and SavedAllClients. 87305b261ecSmrg * Note also that there is no timeout for this in the protocol. 87405b261ecSmrg * This routine is "undone" by ListenToAllClients() 87505b261ecSmrg *****************/ 87605b261ecSmrg 8774642e01fSmrgint 87805b261ecSmrgOnlyListenToOneClient(ClientPtr client) 87905b261ecSmrg{ 8807e31ba66Smrg int rc; 8814642e01fSmrg 8824642e01fSmrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); 8834642e01fSmrg if (rc != Success) 884f7df2e56Smrg return rc; 885f7df2e56Smrg 886f7df2e56Smrg if (!GrabInProgress) { 887f7df2e56Smrg GrabInProgress = client->index; 8887e31ba66Smrg set_poll_clients(); 88905b261ecSmrg } 8907e31ba66Smrg 8914642e01fSmrg return rc; 89205b261ecSmrg} 89305b261ecSmrg 89405b261ecSmrg/**************** 89505b261ecSmrg * ListenToAllClients: 89605b261ecSmrg * Undoes OnlyListentToOneClient() 89705b261ecSmrg ****************/ 89805b261ecSmrg 89905b261ecSmrgvoid 90005b261ecSmrgListenToAllClients(void) 90105b261ecSmrg{ 902f7df2e56Smrg if (GrabInProgress) { 903f7df2e56Smrg GrabInProgress = 0; 9047e31ba66Smrg set_poll_clients(); 905f7df2e56Smrg } 90605b261ecSmrg} 90705b261ecSmrg 90805b261ecSmrg/**************** 90905b261ecSmrg * IgnoreClient 91005b261ecSmrg * Removes one client from input masks. 91105b261ecSmrg * Must have cooresponding call to AttendClient. 91205b261ecSmrg ****************/ 91305b261ecSmrg 9146747b715Smrgvoid 915f7df2e56SmrgIgnoreClient(ClientPtr client) 91605b261ecSmrg{ 917f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 91805b261ecSmrg 9196747b715Smrg client->ignoreCount++; 9206747b715Smrg if (client->ignoreCount > 1) 921f7df2e56Smrg return; 9226747b715Smrg 92305b261ecSmrg isItTimeToYield = TRUE; 9247e31ba66Smrg mark_client_not_ready(client); 9257e31ba66Smrg 9267e31ba66Smrg oc->flags |= OS_COMM_IGNORED; 9277e31ba66Smrg set_poll_client(client); 92805b261ecSmrg} 92905b261ecSmrg 93005b261ecSmrg/**************** 93105b261ecSmrg * AttendClient 93205b261ecSmrg * Adds one client back into the input masks. 93305b261ecSmrg ****************/ 93405b261ecSmrg 9356747b715Smrgvoid 936f7df2e56SmrgAttendClient(ClientPtr client) 93705b261ecSmrg{ 938f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 9396747b715Smrg 9404e185dc0Smrg if (client->clientGone) { 9414e185dc0Smrg /* 9424e185dc0Smrg * client is gone, so any pending requests will be dropped and its 9434e185dc0Smrg * ignore count doesn't matter. 9444e185dc0Smrg */ 9454e185dc0Smrg return; 9464e185dc0Smrg } 9474e185dc0Smrg 9486747b715Smrg client->ignoreCount--; 9496747b715Smrg if (client->ignoreCount) 950f7df2e56Smrg return; 9516747b715Smrg 9527e31ba66Smrg oc->flags &= ~OS_COMM_IGNORED; 9537e31ba66Smrg set_poll_client(client); 9547e31ba66Smrg if (listen_to_client(client)) 9557e31ba66Smrg mark_client_ready(client); 956f7df2e56Smrg else { 9577e31ba66Smrg /* grab active, mark ready when grab goes away */ 9587e31ba66Smrg mark_client_saved_ready(client); 95905b261ecSmrg } 96005b261ecSmrg} 96105b261ecSmrg 96205b261ecSmrg/* make client impervious to grabs; assume only executing client calls this */ 96305b261ecSmrg 9644642e01fSmrgvoid 96505b261ecSmrgMakeClientGrabImpervious(ClientPtr client) 96605b261ecSmrg{ 967f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 96805b261ecSmrg 9697e31ba66Smrg oc->flags |= OS_COMM_GRAB_IMPERVIOUS; 9707e31ba66Smrg set_poll_client(client); 97105b261ecSmrg 972f7df2e56Smrg if (ServerGrabCallback) { 973f7df2e56Smrg ServerGrabInfoRec grabinfo; 974f7df2e56Smrg 975f7df2e56Smrg grabinfo.client = client; 976f7df2e56Smrg grabinfo.grabstate = CLIENT_IMPERVIOUS; 977f7df2e56Smrg CallCallbacks(&ServerGrabCallback, &grabinfo); 97805b261ecSmrg } 97905b261ecSmrg} 98005b261ecSmrg 98105b261ecSmrg/* make client pervious to grabs; assume only executing client calls this */ 98205b261ecSmrg 9834642e01fSmrgvoid 98405b261ecSmrgMakeClientGrabPervious(ClientPtr client) 98505b261ecSmrg{ 986f7df2e56Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 98705b261ecSmrg 9887e31ba66Smrg oc->flags &= ~OS_COMM_GRAB_IMPERVIOUS; 9897e31ba66Smrg set_poll_client(client); 9907e31ba66Smrg isItTimeToYield = TRUE; 99105b261ecSmrg 992f7df2e56Smrg if (ServerGrabCallback) { 993f7df2e56Smrg ServerGrabInfoRec grabinfo; 994f7df2e56Smrg 995f7df2e56Smrg grabinfo.client = client; 996f7df2e56Smrg grabinfo.grabstate = CLIENT_PERVIOUS; 997f7df2e56Smrg CallCallbacks(&ServerGrabCallback, &grabinfo); 99805b261ecSmrg } 99905b261ecSmrg} 100005b261ecSmrg 1001f7df2e56Smrg/* Add a fd (from launchd or similar) to our listeners */ 1002f7df2e56Smrgvoid 1003f7df2e56SmrgListenOnOpenFD(int fd, int noxauth) 1004f7df2e56Smrg{ 10054642e01fSmrg char port[256]; 10064642e01fSmrg XtransConnInfo ciptr; 10076747b715Smrg const char *display_env = getenv("DISPLAY"); 10084642e01fSmrg 1009f7df2e56Smrg if (display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) { 10104642e01fSmrg /* Make the path the launchd socket if our DISPLAY is set right */ 10116747b715Smrg strcpy(port, display_env); 1012f7df2e56Smrg } 1013f7df2e56Smrg else { 10144642e01fSmrg /* Just some default so things don't break and die. */ 1015f7df2e56Smrg snprintf(port, sizeof(port), ":%d", atoi(display)); 10164642e01fSmrg } 10174642e01fSmrg 10184642e01fSmrg /* Make our XtransConnInfo 10194642e01fSmrg * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c 10204642e01fSmrg */ 10214642e01fSmrg ciptr = _XSERVTransReopenCOTSServer(5, fd, port); 1022f7df2e56Smrg if (ciptr == NULL) { 1023f7df2e56Smrg ErrorF("Got NULL while trying to Reopen listen port.\n"); 10244642e01fSmrg return; 10254642e01fSmrg } 1026f7df2e56Smrg 1027f7df2e56Smrg if (noxauth) 10284642e01fSmrg ciptr->flags = ciptr->flags | TRANS_NOXAUTH; 10294642e01fSmrg 10304642e01fSmrg /* Allocate space to store it */ 1031f7df2e56Smrg ListenTransFds = 1032f7df2e56Smrg xnfreallocarray(ListenTransFds, ListenTransCount + 1, sizeof(int)); 1033f7df2e56Smrg ListenTransConns = 1034f7df2e56Smrg xnfreallocarray(ListenTransConns, ListenTransCount + 1, 1035f7df2e56Smrg sizeof(XtransConnInfo)); 1036f7df2e56Smrg 10374642e01fSmrg /* Store it */ 10384642e01fSmrg ListenTransConns[ListenTransCount] = ciptr; 10394642e01fSmrg ListenTransFds[ListenTransCount] = fd; 10404642e01fSmrg 10417e31ba66Smrg SetNotifyFd(fd, QueueNewConnections, X_NOTIFY_READ, NULL); 1042f7df2e56Smrg 10434642e01fSmrg /* Increment the count */ 10444642e01fSmrg ListenTransCount++; 10454642e01fSmrg} 10464642e01fSmrg 1047f7df2e56Smrg/* based on TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) */ 1048f7df2e56SmrgBool 1049f7df2e56SmrgAddClientOnOpenFD(int fd) 1050f7df2e56Smrg{ 1051f7df2e56Smrg XtransConnInfo ciptr; 1052f7df2e56Smrg CARD32 connect_time; 1053f7df2e56Smrg char port[20]; 1054f7df2e56Smrg 1055f7df2e56Smrg snprintf(port, sizeof(port), ":%d", atoi(display)); 1056f7df2e56Smrg ciptr = _XSERVTransReopenCOTSServer(5, fd, port); 1057f7df2e56Smrg if (ciptr == NULL) 1058f7df2e56Smrg return FALSE; 1059f7df2e56Smrg 1060f7df2e56Smrg _XSERVTransSetOption(ciptr, TRANS_NONBLOCKING, 1); 1061f7df2e56Smrg ciptr->flags |= TRANS_NOXAUTH; 1062f7df2e56Smrg 1063f7df2e56Smrg connect_time = GetTimeInMillis(); 1064f7df2e56Smrg 1065f7df2e56Smrg if (!AllocNewConnection(ciptr, fd, connect_time)) { 1066f7df2e56Smrg ErrorConnMax(ciptr); 1067f7df2e56Smrg return FALSE; 1068f7df2e56Smrg } 1069f7df2e56Smrg 1070f7df2e56Smrg return TRUE; 1071f7df2e56Smrg} 10727e31ba66Smrg 10737e31ba66SmrgBool 10747e31ba66Smrglisten_to_client(ClientPtr client) 10757e31ba66Smrg{ 10767e31ba66Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 10777e31ba66Smrg 10787e31ba66Smrg if (oc->flags & OS_COMM_IGNORED) 10797e31ba66Smrg return FALSE; 10807e31ba66Smrg 10817e31ba66Smrg if (!GrabInProgress) 10827e31ba66Smrg return TRUE; 10837e31ba66Smrg 10847e31ba66Smrg if (client->index == GrabInProgress) 10857e31ba66Smrg return TRUE; 10867e31ba66Smrg 10877e31ba66Smrg if (oc->flags & OS_COMM_GRAB_IMPERVIOUS) 10887e31ba66Smrg return TRUE; 10897e31ba66Smrg 10907e31ba66Smrg return FALSE; 10917e31ba66Smrg} 10927e31ba66Smrg 10937e31ba66Smrgstatic void 10947e31ba66Smrgset_poll_client(ClientPtr client) 10957e31ba66Smrg{ 10967e31ba66Smrg OsCommPtr oc = (OsCommPtr) client->osPrivate; 10977e31ba66Smrg 10987e31ba66Smrg if (oc->trans_conn) { 10997e31ba66Smrg if (listen_to_client(client)) 11007e31ba66Smrg ospoll_listen(server_poll, oc->trans_conn->fd, X_NOTIFY_READ); 11017e31ba66Smrg else 11027e31ba66Smrg ospoll_mute(server_poll, oc->trans_conn->fd, X_NOTIFY_READ); 11037e31ba66Smrg } 11047e31ba66Smrg} 11057e31ba66Smrg 11067e31ba66Smrgstatic void 11077e31ba66Smrgset_poll_clients(void) 11087e31ba66Smrg{ 11097e31ba66Smrg int i; 11107e31ba66Smrg 11117e31ba66Smrg for (i = 1; i < currentMaxClients; i++) { 11127e31ba66Smrg ClientPtr client = clients[i]; 11137e31ba66Smrg if (client && !client->clientGone) 11147e31ba66Smrg set_poll_client(client); 11157e31ba66Smrg } 11167e31ba66Smrg} 1117