Annotation of 43BSDReno/contrib/isode-beta/others/X/server/connection.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.