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, &notime);
1705 #else
1706             r = select(curclient + 1, (fd_set *) tmask, (fd_set *) NULL,
1707                        (fd_set *) NULL, &notime);
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