connection.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. /***********************************************************
  2. Copyright 1987, 1989, 1998 The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included in
  9. all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  14. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  15. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. Except as contained in this notice, the name of The Open Group shall not be
  17. used in advertising or otherwise to promote the sale, use or other dealings
  18. in this Software without prior written authorization from The Open Group.
  19. Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
  20. All Rights Reserved
  21. Permission to use, copy, modify, and distribute this software and its
  22. documentation for any purpose and without fee is hereby granted,
  23. provided that the above copyright notice appear in all copies and that
  24. both that copyright notice and this permission notice appear in
  25. supporting documentation, and that the name of Digital not be
  26. used in advertising or publicity pertaining to distribution of the
  27. software without specific, written prior permission.
  28. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34. SOFTWARE.
  35. ******************************************************************/
  36. /*****************************************************************
  37. * Stuff to create connections --- OS dependent
  38. *
  39. * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
  40. * CloseDownConnection, CheckConnections, AddEnabledDevice,
  41. * RemoveEnabledDevice, OnlyListToOneClient,
  42. * ListenToAllClients,
  43. *
  44. * (WaitForSomething is in its own file)
  45. *
  46. * In this implementation, a client socket table is not kept.
  47. * Instead, what would be the index into the table is just the
  48. * file descriptor of the socket. This won't work for if the
  49. * socket ids aren't small nums (0 - 2^8)
  50. *
  51. *****************************************************************/
  52. #ifdef HAVE_DIX_CONFIG_H
  53. #include <dix-config.h>
  54. #endif
  55. #include <X11/X.h>
  56. #include <X11/Xproto.h>
  57. #define XSERV_t
  58. #define TRANS_SERVER
  59. #define TRANS_REOPEN
  60. #include <X11/Xtrans/Xtrans.h>
  61. #include <errno.h>
  62. #include <signal.h>
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <sys/socket.h>
  66. #if defined(TCPCONN)
  67. # include <netinet/in.h>
  68. # include <arpa/inet.h>
  69. # ifdef CSRG_BASED
  70. # include <sys/param.h>
  71. # endif
  72. # include <netinet/tcp.h>
  73. # include <arpa/inet.h>
  74. #endif
  75. #include <sys/uio.h>
  76. #include "misc.h" /* for typedef of pointer */
  77. #include "osdep.h"
  78. #include <X11/Xpoll.h>
  79. #include "opaque.h"
  80. #include "dixstruct.h"
  81. #define Pid_t pid_t
  82. #ifdef HAS_GETPEERUCRED
  83. # include <ucred.h>
  84. # include <zone.h>
  85. #endif
  86. int lastfdesc; /* maximum file descriptor */
  87. fd_set WellKnownConnections; /* Listener mask */
  88. fd_set EnabledDevices; /* mask for input devices that are on */
  89. fd_set AllSockets; /* select on this */
  90. fd_set AllClients; /* available clients */
  91. fd_set LastSelectMask; /* mask returned from last select call */
  92. fd_set ClientsWithInput; /* clients with FULL requests in buffer */
  93. fd_set ClientsWriteBlocked; /* clients who cannot receive output */
  94. fd_set OutputPending; /* clients with reply/event data ready to go */
  95. int MaxClients = 0;
  96. Bool NewOutputPending; /* not yet attempted to write some new output */
  97. Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
  98. Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
  99. Bool PartialNetwork; /* continue even if unable to bind all addrs */
  100. static Pid_t ParentProcess;
  101. static Bool debug_conns = FALSE;
  102. fd_set IgnoredClientsWithInput;
  103. static fd_set GrabImperviousClients;
  104. static fd_set SavedAllClients;
  105. static fd_set SavedAllSockets;
  106. static fd_set SavedClientsWithInput;
  107. _X_EXPORT int GrabInProgress = 0;
  108. int *ConnectionTranslation = NULL;
  109. XtransConnInfo *ListenTransConns = NULL;
  110. int *ListenTransFds = NULL;
  111. int ListenTransCount;
  112. static void ErrorConnMax(XtransConnInfo /* trans_conn */);
  113. static XtransConnInfo
  114. lookup_trans_conn (int fd)
  115. {
  116. if (ListenTransFds)
  117. {
  118. int i;
  119. for (i = 0; i < ListenTransCount; i++)
  120. if (ListenTransFds[i] == fd)
  121. return ListenTransConns[i];
  122. }
  123. return (NULL);
  124. }
  125. /* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
  126. void
  127. InitConnectionLimits(void)
  128. {
  129. lastfdesc = -1;
  130. #if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
  131. lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
  132. #endif
  133. #ifdef HAS_GETDTABLESIZE
  134. if (lastfdesc < 0)
  135. lastfdesc = getdtablesize() - 1;
  136. #endif
  137. #ifdef _NFILE
  138. if (lastfdesc < 0)
  139. lastfdesc = _NFILE - 1;
  140. #endif
  141. /* This is the fallback */
  142. if (lastfdesc < 0)
  143. lastfdesc = MAXSOCKS;
  144. if (lastfdesc > MAXSELECT)
  145. lastfdesc = MAXSELECT;
  146. if (lastfdesc > MAXCLIENTS)
  147. {
  148. lastfdesc = MAXCLIENTS;
  149. if (debug_conns)
  150. ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
  151. }
  152. MaxClients = lastfdesc;
  153. #ifdef DEBUG
  154. ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
  155. #endif
  156. ConnectionTranslation = (int *)malloc(sizeof(int)*(lastfdesc + 1));
  157. }
  158. /*****************
  159. * CreateWellKnownSockets
  160. * At initialization, create the sockets to listen on for new clients.
  161. *****************/
  162. void
  163. CreateWellKnownSockets(void)
  164. {
  165. int i;
  166. int partial;
  167. char port[20];
  168. OsSigHandlerPtr handler;
  169. FD_ZERO(&AllSockets);
  170. FD_ZERO(&AllClients);
  171. FD_ZERO(&LastSelectMask);
  172. FD_ZERO(&ClientsWithInput);
  173. for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
  174. FD_ZERO (&WellKnownConnections);
  175. sprintf (port, "%d", atoi (display));
  176. if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
  177. &ListenTransCount, &ListenTransConns) >= 0) &&
  178. (ListenTransCount >= 1))
  179. {
  180. if (!PartialNetwork && partial)
  181. {
  182. FatalError ("Failed to establish all listening sockets");
  183. }
  184. else
  185. {
  186. ListenTransFds = malloc(ListenTransCount * sizeof (int));
  187. for (i = 0; i < ListenTransCount; i++)
  188. {
  189. int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
  190. ListenTransFds[i] = fd;
  191. FD_SET (fd, &WellKnownConnections);
  192. if (!_XSERVTransIsLocal (ListenTransConns[i]))
  193. {
  194. DefineSelf (fd);
  195. }
  196. }
  197. }
  198. }
  199. if (!XFD_ANYSET (&WellKnownConnections))
  200. FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
  201. OsSignal (SIGPIPE, SIG_IGN);
  202. OsSignal (SIGHUP, AutoResetServer);
  203. OsSignal (SIGINT, GiveUp);
  204. OsSignal (SIGTERM, GiveUp);
  205. XFD_COPYSET (&WellKnownConnections, &AllSockets);
  206. ResetHosts(display);
  207. /*
  208. * Magic: If SIGUSR1 was set to SIG_IGN when
  209. * the server started, assume that either
  210. *
  211. * a- The parent process is ignoring SIGUSR1
  212. *
  213. * or
  214. *
  215. * b- The parent process is expecting a SIGUSR1
  216. * when the server is ready to accept connections
  217. *
  218. * In the first case, the signal will be harmless,
  219. * in the second case, the signal will be quite
  220. * useful
  221. */
  222. handler = OsSignal (SIGUSR1, SIG_IGN);
  223. if ( handler == SIG_IGN)
  224. RunFromSmartParent = TRUE;
  225. OsSignal(SIGUSR1, handler);
  226. ParentProcess = getppid ();
  227. if (RunFromSmartParent) {
  228. if (ParentProcess > 1) {
  229. kill (ParentProcess, SIGUSR1);
  230. }
  231. }
  232. #ifdef XDMCP
  233. XdmcpInit ();
  234. #endif
  235. }
  236. void
  237. ResetWellKnownSockets (void)
  238. {
  239. int i;
  240. ResetOsBuffers();
  241. for (i = 0; i < ListenTransCount; i++)
  242. {
  243. int status = _XSERVTransResetListener (ListenTransConns[i]);
  244. if (status != TRANS_RESET_NOOP)
  245. {
  246. if (status == TRANS_RESET_FAILURE)
  247. {
  248. /*
  249. * ListenTransConns[i] freed by xtrans.
  250. * Remove it from out list.
  251. */
  252. FD_CLR (ListenTransFds[i], &WellKnownConnections);
  253. ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
  254. ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
  255. ListenTransCount -= 1;
  256. i -= 1;
  257. }
  258. else if (status == TRANS_RESET_NEW_FD)
  259. {
  260. /*
  261. * A new file descriptor was allocated (the old one was closed)
  262. */
  263. int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
  264. FD_CLR (ListenTransFds[i], &WellKnownConnections);
  265. ListenTransFds[i] = newfd;
  266. FD_SET(newfd, &WellKnownConnections);
  267. }
  268. }
  269. }
  270. ResetAuthorization ();
  271. ResetHosts(display);
  272. /*
  273. * See above in CreateWellKnownSockets about SIGUSR1
  274. */
  275. if (RunFromSmartParent) {
  276. if (ParentProcess > 1) {
  277. kill (ParentProcess, SIGUSR1);
  278. }
  279. }
  280. /*
  281. * restart XDMCP
  282. */
  283. #ifdef XDMCP
  284. XdmcpReset ();
  285. #endif
  286. }
  287. void
  288. CloseWellKnownConnections(void)
  289. {
  290. int i;
  291. for (i = 0; i < ListenTransCount; i++)
  292. _XSERVTransClose (ListenTransConns[i]);
  293. }
  294. static void
  295. AuthAudit (ClientPtr client, Bool letin,
  296. struct sockaddr *saddr, int len,
  297. unsigned int proto_n, char *auth_proto, int auth_id)
  298. {
  299. char addr[128];
  300. char *out = addr;
  301. int client_uid;
  302. char client_uid_string[64];
  303. #ifdef HAS_GETPEERUCRED
  304. ucred_t *peercred = NULL;
  305. pid_t client_pid = -1;
  306. zoneid_t client_zid = -1;
  307. #endif
  308. if (!len)
  309. strcpy(out, "local host");
  310. else
  311. switch (saddr->sa_family)
  312. {
  313. case AF_UNSPEC:
  314. #if defined(UNIXCONN) || defined(LOCALCONN)
  315. case AF_UNIX:
  316. #endif
  317. strcpy(out, "local host");
  318. break;
  319. #if defined(TCPCONN)
  320. case AF_INET:
  321. sprintf(out, "IP %s",
  322. inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
  323. break;
  324. #if defined(IPv6) && defined(AF_INET6)
  325. case AF_INET6: {
  326. char ipaddr[INET6_ADDRSTRLEN];
  327. inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
  328. ipaddr, sizeof(ipaddr));
  329. sprintf(out, "IP %s", ipaddr);
  330. }
  331. break;
  332. #endif
  333. #endif
  334. default:
  335. strcpy(out, "unknown address");
  336. }
  337. #ifdef HAS_GETPEERUCRED
  338. if (getpeerucred(((OsCommPtr)client->osPrivate)->fd, &peercred) >= 0) {
  339. client_uid = ucred_geteuid(peercred);
  340. client_pid = ucred_getpid(peercred);
  341. client_zid = ucred_getzoneid(peercred);
  342. ucred_free(peercred);
  343. snprintf(client_uid_string, sizeof(client_uid_string),
  344. " (uid %ld, pid %ld, zone %ld)",
  345. (long) client_uid, (long) client_pid, (long) client_zid);
  346. }
  347. #else
  348. if (LocalClientCred(client, &client_uid, NULL) != -1) {
  349. snprintf(client_uid_string, sizeof(client_uid_string),
  350. " (uid %d)", client_uid);
  351. }
  352. #endif
  353. else {
  354. client_uid_string[0] = '\0';
  355. }
  356. if (proto_n)
  357. AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
  358. client->index, letin ? "connected" : "rejected", addr,
  359. client_uid_string, (int)proto_n, auth_proto, auth_id);
  360. else
  361. AuditF("client %d %s from %s%s\n",
  362. client->index, letin ? "connected" : "rejected", addr,
  363. client_uid_string);
  364. }
  365. /*****************************************************************
  366. * ClientAuthorized
  367. *
  368. * Sent by the client at connection setup:
  369. * typedef struct _xConnClientPrefix {
  370. * CARD8 byteOrder;
  371. * BYTE pad;
  372. * CARD16 majorVersion, minorVersion;
  373. * CARD16 nbytesAuthProto;
  374. * CARD16 nbytesAuthString;
  375. * } xConnClientPrefix;
  376. *
  377. * It is hoped that eventually one protocol will be agreed upon. In the
  378. * mean time, a server that implements a different protocol than the
  379. * client expects, or a server that only implements the host-based
  380. * mechanism, will simply ignore this information.
  381. *
  382. *****************************************************************/
  383. const char *
  384. ClientAuthorized(ClientPtr client,
  385. unsigned int proto_n, char *auth_proto,
  386. unsigned int string_n, char *auth_string)
  387. {
  388. OsCommPtr priv;
  389. Xtransaddr *from = NULL;
  390. int family;
  391. int fromlen;
  392. XID auth_id;
  393. const char *reason = NULL;
  394. XtransConnInfo trans_conn;
  395. priv = (OsCommPtr)client->osPrivate;
  396. trans_conn = priv->trans_conn;
  397. auth_id = CheckAuthorization (proto_n, auth_proto,
  398. string_n, auth_string, client, &reason);
  399. if (auth_id == (XID) ~0L)
  400. {
  401. if (
  402. _XSERVTransGetPeerAddr (trans_conn,
  403. &family, &fromlen, &from) != -1)
  404. {
  405. if (InvalidHost ((struct sockaddr *) from, fromlen, client))
  406. AuthAudit(client, FALSE, (struct sockaddr *) from,
  407. fromlen, proto_n, auth_proto, auth_id);
  408. else
  409. {
  410. auth_id = (XID) 0;
  411. if (auditTrailLevel > 1)
  412. AuthAudit(client, TRUE,
  413. (struct sockaddr *) from, fromlen,
  414. proto_n, auth_proto, auth_id);
  415. }
  416. free((char *) from);
  417. }
  418. if (auth_id == (XID) ~0L) {
  419. if (reason)
  420. return reason;
  421. else
  422. return "Client is not authorized to connect to Server";
  423. }
  424. }
  425. else if (auditTrailLevel > 1)
  426. {
  427. if (_XSERVTransGetPeerAddr (trans_conn,
  428. &family, &fromlen, &from) != -1)
  429. {
  430. AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
  431. proto_n, auth_proto, auth_id);
  432. free((char *) from);
  433. }
  434. }
  435. priv->auth_id = auth_id;
  436. priv->conn_time = 0;
  437. #ifdef XDMCP
  438. /* indicate to Xdmcp protocol that we've opened new client */
  439. XdmcpOpenDisplay(priv->fd);
  440. #endif /* XDMCP */
  441. /* At this point, if the client is authorized to change the access control
  442. * list, we should getpeername() information, and add the client to
  443. * the selfhosts list. It's not really the host machine, but the
  444. * true purpose of the selfhosts list is to see who may change the
  445. * access control list.
  446. */
  447. return((char *)NULL);
  448. }
  449. static ClientPtr
  450. AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
  451. {
  452. OsCommPtr oc;
  453. ClientPtr client;
  454. if (
  455. fd >= lastfdesc
  456. )
  457. return NullClient;
  458. oc = (OsCommPtr)malloc(sizeof(OsCommRec));
  459. if (!oc)
  460. return NullClient;
  461. oc->trans_conn = trans_conn;
  462. oc->fd = fd;
  463. oc->input = (ConnectionInputPtr)NULL;
  464. oc->output = (ConnectionOutputPtr)NULL;
  465. oc->auth_id = None;
  466. oc->conn_time = conn_time;
  467. if (!(client = NextAvailableClient((pointer)oc)))
  468. {
  469. free(oc);
  470. return NullClient;
  471. }
  472. ConnectionTranslation[fd] = client->index;
  473. if (GrabInProgress)
  474. {
  475. FD_SET(fd, &SavedAllClients);
  476. FD_SET(fd, &SavedAllSockets);
  477. }
  478. else
  479. {
  480. FD_SET(fd, &AllClients);
  481. FD_SET(fd, &AllSockets);
  482. }
  483. #ifdef DEBUG
  484. ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
  485. client->index, fd);
  486. #endif
  487. return client;
  488. }
  489. /*****************
  490. * EstablishNewConnections
  491. * If anyone is waiting on listened sockets, accept them.
  492. * Returns a mask with indices of new clients. Updates AllClients
  493. * and AllSockets.
  494. *****************/
  495. /*ARGSUSED*/
  496. Bool
  497. EstablishNewConnections(ClientPtr clientUnused, pointer closure)
  498. {
  499. fd_set readyconnections; /* set of listeners that are ready */
  500. int curconn; /* fd of listener that's ready */
  501. int newconn; /* fd of new client */
  502. CARD32 connect_time;
  503. int i;
  504. ClientPtr client;
  505. OsCommPtr oc;
  506. fd_set tmask;
  507. XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
  508. XFD_COPYSET(&tmask, &readyconnections);
  509. if (!XFD_ANYSET(&readyconnections))
  510. return TRUE;
  511. connect_time = GetTimeInMillis();
  512. /* kill off stragglers */
  513. for (i=1; i<currentMaxClients; i++)
  514. {
  515. if ((client = clients[i]))
  516. {
  517. oc = (OsCommPtr)(client->osPrivate);
  518. if ((oc && (oc->conn_time != 0) &&
  519. (connect_time - oc->conn_time) >= TimeOutValue) ||
  520. (client->noClientException != Success && !client->clientGone))
  521. CloseDownClient(client);
  522. }
  523. }
  524. for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
  525. {
  526. while (readyconnections.fds_bits[i])
  527. {
  528. XtransConnInfo trans_conn, new_trans_conn;
  529. int status;
  530. curconn = ffs (readyconnections.fds_bits[i]) - 1;
  531. readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
  532. curconn += (i * (sizeof(fd_mask)*8));
  533. if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
  534. continue;
  535. if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
  536. continue;
  537. newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
  538. if (newconn < lastfdesc)
  539. {
  540. int clientid;
  541. clientid = ConnectionTranslation[newconn];
  542. if(clientid && (client = clients[clientid]))
  543. CloseDownClient(client);
  544. }
  545. _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
  546. if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
  547. {
  548. ErrorConnMax(new_trans_conn);
  549. _XSERVTransClose(new_trans_conn);
  550. }
  551. }
  552. }
  553. return TRUE;
  554. }
  555. #define NOROOM "Maximum number of clients reached"
  556. /************
  557. * ErrorConnMax
  558. * Fail a connection due to lack of client or file descriptor space
  559. ************/
  560. static void
  561. ErrorConnMax(XtransConnInfo trans_conn)
  562. {
  563. int fd = _XSERVTransGetConnectionNumber (trans_conn);
  564. xConnSetupPrefix csp;
  565. char pad[3];
  566. struct iovec iov[3];
  567. char byteOrder = 0;
  568. int whichbyte = 1;
  569. struct timeval waittime;
  570. fd_set mask;
  571. /* if these seems like a lot of trouble to go to, it probably is */
  572. waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
  573. waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
  574. (1000000 / MILLI_PER_SECOND);
  575. FD_ZERO(&mask);
  576. FD_SET(fd, &mask);
  577. (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
  578. /* try to read the byte-order of the connection */
  579. (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
  580. if ((byteOrder == 'l') || (byteOrder == 'B'))
  581. {
  582. csp.success = xFalse;
  583. csp.lengthReason = sizeof(NOROOM) - 1;
  584. csp.length = (sizeof(NOROOM) + 2) >> 2;
  585. csp.majorVersion = X_PROTOCOL;
  586. csp.minorVersion = X_PROTOCOL_REVISION;
  587. if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
  588. (!(*(char *) &whichbyte) && (byteOrder == 'l')))
  589. {
  590. swaps(&csp.majorVersion);
  591. swaps(&csp.minorVersion);
  592. swaps(&csp.length);
  593. }
  594. iov[0].iov_len = sz_xConnSetupPrefix;
  595. iov[0].iov_base = (char *) &csp;
  596. iov[1].iov_len = csp.lengthReason;
  597. iov[1].iov_base = NOROOM;
  598. iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
  599. iov[2].iov_base = pad;
  600. (void)_XSERVTransWritev(trans_conn, iov, 3);
  601. }
  602. }
  603. /************
  604. * CloseDownFileDescriptor:
  605. * Remove this file descriptor and it's I/O buffers, etc.
  606. ************/
  607. static void
  608. CloseDownFileDescriptor(OsCommPtr oc)
  609. {
  610. int connection = oc->fd;
  611. if (oc->trans_conn) {
  612. _XSERVTransDisconnect(oc->trans_conn);
  613. _XSERVTransClose(oc->trans_conn);
  614. }
  615. ConnectionTranslation[connection] = 0;
  616. FD_CLR(connection, &AllSockets);
  617. FD_CLR(connection, &AllClients);
  618. FD_CLR(connection, &ClientsWithInput);
  619. FD_CLR(connection, &GrabImperviousClients);
  620. if (GrabInProgress)
  621. {
  622. FD_CLR(connection, &SavedAllSockets);
  623. FD_CLR(connection, &SavedAllClients);
  624. FD_CLR(connection, &SavedClientsWithInput);
  625. }
  626. FD_CLR(connection, &ClientsWriteBlocked);
  627. if (!XFD_ANYSET(&ClientsWriteBlocked))
  628. AnyClientsWriteBlocked = FALSE;
  629. FD_CLR(connection, &OutputPending);
  630. }
  631. /*****************
  632. * CheckConnections
  633. * Some connection has died, go find which one and shut it down
  634. * The file descriptor has been closed, but is still in AllClients.
  635. * If would truly be wonderful if select() would put the bogus
  636. * file descriptors in the exception mask, but nooooo. So we have
  637. * to check each and every socket individually.
  638. *****************/
  639. void
  640. CheckConnections(void)
  641. {
  642. fd_mask mask;
  643. fd_set tmask;
  644. int curclient, curoff;
  645. int i;
  646. struct timeval notime;
  647. int r;
  648. notime.tv_sec = 0;
  649. notime.tv_usec = 0;
  650. for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
  651. {
  652. mask = AllClients.fds_bits[i];
  653. while (mask)
  654. {
  655. curoff = ffs (mask) - 1;
  656. curclient = curoff + (i * (sizeof(fd_mask)*8));
  657. FD_ZERO(&tmask);
  658. FD_SET(curclient, &tmask);
  659. r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
  660. if (r < 0)
  661. CloseDownClient(clients[ConnectionTranslation[curclient]]);
  662. mask &= ~((fd_mask)1 << curoff);
  663. }
  664. }
  665. }
  666. static void FreeOsBuffers(OsCommPtr oc) {
  667. ConnectionInputPtr oci;
  668. ConnectionOutputPtr oco;
  669. if (AvailableInput == oc)
  670. AvailableInput = (OsCommPtr)NULL;
  671. if ((oci = oc->input)) {
  672. if (FreeInputs) {
  673. free(oci->buffer);
  674. free(oci);
  675. } else {
  676. FreeInputs = oci;
  677. oci->next = (ConnectionInputPtr)NULL;
  678. oci->bufptr = oci->buffer;
  679. oci->bufcnt = 0;
  680. oci->lenLastReq = 0;
  681. }
  682. }
  683. if ((oco = oc->output)) {
  684. if (FreeOutputs) {
  685. free(oco->buf);
  686. free(oco);
  687. } else {
  688. FreeOutputs = oco;
  689. oco->next = (ConnectionOutputPtr)NULL;
  690. oco->count = 0;
  691. }
  692. }
  693. }
  694. /*****************
  695. * CloseDownConnection
  696. * Delete client from AllClients and free resources
  697. *****************/
  698. void
  699. CloseDownConnection(ClientPtr client)
  700. {
  701. OsCommPtr oc = (OsCommPtr)client->osPrivate;
  702. if (oc->output && oc->output->count)
  703. FlushClient(client, oc, (char *)NULL, 0);
  704. #ifdef XDMCP
  705. XdmcpCloseDisplay(oc->fd);
  706. #endif
  707. CloseDownFileDescriptor(oc);
  708. FreeOsBuffers(oc);
  709. client->osPrivate = (pointer)NULL;
  710. if (auditTrailLevel > 1)
  711. AuditF("client %d disconnected\n", client->index);
  712. free(oc);
  713. }
  714. _X_EXPORT void
  715. AddGeneralSocket(int fd)
  716. {
  717. FD_SET(fd, &AllSockets);
  718. if (GrabInProgress)
  719. FD_SET(fd, &SavedAllSockets);
  720. }
  721. _X_EXPORT void
  722. AddEnabledDevice(int fd)
  723. {
  724. FD_SET(fd, &EnabledDevices);
  725. AddGeneralSocket(fd);
  726. }
  727. _X_EXPORT void
  728. RemoveGeneralSocket(int fd)
  729. {
  730. FD_CLR(fd, &AllSockets);
  731. if (GrabInProgress)
  732. FD_CLR(fd, &SavedAllSockets);
  733. }
  734. _X_EXPORT void
  735. RemoveEnabledDevice(int fd)
  736. {
  737. FD_CLR(fd, &EnabledDevices);
  738. RemoveGeneralSocket(fd);
  739. }
  740. /*****************
  741. * OnlyListenToOneClient:
  742. * Only accept requests from one client. Continue to handle new
  743. * connections, but don't take any protocol requests from the new
  744. * ones. Note that if GrabInProgress is set, EstablishNewConnections
  745. * needs to put new clients into SavedAllSockets and SavedAllClients.
  746. * Note also that there is no timeout for this in the protocol.
  747. * This routine is "undone" by ListenToAllClients()
  748. *****************/
  749. void
  750. OnlyListenToOneClient(ClientPtr client)
  751. {
  752. OsCommPtr oc = (OsCommPtr)client->osPrivate;
  753. int connection = oc->fd;
  754. if (! GrabInProgress)
  755. {
  756. XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
  757. XFD_ANDSET(&ClientsWithInput,
  758. &ClientsWithInput, &GrabImperviousClients);
  759. if (FD_ISSET(connection, &SavedClientsWithInput))
  760. {
  761. FD_CLR(connection, &SavedClientsWithInput);
  762. FD_SET(connection, &ClientsWithInput);
  763. }
  764. XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
  765. XFD_COPYSET(&AllSockets, &SavedAllSockets);
  766. XFD_COPYSET(&AllClients, &SavedAllClients);
  767. XFD_UNSET(&AllSockets, &AllClients);
  768. XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
  769. FD_SET(connection, &AllClients);
  770. XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
  771. GrabInProgress = client->index;
  772. }
  773. }
  774. /****************
  775. * ListenToAllClients:
  776. * Undoes OnlyListentToOneClient()
  777. ****************/
  778. void
  779. ListenToAllClients(void)
  780. {
  781. if (GrabInProgress)
  782. {
  783. XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
  784. XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
  785. XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
  786. GrabInProgress = 0;
  787. }
  788. }
  789. /****************
  790. * IgnoreClient
  791. * Removes one client from input masks.
  792. * Must have cooresponding call to AttendClient.
  793. ****************/
  794. _X_EXPORT void
  795. IgnoreClient (ClientPtr client)
  796. {
  797. OsCommPtr oc = (OsCommPtr)client->osPrivate;
  798. int connection = oc->fd;
  799. isItTimeToYield = TRUE;
  800. if (!GrabInProgress || FD_ISSET(connection, &AllClients))
  801. {
  802. if (FD_ISSET (connection, &ClientsWithInput))
  803. FD_SET(connection, &IgnoredClientsWithInput);
  804. else
  805. FD_CLR(connection, &IgnoredClientsWithInput);
  806. FD_CLR(connection, &ClientsWithInput);
  807. FD_CLR(connection, &AllSockets);
  808. FD_CLR(connection, &AllClients);
  809. FD_CLR(connection, &LastSelectMask);
  810. }
  811. else
  812. {
  813. if (FD_ISSET (connection, &SavedClientsWithInput))
  814. FD_SET(connection, &IgnoredClientsWithInput);
  815. else
  816. FD_CLR(connection, &IgnoredClientsWithInput);
  817. FD_CLR(connection, &SavedClientsWithInput);
  818. FD_CLR(connection, &SavedAllSockets);
  819. FD_CLR(connection, &SavedAllClients);
  820. }
  821. }
  822. /****************
  823. * AttendClient
  824. * Adds one client back into the input masks.
  825. ****************/
  826. _X_EXPORT void
  827. AttendClient (ClientPtr client)
  828. {
  829. OsCommPtr oc = (OsCommPtr)client->osPrivate;
  830. int connection = oc->fd;
  831. if (!GrabInProgress || GrabInProgress == client->index ||
  832. FD_ISSET(connection, &GrabImperviousClients))
  833. {
  834. FD_SET(connection, &AllClients);
  835. FD_SET(connection, &AllSockets);
  836. FD_SET(connection, &LastSelectMask);
  837. if (FD_ISSET (connection, &IgnoredClientsWithInput))
  838. FD_SET(connection, &ClientsWithInput);
  839. }
  840. else
  841. {
  842. FD_SET(connection, &SavedAllClients);
  843. FD_SET(connection, &SavedAllSockets);
  844. if (FD_ISSET(connection, &IgnoredClientsWithInput))
  845. FD_SET(connection, &SavedClientsWithInput);
  846. }
  847. }
  848. /* make client impervious to grabs; assume only executing client calls this */
  849. _X_EXPORT void
  850. MakeClientGrabImpervious(ClientPtr client)
  851. {
  852. OsCommPtr oc = (OsCommPtr)client->osPrivate;
  853. int connection = oc->fd;
  854. FD_SET(connection, &GrabImperviousClients);
  855. if (ServerGrabCallback)
  856. {
  857. ServerGrabInfoRec grabinfo;
  858. grabinfo.client = client;
  859. grabinfo.grabstate = CLIENT_IMPERVIOUS;
  860. CallCallbacks(&ServerGrabCallback, &grabinfo);
  861. }
  862. }
  863. /* make client pervious to grabs; assume only executing client calls this */
  864. _X_EXPORT void
  865. MakeClientGrabPervious(ClientPtr client)
  866. {
  867. OsCommPtr oc = (OsCommPtr)client->osPrivate;
  868. int connection = oc->fd;
  869. FD_CLR(connection, &GrabImperviousClients);
  870. if (GrabInProgress && (GrabInProgress != client->index))
  871. {
  872. if (FD_ISSET(connection, &ClientsWithInput))
  873. {
  874. FD_SET(connection, &SavedClientsWithInput);
  875. FD_CLR(connection, &ClientsWithInput);
  876. }
  877. FD_CLR(connection, &AllSockets);
  878. FD_CLR(connection, &AllClients);
  879. isItTimeToYield = TRUE;
  880. }
  881. if (ServerGrabCallback)
  882. {
  883. ServerGrabInfoRec grabinfo;
  884. grabinfo.client = client;
  885. grabinfo.grabstate = CLIENT_PERVIOUS;
  886. CallCallbacks(&ServerGrabCallback, &grabinfo);
  887. }
  888. }