|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24: /* $XConsortium: connection.c,v 1.88 88/10/22 22:06:31 keith Exp $ */
25: /*****************************************************************
26: * Stuff to create connections --- OS dependent
27: *
28: * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
29: * CloseDownConnection, CheckConnections, AddEnabledDevice,
30: * RemoveEnabledDevice, OnlyListToOneClient,
31: * ListenToAllClients,
32: *
33: * (WaitForSomething is in its own file)
34: *
35: * In this implementation, a client socket table is not kept.
36: * Instead, what would be the index into the table is just the
37: * file descriptor of the socket. This won't work for if the
38: * socket ids aren't small nums (0 - 2^8)
39: *
40: *****************************************************************/
41:
42: #ifdef ISOCONN
43: #include <math.h>
44: #endif /* ISOCONN */
45:
46: #include <dbm.h>
47: #undef NULL
48: #include "X.h"
49: #include "Xproto.h"
50: #include <sys/param.h>
51: #include <errno.h>
52: #include "Xos.h" /* for strings, file, time */
53: #include <sys/socket.h>
54:
55: #include <signal.h>
56: #include <fcntl.h>
57: #include <setjmp.h>
58:
59: #ifdef hpux
60: #include <sys/ioctl.h>
61: #endif
62:
63: #ifdef TCPCONN
64: #include <netinet/in.h>
65: #ifndef hpux
66: #include <netinet/tcp.h>
67: #endif
68: #endif
69:
70: #ifdef UNIXCONN
71: /*
72: * sites should be careful to have separate /tmp directories for diskless nodes
73: */
74: #include <sys/un.h>
75: #include <sys/stat.h>
76: static int unixDomainConnection = -1;
77: #endif
78:
79: #include <stdio.h>
80: #include <sys/uio.h>
81: #include "osstruct.h"
82: #include "osdep.h"
83: #include "opaque.h"
84: #include "dixstruct.h"
85:
86: #ifdef DNETCONN
87: #include <netdnet/dn.h>
88: #endif /* DNETCONN */
89:
90: #ifdef ISOCONN
91: #include <isode/psap.h>
92: #include <isode/tsap.h>
93: #include <isode/isoservent.h>
94:
95: extern char *isodetcpath;
96:
97: #ifdef ISODEBUG
98: /*
99: * Set to true for loads of TSAP messages...
100: */
101: int isodexbug = FALSE;
102: #endif /* ISODEBUG */
103:
104: /*
105: * array of fd 2 family map so we can lookup right function below...
106: * Its initialised at connection setup...
107: */
108: int fd2family[MAXSOCKS];
109: /*
110: * Globals for storing functions appropos each fd/socket type
111: * UNIX_IO (0) map to sys calls
112: * ISODE_IO (1) maps to my fns...
113: */
114:
115: extern int accept(), TAcceptFromClient();
116: int (*acceptfn[])() =
117: {
118: accept, TAcceptFromClient
119: };
120: extern getpeername(), getISOpeername();
121: int (*getpeerfn[])() =
122: {
123: getpeername, getISOpeername
124: };
125: /*
126: * Note yuckiness here XXX
127: * TReadFromClient takes one more param than read - must fix...
128: */
129: extern int read(), TReadFromClient();
130: int (*readfn[])() =
131: {
132: read, TReadFromClient
133: };
134: extern int write(), TWriteToClient();
135: int (*writefn[])() =
136: {
137: write, TWriteToClient
138: };
139: extern writev(), TWritevToClient();
140: int (*writevfn[])() =
141: {
142: writev, TWritevToClient
143: };
144: extern int close(), TDiscFromClient();
145: int (*closefn[])() =
146: {
147: close, TDiscFromClient
148: };
149:
150: #endif /* ISOCONN */
151:
152: typedef long CCID; /* mask of indices into client socket table */
153:
154: #ifndef X_UNIX_PATH
155: #define X_UNIX_DIR "/tmp/.X11-unix"
156: #define X_UNIX_PATH "/tmp/.X11-unix/X"
157: #endif
158:
159: #ifdef ISOCONN
160: char *display = NULLCP; /* The display number */
161: #else /* ISOCONN */
162: char *display; /* The display number */
163: #endif /* ISOCONN */
164: int lastfdesc; /* maximum file descriptor */
165:
166: long WellKnownConnections; /* Listener mask */
167: long EnabledDevices; /* mask for input devices that are on */
168: long AllSockets[mskcnt]; /* select on this */
169: long AllClients[mskcnt]; /* available clients */
170: long LastSelectMask[mskcnt]; /* mask returned from last select call */
171: long ClientsWithInput[mskcnt]; /* clients with FULL requests in buffer */
172: long ClientsWriteBlocked[mskcnt];/* clients who cannot receive output */
173: long OutputPending[mskcnt]; /* clients with reply/event data ready to go */
174: long MaxClients = MAXSOCKS ;
175: long OutputBufferSize = BUFSIZ; /* output buffer size (must be > 0) */
176: long NConnBitArrays = mskcnt;
177: long FirstClient;
178: Bool NewOutputPending; /* not yet attempted to write some new output */
179: Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
180:
181: static Bool debug_conns = FALSE;
182:
183: static char whichByteIsFirst;
184:
185: static int SavedAllClients[mskcnt];
186: static int SavedAllSockets[mskcnt];
187: static int SavedClientsWithInput[mskcnt];
188: static Bool GrabDone = FALSE;
189:
190: ClientPtr ConnectionTranslation[MAXSOCKS];
191: extern ClientPtr NextAvailableClient();
192:
193: extern ConnectionInput inputBuffers[];
194:
195: int swappedClients[MAXSOCKS];
196:
197: extern int AutoResetServer();
198: extern int GiveUp();
199:
200: #ifdef UNIXCONN
201:
202: static struct sockaddr_un unsock;
203:
204: static int open_unix_socket ()
205: {
206: int oldUmask;
207: int request;
208:
209: unsock.sun_family = AF_UNIX;
210: oldUmask = umask (0);
211: #ifdef X_UNIX_DIR
212: mkdir (X_UNIX_DIR, 0777);
213: #endif
214: strcpy (unsock.sun_path, X_UNIX_PATH);
215: strcat (unsock.sun_path, display);
216: unlink (unsock.sun_path);
217: if ((request = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
218: {
219: Notice ("Creating Unix socket");
220: }
221: else
222: {
223: if(bind(request,(struct sockaddr *)&unsock, strlen(unsock.sun_path)+2))
224: Error ("Binding Unix socket");
225: if (listen (request, 5)) Error ("Unix Listening");
226: }
227: (void)umask(oldUmask);
228: return request;
229: }
230: #endif /*UNIXCONN */
231:
232: /*****************
233: * CreateWellKnownSockets
234: * At initialization, create the sockets to listen on for new clients.
235: * There are potentially 4: DECnet, UNIX Domain, TCP-IP with MSB first,
236: * with TCP-IP with LSB first.
237: *****************/
238:
239: void
240: CreateWellKnownSockets()
241: {
242: int request, i;
243: int whichbyte; /* used to figure out whether this is
244: LSB or MSB */
245: #ifdef TCPCONN
246: struct sockaddr_in insock;
247: int tcpportReg; /* port with same byte order as server */
248:
249: #ifdef SO_LINGER
250: static int linger[2] = { 0, 0 };
251: #endif /* SO_LINGER */
252:
253: #endif /* TCPCONN */
254:
255: #ifdef DNETCONN
256: struct sockaddr_dn dnsock;
257: #endif /* DNETCONN */
258:
259: #ifdef ISOCONN
260: struct TSAPdisconnect tds;
261: struct TSAPdisconnect *td = &tds;
262: struct TSAPaddr tas;
263: struct TSAPaddr *ta = &tas;
264: struct PSAPaddr *pa;
265: AEI aei;
266: #endif /* ISOCONN */
267: int retry;
268:
269: #ifdef ISOCONN
270: #ifdef ISODEBUG
271: isodetcpath = ISODEPATH;
272: #endif
273: #endif /* ISOCONN */
274:
275: CLEARBITS(AllSockets);
276: CLEARBITS(AllClients);
277: CLEARBITS(LastSelectMask);
278: CLEARBITS(ClientsWithInput);
279:
280: for (i=0; i<MAXSOCKS; i++) ConnectionTranslation[i] = (ClientPtr)NULL;
281:
282: #ifdef hpux
283: lastfdesc = _NFILE - 1;
284: #else
285: lastfdesc = getdtablesize() - 1;
286: #endif /* hpux */
287:
288: if (lastfdesc > MAXSOCKS)
289: {
290: lastfdesc = MAXSOCKS;
291: if (debug_conns)
292: ErrorF( "GOT TO END OF SOCKETS %d\n", MAXSOCKS);
293: }
294:
295: WellKnownConnections = 0;
296: whichbyte = 1;
297:
298: if (*(char *) &whichbyte)
299: whichByteIsFirst = 'l';
300: else
301: whichByteIsFirst = 'B';
302:
303:
304: #ifdef TCPCONN
305:
306: tcpportReg = atoi (display);
307: tcpportReg += X_TCP_PORT;
308:
309: if ((request = socket (AF_INET, SOCK_STREAM, 0)) < 0)
310: {
311: Notice ("Creating TCP socket");
312: }
313: else
314: {
315: bzero ((char *)&insock, sizeof (insock));
316: insock.sin_family = AF_INET;
317: insock.sin_port = htons (tcpportReg);
318: insock.sin_addr.s_addr = htonl(INADDR_ANY);
319: retry = 20;
320: while (i = bind(request, (struct sockaddr *) &insock, sizeof (insock)))
321: {
322: #ifdef hpux
323: /* Necesary to restart the server without a reboot */
324: if (errno == EADDRINUSE)
325: set_socket_option (request, SO_REUSEADDR);
326: if (--retry == 0)
327: Error ("Binding TCP socket");
328: sleep (1);
329: #else
330: if (--retry == 0)
331: Error ("Binding MSB TCP socket");
332: sleep (10);
333: #endif /* hpux */
334: }
335: #ifdef hpux
336: /* return the socket option to the original */
337: if (errno)
338: unset_socket_option (request, SO_REUSEADDR);
339: #endif /* hpux */
340: #ifdef SO_LINGER
341: if(setsockopt (request, SOL_SOCKET, SO_LINGER,
342: (char *)linger, sizeof(linger)))
343: Notice ("Setting TCP SO_LINGER\n");
344: #endif /* SO_LINGER */
345: if (listen (request, 5))
346: Error ("Reg TCP Listening");
347: WellKnownConnections |= (1 << request);
348: DefineSelf (request);
349: #ifdef ISOCONN
350: fd2family[request] = UNIX_IO;
351: #endif /* ISOCONN */
352: }
353:
354: #endif /* TCPCONN */
355:
356: #ifdef UNIXCONN
357: if ((request = open_unix_socket ()) != -1) {
358: WellKnownConnections |= (1L << request);
359: unixDomainConnection = request;
360: #ifdef ISOCONN
361: fd2family[request] = UNIX_IO;
362: #endif /* ISOCONN */
363: }
364: #endif /*UNIXCONN */
365:
366: #ifdef DNETCONN
367: if ((request = socket (AF_DECnet, SOCK_STREAM, 0)) < 0)
368: {
369: Notice ("Creating DECnet socket");
370: }
371: else
372: {
373: bzero ((char *)&dnsock, sizeof (dnsock));
374: dnsock.sdn_family = AF_DECnet;
375: sprintf(dnsock.sdn_objname, "X$X%d", atoi (display));
376: dnsock.sdn_objnamel = strlen(dnsock.sdn_objname);
377: if (bind (request, (struct sockaddr *) &dnsock, sizeof (dnsock)))
378: Error ("Binding DECnet socket");
379: if (listen (request, 5)) Error ("DECnet Listening");
380: WellKnownConnections |= (1 << request);
381: DefineSelf (request);
382: #ifdef ISOCONN
383: fd2family[request] = UNIX_IO;
384: #endif /* ISOCONN */
385: }
386: #endif /* DNETCONN */
387: #ifdef ISOCONN
388: /*
389: * If display is set, its the string after the Colon:
390: * i.e. X0 or X1 or T0 or T1...
391: */
392: if ((display == NULLCP) || (atoi(display) == 0))
393: aei = str2aei(TLocalHostName(), DEFAULTTSERVICE);
394: else
395: aei = str2aei(TLocalHostName(), display);
396:
397: if (aei == NULLAEI) {
398: ErrorF("No AEI for me:");
399: FatalError(TLocalHostName());
400: }
401:
402: /*
403: * This hack only works if the PSAPaddr and SSAP addrsd are null!!
404: */
405: if ((pa = aei2addr (aei)) == NULLPA)
406: FatalError("address translation failed");
407:
408: ta = (struct TSAPaddr *)&(pa->pa_addr.sa_addr);
409:
410: /*
411: * Just put out a listen for now
412: */
413: if ((request = TNetListen(ta, td)) != OK) {
414: Error(TErrString(td->td_reason));
415: FatalError("TNetListen");
416: }
417:
418: WellKnownConnections |= (1 << request);
419: DefineSelf (request);
420: fd2family[request] = ISODE_IO;
421: #endif /* ISOCONN */
422: if (WellKnownConnections == 0)
423: Error ("No Listeners, nothing to do");
424: signal (SIGPIPE, SIG_IGN);
425: signal (SIGHUP, AutoResetServer);
426: signal (SIGINT, GiveUp);
427: signal (SIGTERM, GiveUp);
428: FirstClient = request + 1;
429: AllSockets[0] = WellKnownConnections;
430: ResetHosts(display);
431:
432: for (i=0; i<MaxClients; i++)
433: {
434: inputBuffers[i].buffer = (char *) NULL;
435: inputBuffers[i].bufptr = (char *) NULL;
436: inputBuffers[i].bufcnt = 0;
437: inputBuffers[i].lenLastReq = 0;
438: inputBuffers[i].size = 0;
439: }
440: }
441:
442: void
443: ResetWellKnownSockets ()
444: {
445: #ifdef UNIXCONN
446: if (unixDomainConnection != -1)
447: {
448: /*
449: * see if the unix domain socket has disappeared
450: */
451: struct stat statb;
452:
453: if (stat (unsock.sun_path, &statb) == -1 ||
454: (statb.st_mode & S_IFMT) != S_IFSOCK)
455: {
456: ErrorF ("Unix domain socket %s trashed, recreating\n",
457: unsock.sun_path);
458: (void) unlink (unsock.sun_path);
459: (void) close (unixDomainConnection);
460: WellKnownConnections &= ~(1L << unixDomainConnection);
461: unixDomainConnection = open_unix_socket ();
462: if (unixDomainConnection != -1)
463: WellKnownConnections |= (1L << unixDomainConnection);
464: }
465: }
466: #endif /* UNIXCONN */
467: }
468:
469: #ifdef ISOCONN
470: /*
471: * Convenience routine...
472: * client = transport descriptor
473: * data, size = buffer
474: * nonblock = NOTOK, blocks, OK, non blocks
475: */
476: TReadFromClient(client, data, size, nonblock)
477: int client, size, nonblock;
478: char *data;
479: {
480: struct TSAPdisconnect tds;
481: struct TSAPdisconnect *td = &tds;
482: int ret;
483: static struct TSAPdata txs;
484: static struct TSAPdata *tx = &txs;
485: char *aptr;
486: static struct qbuf *qb;
487: static char *qptr;
488: static int ingot, qcpy, result = 0;
489: int q2data;
490:
491: #ifdef ISODEBUG
492: if (isodexbug) {
493: fprintf(stderr, "TReadFromClient %d want %d (%d buffered)\n",
494: client, size, result);
495: }
496: #endif /* ISODEBUG */
497: if (result == 0) {
498: if ((ret = TReadRequest(client, tx, nonblock, td)) == NOTOK) {
499: #ifdef ISODEBUG
500: if(errno == EWOULDBLOCK ) {
501: fprintf(stderr, "Server TReadReq: would block %s\n",
502: TErrString(td->td_reason));
503: if (!DR_FATAL(td->td_reason))
504: errno = EWOULDBLOCK;
505: else
506: errno = EBADF;
507: return ret;
508: }
509: if (isodexbug)
510: fprintf(stderr, "Server TReadReq: %s\n",
511: TErrString(td->td_reason));
512: #endif /* ISODEBUG */
513: /*
514: * map problems here - eg TimeOut...
515: */
516: if (td->td_reason == DR_TIMER)
517: errno = EWOULDBLOCK;
518: return ret;
519: }
520: result = tx->tx_cc;
521: qb = &(tx->tx_qbuf);
522: qptr = qb->qb_data;
523: #ifdef ISODEBUG
524: if (isodexbug)
525: fprintf(stderr, "TReadRequest want %d got %d\n",
526: size, result);
527: #endif
528: }
529: #ifdef ISODEBUG
530: else {
531: if (isodexbug)
532: fprintf(stderr, "TReadFromClient want %d buffered %d\n",
533: size, result);
534: }
535: #endif
536: /*
537: * Buffer it
538: */
539: ingot = 0;
540: aptr = data;
541: for(ingot = 0, aptr = data, q2data = min(size, result);
542: ingot<q2data;
543: aptr += qcpy, ingot+= qcpy) {
544: int aleft = q2data - ingot;
545: if (qb->qb_len > aleft) {
546: qcpy = aleft;
547: bcopy(qptr, aptr, qcpy);
548: qptr += aleft;
549: } else {
550: qcpy = qb->qb_len;
551: bcopy(qb->qb_data, aptr, qcpy);
552: if ((qb = qb->qb_forw) == NULL)
553: break;
554: qptr = qb->qb_data;
555: }
556: }
557: if ((result -= ingot) <= 0) {
558: result = 0;
559: TXFREE(tx);
560: }
561: return ingot;
562: }
563:
564: #endif /* ISOCONN */
565:
566: /* We want to read the connection information. If the client doesn't
567: * send us enough data, however, we want to time out eventually.
568: * The scheme is to clear a flag, set an alarm, and keep doing non-blocking
569: * reads until we get all the data we want. If the alarm goes
570: * off, the handler will clear the flag. If we see that the flag is
571: * cleared, we know we've timed out and return with an error.
572: *
573: * there remains one problem with this code:
574: * there is a window of vulnerability in which we might get an alarm
575: * even though all the data has come in properly. This is because I
576: * can't atomically clear the alarm.
577: *
578: * Anyone who sees how to fix this problem should do so and
579: * submit a fix.
580: */
581:
582: jmp_buf env;
583: void TimeOut()
584: {
585: longjmp(env, 1);
586: }
587: static Bool
588: ReadBuffer(conn, buffer, charsWanted)
589: long conn;
590: char *buffer;
591: int charsWanted;
592: {
593: char *bptr = buffer;
594: int got, fTimeOut;
595: struct itimerval itv;
596:
597: signal(SIGALRM, TimeOut);
598: fTimeOut = FALSE;
599: /* only 1 alarm, please, not 1 per minute */
600: timerclear(&itv.it_interval);
601: itv.it_value.tv_sec = TimeOutValue;
602: itv.it_value.tv_usec = 0;
603: setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL);
604: /* It better not take a full minute to get to the read call */
605:
606: while (charsWanted && (fTimeOut = setjmp(env)) == FALSE)
607: {
608: #ifdef ISOCONN
609: got = SRead(conn, bptr, charsWanted, NOTOK);
610: #else /* ISOCONN */
611: got = read(conn, bptr, charsWanted);
612: #endif /* ISOCONN */
613: if (got <= 0)
614: return FALSE;
615: if(got > 0)
616: {
617: charsWanted -= got;
618: bptr += got;
619: /* Ok, we got something, reset the timer */
620: itv.it_value.tv_sec = TimeOutValue;
621: itv.it_value.tv_usec = 0;
622: setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL);
623: }
624: }
625: /* disable the timer */
626: timerclear(&itv.it_value);
627: setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL);
628: /* If we got here and we didn't time out, then return TRUE, because
629: * we must have read what we wanted. If we timed out, return FALSE */
630: if(fTimeOut && debug_conns)
631: ErrorF("Timed out on connection %d\n", conn);
632: return (!fTimeOut);
633: }
634:
635: #ifdef ISOCONN
636: /*
637: * Who's calling us?
638: */
639: getISOpeername (conn, from, alen)
640: int conn;
641: struct TSAPaddr *from;
642: int *alen;
643: {
644: struct TSAPdisconnect td;
645: if (TGetAddresses (conn, from, NULLTA, &td) == NOTOK) {
646: Error(TErrString(td.td_reason));
647: return TRUE;
648: };
649: *alen = sizeof(struct TSAPaddr);
650: return FALSE;
651: }
652: #endif /* ISOCONN */
653: /*****************************************************************
654: * ClientAuthorized
655: *
656: * Sent by the client at connection setup:
657: * typedef struct _xConnClientPrefix {
658: * CARD8 byteOrder;
659: * BYTE pad;
660: * CARD16 majorVersion, minorVersion;
661: * CARD16 nbytesAuthProto;
662: * CARD16 nbytesAuthString;
663: * } xConnClientPrefix;
664: *
665: * It is hoped that eventually one protocol will be agreed upon. In the
666: * mean time, a server that implements a different protocol than the
667: * client expects, or a server that only implements the host-based
668: * mechanism, will simply ignore this information.
669: *
670: *****************************************************************/
671:
672: int
673: ClientAuthorized(conn, pswapped, reason)
674: long conn;
675: int *pswapped;
676: char **reason; /* if authorization fails, put reason in here */
677: {
678: short slen;
679: union {
680: struct sockaddr sa;
681: #ifdef UNIXCONN
682: struct sockaddr_un un;
683: #endif /* UNIXCONN */
684: #ifdef TCPCONN
685: struct sockaddr_in in;
686: #endif /* TCPCONN */
687: #ifdef DNETCONN
688: struct sockaddr_dn dn;
689: #endif /* DNETCONN */
690: #ifdef ISOCONN
691: struct TSAPaddr ts;
692: #endif /* ISOCONN */
693: } from;
694: int fromlen;
695: xConnClientPrefix xccp;
696: char auth_proto[100];
697: char auth_string[100];
698:
699: #ifdef ISOCONN
700: /*
701: * For now we always auth an ISO client!!
702: * should use directory etc etc
703: */
704: *reason = 0;
705: #endif /* ISOCONN */
706: if (!ReadBuffer(conn, (char *)&xccp, sizeof(xConnClientPrefix)))
707: {
708: /* If they can't even give us this much, just blow them off
709: * without an error message */
710: *reason = 0;
711: return 0;
712: }
713: if (xccp.byteOrder != whichByteIsFirst)
714: {
715: SwapConnClientPrefix(&xccp);
716: *pswapped = TRUE;
717: }
718: else
719: *pswapped = FALSE;
720: if ((xccp.majorVersion != X_PROTOCOL) ||
721: (xccp.minorVersion != X_PROTOCOL_REVISION))
722: {
723: #define STR "Protocol version mismatch"
724: *reason = (char *)xalloc(sizeof(STR));
725: strcpy(*reason, STR);
726: if (debug_conns)
727: ErrorF("%s\n", STR);
728: #undef STR
729: return 0;
730: }
731: fromlen = sizeof (from);
732: #ifdef ISOCONN
733: if (SGetPeerName (conn, &(from.ts), &fromlen) ||
734: InvalidHost (&(from.ts), fromlen))
735: #else /* ISOCONN */
736: if (getpeername (conn, &from.sa, &fromlen) ||
737: InvalidHost (&from.sa, fromlen))
738: #endif /* ISOCONN */
739: {
740: #define STR "Server is not authorized to connect to host"
741: *reason = (char *)xalloc(sizeof(STR));
742: strcpy(*reason, STR);
743: #undef STR
744: return 0;
745: }
746:
747: slen = (xccp.nbytesAuthProto + 3) & ~3;
748: if ( slen )
749: if (!ReadBuffer(conn, auth_proto, slen))
750: {
751: #define STR "Length error in xConnClientPrefix for protocol authorization "
752: *reason = (char *)xalloc(sizeof(STR));
753: strcpy(*reason, STR);
754: return 0;
755: #undef STR
756: }
757: auth_proto[slen] = '\0';
758:
759: slen = (xccp.nbytesAuthString + 3) & ~3;
760: if ( slen)
761: if (!ReadBuffer(conn, auth_string, slen))
762: {
763: #define STR "Length error in xConnClientPrefix for protocol string"
764: *reason = (char *)xalloc(sizeof(STR));
765: strcpy(*reason, STR);
766: return 0;
767: #undef STR
768: }
769: auth_string[slen] = '\0';
770:
771: /* At this point, if the client is authorized to change the access control
772: * list, we should getpeername() information, and add the client to
773: * the selfhosts list. It's not really the host machine, but the
774: * true purpose of the selfhosts list is to see who may change the
775: * access control list.
776: */
777: return(1);
778: }
779:
780: static int padlength[4] = {0, 3, 2, 1};
781:
782: /*****************
783: * EstablishNewConnections
784: * If anyone is waiting on listened sockets, accept them.
785: * Returns a mask with indices of new clients. Updates AllClients
786: * and AllSockets.
787: *****************/
788:
789: void
790: #ifdef ISOCONN
791: EstablishNewConnections(newclients, nnew, vecp, vec)
792: ClientPtr *newclients;
793: int *nnew;
794: int vecp;
795: char **vec;
796: #else /* ISOCONN */
797: EstablishNewConnections(newclients, nnew)
798: ClientPtr *newclients;
799: int *nnew;
800: #endif /* ISOCONN */
801: {
802: long readyconnections; /* mask of listeners that are ready */
803: long curconn; /* fd of listener that's ready */
804: long newconn; /* fd of new client */
805: int swapped; /* set by ClientAuthorized if connection is
806: * swapped */
807: char *reason;
808: struct iovec iov[2];
809: #ifdef ISOCONN
810: struct udvec uv[3];
811: struct TSAPdisconnect tds;
812: struct TSAPdisconnect *td = &tds;
813: struct TSAPstart tsts;
814: struct TSAPstart *tst = &tsts;
815: #endif /* ISOCONN */
816: char p[3];
817:
818: #ifdef TCP_NODELAY
819: union {
820: struct sockaddr sa;
821: #ifdef UNIXCONN
822: struct sockaddr_un un;
823: #endif /* UNIXCONN */
824: #ifdef TCPCONN
825: struct sockaddr_in in;
826: #endif /* TCPCONN */
827: #ifdef DNETCONN
828: struct sockaddr_dn dn;
829: #endif /* DNETCONN */
830: } from;
831: int fromlen;
832: #endif TCP_NODELAY
833:
834: *nnew = 0;
835: if (readyconnections = (LastSelectMask[0] & WellKnownConnections))
836: {
837: while (readyconnections)
838: {
839: curconn = ffs (readyconnections) - 1;
840: #ifdef ISOCONN
841: /*
842: * At this point, a TAccept has finished with a vec > 0
843: * so we need to init them...
844: */
845: if ((newconn = SAccept(curconn, vecp, vec)) >= 0)
846: {
847: fd2family[newconn] = ISODE_IO;
848: #else /* ISOCONN */
849: if ((newconn = accept (curconn,
850: (struct sockaddr *) NULL,
851: (int *)NULL)) >= 0)
852: {
853: fd2family[newconn] = UNIX_IO;
854: #endif /* ISOCONN */
855: if (newconn >= lastfdesc)
856: {
857: if (debug_conns)
858: ErrorF("Didn't make connection: Out of file descriptors for connections\n");
859: #ifdef ISOCONN
860: SClose(newconn);
861: #else /* ISOCONN */
862: close (newconn);
863: #endif /* ISOCONN */
864: }
865: else
866: {
867: ClientPtr next = (ClientPtr)NULL;
868:
869: #ifdef TCP_NODELAY
870: #ifdef ISOCONN
871: if (fd2family(newconn) == UNIX_IO)
872: {
873: #endif /* ISOCONN */
874: fromlen = sizeof (from);
875: if (!getpeername (newconn, &from.sa, &fromlen))
876: {
877: if (fromlen && (from.sa.sa_family == AF_INET))
878: {
879: int mi = 1;
880: setsockopt (newconn, IPPROTO_TCP, TCP_NODELAY,
881: (char *)&mi, sizeof (int));
882: }
883: }
884: #ifdef ISOCONN
885: }
886: #endif /* ISOCONN */
887: #endif /* TCP_NODELAY */
888: if (ClientAuthorized(newconn, &swapped, &reason))
889: {
890: #ifdef hpux
891: /*
892: * HPUX does not have FNDELAY
893: */
894: {
895: int arg;
896: arg = 1;
897: ioctl(newconn, FIOSNBIO, &arg);
898: }
899: #else
900: fcntl (newconn, F_SETFL, FNDELAY);
901: #endif /* hpux */
902: inputBuffers[newconn].used = 1;
903: if (! inputBuffers[newconn].size)
904: {
905: inputBuffers[newconn].buffer =
906: (char *)xalloc(BUFSIZE);
907: inputBuffers[newconn].size = BUFSIZE;
908: inputBuffers[newconn].bufptr =
909: inputBuffers[newconn].buffer;
910: }
911: if (GrabDone)
912: {
913: BITSET(SavedAllClients, newconn);
914: BITSET(SavedAllSockets, newconn);
915: }
916: else
917: {
918: BITSET(AllClients, newconn);
919: BITSET(AllSockets, newconn);
920: }
921: next = NextAvailableClient();
922: if (next != (ClientPtr)NULL)
923: {
924: OsCommPtr priv;
925:
926: newclients[(*nnew)++] = next;
927: next->swapped = swapped;
928: ConnectionTranslation[newconn] = next;
929: priv = (OsCommPtr)xalloc(sizeof(OsCommRec));
930: priv->fd = newconn;
931: priv->buf = (unsigned char *)
932: xalloc(OutputBufferSize);
933: priv->bufsize = OutputBufferSize;
934: priv->count = 0;
935: next->osPrivate = (pointer)priv;
936: }
937: else
938: {
939: #define STR "Maximum number of clients exceeded"
940: reason = (char *)xalloc(sizeof(STR));
941: strcpy(reason, STR);
942: #undef STR
943: }
944: }
945: if (next == (ClientPtr)NULL)
946: {
947: xConnSetupPrefix c;
948:
949: if(reason)
950: {
951: c.success = xFalse;
952: c.lengthReason = strlen(reason);
953: c.length = (c.lengthReason + 3) >> 2;
954: c.majorVersion = X_PROTOCOL;
955: c.minorVersion = X_PROTOCOL_REVISION;
956: if(swapped)
957: {
958: int n;
959:
960: swaps(&c.majorVersion, n);
961: swaps(&c.minorVersion, n);
962: swaps(&c.length, n);
963: }
964:
965: #ifdef ISOCONN
966: (void)SWrite(newconn, (char *)&c, sizeof(xConnSetupPrefix));
967: #else /* ISOCONN */
968: write(newconn, (char *)&c, sizeof(xConnSetupPrefix));
969: #endif /* ISOCONN */
970: iov[0].iov_len = c.lengthReason;
971: iov[0].iov_base = reason;
972: iov[1].iov_len = padlength[c.lengthReason & 3];
973: iov[1].iov_base = p;
974: #ifdef ISOCONN
975: SWritev(newconn, iov, 2);
976: #else /* ISOCONN */
977: writev(newconn, iov, 2);
978: #endif /* ISOCONN */
979: if (debug_conns)
980: ErrorF("Didn't make connection:%s\n", reason);
981: }
982: #ifdef ISOCONN
983: SClose(newconn);
984: #else /* ISOCONN */
985: close(newconn);
986: #endif /* ISOCONN */
987: xfree(reason);
988: }
989:
990: }
991: }
992: readyconnections &= ~(1 << curconn);
993: }
994: }
995: }
996:
997: /************
998: * CloseDownFileDescriptor:
999: * Remove this file descriptor and it's inputbuffers, etc.
1000: ************/
1001:
1002: void
1003: CloseDownFileDescriptor(connection)
1004: int connection;
1005: {
1006: #ifdef ISOCONN
1007: struct TSAPdisconnect tds;
1008: #ifdef ISODEBUG
1009: if (isodexbug)
1010: fprintf(stderr, "server: TDiscReq\n");
1011: #endif /* ISODEBUG */
1012: SClose(connection);
1013: #else /* ISOCONN */
1014: close(connection);
1015: #endif /* ISOCONN */
1016:
1017: if (inputBuffers[connection].size)
1018: {
1019: xfree(inputBuffers[connection].buffer);
1020: inputBuffers[connection].buffer = (char *) NULL;
1021: inputBuffers[connection].bufptr = (char *) NULL;
1022: inputBuffers[connection].size = 0;
1023: }
1024: inputBuffers[connection].bufcnt = 0;
1025: inputBuffers[connection].lenLastReq = 0;
1026: inputBuffers[connection].used = 0;
1027:
1028: BITCLEAR(AllSockets, connection);
1029: BITCLEAR(AllClients, connection);
1030: BITCLEAR(ClientsWithInput, connection);
1031: BITCLEAR(ClientsWriteBlocked, connection);
1032: if (!ANYSET(ClientsWriteBlocked))
1033: AnyClientsWriteBlocked = FALSE;
1034: }
1035:
1036: /*****************
1037: * CheckConections
1038: * Some connection has died, go find which one and shut it down
1039: * The file descriptor has been closed, but is still in AllClients.
1040: * If would truly be wonderful if select() would put the bogus
1041: * file descriptors in the exception mask, but nooooo. So we have
1042: * to check each and every socket individually.
1043: *****************/
1044:
1045: void
1046: CheckConnections()
1047: {
1048: long mask[mskcnt];
1049: long tmask[mskcnt];
1050: register int curclient;
1051: int i;
1052: struct timeval notime;
1053: ClientPtr bad;
1054: int r;
1055: #ifdef ISOCONN
1056: struct TSAPdisconnect tds;
1057: struct TSAPdisconnect *td = &tds;
1058: char *vec[4];
1059: int vecp;
1060: #endif /* ISOCONN */
1061:
1062: notime.tv_sec = 0;
1063: notime.tv_usec = 0;
1064:
1065: COPYBITS(AllClients, mask);
1066: for (i=0; i<mskcnt; i++)
1067: {
1068: while (mask[i])
1069: {
1070: curclient = ffs (mask[i]) - 1 + (i << 5);
1071: CLEARBITS(tmask);
1072: BITSET(tmask, curclient);
1073: #ifdef ISOCONN
1074: r = TNetAccept (&vecp, vec,
1075: curclient + 1, tmask, (int *)NULL, (int *)NULL,
1076: OK, td);
1077: if (r == NOTOK)
1078: {
1079: Error(TErrString(td->td_reason));
1080: Error("TNetAccept");
1081: #else /* ISOCONN */
1082: r = select (curclient + 1, tmask, (int *)NULL, (int *)NULL,
1083: ¬ime);
1084: if (r < 0)
1085: {
1086: #endif /* ISOCONN */
1087: if (bad = ConnectionTranslation[curclient])
1088: CloseDownClient(bad);
1089: else
1090: CloseDownFileDescriptor(curclient);
1091: }
1092: BITCLEAR(mask, curclient);
1093: }
1094: }
1095: }
1096:
1097:
1098: /*****************
1099: * CloseDownConnection
1100: * Delete client from AllClients and free resources
1101: *****************/
1102:
1103: CloseDownConnection(client)
1104: ClientPtr client;
1105: {
1106: OsCommPtr oc = (OsCommPtr)client->osPrivate;
1107:
1108: ConnectionTranslation[oc->fd] = (ClientPtr)NULL;
1109: CloseDownFileDescriptor(oc->fd);
1110: if (oc->buf != NULL) /* an Xrealloc may have returned NULL */
1111: xfree(oc->buf);
1112: xfree(client->osPrivate);
1113: }
1114:
1115:
1116: AddEnabledDevice(fd)
1117: int fd;
1118: {
1119: EnabledDevices |= (1<<fd);
1120: BITSET(AllSockets, fd);
1121: }
1122:
1123:
1124: RemoveEnabledDevice(fd)
1125: int fd;
1126: {
1127: EnabledDevices &= ~(1<<fd);
1128: BITCLEAR(AllSockets, fd);
1129: }
1130:
1131: /*****************
1132: * OnlyListenToOneClient:
1133: * Only accept requests from one client. Continue to handle new
1134: * connections, but don't take any protocol requests from the new
1135: * ones. Note that if GrabDone is set, EstablishNewConnections
1136: * needs to put new clients into SavedAllSockets and SavedAllClients.
1137: * Note also that there is no timeout for this in the protocol.
1138: * This routine is "undone" by ListenToAllClients()
1139: *****************/
1140:
1141: OnlyListenToOneClient(client)
1142: ClientPtr client;
1143: {
1144: OsCommPtr oc = (OsCommPtr)client->osPrivate;
1145: int connection = oc->fd;
1146:
1147: if (! GrabDone)
1148: {
1149: COPYBITS (ClientsWithInput, SavedClientsWithInput);
1150: BITCLEAR (SavedClientsWithInput, connection);
1151: if (GETBIT(ClientsWithInput, connection))
1152: {
1153: CLEARBITS(ClientsWithInput);
1154: BITSET(ClientsWithInput, connection);
1155: }
1156: else
1157: {
1158: CLEARBITS(ClientsWithInput);
1159: }
1160: COPYBITS(AllSockets, SavedAllSockets);
1161: COPYBITS(AllClients, SavedAllClients);
1162:
1163: UNSETBITS(AllSockets, AllClients);
1164: BITSET(AllSockets, connection);
1165: CLEARBITS(AllClients);
1166: BITSET(AllClients, connection);
1167: GrabDone = TRUE;
1168: }
1169: }
1170:
1171: /****************
1172: * ListenToAllClients:
1173: * Undoes OnlyListentToOneClient()
1174: ****************/
1175:
1176: ListenToAllClients()
1177: {
1178: if (GrabDone)
1179: {
1180: ORBITS(AllSockets, AllSockets, SavedAllSockets);
1181: ORBITS(AllClients, AllClients, SavedAllClients);
1182: ORBITS(ClientsWithInput, ClientsWithInput, SavedClientsWithInput);
1183: GrabDone = FALSE;
1184: }
1185: }
1186:
1187:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.