1 /*
2 * Copyright 1993 Network Computing Devices, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name Network Computing Devices, Inc. not be
9 * used in advertising or publicity pertaining to distribution of this
10 * software without specific, written prior permission.
11 *
12 * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
13 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
14 * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15 * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
16 * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
17 * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
18 * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
19 * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 *
22 * $NCDId: @(#)connection.c,v 1.11 1996/04/24 17:15:49 greg Exp $
23 */
24 /***********************************************************
25 Some portions derived from:
26
27 Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts,
28 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
29
30 All Rights Reserved
31
32 Permission to use, copy, modify, and distribute this software and its
33 documentation for any purpose and without fee is hereby granted,
34 provided that the above copyright notice appear in all copies and that
35 both that copyright notice and this permission notice appear in
36 supporting documentation, and that the names of Digital or MIT not be
37 used in advertising or publicity pertaining to distribution of the
38 software without specific, written prior permission.
39
40 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
41 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
42 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
43 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 SOFTWARE.
47
48 ******************************************************************/
49 /*****************************************************************
50 * Stuff to create connections --- OS dependent
51 *
52 * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
53 * CloseDownConnection, CheckConnections, AddEnabledDevice,
54 * RemoveEnabledDevice, OnlyListToOneClient,
55 * ListenToAllClients,
56 *
57 * (WaitForSomething is in its own file)
58 *
59 * In this implementation, a client socket table is not kept.
60 * Instead, what would be the index into the table is just the
61 * file descriptor of the socket. This won't work for if the
62 * socket ids aren't small nums (0 - 2^8)
63 *
64 *****************************************************************/
65
66 #include "nasconf.h"
67
68 #if defined(__CYGWIN__)
69 #define S_IFSOCK _IFSOCK
70 #define S_IFMT _IFMT
71 #endif /* __CYGWIN__ */
72
73 #if defined(__CYGWIN__) || defined(linux)
74 #include <stdlib.h>
75 #include <limits.h>
76 #include <string.h>
77 #include <sys/types.h>
78 #include <sys/socket.h>
79 #include <sys/stat.h>
80 #include <netinet/in.h>
81 #include <arpa/inet.h>
82 #include <netdb.h>
83 #endif /* defined(__CYGWIN__) || defined(linux) */
84
85
86
87 #include <audio/audio.h>
88 #include <audio/Aproto.h>
89 #ifndef _MINIX
90 #include <sys/param.h>
91 #endif
92 #include <errno.h>
93 #include <audio/Aos.h>
94 #if !defined(AMOEBA) && !defined(_MINIX)
95 #ifdef ESIX
96 #include <lan/socket.h>
97 #else
98 #include <sys/socket.h>
99 #endif
100 #endif
101
102 #include <signal.h>
103 #include <setjmp.h>
104
105 #ifdef hpux
106 #include <sys/utsname.h>
107 #include <sys/ioctl.h>
108 #endif
109
110 #ifdef SVR4
111 #include <sys/resource.h>
112 #endif
113
114 #ifdef AIXV3
115 #include <sys/ioctl.h>
116 #endif
117
118 #ifdef TCPCONN
119 #ifndef _MINIX
120 # include <netinet/in.h>
121 # ifndef hpux
122 # ifdef apollo
123 # ifndef NO_TCP_H
124 # include <netinet/tcp.h>
125 # endif
126 # else
127 # include <netinet/tcp.h>
128 # endif
129 # endif
130 #else /* _MINIX */
131 #include <sys/ioctl.h>
132 #include <stdlib.h>
133 #include <net/netlib.h>
134 #include <net/gen/in.h>
135 #include <net/gen/tcp.h>
136 #include <net/gen/tcp_io.h>
137 #endif /* _MINIX */
138 #endif
139
140 #if defined(SO_DONTLINGER) && defined(SO_LINGER)
141 #undef SO_DONTLINGER
142 #endif
143
144 #ifdef UNIXCONN
145 /*
146 * sites should be careful to have separate /tmp directories for diskless nodes
147 */
148 #include <sys/un.h>
149 #include <sys/stat.h>
150 static int unixDomainConnection = -1;
151 #endif
152
153 #include <stdio.h>
154 #if !defined(AMOEBA) && !defined(_MINIX)
155 #include <sys/uio.h>
156 #endif
157 #include "os.h"
158 #include "osdep.h"
159 #include "opaque.h"
160 #include "dixstruct.h"
161
162 #if defined(SYSV) || defined(SVR4)
163 #ifdef hpux
164 #define signal _local_signal
165 #define sigset _local_signal
166
167 #ifndef NeedFunctionPrototypes
168 static void (*_local_signal(sig, action)) ()
169 int sig;
170 void (*action) ();
171 #else /* NeedFunctionPrototypes */
_local_signal(int sig,void (* action)(int))172 static void (*_local_signal(int sig, void (*action) (int))) (int)
173 #endif /* NeedFunctionPrototypes */
174 {
175 struct sigvec vec;
176 struct sigvec ovec;
177
178 vec.sv_handler = action;
179 vec.sv_flags = 0;
180 sigvector(sig, &vec, &ovec);
181
182 return (ovec.sv_handler);
183 }
184 #else
185 #define signal sigset
186 #endif
187 #endif
188
189 #ifdef DNETCONN
190 #include <netdnet/dn.h>
191 #endif /* DNETCONN */
192
193 #ifndef SCO
194 #define _OSWriteV writev
195 #endif /* SCO */
196
197 #ifdef SIGNALRETURNSINT
198 #define SIGVAL int
199 #else
200 #define SIGVAL void
201 #endif
202
203 typedef long CCID; /* mask of indices into client socket table */
204
205 #ifndef X_UNIX_PATH
206 # ifdef hpux
207 # define X_UNIX_DIR "/usr/spool/sockets/audio"
208 # define X_UNIX_PATH "/usr/spool/sockets/audio/"
209 # define OLD_UNIX_DIR "/tmp/.sockets"
210 # else
211 # if defined(linux)
212 # define X_UNIX_DIR "/var/run/nasd"
213 # define X_UNIX_PATH "/var/run/nasd/audio"
214 # else
215 # define X_UNIX_DIR "/tmp/.sockets"
216 # define X_UNIX_PATH "/tmp/.sockets/audio"
217 # endif
218 # endif
219 #endif
220
221 #ifdef SERVER_LOCALCONN
222 #include <sys/stream.h>
223 #include <sys/stropts.h>
224 #include <sys/utsname.h>
225 #ifndef UNIXCONN
226 #include <sys/stat.h>
227 #endif
228 #ifdef SVR4
229 static int NstrFd = -1;
230 #endif
231 static int ptsFd = -1;
232 static int spxFd = -1;
233 static int xsFd = -1;
234 static long AllStreams[mskcnt]; /* keep up, whos on a STREAMS pipe */
235 /*
236 * Why not use the same path as for UNIXCONN ??
237 * Diskless workstations may have a common /tmp directory. This may cause much
238 * trouble. Since every workstation MUST have it's own /dev, so lets use this
239 * directory.
240 */
241 #define AUDIO_STREAMS_DIR "/dev/Au"
242 #define AUDIO_STREAMS_PATH "/dev/Au/server."
243 #ifdef SVR4
244 # define AUDIO_NSTREAMS_PATH "/dev/Au/Nserver."
245 #endif
246 #define AUDIO_XSIGHT_PATH "/dev/Au"
247 #if defined(SVR4_ACP) && defined(UNIXCONN)
248 # define AUDIO_ISC_DIR "/tmp/.ISC-unix"
249 # define AUDIO_ISC_PATH "/tmp/.ISC-unix/Au"
250 #endif
251 #endif /* SERVER_LOCALCONN */
252
253 extern char *display; /* The display number */
254 #ifndef AMOEBA
255 int lastfdesc; /* maximum file descriptor */
256
257 #ifndef _MINIX
258 long WellKnownConnections; /* Listener mask */
259 long EnabledDevices[mskcnt]; /* mask for input devices that are on */
260 long AllSockets[mskcnt]; /* select on this */
261 long AllClients[mskcnt]; /* available clients */
262 long LastSelectMask[mskcnt]; /* mask returned from last select call */
263 long ClientsWithInput[mskcnt]; /* clients with FULL requests in buffer */
264 long ClientsWriteBlocked[mskcnt]; /* clients who cannot receive output */
265 long OutputPending[mskcnt]; /* clients with reply/event data ready to go */
266 long NConnBitArrays = mskcnt;
267 #endif
268 long MaxClients = MAXSOCKS;
269 Bool NewOutputPending; /* not yet attempted to write some new output */
270 Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
271
272 Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
273 Bool PartialNetwork; /* continue even if unable to bind all addrs */
274 static int ParentProcess;
275
276 int AudioListenPort = AU_DEFAULT_TCP_PORT;
277
278 static Bool debug_conns = FALSE;
279
280 static long IgnoredClientsWithInput[mskcnt];
281 static long GrabImperviousClients[mskcnt];
282 #ifndef _MINIX
283 static long SavedAllClients[mskcnt];
284 static long SavedAllSockets[mskcnt];
285 static long SavedClientsWithInput[mskcnt];
286 #endif /* _MINIX */
287 int GrabInProgress = 0;
288
289 int ConnectionTranslation[MAXSOCKS];
290 #endif /* !AMOEBA */
291
292 #ifdef _MINIX
293 asio_fd_set_t InprogressFdSet; /* fds that have an operation in progress */
294 asio_fd_set_t ListenFdSet; /* fds that accept new connections */
295 asio_fd_set_t CompletedFdSet; /* fds that completed some I/O but have not
296 * been able to process this information
297 * synchronously (or completely) */
298 asio_fd_set_t ClientFdSet; /* fds that belong to clients */
299 asio_fd_set_t IgnoreFdSet; /* Ignore these clients if they have completed
300 * I/O */
301 asio_fd_set_t GrabFdSet; /* This is the client who has the grab,
302 * if any */
303
304 static int TcpListenFd = -1; /* initialy there is no tcp fd. */
305 Bool AnyClientsWithInput = FALSE;
306
307 struct NewConnection {
308 int nc_result; /* What was the result */
309 int nc_errno; /* and the error */
310 } NewTcpConnection;
311 #endif
312
313 extern int auditTrailLevel;
314 extern ClientPtr NextAvailableClient();
315
316 extern SIGVAL AutoResetServer();
317 extern SIGVAL GiveUp();
318 extern AuID CheckAuthorization();
319 #ifndef AMOEBA
320 static void CloseDownFileDescriptor(), ErrorConnMax();
321 #endif
322 extern void FreeOsBuffers(), ResetOsBuffers();
323
324 #ifdef TCPCONN
325 #ifndef _MINIX
326 static int
open_tcp_socket()327 open_tcp_socket()
328 {
329 struct sockaddr_in insock;
330 int request;
331 int retry;
332 #ifdef SVR4
333 #undef SO_DONTLINGER
334 #endif
335 #ifndef SO_DONTLINGER
336 #ifdef SO_LINGER
337 static int linger[2] = { 0, 0 };
338 #endif /* SO_LINGER */
339 #endif /* SO_DONTLINGER */
340
341 #ifdef AIXV3
342 #ifndef FORCE_DISPLAY_NUM
343 extern int AIXTCPSocket;
344 if (AIXTCPSocket >= 0) {
345 request = AIXTCPSocket;
346 } else
347 #endif /* FORCE_DISPLAY_NUM */
348 #endif /* AIX && etc. */
349 if ((request = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
350 Error("Creating TCP socket");
351 return -1;
352 }
353 #ifdef SO_REUSEADDR
354 /* Necesary to restart the server without a reboot */
355 {
356 int one = 1;
357 setsockopt(request, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
358 sizeof(int));
359 }
360 #endif /* SO_REUSEADDR */
361 #ifdef AIXV3
362 #ifndef FORCE_DISPLAY_NUMBER
363 if (AIXTCPSocket < 0)
364 #endif
365 #endif
366 {
367 bzero((char *) &insock, sizeof(insock));
368 #ifdef BSD44SOCKETS
369 insock.sin_len = sizeof(insock);
370 #endif
371 insock.sin_family = AF_INET;
372 insock.sin_port =
373 htons((unsigned short) (AudioListenPort + atoi(display)));
374
375 if (NasConfig.LocalOnly) {
376 insock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
377 } else {
378 insock.sin_addr.s_addr = htonl(INADDR_ANY);
379 }
380
381 retry = 20;
382 while (bind(request, (struct sockaddr *) &insock, sizeof(insock))) {
383 if (--retry == 0) {
384 Error("Binding TCP socket");
385 close(request);
386 return -1;
387 }
388 #ifdef SO_REUSEADDR
389 sleep(1);
390 #else
391 sleep(10);
392 #endif /* SO_REUSEDADDR */
393 }
394 }
395 #ifdef SO_DONTLINGER
396 if (setsockopt(request, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0))
397 Error("Setting TCP SO_DONTLINGER");
398 #else
399 #ifdef SO_LINGER
400 if (setsockopt(request, SOL_SOCKET, SO_LINGER,
401 (char *) linger, sizeof(linger)))
402 Error("Setting TCP SO_LINGER");
403 #endif /* SO_LINGER */
404 #endif /* SO_DONTLINGER */
405 if (listen(request, 5)) {
406 Error("TCP Listening");
407 close(request);
408 return -1;
409 }
410 return request;
411 }
412 #else /* _MINIX */
413
414 Bool EstablishNewConnections();
415
416 static int
MNX_open_tcp_socket(int * extra_fd)417 MNX_open_tcp_socket(int *extra_fd)
418 {
419 int fd, r, flags, retry;
420 char *tcp_dev, *check;
421 int display_no;
422 nwio_tcpconf_t tcpconf;
423 nwio_tcpcl_t tcpcl;
424
425 /* Allow the audio server to run on a different IP device with the
426 * TCP_DEVICE environment variable, otherwise we take the default.
427 * A different IP device is specified via its number concatenated
428 * to the TCP device name, so check that the default TCP device is
429 * a prefix of the value read from the TCP_DEVICE environment
430 * variable.
431 */
432 tcp_dev = getenv("TCP_DEVICE");
433 if (!tcp_dev || strncmp(tcp_dev, TCP_DEVICE, strlen(TCP_DEVICE))) {
434 fprintf(stderr, "Ignoring invalid TCP_DEVICE environment variable.\n");
435 tcp_dev = TCP_DEVICE;
436 }
437
438 fd = open(tcp_dev, O_RDWR);
439 if (fd == -1) {
440 Error("Creating TCP socket");
441 return -1;
442 }
443 if (extra_fd) {
444 *extra_fd = fd;
445
446 fd = open(tcp_dev, O_RDWR);
447 if (fd == -1) {
448 Error("Creating TCP socket");
449 close(*extra_fd);
450 return -1;
451 }
452 }
453
454 /* Bind the socket */
455 display_no = strtol(display, &check, 0);
456 if (check[0] != '\0') {
457 Error("Unable to parse display number");
458 return -1;
459 }
460 tcpconf.nwtc_flags = NWTC_SHARED | NWTC_LP_SET | NWTC_UNSET_RA |
461 NWTC_UNSET_RP;
462 tcpconf.nwtc_locport = htons(AUDIO_TCP_PORT + display_no);
463 r = ioctl(fd, NWIOSTCPCONF, &tcpconf);
464 if (r == -1) {
465 Error("Binding TCP socket");
466 close(fd);
467 return -1;
468 }
469
470 /* Mark the filedescriptor as asynchronous */
471 flags = fcntl(fd, F_GETFL);
472 if (flags == -1) {
473 Error("Unable to get the flags of a tcp fd");
474 close(fd);
475 return -1;
476 }
477 r = fcntl(fd, F_SETFD, flags | FD_ASYNCHIO);
478 if (r == -1) {
479 Error("Unable to enable asynchronous I/O on a tcp fd");
480 close(fd);
481 return -1;
482 }
483
484 /* Now try to listen, possible return values are:
485 * EINPROGRESS: the default, we can return the fd
486 * EAGAIN: all entry in the connection table are inuse,
487 * we wait a few seconds.
488 * 0: some client arrived, we enqueue
489 * EstablishNewConnections
490 */
491 for (retry = 0; retry < 10; retry++) {
492 tcpcl.nwtcl_flags = 0;
493 r = ioctl(fd, NWIOTCPLISTEN, &tcpcl);
494 if (r == -1 && errno == EINPROGRESS)
495 return fd; /* Normal case */
496 else if (r == -1 && errno == EAGAIN) {
497 sleep(1);
498 continue;
499 } else {
500 NewTcpConnection.nc_result = r;
501 NewTcpConnection.nc_errno = errno;
502
503 /* Let EstablishNewConnections deal with this
504 * situation
505 */
506 QueueWorkProc(EstablishNewConnections, NULL,
507 (pointer) & NewTcpConnection);
508 return fd;
509 }
510 }
511 Error("Binding TCP socket");
512 close(fd);
513 return -1;
514 }
515 #endif /* _MINIX */
516 #endif /* TCPCONN */
517
518 #ifdef UNIXCONN
519
520 static struct sockaddr_un unsock;
521
522 static int
open_unix_socket(void)523 open_unix_socket(void)
524 {
525 int oldUmask;
526 int request;
527
528 bzero((char *) &unsock, sizeof(unsock));
529 unsock.sun_family = AF_UNIX;
530 oldUmask = umask(0);
531
532 #ifdef X_UNIX_DIR
533 # ifndef S_ISVTX
534 # define S_ISVTX 0 /* shouldn't use it if not available */
535 # endif
536
537 /* JET - 2/23/2002 this is problematic when nasd is run as a
538 normal user and root has run nasd beforehand - ie: you can't
539 remove the old socket, but security is improved. ideally nasd should
540 just remove the socket on termination (SIGINT)
541 */
542 if (!mkdir(X_UNIX_DIR, 0777))
543 chmod(X_UNIX_DIR, 0777 | S_ISVTX);
544 #endif
545
546 strncpy(unsock.sun_path, X_UNIX_PATH, sizeof unsock.sun_path);
547 unsock.sun_path[sizeof unsock.sun_path - 1] = '\0';
548 strncat(unsock.sun_path, display,
549 sizeof unsock.sun_path - strlen(unsock.sun_path) - 1);
550 #ifdef BSD44SOCKETS
551 unsock.sun_len = strlen(unsock.sun_path);
552 #endif
553 #ifdef hpux
554 {
555 /* The following is for backwards compatibility
556 * with old HP clients. This old scheme predates the use
557 * of the /usr/spool/sockets directory, and uses hostname:display
558 * in the /tmp/.sockets directory
559 */
560 struct utsname systemName;
561 static char oldLinkName[256];
562
563 uname(&systemName);
564 strncpy(oldLinkName, OLD_UNIX_DIR, sizeof oldLinkName);
565 oldLinkName[sizeof oldLinkName - 1] = '\0';
566 if (!mkdir(oldLinkName, 0777))
567 chown(oldLinkName, 2, 3);
568 strncat(oldLinkName, "/", sizeof oldLinkName - strlen(oldLinkName) - 1);
569 strncat(oldLinkName, systemName.nodename,
570 sizeof oldLinkName - strlen(oldLinkName) - 1);
571 strncat(oldLinkName, display,
572 sizeof oldLinkName - strlen(oldLinkName) - 1);
573 unlink(oldLinkName);
574 symlink(unsock.sun_path, oldLinkName);
575 }
576 #endif /* hpux */
577 unlink(unsock.sun_path);
578 if ((request = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
579 char *buffer;
580 int i;
581
582 i = strlen(unsock.sun_path);
583 buffer = (char *) malloc(i + 80);
584 if (buffer) {
585 snprintf(buffer, i+80, "Error creating unix socket: %s\n",
586 unsock.sun_path);
587 Error(buffer);
588 free(buffer);
589 } else
590 Error("Creating Unix socket");
591
592 return -1;
593 }
594 #ifdef BSD44SOCKETS
595 if (bind(request, (struct sockaddr *) &unsock, SUN_LEN(&unsock)))
596 #else
597 if (bind
598 (request, (struct sockaddr *) &unsock,
599 strlen(unsock.sun_path) + 2))
600 #endif
601 {
602 char *buffer;
603 int i;
604
605 i = strlen(unsock.sun_path);
606 buffer = (char *) malloc(i + 80);
607 if (buffer) {
608 snprintf(buffer, i+80, "Error binding unix socket: %s\n",
609 unsock.sun_path);
610 Error(buffer);
611 free(buffer);
612 } else
613 Error("Creating Unix socket");
614
615 close(request);
616 return -1;
617 }
618 if (listen(request, 5)) {
619 Error("Unix Listen");
620 close(request);
621 return -1;
622 }
623 (void) umask(oldUmask);
624 return request;
625 }
626 #endif /*UNIXCONN */
627
628 #ifdef SERVER_LOCALCONN
629
630 #if !defined(SVR4) || defined(SVR4_ACP)
631 static int
connect_spipe(int fd1,int fd2)632 connect_spipe(int fd1, int fd2)
633 {
634 long temp;
635 struct strfdinsert sbuf;
636
637 sbuf.databuf.maxlen = -1;
638 sbuf.databuf.len = -1;
639 sbuf.databuf.buf = NULL;
640 sbuf.ctlbuf.maxlen = sizeof(long);
641 sbuf.ctlbuf.len = sizeof(long);
642 sbuf.ctlbuf.buf = (caddr_t) & temp;
643 sbuf.offset = 0;
644 sbuf.fildes = fd2;
645 sbuf.flags = 0;
646 if (ioctl(fd1, I_FDINSERT, &sbuf) == -1)
647 return (-1);
648
649 return (0);
650 }
651
652 static int
named_spipe(int fd,char * path)653 named_spipe(int fd, char *path)
654 {
655 int oldUmask, ret;
656 struct stat sbuf;
657
658 oldUmask = umask(0);
659
660 (void) fstat(fd, &sbuf);
661 ret = mknod(path, 0020666, sbuf.st_rdev);
662
663 umask(oldUmask);
664
665 return (ret < 0 ? -1 : fd);
666 }
667
668 static int
open_isc_local(void)669 open_isc_local(void)
670 {
671 int fd = -1, fds = -1;
672 long temp;
673 struct strfdinsert buf;
674 char path[64];
675
676 #if defined(SVR4_ACP) && defined(UNIXCONN)
677 /*
678 * ISC local connections go the same place as Unix-domain sockets (brain
679 * death of the highest magnitude. To allow this to function, we put
680 * the ISC streams pipe elsewhere. This will require that a binary edit
681 * be done on ISC binaries under SVR4, but life is tough some times.
682 */
683 mkdir(AUDIO_ISC_DIR, 0777);
684 chmod(AUDIO_ISC_DIR, 0777);
685
686 strncpy(path, AUDIO_ISC_PATH, sizeof path); path[sizeof path - 1] = '\0';
687 #else /* SVR4_ACP && UNIXCONN */
688 mkdir(X_UNIX_DIR, 0777);
689 chmod(X_UNIX_DIR, 0777);
690
691 strncpy(path, X_UNIX_PATH, sizeof path); path[sizeof path - 1] = '\0';
692 #endif /* SVR4_ACP && UNIXCONN */
693
694 strncat(path, display, sizeof path - strlen(path) - 1);
695
696 if (unlink(path) < 0 && errno != ENOENT) {
697 ErrorF("audio server: ISC listener pipe in use (%s)\n", path);
698 return (-1);
699 }
700
701 if ((fds = open("/dev/spx", O_RDWR)) >= 0 &&
702 (fd = open("/dev/spx", O_RDWR)) >= 0)
703
704 if (connect_spipe(fds, fd) != -1 && named_spipe(fds, path) != -1)
705
706 return (fd);
707 else
708 Error("audio server: Can't set up ISC listener pipes");
709
710 #ifndef SVR4
711 /*
712 * At this point, most SVR4 versions will fail on this, so leave out the
713 * warning
714 */
715 else
716 Error("audio server: Cannot open \"/dev/spx\" for ISC listener");
717 #endif
718
719 (void) close(fds);
720 (void) close(fd);
721 return (-1);
722 }
723
724
725 static int
accept_isc_local(void)726 accept_isc_local(void)
727 {
728 struct strrecvfd buf;
729
730 while (ioctl(spxFd, I_RECVFD, &buf) < 0)
731 if (errno != EAGAIN) {
732 Error("audio server: Can't read fildes from ISC client");
733 return (-1);
734 }
735
736 BITSET(AllStreams, buf.fd);
737 return (buf.fd);
738 }
739
740 static int
open_xsight_local(void)741 open_xsight_local(void)
742 {
743 int fds = -1, fdr = -1;
744 char pathS[64], pathR[64];
745
746 snprintf(pathS, sizeof pathS, "%s%sS", AUDIO_XSIGHT_PATH, display);
747 snprintf(pathR, sizeof pathR, "%s%sR", AUDIO_XSIGHT_PATH, display);
748
749 if ((unlink(pathS) < 0 && errno != ENOENT) ||
750 (unlink(pathR) < 0 && errno != ENOENT)) {
751 ErrorF("audio server: SCO listener pipe in use (%s)\n", pathR);
752 return (-1);
753 }
754
755 if ((fds = open("/dev/spx", O_RDWR)) >= 0 &&
756 (fdr = open("/dev/spx", O_RDWR)) >= 0)
757
758 if (connect_spipe(fds, fdr) != -1 &&
759 named_spipe(fds, pathS) != -1 && named_spipe(fdr, pathR) != -1)
760
761 return (fds);
762 else
763 Error("audio server: Can't set up SCO listener pipes");
764
765 #ifndef SVR4
766 /*
767 * At this point, most SVR4 versions will fail on this, so leave out the
768 * warning
769 */
770 else
771 Error("audio server: Cannot open \"/dev/spx\" for SCO listener");
772 #endif
773
774 (void) close(fds);
775 (void) close(fdr);
776 return (-1);
777 }
778
779
780 static int
accept_xsight_local(void)781 accept_xsight_local(void)
782 {
783 char c;
784 int fd;
785 long temp;
786 struct strfdinsert buf;
787
788 if (read(xsFd, &c, 1) < 0) {
789 Error("audio server: Can't read from SCO client");
790 return (-1);
791 }
792
793 if ((fd = open("/dev/spx", O_RDWR)) < 0) {
794 Error("audio server: Can't open \"/dev/spx\" for SCO client connection");
795 return (-1);
796 }
797
798 if (connect_spipe(xsFd, fd) < 0) {
799 Error("audio server: Can't connect pipes for SCO client connection");
800 (void) close(fd);
801 return (-1);
802 }
803
804 BITSET(AllStreams, fd);
805 return (fd);
806 }
807 #endif /* SVR4 */
808
809 static int
open_att_local(void)810 open_att_local(void)
811 {
812 char *slave;
813 int fd;
814 char path[64];
815
816 mkdir(AUDIO_STREAMS_DIR, 0777);
817 chmod(AUDIO_STREAMS_DIR, 0777);
818
819 strncpy(path, AUDIO_STREAMS_PATH, sizeof path);
820 path[sizeof path - 1] = '\0';
821 strncat(path, display, sizeof path - strlen(path) - 1);
822
823 if ((unlink(path) < 0 && errno != ENOENT)) {
824 ErrorF("audio server: USL listener pipe in use (%s)\n", path);
825 return (-1);
826 }
827
828 if ((fd = open("/dev/ptmx", O_RDWR)) < 0) {
829 Error("audio server: Cannot open \"/dev/ptmx\" for USL listener");
830 return (-1);
831 }
832
833 grantpt(fd);
834 unlockpt(fd);
835 slave = (char *) ptsname(fd);
836 if (link(slave, path) < 0 || chmod(path, 0666) < 0) {
837 Error("audio server: Can't set up local USL listener");
838 return (-1);
839 }
840
841 if (open(path, O_RDWR) < 0) {
842 ErrorF("audio server: Can't open %s for USL listener\n", path);
843 close(fd);
844 return (-1);
845 }
846
847 return (fd);
848 }
849
850 #ifdef SVR4
851 static int
open_att_svr4_local(void)852 open_att_svr4_local(void)
853 {
854 int fd[2], tfd;
855 char path[64];
856
857 mkdir(AUDIO_STREAMS_DIR, 0777);
858 chmod(AUDIO_STREAMS_DIR, 0777);
859
860 strncpy(path, AUDIO_NSTREAMS_PATH, sizeof path);
861 path[sizeof path - 1] = '\0';
862 strncat(path, display, sizeof path - strlen(path) - 1);
863
864 if ((unlink(path) < 0 && errno != ENOENT)) {
865 ErrorF("audio server: SVR4 named listener pipe in use (%s)\n",
866 path);
867 return (-1);
868 }
869
870 if ((tfd = creat(path, (mode_t) 0666)) < 0) {
871 ErrorF("audio server: Can't create named-streams path (%s)\n",
872 path);
873 return (-1);
874 }
875 close(tfd);
876 if (chmod(path, (mode_t) 0666) < 0) {
877 ErrorF("audio server: Can't change mode on %s\n", path);
878 return (-1);
879 }
880
881 if (pipe(fd) != 0) {
882 Error("audio server: SVR4 named listener pipe creation failed\n");
883 return (-1);
884 }
885
886 if (ioctl(fd[0], I_PUSH, "connld") != 0) {
887 Error("audio server: ioctl(I_PUSH) failed for SVR4 named listener pipe\n");
888 return (-1);
889 }
890
891 if (fattach(fd[0], path) != 0) {
892 ErrorF("SVR4: fattach on %s failed for SVR4 named listener pipe\n",
893 path);
894 return (-1);
895 }
896
897 return (fd[1]);
898 }
899 #endif /* SVR4 */
900
901 /* JET 3/17/2007 - Luigi Auriemma's nasbugs, attack #1, simple buffer
902 overflow. Now we limit to _MAX_SALVENM.
903 */
904
905 #define _MAX_SLAVENM (256)
906
907 static int
accept_att_local(void)908 accept_att_local(void)
909 {
910 int newconn;
911 int read_in;
912 unsigned char length;
913 char path[_MAX_SLAVENM];
914
915 /*
916 * first get device-name
917 */
918 if ((read_in = read(ptsFd, &length, 1)) <= 0) {
919 Error("audio server: Can't read slave name length from USL client connection");
920 return (-1);
921 }
922
923 if (length >= _MAX_SLAVENM)
924 length = _MAX_SLAVENM - 1;
925
926 if ((read_in = read(ptsFd, path, length)) <= 0) {
927 Error("audio server: Can't read slave name from USL client connection");
928 return (-1);
929 }
930
931 path[length] = '\0';
932
933 if ((newconn = open(path, O_RDWR)) < 0) {
934 Error("audio server: Can't open slave for USL client connection");
935 return (-1);
936 }
937
938 (void) write(newconn, "1", 1); /* send an acknowledge to the client */
939
940 BITSET(AllStreams, newconn);
941 return (newconn);
942 }
943
944 #ifdef SVR4
945 static int
accept_att_svr4_local(void)946 accept_att_svr4_local(void)
947 {
948 struct strrecvfd str;
949
950 if (ioctl(NstrFd, I_RECVFD, &str) < 0) {
951 ErrorF("audio server: I_RECVFD failed on SVR4 named client connection\n");
952 return (-1);
953 }
954 BITSET(AllStreams, str.fd);
955 return (str.fd);
956 }
957 #endif /* SVR4 */
958 #endif /* SERVER_LOCALCONN */
959
960 #ifdef SYSV386
961 int
sysv386_getpeername(fd,from,fromlen)962 sysv386_getpeername(fd, from, fromlen)
963 int fd;
964 struct sockaddr *from;
965 int *fromlen;
966 {
967 #ifdef SERVER_LOCALCONN
968 /*
969 * check up whether our fd is really a streams pipe ( /dev/pts??? )
970 */
971 if (GETBIT(AllStreams, fd)) {
972 from->sa_family = AF_UNSPEC;
973 *fromlen = 0;
974 return 0;
975 }
976 #endif /* SERVER_LOCALCONN */
977 #if defined(TCPCONN) || defined(DNETCONN) || defined(UNIXCONN)
978 return getpeername(fd, from, fromlen);
979 #endif
980 }
981
982 int
sysv386_accept(fd,from,fromlen)983 sysv386_accept(fd, from, fromlen)
984 int fd;
985 struct sockaddr *from;
986 int *fromlen;
987 {
988 #ifdef SERVER_LOCALCONN
989 if (fd == ptsFd)
990 return accept_att_local();
991 #ifdef SVR4
992 if (fd == NstrFd)
993 return accept_att_svr4_local();
994 #endif /* SVR4 */
995 #if !defined(SVR4) || defined(SVR4_ACP)
996 if (fd == spxFd)
997 return accept_isc_local();
998 if (fd == xsFd)
999 return accept_xsight_local();
1000 #endif /* !SVR4 || SVR4_ACP) */
1001 #endif /* SERVER_LOCALCONN */
1002 /*
1003 * else we are handling the normal accept case
1004 */
1005 #if defined(TCPCONN) || defined(DNETCONN) || defined(UNIXCONN)
1006 return accept(fd, from, fromlen);
1007 #endif
1008 }
1009
1010 #define getpeername sysv386_getpeername
1011 #define accept sysv386_accept
1012
1013 #endif /* SYSV386 */
1014
1015 #ifdef hpux
1016 /*
1017 * hpux returns EOPNOTSUPP when using getpeername on a unix-domain
1018 * socket. In this case, smash the socket address with the address
1019 * used to bind the connection socket and return success.
1020 */
hpux_getpeername(fd,from,fromlen)1021 hpux_getpeername(fd, from, fromlen)
1022 int fd;
1023 struct sockaddr *from;
1024 int *fromlen;
1025 {
1026 int ret;
1027 int len;
1028
1029 ret = getpeername(fd, from, fromlen);
1030 if (ret == -1 && errno == EOPNOTSUPP) {
1031 ret = 0;
1032 len = strlen(unsock.sun_path) + 2;
1033 if (len > *fromlen)
1034 len = *fromlen;
1035 bcopy((char *) &unsock, (char *) from, len);
1036 *fromlen = len;
1037 }
1038 return ret;
1039 }
1040
1041 #define getpeername(fd, from, fromlen) hpux_getpeername(fd, from, fromlen)
1042
1043 #endif
1044
1045 #ifdef DNETCONN
1046 static int
open_dnet_socket(void)1047 open_dnet_socket(void)
1048 {
1049 int request;
1050 struct sockaddr_dn dnsock;
1051
1052 if ((request = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) {
1053 Error("Creating DECnet socket");
1054 return -1;
1055 }
1056 bzero((char *) &dnsock, sizeof(dnsock));
1057 dnsock.sdn_family = AF_DECnet;
1058 snprintf(dnsock.sdn_objname, sizeof(dnsock.sdn_objname), "AUDIO$%d",
1059 atoi(display));
1060 dnsock.sdn_objnamel = strlen(dnsock.sdn_objname);
1061 if (bind(request, (struct sockaddr *) &dnsock, sizeof(dnsock))) {
1062 Error("Binding DECnet socket");
1063 close(request);
1064 return -1;
1065 }
1066 if (listen(request, 5)) {
1067 Error("DECnet Listening");
1068 close(request);
1069 return -1;
1070 }
1071 return request;
1072 }
1073 #endif /* DNETCONN */
1074
1075 #define NOROOM "Maximum number of clients reached"
1076
1077 #ifndef AMOEBA
1078
1079 /*****************
1080 * CreateWellKnownSockets
1081 * At initialization, create the sockets to listen on for new clients.
1082 *****************/
1083
1084 void
CreateWellKnownSockets(void)1085 CreateWellKnownSockets(void)
1086 {
1087 int request, i;
1088 #ifdef SVR4
1089 struct rlimit Rlimit;
1090 #endif
1091 #if _MINIX
1092 int extra_fd;
1093 #endif
1094
1095 #if defined(SERVER_LOCK)
1096 Lock_Server();
1097 #endif /* SERVER_LOCK */
1098
1099 #ifndef _MINIX
1100 CLEARBITS(AllSockets);
1101 CLEARBITS(AllClients);
1102 CLEARBITS(LastSelectMask);
1103 CLEARBITS(ClientsWithInput);
1104
1105 for (i = 0; i < MAXSOCKS; i++)
1106 ConnectionTranslation[i] = 0;
1107 #ifndef X_NOT_POSIX
1108 #ifdef __FreeBSD__
1109 lastfdesc = getdtablesize() - 1;
1110 #else
1111 lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
1112 #endif
1113 #else
1114 #ifdef hpux
1115 lastfdesc = _NFILE - 1;
1116 #else
1117 #ifdef SVR4
1118 if (getrlimit(RLIMIT_NOFILE, &Rlimit) != 0) {
1119 lastfdesc = _NFILE - 1;
1120 } else {
1121 /*
1122 * If the limit is at infinity, the server could be QUITE busy,
1123 * so set a reasonable limit.
1124 */
1125 if (Rlimit.rlim_cur == RLIM_INFINITY)
1126 lastfdesc = 1024;
1127 else
1128 lastfdesc = Rlimit.rlim_cur;
1129 }
1130 #else
1131 lastfdesc = getdtablesize() - 1;
1132 #endif /* SVR4 */
1133 #endif /* hpux */
1134 #endif /* X_NOT_POSIX */
1135 if (lastfdesc > MAXSOCKS) {
1136 lastfdesc = MAXSOCKS;
1137 if (debug_conns)
1138 ErrorF("GOT TO END OF SOCKETS %d\n", MAXSOCKS);
1139 }
1140
1141 WellKnownConnections = 0;
1142 #ifdef SERVER_LOCALCONN
1143 CLEARBITS(AllStreams);
1144 if ((ptsFd = open_att_local()) != -1) {
1145 WellKnownConnections |= (1L << ptsFd);
1146 }
1147 #ifdef SVR4
1148 if ((NstrFd = open_att_svr4_local()) != -1) {
1149 WellKnownConnections |= (1L << NstrFd);
1150 }
1151 #endif /* SVR4 */
1152 #if !defined(SVR4) || defined(SVR4_ACP)
1153 if ((spxFd = open_isc_local()) != -1) {
1154 WellKnownConnections |= (1L << spxFd);
1155 }
1156 if ((xsFd = open_xsight_local()) != -1) {
1157 WellKnownConnections |= (1L << xsFd);
1158 }
1159 #endif /* !SVR4 || SVR4_ACP */
1160 #endif /* SERVER_LOCALCONN */
1161 #ifdef TCPCONN
1162 if ((request = open_tcp_socket()) != -1) {
1163 WellKnownConnections |= (1L << request);
1164 DefineSelf(request);
1165 } else if (!PartialNetwork) {
1166 FatalError("Cannot establish tcp listening socket\n");
1167 } else {
1168 ErrorF("Cannot establish tcp listening socket\n");
1169 }
1170 #endif /* TCPCONN */
1171 #ifdef DNETCONN
1172 if ((request = open_dnet_socket()) != -1) {
1173 WellKnownConnections |= (1L << request);
1174 DefineSelf(request);
1175 } else if (!PartialNetwork) {
1176 FatalError("Cannot establish dnet listening socket\n");
1177 } else {
1178 ErrorF("Cannot establish dnet listening socket\n");
1179 }
1180 #endif /* DNETCONN */
1181 #ifdef UNIXCONN
1182 if ((request = open_unix_socket()) != -1) {
1183 WellKnownConnections |= (1L << request);
1184 unixDomainConnection = request;
1185 } else if (!PartialNetwork) {
1186 FatalError("Cannot establish unix listening socket\n");
1187 } else {
1188 ErrorF("Cannot establish unix listening socket\n");
1189 }
1190 #endif /* UNIXCONN */
1191 if (WellKnownConnections == 0)
1192 FatalError("Cannot establish any listening sockets\n");
1193 #else /* _MINIX */
1194 {
1195 int no_listeners = 0;
1196
1197 for (i = 0; i < MAXSOCKS; i++)
1198 ConnectionTranslation[i] = 0;
1199
1200 lastfdesc = ASIO_FD_SETSIZE - 1; /* Can only fwait on these. */
1201
1202 if (lastfdesc > MAXSOCKS) {
1203 lastfdesc = MAXSOCKS;
1204 if (debug_conns)
1205 ErrorF("GOT TO END OF SOCKETS %d\n", MAXSOCKS);
1206 }
1207
1208 ASIO_FD_ZERO(&ListenFdSet);
1209 ASIO_FD_ZERO(&InprogressFdSet);
1210 ASIO_FD_ZERO(&CompletedFdSet);
1211 ASIO_FD_ZERO(&ClientFdSet);
1212 ASIO_FD_ZERO(&IgnoreFdSet);
1213 ASIO_FD_ZERO(&GrabFdSet);
1214 #ifdef TCPCONN
1215 TcpListenFd = MNX_open_tcp_socket(&extra_fd);
1216 if (TcpListenFd != -1) {
1217 if (TcpListenFd < 0 || TcpListenFd > lastfdesc)
1218 FatalError("invaling tcp fd: %d\n", TcpListenFd);
1219 ASIO_FD_SET(TcpListenFd, ASIO_IOCTL, &ListenFdSet);
1220 ASIO_FD_SET(TcpListenFd, ASIO_IOCTL, &InprogressFdSet);
1221 DefineSelf(extra_fd);
1222 close(extra_fd);
1223 no_listeners++;
1224 } else if (!PartialNetwork) {
1225 FatalError("Cannot establish tcp listening socket");
1226 }
1227 #endif /* TCPCONN */
1228 if (no_listeners == 0)
1229 FatalError("Cannot establish any listening sockets");
1230 }
1231 #endif /* _MINIX */
1232 signal(SIGPIPE, SIG_IGN);
1233 signal(SIGHUP, AutoResetServer);
1234 signal(SIGINT, GiveUp);
1235 signal(SIGTERM, GiveUp);
1236 #ifndef _MINIX
1237 AllSockets[0] = WellKnownConnections;
1238 #endif
1239 ResetHosts(display);
1240 /*
1241 * Magic: If SIGUSR1 was set to SIG_IGN when
1242 * the server started, assume that either
1243 *
1244 * a- The parent process is ignoring SIGUSR1
1245 *
1246 * or
1247 *
1248 * b- The parent process is expecting a SIGUSR1
1249 * when the server is ready to accept connections
1250 *
1251 * In the first case, the signal will be harmless,
1252 * in the second case, the signal will be quite
1253 * useful
1254 */
1255 if (signal(SIGUSR1, SIG_IGN) == SIG_IGN)
1256 RunFromSmartParent = TRUE;
1257 ParentProcess = getppid();
1258 if (RunFromSmartParent) {
1259 if (ParentProcess > 0) {
1260 kill(ParentProcess, SIGUSR1);
1261 }
1262 }
1263 }
1264
1265 void
ResetWellKnownSockets()1266 ResetWellKnownSockets()
1267 {
1268 ResetOsBuffers();
1269 #if defined(UNIXCONN) && !defined(SVR4)
1270 if (unixDomainConnection != -1) {
1271 /*
1272 * see if the unix domain socket has disappeared
1273 */
1274 struct stat statb;
1275
1276 if (stat(unsock.sun_path, &statb) == -1 ||
1277 (statb.st_mode & S_IFMT) != S_IFSOCK) {
1278 ErrorF("Unix domain socket %s trashed, recreating\n",
1279 unsock.sun_path);
1280 (void) unlink(unsock.sun_path);
1281 (void) close(unixDomainConnection);
1282 WellKnownConnections &= ~(1L << unixDomainConnection);
1283 unixDomainConnection = open_unix_socket();
1284 if (unixDomainConnection != -1)
1285 WellKnownConnections |= (1L << unixDomainConnection);
1286 }
1287 }
1288 #endif /* UNIXCONN */
1289 #ifdef SERVER_LOCALCONN
1290 CLEARBITS(AllStreams);
1291 #endif /* SERVER_LOCALCONN */
1292 ResetAuthorization();
1293 ResetHosts(display);
1294 /*
1295 * See above in CreateWellKnownSockets about SIGUSR1
1296 */
1297 if (RunFromSmartParent) {
1298 if (ParentProcess > 0) {
1299 kill(ParentProcess, SIGUSR1);
1300 }
1301 }
1302 /*
1303 * restart XDMCP
1304 */
1305 }
1306
1307 static void
AuthAudit(int client,Bool letin,struct sockaddr * saddr,int len,unsigned short proto_n,char * auth_proto)1308 AuthAudit(int client, Bool letin, struct sockaddr *saddr, int len,
1309 unsigned short proto_n, char *auth_proto)
1310 {
1311 char addr[128];
1312
1313 if (!len) {
1314 strncpy(addr, "local host", sizeof addr);
1315 addr[sizeof addr - 1] = '\0';
1316 }
1317 else
1318 switch (saddr->sa_family) {
1319 case AF_UNSPEC:
1320 #ifdef UNIXCONN
1321 case AF_UNIX:
1322 #endif
1323 strncpy(addr, "local host", sizeof addr);
1324 addr[sizeof addr - 1] = '\0';
1325 break;
1326 #ifdef TCPCONN
1327 case AF_INET:
1328 snprintf(addr, sizeof addr, "IP %s port %d",
1329 inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr),
1330 (int) ntohs(((struct sockaddr_in *) saddr)->sin_port));
1331 break;
1332 #endif
1333 #ifdef DNETCONN
1334 case AF_DECnet:
1335 snprintf(addr, sizeof addr, "DN %s",
1336 dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add));
1337 break;
1338 #endif
1339 default:
1340 strncpy(addr, "unknown address", sizeof addr);
1341 addr[sizeof addr - 1] = '\0';
1342 }
1343 if (letin)
1344 AuditF("client %d connected from %s\n", client, addr);
1345 else
1346 AuditF("client %d rejected from %s\n", client, addr);
1347 if (proto_n)
1348 AuditF(" Auth name: %.*s\n", proto_n, auth_proto);
1349 }
1350
1351 /*****************************************************************
1352 * ClientAuthorized
1353 *
1354 * Sent by the client at connection setup:
1355 * typedef struct _auConnClientPrefix {
1356 * CARD8 byteOrder;
1357 * BYTE pad;
1358 * CARD16 majorVersion, minorVersion;
1359 * CARD16 nbytesAuthProto;
1360 * CARD16 nbytesAuthString;
1361 * } auConnClientPrefix;
1362 *
1363 * It is hoped that eventually one protocol will be agreed upon. In the
1364 * mean time, a server that implements a different protocol than the
1365 * client expects, or a server that only implements the host-based
1366 * mechanism, will simply ignore this information.
1367 *
1368 *****************************************************************/
1369
1370 #ifndef _MINIX
1371 char *
ClientAuthorized(client,proto_n,auth_proto,string_n,auth_string)1372 ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string)
1373 ClientPtr client;
1374 char *auth_proto, *auth_string;
1375 unsigned short proto_n, string_n;
1376 {
1377 OsCommPtr priv;
1378 union {
1379 struct sockaddr sa;
1380 #ifdef UNIXCONN
1381 struct sockaddr_un un;
1382 #endif /* UNIXCONN */
1383 #ifdef TCPCONN
1384 struct sockaddr_in in;
1385 #endif /* TCPCONN */
1386 #ifdef DNETCONN
1387 struct sockaddr_dn dn;
1388 #endif /* DNETCONN */
1389 } from;
1390 socklen_t fromlen = sizeof(from);
1391 AuID auth_id;
1392
1393 auth_id = CheckAuthorization(proto_n, auth_proto,
1394 string_n, auth_string);
1395
1396 priv = (OsCommPtr) client->osPrivate;
1397 if (auth_id == (AuID) ~ 0L && !NasConfig.AllowAny) {
1398 if (getpeername(priv->fd, &from.sa, &fromlen) != -1) {
1399 if (InvalidHost(&from.sa, fromlen))
1400 AuthAudit(client->index, FALSE, &from.sa, fromlen,
1401 proto_n, auth_proto);
1402 else {
1403 auth_id = (AuID) 0;
1404 if (auditTrailLevel > 1)
1405 AuthAudit(client->index, TRUE, &from.sa, fromlen,
1406 proto_n, auth_proto);
1407 }
1408 }
1409 if (auth_id == (AuID) ~ 0L)
1410 return "Client is not authorized to connect to Server";
1411 } else if (auditTrailLevel > 1) {
1412 if (getpeername(priv->fd, &from.sa, &fromlen) != -1)
1413 AuthAudit(client->index, TRUE, &from.sa, fromlen,
1414 proto_n, auth_proto);
1415 }
1416
1417 priv->auth_id = auth_id;
1418 priv->conn_time = 0;
1419
1420 /* At this point, if the client is authorized to change the access control
1421 * list, we should getpeername() information, and add the client to
1422 * the selfhosts list. It's not really the host machine, but the
1423 * true purpose of the selfhosts list is to see who may change the
1424 * access control list.
1425 */
1426 return ((char *) NULL);
1427 }
1428
1429 /*****************
1430 * EstablishNewConnections
1431 * If anyone is waiting on listened sockets, accept them.
1432 * Returns a mask with indices of new clients. Updates AllClients
1433 * and AllSockets.
1434 *****************/
1435
1436 /*ARGSUSED*/ Bool
EstablishNewConnections(clientUnused,closure)1437 EstablishNewConnections(clientUnused, closure)
1438 ClientPtr clientUnused;
1439 pointer closure;
1440 {
1441 long readyconnections; /* mask of listeners that are ready */
1442 int curconn; /* fd of listener that's ready */
1443 int newconn; /* fd of new client */
1444 long connect_time;
1445 int i;
1446 ClientPtr client;
1447 OsCommPtr oc;
1448
1449 #ifdef TCP_NODELAY
1450 union {
1451 struct sockaddr sa;
1452 #ifdef UNIXCONN
1453 struct sockaddr_un un;
1454 #endif /* UNIXCONN */
1455 #ifdef TCPCONN
1456 struct sockaddr_in in;
1457 #endif /* TCPCONN */
1458 #ifdef DNETCONN
1459 struct sockaddr_dn dn;
1460 #endif /* DNETCONN */
1461 } from;
1462 socklen_t fromlen;
1463 #endif /* TCP_NODELAY */
1464
1465 readyconnections = (((long) closure) & WellKnownConnections);
1466 if (!readyconnections)
1467 return TRUE;
1468 connect_time = GetTimeInMillis();
1469 /* kill off stragglers */
1470 for (i = 1; i < currentMaxClients; i++) {
1471 if (client = clients[i]) {
1472 oc = (OsCommPtr) (client->osPrivate);
1473 if (oc && (oc->conn_time != 0) &&
1474 (connect_time - oc->conn_time) >= TimeOutValue)
1475 CloseDownClient(client);
1476 }
1477 }
1478 while (readyconnections) {
1479 curconn = ffs(readyconnections) - 1;
1480 readyconnections &= ~(1 << curconn);
1481 if ((newconn = accept(curconn,
1482 (struct sockaddr *) NULL,
1483 (socklen_t *) NULL)) < 0)
1484 continue;
1485
1486
1487
1488 /* JET 3/17/2007 - Luigi Auriemma's nasbugs, attack #8.
1489 shut down the client if the max is exceeded. Note,
1490 if the client does not send any data or disconnect,
1491 ErrorConnMax() has been modified to return if a
1492 timeout occurs. If this happens the client will simply
1493 be disconnected.
1494 */
1495
1496 if (newconn >= lastfdesc - 1) {
1497 ErrorConnMax(newconn);
1498 close(newconn);
1499 continue;
1500 }
1501 #ifdef TCP_NODELAY
1502 fromlen = sizeof(from);
1503 if (!getpeername(newconn, &from.sa, &fromlen)) {
1504 if (fromlen && (from.sa.sa_family == AF_INET)) {
1505 int mi = 1;
1506 setsockopt(newconn, IPPROTO_TCP, TCP_NODELAY,
1507 (char *) &mi, sizeof(int));
1508 }
1509 }
1510 #endif /* TCP_NODELAY */
1511 /* ultrix reads hang on Unix sockets, hpux reads fail, AIX fails too */
1512 #if defined(O_NONBLOCK) && (!defined(SCO) && !defined(ultrix) && !defined(hpux) && !defined(AIXV3) && !defined(uniosu))
1513 (void) fcntl(newconn, F_SETFL, O_NONBLOCK);
1514 #else
1515 #ifdef FIOSNBIO
1516 {
1517 int arg;
1518 arg = 1;
1519 ioctl(newconn, FIOSNBIO, &arg);
1520 }
1521 #else
1522 #if (defined(AIXV3) || defined(uniosu)) && defined(FIONBIO)
1523 {
1524 int arg;
1525 arg = 1;
1526 ioctl(newconn, FIONBIO, &arg);
1527 }
1528 #else
1529 fcntl(newconn, F_SETFL, FNDELAY);
1530 #endif
1531 #endif
1532 #endif
1533 oc = (OsCommPtr) xalloc(sizeof(OsCommRec));
1534 if (!oc) {
1535 ErrorConnMax(newconn);
1536 close(newconn);
1537 continue;
1538 }
1539 if (GrabInProgress) {
1540 BITSET(SavedAllClients, newconn);
1541 BITSET(SavedAllSockets, newconn);
1542 } else {
1543 BITSET(AllClients, newconn);
1544 BITSET(AllSockets, newconn);
1545 }
1546 oc->fd = newconn;
1547 oc->input = (ConnectionInputPtr) NULL;
1548 oc->output = (ConnectionOutputPtr) NULL;
1549 oc->conn_time = connect_time;
1550 if (client = NextAvailableClient((pointer) oc)) {
1551 ConnectionTranslation[newconn] = client->index;
1552 } else {
1553 ErrorConnMax(newconn);
1554 CloseDownFileDescriptor(oc);
1555 }
1556 }
1557 return TRUE;
1558 }
1559 #endif /* _MINIX */
1560
1561 /************
1562 * ErrorConnMax
1563 * Fail a connection due to lack of client or file descriptor space
1564 ************/
1565
1566 static void
ErrorConnMax(int fd)1567 ErrorConnMax(int fd)
1568 {
1569 auConnSetupPrefix csp;
1570 char pad[3];
1571 struct iovec iov[3];
1572 char byteOrder = 0;
1573 int whichbyte = 1;
1574 struct timeval waittime;
1575 int rv = 0;
1576 #ifndef _MINIX
1577 long mask[mskcnt];
1578 #endif /* !_MINIX */
1579
1580 #ifndef _MINIX
1581 /* if these seems like a lot of trouble to go to, it probably is */
1582 waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
1583 waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
1584 (1000000 / MILLI_PER_SECOND);
1585 CLEARBITS(mask);
1586 BITSET(mask, fd);
1587 #ifdef hpux
1588 rv = select(fd + 1, (int *) mask, (int *) NULL, (int *) NULL,
1589 &waittime);
1590 #else
1591 rv = select(fd + 1, (fd_set *) mask, (fd_set *) NULL,
1592 (fd_set *) NULL, &waittime);
1593 #endif
1594
1595 /* JET 3/17/2007, if we timed out, simply return */
1596 if (rv == 0)
1597 return;
1598
1599 /* try to read the byte-order of the connection */
1600 (void) read(fd, &byteOrder, 1);
1601 #else
1602 /* Try to read the byte-order of the connection.
1603 * We sleep to avoid a call fwait.
1604 */
1605 sleep(1);
1606 if (read(fd, &byteOrder, 1) == -1) {
1607 /* Out of luck */
1608 return;
1609 }
1610 #endif
1611 if ((byteOrder == 'l') || (byteOrder == 'B')) {
1612 csp.success = auFalse;
1613 csp.lengthReason = sizeof(NOROOM) - 1;
1614 csp.length = (sizeof(NOROOM) + 2) >> 2;
1615 csp.majorVersion = AuProtocolMajorVersion;
1616 csp.minorVersion = AuProtocolMinorVersion;
1617 if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
1618 (!(*(char *) &whichbyte) && (byteOrder == 'l'))) {
1619 swaps(&csp.majorVersion, whichbyte);
1620 swaps(&csp.minorVersion, whichbyte);
1621 swaps(&csp.length, whichbyte);
1622 }
1623 #ifndef _MINIX
1624 iov[0].iov_len = sz_auConnSetupPrefix;
1625 iov[0].iov_base = (char *) &csp;
1626 iov[1].iov_len = csp.lengthReason;
1627 iov[1].iov_base = NOROOM;
1628 iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
1629 iov[2].iov_base = pad;
1630 (void) _OSWriteV(fd, iov, 3);
1631 #else
1632 /* assume the underlying devices buffer a bit */
1633 write(fd, (char *) &csp, sz_xConnSetupPrefix);
1634 write(fd, NOROOM, csp.lengthReason);
1635 write(fd, pad, (4 - (csp.lengthReason & 3)) & 3);
1636 #endif
1637 }
1638 }
1639
1640 /************
1641 * CloseDownFileDescriptor:
1642 * Remove this file descriptor and it's I/O buffers, etc.
1643 ************/
1644
1645 #ifndef _MINIX
1646
1647 static void
CloseDownFileDescriptor(OsCommPtr oc)1648 CloseDownFileDescriptor(OsCommPtr oc)
1649 {
1650 int connection = oc->fd;
1651
1652 close(connection);
1653 FreeOsBuffers(oc);
1654 BITCLEAR(AllSockets, connection);
1655 BITCLEAR(AllClients, connection);
1656 #ifdef SERVER_LOCALCONN
1657 BITCLEAR(AllStreams, connection);
1658 #endif
1659 BITCLEAR(ClientsWithInput, connection);
1660 BITCLEAR(GrabImperviousClients, connection);
1661 if (GrabInProgress) {
1662 BITCLEAR(SavedAllSockets, connection);
1663 BITCLEAR(SavedAllClients, connection);
1664 BITCLEAR(SavedClientsWithInput, connection);
1665 }
1666 BITCLEAR(ClientsWriteBlocked, connection);
1667 if (!ANYSET(ClientsWriteBlocked))
1668 AnyClientsWriteBlocked = FALSE;
1669 BITCLEAR(OutputPending, connection);
1670 xfree(oc);
1671 }
1672
1673 /*****************
1674 * CheckConections
1675 * Some connection has died, go find which one and shut it down
1676 * The file descriptor has been closed, but is still in AllClients.
1677 * If would truly be wonderful if select() would put the bogus
1678 * file descriptors in the exception mask, but nooooo. So we have
1679 * to check each and every socket individually.
1680 *****************/
1681
1682 void
CheckConnections()1683 CheckConnections()
1684 {
1685 long mask;
1686 long tmask[mskcnt];
1687 int curclient, curoff;
1688 int i;
1689 struct timeval notime;
1690 int r;
1691
1692 notime.tv_sec = 0;
1693 notime.tv_usec = 0;
1694
1695 for (i = 0; i < mskcnt; i++) {
1696 mask = AllClients[i];
1697 while (mask) {
1698 curoff = ffs(mask) - 1;
1699 curclient = curoff + (i << 5);
1700 CLEARBITS(tmask);
1701 BITSET(tmask, curclient);
1702 #ifdef hpux
1703 r = select(curclient + 1, (int *) tmask, (int *) NULL,
1704 (int *) NULL, ¬ime);
1705 #else
1706 r = select(curclient + 1, (fd_set *) tmask, (fd_set *) NULL,
1707 (fd_set *) NULL, ¬ime);
1708 #endif
1709 if (r < 0 && errno != EINTR)
1710 CloseDownClient(clients[ConnectionTranslation[curclient]]);
1711 mask &= ~(1 << curoff);
1712 }
1713 }
1714 }
1715
1716 /*****************
1717 * CloseDownConnection
1718 * Delete client from AllClients and free resources
1719 *****************/
1720
1721 void
CloseDownConnection(client)1722 CloseDownConnection(client)
1723 ClientPtr client;
1724 {
1725 OsCommPtr oc = (OsCommPtr) client->osPrivate;
1726
1727 if (oc->output && oc->output->count)
1728 FlushClient(client, oc, (char *) NULL, 0);
1729 ConnectionTranslation[oc->fd] = 0;
1730 CloseDownFileDescriptor(oc);
1731 client->osPrivate = (pointer) NULL;
1732 if (auditTrailLevel > 1)
1733 AuditF("client %d disconnected\n", client->index);
1734 }
1735
1736
AddEnabledDevice(fd)1737 AddEnabledDevice(fd)
1738 int fd;
1739 {
1740 BITSET(EnabledDevices, fd);
1741 BITSET(AllSockets, fd);
1742 }
1743
1744
RemoveEnabledDevice(fd)1745 RemoveEnabledDevice(fd)
1746 int fd;
1747 {
1748 BITCLEAR(EnabledDevices, fd);
1749 BITCLEAR(AllSockets, fd);
1750 }
1751
1752 /*****************
1753 * OnlyListenToOneClient:
1754 * Only accept requests from one client. Continue to handle new
1755 * connections, but don't take any protocol requests from the new
1756 * ones. Note that if GrabInProgress is set, EstablishNewConnections
1757 * needs to put new clients into SavedAllSockets and SavedAllClients.
1758 * Note also that there is no timeout for this in the protocol.
1759 * This routine is "undone" by ListenToAllClients()
1760 *****************/
1761
OnlyListenToOneClient(client)1762 OnlyListenToOneClient(client)
1763 ClientPtr client;
1764 {
1765 OsCommPtr oc = (OsCommPtr) client->osPrivate;
1766 int connection = oc->fd;
1767
1768 if (!GrabInProgress) {
1769 COPYBITS(ClientsWithInput, SavedClientsWithInput);
1770 MASKANDSETBITS(ClientsWithInput,
1771 ClientsWithInput, GrabImperviousClients);
1772 if (GETBIT(SavedClientsWithInput, connection)) {
1773 BITCLEAR(SavedClientsWithInput, connection);
1774 BITSET(ClientsWithInput, connection);
1775 }
1776 UNSETBITS(SavedClientsWithInput, GrabImperviousClients);
1777 COPYBITS(AllSockets, SavedAllSockets);
1778 COPYBITS(AllClients, SavedAllClients);
1779 UNSETBITS(AllSockets, AllClients);
1780 MASKANDSETBITS(AllClients, AllClients, GrabImperviousClients);
1781 BITSET(AllClients, connection);
1782 ORBITS(AllSockets, AllSockets, AllClients);
1783 GrabInProgress = client->index;
1784 }
1785 }
1786
1787 /****************
1788 * ListenToAllClients:
1789 * Undoes OnlyListentToOneClient()
1790 ****************/
1791
ListenToAllClients()1792 ListenToAllClients()
1793 {
1794 if (GrabInProgress) {
1795 ORBITS(AllSockets, AllSockets, SavedAllSockets);
1796 ORBITS(AllClients, AllClients, SavedAllClients);
1797 ORBITS(ClientsWithInput, ClientsWithInput, SavedClientsWithInput);
1798 GrabInProgress = 0;
1799 }
1800 }
1801
1802 /* make client impervious to grabs; assume only executing client calls this */
1803
MakeClientGrabImpervious(client)1804 MakeClientGrabImpervious(client)
1805 ClientPtr client;
1806 {
1807 OsCommPtr oc = (OsCommPtr) client->osPrivate;
1808 int connection = oc->fd;
1809
1810 BITSET(GrabImperviousClients, connection);
1811 }
1812
1813 /* make client pervious to grabs; assume only executing client calls this */
1814
MakeClientGrabPervious(client)1815 MakeClientGrabPervious(client)
1816 ClientPtr client;
1817 {
1818 OsCommPtr oc = (OsCommPtr) client->osPrivate;
1819 int connection = oc->fd;
1820
1821 BITCLEAR(GrabImperviousClients, connection);
1822 if (GrabInProgress && (GrabInProgress != client->index)) {
1823 if (GETBIT(ClientsWithInput, connection)) {
1824 BITSET(SavedClientsWithInput, connection);
1825 BITCLEAR(ClientsWithInput, connection);
1826 }
1827 BITCLEAR(AllSockets, connection);
1828 BITCLEAR(AllClients, connection);
1829 isItTimeToYield = TRUE;
1830 }
1831 }
1832
1833 #else /* _MINIX */
1834
1835 char *
ClientAuthorized(client,proto_n,auth_proto,string_n,auth_string)1836 ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string)
1837 ClientPtr client;
1838 char *auth_proto, *auth_string;
1839 unsigned short proto_n, string_n;
1840 {
1841 OsCommPtr priv;
1842 AuID auth_id;
1843 int len;
1844 int r;
1845 struct sockaddr addr;
1846 nwio_tcpconf_t tcpconf;
1847
1848 auth_id = CheckAuthorization(proto_n, auth_proto,
1849 string_n, auth_string);
1850
1851 priv = (OsCommPtr) client->osPrivate;
1852
1853 /* Assume we only have tcp connections. */
1854 r = ioctl(priv->fd, NWIOGTCPCONF, &tcpconf);
1855 if (r == -1) {
1856 Error("Unable to get remote address from tcp fd");
1857 return;
1858 }
1859 addr.sa_u.sa_in.sin_family = AF_INET;
1860 addr.sa_u.sa_in.sin_addr = tcpconf.nwtc_remaddr;
1861 addr.sa_u.sa_in.sin_port = tcpconf.nwtc_remport;
1862 len = sizeof(addr);
1863
1864 if (auth_id == (AuID) ~ 0L && !InvalidHost(&addr, len)) {
1865 ErrorF("(warning) Authorization succeeded\n");
1866 auth_id = (AuID) 0;
1867 }
1868
1869 if (auth_id == (AuID) ~ 0L)
1870 return "Client is not authorized to connect to Server";
1871
1872 priv->auth_id = auth_id;
1873 priv->conn_time = 0;
1874
1875 #ifdef XDMCP
1876 /* indicate to Xdmcp protocol that we've opened new client */
1877 XdmcpOpenDisplay(priv->fd);
1878 #endif /* XDMCP */
1879
1880 return ((char *) NULL);
1881 }
1882
1883 void CheckListeners();
1884
1885 Bool
EstablishNewConnections(clientUnused,closure)1886 EstablishNewConnections(clientUnused, closure)
1887 ClientPtr clientUnused;
1888 pointer closure;
1889 {
1890 struct NewConnection *newConnP;
1891 int newconn; /* fd of new client */
1892 long connect_time;
1893 ClientPtr client;
1894 OsCommPtr oc;
1895 int i;
1896
1897 newConnP = (struct NewConnection *) closure;
1898
1899 newconn = -1;
1900
1901 /* Let's take some transport protocol specific actions */
1902 if (newConnP == &NewTcpConnection) {
1903 if (TcpListenFd < 0 || TcpListenFd > lastfdesc)
1904 FatalError("strange value in TcpListenFd\n");
1905 if (!ASIO_FD_ISSET(TcpListenFd, ASIO_IOCTL, &ListenFdSet) ||
1906 !ASIO_FD_ISSET(TcpListenFd, ASIO_IOCTL, &InprogressFdSet))
1907 FatalError("TcpListenFd not in progress\n");
1908 ASIO_FD_CLR(TcpListenFd, ASIO_IOCTL, &ListenFdSet);
1909 ASIO_FD_CLR(TcpListenFd, ASIO_IOCTL, &InprogressFdSet);
1910 newconn = TcpListenFd;
1911 TcpListenFd = -1;
1912 }
1913
1914 if (newconn == -1)
1915 FatalError
1916 ("Unable to locate transport protocol for NewConnection\n");
1917
1918 connect_time = GetTimeInMillis();
1919 /* kill off stragglers */
1920 for (i = 1; i < currentMaxClients; i++) {
1921 if (client = clients[i]) {
1922 oc = (OsCommPtr) (client->osPrivate);
1923 if (oc && (oc->conn_time != 0) &&
1924 (connect_time - oc->conn_time) >= TimeOutValue)
1925 CloseDownClient(client);
1926 }
1927 }
1928
1929 /* Let's check if we can start some listeners that stopped */
1930 CheckListeners();
1931
1932 oc = (OsCommPtr) xalloc(sizeof(OsCommRec));
1933 if (!oc) {
1934 ErrorConnMax(newconn);
1935 close(newconn);
1936 return TRUE;
1937 }
1938 /* Make sure that the client get called the first time */
1939 ASIO_FD_SET(newconn, ASIO_READ, &CompletedFdSet);
1940 AnyClientsWithInput = TRUE;
1941
1942 oc->fd = newconn;
1943 oc->input = (ConnectionInputPtr) NULL;
1944 oc->inputFake = (ConnectionInputPtr) NULL;
1945 oc->output = (ConnectionOutputPtr) NULL;
1946 oc->outputNext = (ConnectionOutputPtr) NULL;
1947 oc->conn_time = connect_time;
1948 if ((newconn < lastfdesc) &&
1949 (client = NextAvailableClient((pointer) oc))) {
1950 ConnectionTranslation[newconn] = client->index;
1951 } else {
1952 ErrorConnMax(newconn);
1953 CloseDownFileDescriptor(oc);
1954 }
1955 return TRUE;
1956 }
1957
1958 static void
CloseDownFileDescriptor(OsCommPtr oc)1959 CloseDownFileDescriptor(OsCommPtr oc)
1960 {
1961 int connection = oc->fd;
1962 int i;
1963
1964 close(connection);
1965 FreeOsBuffers(oc);
1966
1967 for (i = 0; i < ASIO_NR; i++) {
1968 ASIO_FD_CLR(connection, i, &InprogressFdSet);
1969 ASIO_FD_CLR(connection, i, &CompletedFdSet);
1970 ASIO_FD_CLR(connection, i, &ClientFdSet);
1971 ASIO_FD_CLR(connection, i, &IgnoreFdSet);
1972 ASIO_FD_CLR(connection, i, &GrabFdSet);
1973 }
1974 xfree(oc);
1975 }
1976
CloseDownConnection(client)1977 CloseDownConnection(client)
1978 ClientPtr client;
1979 {
1980 OsCommPtr oc = (OsCommPtr) client->osPrivate;
1981
1982 if (oc->output && oc->output->count)
1983 FlushClient(client, oc, (char *) NULL, 0);
1984 ConnectionTranslation[oc->fd] = 0;
1985 #ifdef XDMCP
1986 XdmcpCloseDisplay(oc->fd);
1987 #endif
1988 CloseDownFileDescriptor(oc);
1989 client->osPrivate = (pointer) NULL;
1990 }
1991
AddEnabledDevice(fd)1992 AddEnabledDevice(fd)
1993 int fd;
1994 {
1995 ASIO_FD_SET(fd, ASIO_READ, &InprogressFdSet);
1996 }
1997
RemoveEnabledDevice(fd)1998 RemoveEnabledDevice(fd)
1999 int fd;
2000 {
2001 ASIO_FD_CLR(fd, ASIO_READ, &InprogressFdSet);
2002 }
2003
OnlyListenToOneClient(client)2004 OnlyListenToOneClient(client)
2005 ClientPtr client;
2006 {
2007 OsCommPtr oc = (OsCommPtr) client->osPrivate;
2008 int connection = oc->fd;
2009
2010 if (!GrabInProgress) {
2011 ASIO_FD_ZERO(&GrabFdSet);
2012 ASIO_FD_SET(connection, ASIO_READ, &GrabFdSet);
2013 GrabInProgress = TRUE;
2014 }
2015 }
2016
ListenToAllClients()2017 ListenToAllClients()
2018 {
2019 if (GrabInProgress) {
2020 GrabInProgress = 0;
2021 AnyClientsWithInput = TRUE;
2022 }
2023 }
2024
2025 void
EnqueueNewConnection(fd,operation,result,error)2026 EnqueueNewConnection(fd, operation, result, error)
2027 int fd;
2028 int operation;
2029 int result;
2030 int error;
2031 {
2032 /* Let's see which transport protocol got a new connection */
2033 if (!ASIO_FD_ISSET(fd, operation, &ListenFdSet))
2034 FatalError("result not in ListenFdSet\n");
2035
2036 if (fd == TcpListenFd) {
2037 /* New tcp connection */
2038 NewTcpConnection.nc_result = result;
2039 NewTcpConnection.nc_errno = error;
2040
2041 /* Let EstablishNewConnections deal with this
2042 * situation
2043 */
2044 QueueWorkProc(EstablishNewConnections, NULL,
2045 (pointer) & NewTcpConnection);
2046 return;
2047 }
2048
2049 FatalError("Unable to find transport protocol for new connection\n");
2050 }
2051
2052 void
CheckListeners()2053 CheckListeners()
2054 {
2055 /* Check if all devices have listeners hanging around */
2056 #ifdef TCPCONN
2057 if (TcpListenFd == -1) {
2058 TcpListenFd = MNX_open_tcp_socket(NULL);
2059 if (TcpListenFd != -1) {
2060 if (TcpListenFd < 0 || TcpListenFd > lastfdesc)
2061 FatalError("invalid tcp fd: %d\n", TcpListenFd);
2062 ASIO_FD_SET(TcpListenFd, ASIO_IOCTL, &ListenFdSet);
2063 ASIO_FD_SET(TcpListenFd, ASIO_IOCTL, &InprogressFdSet);
2064 }
2065 }
2066 #endif /* TCPCONN */
2067 }
2068 #endif /* _MINIX */
2069
2070 #else /* AMOEBA */
2071
2072 #include <amoeba.h>
2073 #include <cmdreg.h>
2074 #include <stdcom.h>
2075 #include <stderr.h>
2076 #include <ampolicy.h>
2077 #include <server/ip/hton.h>
2078 #include <server/ip/types.h>
2079 #include <server/ip/tcpip.h>
2080 #include <server/ip/tcp_io.h>
2081 #include <server/ip/gen/in.h>
2082 #include <server/ip/gen/tcp.h>
2083 #include <server/ip/gen/tcp_io.h>
2084
2085 /*
2086 * Size of reply buffer
2087 */
2088 #define REPLY_BUFSIZE 30000
2089
2090 #ifdef XDEBUG
2091 Bool amDebug; /* amoeba debug toggle */
2092 #define dbprintf(list) if (amDebug) { ErrorF list; }
2093 #else
2094 #define dbprintf(list) /* nothing */
2095 #endif /* XDEBUG */
2096
2097 capability Au; /* AudioServer capability */
2098 char *AuServerHostName; /* audio server host name */
2099 char *AuTcpServerName; /* TCP/IP server name */
2100 long MaxClients = MAXTASKS;
2101 ClientPtr newClient = NULL; /* new connections */
2102 ClientPtr Clients[MAXTASKS]; /* clients with input */
2103 int maxClient; /* Highest numbered client */
2104 int totalClients; /* all connected applications */
2105 ClientPtr grabClient = NULL; /* for grabs */
2106
2107 mutex NewConnsLock; /* prevent concurrent updates */
2108 int nNewConns; /* # of new clients */
2109 OsCommPtr NewConns[MAXTASKS]; /* new client connections */
2110
2111 static void AmoebaConnectorThread();
2112 static void AmoebaTCPConnectorThread();
2113
2114 void
CreateWellKnownSockets(void)2115 CreateWellKnownSockets(void)
2116 {
2117 char host[100];
2118 char *getenv();
2119 void DeviceReader();
2120 errstat err;
2121 capability pubAu;
2122 static int threadsStarted = FALSE;
2123
2124 /*
2125 * Each time the server is reset this routine is called to
2126 * setup the new well known sockets. For Amoeba we'll just
2127 * keep using the old threads that are already running.
2128 */
2129 if (!threadsStarted) {
2130 threadsStarted = TRUE;
2131 /*
2132 * Create a new capability for this audio server
2133 */
2134 if (AuServerHostName == NULL)
2135 AuServerHostName = getenv("AUDIOHOST");
2136 if (AuServerHostName == NULL)
2137 FatalError
2138 ("AUDIOHOST not set, or server host name not given\n");
2139 snprintf(host, sizeof host, "%s/%s:%s", DEF_AUSVRDIR, AuServerHostName,
2140 0 /* port */ );
2141
2142 uniqport(&Au.cap_port);
2143 priv2pub(&Au.cap_port, &pubAu.cap_port);
2144 (void) name_delete(host);
2145 if ((err = name_append(host, &pubAu)) != 0) {
2146 (void) ErrorF("Cannot create capability %s: %s\n",
2147 host, err_why(err));
2148 exit(1);
2149 }
2150
2151 /*
2152 * Initialize new connections lock
2153 */
2154 mu_init(&NewConnsLock);
2155
2156 /*
2157 * This critical region prevents the subthread from proceeding until
2158 * main has finished initializing. The matching sema_down() is in
2159 * WaitFor.c.
2160 */
2161 sema_init(&init_sema, 0);
2162
2163 /*
2164 * Also, initialize main thread locking
2165 */
2166 InitMainThread();
2167
2168 /*
2169 * Initialize and start IOP reader thread
2170 */
2171 InitializeIOPServerReader();
2172
2173 /*
2174 * Start native Amoeba service threads
2175 */
2176 if (thread_newthread(AmoebaConnectorThread, CONNECTOR_STACK, 0, 0)
2177 <= 0)
2178 FatalError("Cannot start Amoeba connector thread\n");
2179 if (thread_newthread(AmoebaConnectorThread, CONNECTOR_STACK, 0, 0)
2180 <= 0)
2181 FatalError("Cannot start Amoeba connector thread\n");
2182
2183 /*
2184 * Start TCP/IP service threads
2185 */
2186 if (AuTcpServerName) {
2187 if (thread_newthread(AmoebaTCPConnectorThread,
2188 CONNECTOR_STACK, 0, 0) <= 0)
2189 FatalError("Cannot start TCP connector thread\n");
2190 if (thread_newthread(AmoebaTCPConnectorThread,
2191 CONNECTOR_STACK, 0, 0) <= 0)
2192 FatalError("Cannot start TCP connector thread\n");
2193 }
2194 }
2195
2196 ResetHosts(display);
2197
2198 #ifdef XDMCP
2199 XdmcpInit();
2200 #endif
2201 }
2202
2203 void
ResetWellKnownSockets()2204 ResetWellKnownSockets()
2205 {
2206 ResetAuthorization();
2207 ResetHosts(display);
2208
2209 /*
2210 * restart XDMCP
2211 */
2212 #ifdef XDMCP
2213 XdmcpReset();
2214 #endif
2215 }
2216
2217 char *
ClientAuthorized(client,proto_n,auth_proto,string_n,auth_string)2218 ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string)
2219 ClientPtr client;
2220 char *auth_proto, *auth_string;
2221 unsigned short proto_n, string_n;
2222 {
2223 OsCommPtr priv;
2224 AuID auth_id;
2225
2226 auth_id = CheckAuthorization(proto_n, auth_proto,
2227 string_n, auth_string);
2228
2229 priv = (OsCommPtr) client->osPrivate;
2230 /*
2231 * Access control only works for audio connections over a TCP/IP stream.
2232 * The Amoeba philosophy is, when you have the capability you are
2233 * allowed to talk with the server.
2234 */
2235 if (auth_id == (AuID) ~ 0L) {
2236 nwio_tcpconf_t tcpconf;
2237
2238 if (priv->family == FamilyInternet &&
2239 tcp_ioc_getconf(&priv->conn.tcp.cap, &tcpconf) == STD_OK &&
2240 !InvalidHost(&tcpconf.nwtc_remaddr, sizeof(ipaddr_t)))
2241 auth_id = (AuID) 0;
2242 if (priv->family == FamilyAmoeba)
2243 auth_id = (AuID) 0;
2244 }
2245
2246 if (auth_id == (AuID) ~ 0L)
2247 return "Client is not authorized to connect to Server";
2248
2249 priv->auth_id = auth_id;
2250 priv->conn_time = 0;
2251
2252 #ifdef XDMCP
2253 /* indicate to Xdmcp protocol that we've opened new client */
2254 XdmcpOpenDisplay(priv->fd);
2255 #endif /* XDMCP */
2256 /* At this point, if the client is authorized to change the access control
2257 * list, we should getpeername() information, and add the client to
2258 * the selfhosts list. It's not really the host machine, but the
2259 * true purpose of the selfhosts list is to see who may change the
2260 * access control list.
2261 */
2262 return ((char *) NULL);
2263 }
2264
2265 /*ARGSUSED*/ Bool
EstablishNewConnections(clientUnused,closure)2266 EstablishNewConnections(clientUnused, closure)
2267 ClientPtr clientUnused;
2268 pointer closure;
2269 {
2270 ClientPtr newClient;
2271 OsCommPtr oc;
2272 int i;
2273 struct vc *vc;
2274 int index;
2275
2276 mu_lock(&NewConnsLock);
2277 for (index = 0; index < nNewConns; index++) {
2278 oc = NewConns[index];
2279
2280 /*
2281 * Find a new slot
2282 */
2283 if (totalClients >= MAXTASKS) {
2284 ErrorF("Too many audio-clients are being served already\n");
2285 am_close(oc, VC_BOTH | VC_ASYNC);
2286 xfree((char *) oc);
2287 continue;
2288 }
2289 totalClients++;
2290 for (i = 0; i < maxClient + 1; i++)
2291 if (Clients[i] == 0)
2292 break;
2293 if (i == maxClient)
2294 maxClient++;
2295
2296 /*
2297 * Fill in client's connection number
2298 */
2299 oc->number = i;
2300
2301 /*
2302 * Now stuff the new client in the array where
2303 * WaitForSomething will find it and hand it up.
2304 */
2305 newClient = NextAvailableClient((pointer) oc);
2306 Clients[i] = newClient;
2307 }
2308 nNewConns = 0;
2309 mu_unlock(&NewConnsLock);
2310 return TRUE;
2311 }
2312
2313 #define NOROOM "Maximum number of clients reached"
2314
OnlyListenToOneClient(client)2315 OnlyListenToOneClient(client)
2316 ClientPtr client;
2317 {
2318 if (grabClient != NULL && grabClient != client) {
2319 ErrorF("Uncancelled OnlyListenToOneClient()?\n");
2320 grabClient = NULL;
2321 } else
2322 grabClient = client;
2323 }
2324
CloseDownConnection(client)2325 CloseDownConnection(client)
2326 ClientPtr client;
2327 {
2328 OsCommPtr oc;
2329
2330 dbprintf(("Connection closed\n"));
2331 oc = (OsCommPtr) client->osPrivate;
2332 Clients[oc->number] = NULL;
2333 if (oc->number == maxClient)
2334 maxClient--;
2335 am_close(oc, VC_BOTH | VC_ASYNC);
2336 if (oc->buffer)
2337 xfree(oc->buffer);
2338 xfree(oc);
2339 client->osPrivate = (pointer) NULL;
2340 }
2341
ListenToAllClients()2342 ListenToAllClients()
2343 {
2344 grabClient = NULL;
2345 }
2346
2347 /* These two are dummies -- and are never called at run-time */
AddEnabledDevice(fd)2348 AddEnabledDevice(fd)
2349 int fd;
2350 {
2351 return;
2352 }
2353
RemoveEnabledDevice(fd)2354 RemoveEnabledDevice(fd)
2355 int fd;
2356 {
2357 return;
2358 }
2359
2360 /*
2361 * Wakeup main thread if necessary
2362 */
2363 static void
UnblockMain(reguster OsCommPtr oc)2364 UnblockMain(reguster OsCommPtr oc)
2365 {
2366 if ((oc->status & IGNORE) == 0) {
2367 WakeUpMainThread();
2368 }
2369 }
2370
2371 static char *
OsCommFamily(int family)2372 OsCommFamily(int family)
2373 {
2374 switch (family) {
2375 case FamilyAmoeba:
2376 return "AMOEBA";
2377 case FamilyInternet:
2378 return "TCP/IP";
2379 }
2380 return "UNKNOWN";
2381 }
2382
2383 static char *
OsCommStatus(int status)2384 OsCommStatus(int status)
2385 {
2386 static char buf[100];
2387
2388 buf[0] = '\0';
2389 if (status == 0)
2390 snprintf(buf, sizeof buf, "NONE");
2391 if (status & CONN_KILLED)
2392 strncat(buf, " KILLED", sizeof buf - strlen(buf) - 1);
2393 if (status & REQ_PUSHBACK)
2394 strncat(buf, " PUSHBACK", sizeof buf - strlen(buf) - 1);
2395 if (status & IGNORE)
2396 strncat(buf, " IGNORE", sizeof buf - strlen(buf) - 1);
2397 return buf;
2398 }
2399
2400 /*
2401 * Return status information about the open connections
2402 */
2403 errstat
ConnectionStatus(hdr,buf,size)2404 ConnectionStatus(hdr, buf, size)
2405 header *hdr;
2406 char *buf;
2407 int size;
2408 {
2409 OsCommPtr oc;
2410 int i;
2411 char *begin, *end;
2412 char *bprintf();
2413
2414 begin = buf;
2415 end = buf + size;
2416
2417 /* all active clients */
2418 if (maxClient > 0) {
2419 begin = bprintf(begin, end, "Active clients:\n");
2420 for (i = 0; i < maxClient; i++) {
2421 if (Clients[i] && (oc = (OsCommPtr) Clients[i]->osPrivate)) {
2422 begin = bprintf(begin, end, "%d: Family %s, Status %s\n",
2423 i, OsCommFamily(oc->family),
2424 OsCommStatus(oc->status));
2425 }
2426 }
2427 }
2428
2429 /* all new (awaiting) clients */
2430 mu_lock(&NewConnsLock);
2431 if (nNewConns > 0) {
2432 begin = bprintf(begin, end, "New clients:\n");
2433 for (i = 0; i < nNewConns; i++) {
2434 oc = NewConns[i];
2435 begin = bprintf(begin, end, "%d: Family %s, Status %s\n",
2436 i, OsCommFamily(oc->family),
2437 OsCommStatus(oc->status));
2438 }
2439 }
2440 mu_unlock(&NewConnsLock);
2441
2442 if (begin == NULL) {
2443 hdr->h_size = 0;
2444 return STD_SYSERR;
2445 } else {
2446 hdr->h_size = begin - buf;
2447 return STD_OK;
2448 }
2449
2450 }
2451
2452 /*
2453 * Establishing a new connection is done in two phases. This thread does the
2454 * first part. It filters out bad connect requests. A new rendevous port is
2455 * sent to the client and the main loop is informed if there is a legal
2456 * request. The sleep synchronizes with the main loop so that the paperwork
2457 * is finished for the current connect request before the thread is ready to
2458 * accept another connect.
2459 */
2460 static void
AmoebaConnectorThread()2461 AmoebaConnectorThread()
2462 {
2463 header req, rep;
2464 port client_ports[2];
2465 port server_ports[2];
2466 short s;
2467 OsCommPtr oc;
2468 char *repb;
2469 extern CreateNewClient();
2470
2471 WaitForInitialization();
2472 dbprintf(("AmoebaConnectorThread() running ...\n"));
2473 if ((repb = (char *) malloc(REPLY_BUFSIZE)) == NULL)
2474 FatalError("Amoeba connector thread: malloc failed");
2475 for (;;) {
2476 do {
2477 req.h_port = Au.cap_port;
2478 s = getreq(&req, NILBUF, 0);
2479 } while (ERR_CONVERT(s) == RPC_ABORTED);
2480 if (ERR_STATUS(s))
2481 FatalError("Amoeba connector thread: getreq failed");
2482 /* TODO: check privilege fields here */
2483
2484 dbprintf(("AmoebaConnectorThread() accepting a request\n"));
2485
2486 switch (req.h_command) {
2487
2488 case STD_INFO:
2489 rep.h_status = STD_OK;
2490 snprintf(repb, REPLY_BUFSIZE, "audio server on %s",
2491 AuServerHostName);
2492 rep.h_size = strlen(repb);
2493 putrep(&rep, repb, rep.h_size);
2494 break;
2495
2496 case STD_STATUS:
2497 rep.h_status = ConnectionStatus(&rep, repb, REPLY_BUFSIZE);
2498 putrep(&rep, repb, rep.h_size);
2499 break;
2500
2501 case AX_SHUTDOWN:
2502 GiveUp();
2503 rep.h_status = STD_OK;
2504 putrep(&rep, NILBUF, 0);
2505 break;
2506
2507 case AX_REINIT:
2508 AutoResetServer();
2509 rep.h_status = STD_OK;
2510 putrep(&rep, NILBUF, 0);
2511 break;
2512
2513 case AX_CONNECT:
2514 /*
2515 * All is well. Open a virtual circuit and read the prefix
2516 */
2517 if (totalClients >= MAXTASKS) {
2518 ErrorF("Connection refused: %s\n", NOROOM);
2519 goto NoSpace;
2520 }
2521
2522 /*
2523 * Fill operating system's communication structure
2524 */
2525 oc = (OsCommPtr) xalloc(sizeof(OsCommRec));
2526 if (oc == (OsCommPtr) NULL) {
2527 ErrorF("Connection refused: No memory for connection data\n");
2528 goto NoSpace;
2529 }
2530 oc->number = -1;
2531 oc->buffer = NULL;
2532 oc->size = 0;
2533 oc->status = 0;
2534 oc->family = FamilyAmoeba;
2535 oc->conn_time = 0L;
2536
2537 /*
2538 * Now some priv2pub magic vc_create must be called with a put
2539 * port as first parameter and a get port as 2nd parameter.
2540 * Since we are a server we send the opposite to the client; ie.
2541 * a get port and a put port respectively.
2542 */
2543 uniqport(&client_ports[0]);
2544 uniqport(&server_ports[1]);
2545 priv2pub(&client_ports[0], &server_ports[0]);
2546 priv2pub(&server_ports[1], &client_ports[1]);
2547 oc->conn.vc = vc_create(&server_ports[0], &server_ports[1],
2548 MAXBUFSIZE, MAXBUFSIZE);
2549 if (oc->conn.vc == (struct vc *) NULL) {
2550 NoSpace:
2551 rep.h_status = AX_FULLHOUSE;
2552 putrep(&rep, NILBUF, 0);
2553 } else {
2554 rep.h_status = AX_OK;
2555 putrep(&rep, (bufptr) client_ports, 2 * sizeof(port));
2556 dbprintf(("Amoeba connection accepted\n"));
2557
2558 /*
2559 * Store for the main loop to finish creation
2560 */
2561 vc_warn(oc->conn.vc, VC_IN, UnblockMain, (int) oc);
2562 mu_lock(&NewConnsLock);
2563 NewConns[nNewConns++] = oc;
2564 mu_unlock(&NewConnsLock);
2565 WakeUpMainThread();
2566 }
2567 break;
2568
2569 default:
2570 rep.h_status = STD_COMBAD;
2571 putrep(&rep, NILBUF, 0);
2572 break;
2573 }
2574 }
2575 }
2576
2577 static void
TcpIpReaderSignalCatcher(signum sig,thread_ustate * us,char * extra)2578 TcpIpReaderSignalCatcher(signum sig, thread_ustate * us, char *extra)
2579 {
2580 OsCommPtr oc = (OsCommPtr) extra;
2581
2582 dbprintf(("TcpIpReaderSignalCatcher(%d), number %d\n", sig,
2583 oc->number));
2584 if (oc->conn.tcp.signal != sig) {
2585 ErrorF("TCP/IP Reader: Connection %s got unexpected signal %d\n",
2586 oc->number, sig);
2587 }
2588 oc->conn.tcp.signal = -1;
2589 thread_exit();
2590 }
2591
2592 /*
2593 * TCP/IP reader thread
2594 */
2595 static void
TcpIpReaderThread(void * argptr,argsize argsize)2596 TcpIpReaderThread(void *argptr, argsize argsize)
2597 {
2598 OsCommPtr oc;
2599
2600 if (argsize != sizeof(OsCommPtr))
2601 FatalError
2602 ("Internal error: TcpIpReaderThread incorrectly called\n");
2603 oc = *((OsCommPtr *) argptr);
2604 (void) sig_catch(oc->conn.tcp.signal, TcpIpReaderSignalCatcher,
2605 (char *) oc);
2606 while (TRUE) {
2607 char buffer[MAXBUFSIZE];
2608 bufsize size;
2609
2610 size = tcpip_read(&oc->conn.tcp.cap, buffer, sizeof(buffer));
2611 dbprintf(("TcpIpReaderThread() read %d bytes\n", size));
2612 if (ERR_STATUS(size)) {
2613 ErrorF("TCP/IP read failed (%s)\n",
2614 tcpip_why(ERR_CONVERT(size)));
2615 oc->status |= CONN_KILLED;
2616 oc->conn.tcp.signal = -1;
2617 thread_exit();
2618 }
2619 if (size == 0 || cb_puts(oc->conn.tcp.cb, buffer, size)) {
2620 if (size != 0)
2621 ErrorF("TCP/IP short write to circular buffer\n");
2622 oc->status |= CONN_KILLED;
2623 oc->conn.tcp.signal = -1;
2624 thread_exit();
2625 }
2626 UnblockMain(oc);
2627 }
2628 }
2629
2630 /*
2631 * To prevent the audio-server from generating lots of error messages,
2632 * in case the server is gone or when its full.
2633 */
2634 #define LOOP_OPEN 1
2635 #define LOOP_SETCONF 2
2636 #define LOOP_LISTEN 4
2637
2638 /*
2639 * The TCP/IP connector thread listens to a well known port (6000 +
2640 * display number) for connection request. When such a request arrives
2641 * it allocates a communication structure and a reader thread. This
2642 * thread prevents the main loop from blocking when there's no data.
2643 */
2644 static void
AmoebaTCPConnectorThread(void)2645 AmoebaTCPConnectorThread(void)
2646 {
2647 capability svrcap, chancap;
2648 nwio_tcpconf_t tcpconf;
2649 nwio_tcpcl_t tcpconnopt;
2650 char name[BUFSIZ];
2651 OsCommPtr oc, *param;
2652 errstat err;
2653 int result;
2654 int looping = 0;
2655
2656 strncpy(name, AuTcpServerName, BUFSIZ); name[BUFSIZ-1] = '\0';
2657 if ((err = name_lookup(name, &svrcap)) != STD_OK) {
2658 snprintf(name, BUFSIZ, "%s/%s", TCP_SVR_NAME, AuTcpServerName);
2659 if ((err = name_lookup(name, &svrcap)) != STD_OK)
2660 FatalError("Lookup %s failed: %s\n", AuTcpServerName,
2661 err_why(err));
2662 }
2663
2664 WaitForInitialization();
2665 dbprintf(("AmoebaTCPConnectorThread() running ...\n"));
2666
2667 for (;;) {
2668 /*
2669 * Listen to TCP/IP port AUDIO_TCP_PORT + offset for connections.
2670 * Some interesting actions have to be taken to keep this connection
2671 * alive and kicking :-)
2672 */
2673 if ((err = tcpip_open(&svrcap, &chancap)) != STD_OK) {
2674 /* the server probably disappeared, just wait for it to return */
2675 if (looping & LOOP_OPEN) {
2676 ErrorF("TCP/IP open failed: %s\n", tcpip_why(err));
2677 looping |= LOOP_OPEN;
2678 }
2679 sleep(60);
2680 (void) name_lookup(name, &svrcap);
2681 continue;
2682 }
2683 looping &= ~LOOP_OPEN;
2684
2685 tcpconf.nwtc_locport = htons(AUDIO_TCP_PORT + atoi(offset));
2686 tcpconf.nwtc_flags = NWTC_EXCL | NWTC_LP_SET | NWTC_UNSET_RA |
2687 NWTC_UNSET_RP;
2688 if ((err = tcp_ioc_setconf(&chancap, &tcpconf)) != STD_OK) {
2689 /* couldn't configure, probably server space problem */
2690 if (looping & LOOP_SETCONF) {
2691 ErrorF("TCP/IP setconf failed: %s\n", tcpip_why(err));
2692 looping |= LOOP_SETCONF;
2693 }
2694 std_destroy(&chancap);
2695 sleep(60);
2696 continue;
2697 }
2698 looping &= ~LOOP_SETCONF;
2699
2700 tcpconnopt.nwtcl_flags = 0;
2701 if ((err = tcp_ioc_listen(&chancap, &tcpconnopt)) != STD_OK) {
2702 /* couldn't listen, definitely a server memory problem */
2703 if (looping & LOOP_LISTEN) {
2704 ErrorF("TCP/IP listen failed: %s\n", tcpip_why(err));
2705 looping |= LOOP_LISTEN;
2706 }
2707 std_destroy(&chancap);
2708 sleep(60);
2709 continue;
2710 }
2711 looping &= ~LOOP_LISTEN;
2712
2713 if ((err = tcpip_keepalive_cap(&chancap)) != STD_OK) {
2714 ErrorF("TCP/IP keep alive failed: %s\n", tcpip_why(err));
2715 std_destroy(&chancap);
2716 continue;
2717 }
2718
2719 /*
2720 * Fill operating system's communication structure
2721 */
2722 oc = (OsCommPtr) xalloc(sizeof(OsCommRec));
2723 if (oc == (OsCommPtr) NULL) {
2724 ErrorF("Connection refused: No memory for connection data\n");
2725 goto NoSpace;
2726 }
2727 oc->number = -1;
2728 oc->buffer = NULL;
2729 oc->size = 0;
2730 oc->status = 0;
2731 oc->family = FamilyInternet;
2732 oc->conn_time = 0L;
2733 oc->conn.tcp.cap = chancap;
2734 if ((oc->conn.tcp.cb = cb_alloc(MAXBUFSIZE)) == NULL) {
2735 ErrorF("Connection refused: No memory for circular buffer\n");
2736 xfree((char *) oc);
2737 goto NoSpace;
2738 }
2739
2740 /*
2741 * Start TCP/IP reader thread
2742 */
2743 oc->conn.tcp.signal = sig_uniq();
2744 param = (OsCommPtr *) malloc(sizeof(OsCommPtr));
2745 *param = oc; /* stupid convention */
2746 result = thread_newthread(TcpIpReaderThread,
2747 MAXBUFSIZE + CONNECTOR_STACK,
2748 (char *) param, sizeof(OsCommPtr));
2749 if (result == 0) {
2750 ErrorF("Cannot start reader thread\n");
2751 cb_close(oc->conn.tcp.cb);
2752 cb_free(oc->conn.tcp.cb);
2753 xfree((char *) oc);
2754 NoSpace:
2755 std_destroy(&chancap);
2756 continue;
2757 }
2758
2759 /*
2760 * Store for the main loop to finish creation
2761 */
2762 mu_lock(&NewConnsLock);
2763 NewConns[nNewConns++] = oc;
2764 mu_unlock(&NewConnsLock);
2765 WakeUpMainThread();
2766 }
2767 }
2768 #endif /* AMOEBA */
2769
2770 #ifdef AIXV3
2771
2772 static long pendingActiveClients[mskcnt];
2773 static BOOL reallyGrabbed;
2774
2775 /****************
2776 * DontListenToAnybody:
2777 * Don't listen to requests from any clients. Continue to handle new
2778 * connections, but don't take any protocol requests from anybody.
2779 * We have to take care if there is already a grab in progress, though.
2780 * Undone by PayAttentionToClientsAgain. We also have to be careful
2781 * not to accept any more input from the currently dispatched client.
2782 * we do this be telling dispatch it is time to yield.
2783
2784 * We call this when the server loses access to the glass
2785 * (user hot-keys away). This looks like a grab by the
2786 * server itself, but gets a little tricky if there is already
2787 * a grab in progress.
2788 ******************/
2789
2790 void
DontListenToAnybody()2791 DontListenToAnybody()
2792 {
2793 if (!GrabInProgress) {
2794 COPYBITS(ClientsWithInput, SavedClientsWithInput);
2795 COPYBITS(AllSockets, SavedAllSockets);
2796 COPYBITS(AllClients, SavedAllClients);
2797 GrabInProgress = TRUE;
2798 reallyGrabbed = FALSE;
2799 } else {
2800 COPYBITS(AllClients, pendingActiveClients);
2801 reallyGrabbed = TRUE;
2802 }
2803 CLEARBITS(ClientsWithInput);
2804 UNSETBITS(AllSockets, AllClients);
2805 CLEARBITS(AllClients);
2806 isItTimeToYield = TRUE;
2807 }
2808
2809 void
PayAttentionToClientsAgain()2810 PayAttentionToClientsAgain()
2811 {
2812 if (reallyGrabbed) {
2813 ORBITS(AllSockets, AllSockets, pendingActiveClients);
2814 ORBITS(AllClients, AllClients, pendingActiveClients);
2815 } else {
2816 ListenToAllClients();
2817 }
2818 reallyGrabbed = FALSE;
2819 }
2820
2821 #endif
2822
2823
2824 #if defined(SYSV) && defined(SYSV386) && !defined(STREAMSCONN)
2825 #ifdef SCO
2826
2827 /*
2828 * SCO does not have writev so we emulate
2829 */
2830
2831 #include <sys/uio.h>
2832
2833 int
_OSWriteV(fd,iov,iovcnt)2834 _OSWriteV(fd, iov, iovcnt)
2835 int fd;
2836 struct iovec *iov;
2837 int iovcnt;
2838 {
2839 int i, len, total;
2840 char *base;
2841
2842 errno = 0;
2843 for (i = 0, total = 0; i < iovcnt; i++, iov++) {
2844 len = iov->iov_len;
2845 base = iov->iov_base;
2846 while (len > 0) {
2847 int nbytes;
2848
2849 nbytes = write(fd, base, len);
2850 if (nbytes < 0 && total == 0)
2851 return (-1);
2852 if (nbytes <= 0)
2853 return (total);
2854 errno = 0;
2855 len -= nbytes;
2856 total += nbytes;
2857 base += nbytes;
2858 }
2859 }
2860 return (total);
2861 }
2862
2863 #endif /* SCO */
2864 #endif /* SYSV && SYSV386 && !STREAMSCONN */
2865