Annotation of researchv9/X11/src/X.V11R1/server/os/v9/connection.c, revision 1.1.1.2

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: /* $Header: connection.c,v 1.62 87/09/07 17:12:18 rws Exp $ */
                     25: /*****************************************************************
                     26:  *  Stuff to create connections --- OS dependent
                     27:  *
                     28:  *      EstablishNewConnections, CreateWellKnownSockets,
                     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: #undef NULL
                     43: #include "X.h"
                     44: #include "Xproto.h"
                     45: #include <sys/param.h>
                     46: #include <errno.h>
                     47: #include <sys/types.h>
                     48: #include <sys/filio.h>
                     49: #include <signal.h>
                     50: #include <setjmp.h>
                     51: #include <ipc.h>
                     52: #include <stdio.h>
                     53: #include <strings.h>
                     54: #include "osstruct.h"
                     55: #include "osdep.h"
                     56: #include "opaque.h"
                     57: 
                     58: #include "dixstruct.h"
                     59: 
                     60: char *display;                 /* The display number */
                     61: int lastfdesc;                  /* maximum file descriptor */
                     62: 
                     63: long WellKnownConnections;    /* Listener mask */
                     64: long EnabledDevices;           /* mask for input devices that are on */
                     65: long AllSockets[mskcnt];        /* select on this */
                     66: long AllClients[mskcnt];              /* available clients */
                     67: long LastSelectMask[mskcnt];          /* mask returned from last select call */
                     68: long ClientsWithInput[mskcnt];
                     69: long MaxClients = MAXSOCKS ;
                     70: long NConnBitArrays = mskcnt;
                     71: long FirstClient;
                     72: 
                     73: static Bool debug_conns = FALSE;
                     74: 
                     75: static char whichByteIsFirst;
                     76: 
                     77: static int SavedAllClients[mskcnt];
                     78: static int SavedAllSockets[mskcnt];
                     79: static int SavedClientsWithInput[mskcnt];
                     80: static Bool GrabDone = FALSE;
                     81: 
                     82: ClientPtr ConnectionTranslation[MAXSOCKS];
                     83: extern ClientPtr NextAvailableClient();
                     84: 
                     85: extern ConnectionInput inputBuffers[];
                     86: 
                     87: int swappedClients[MAXSOCKS];
                     88: 
                     89: extern int AutoResetServer();
                     90: extern int GiveUp();
                     91: 
                     92: /*****************
                     93:  * CreateWellKnownSockets
                     94:  *    At initialization, create the sockets to listen on for new clients.
                     95:  *    There are potentially 4: DECnet, UNIX Domain, TCP-IP with MSB first, 
                     96:  *    with TCP-IP with LSB first.
                     97:  *****************/
                     98: 
                     99: void
                    100: CreateWellKnownSockets()
                    101: {
                    102:     char       fname[32];
                    103:     char       port[32];
                    104:     int                request, i;
                    105:     int                whichbyte;          /* used to figure out whether this is
                    106:                                         LSB or MSB */
                    107:     int retry;
                    108: 
                    109:     CLEARBITS(AllSockets);
                    110:     CLEARBITS(AllClients);
                    111:     CLEARBITS(LastSelectMask);
                    112:     CLEARBITS(ClientsWithInput);
                    113: 
                    114:     for (i=0; i<MAXSOCKS; i++) ConnectionTranslation[i] = (ClientPtr)NULL;
                    115:     
                    116:     lastfdesc = MAXSOCKS - 1;
                    117: 
                    118:        /* hack test to decide where to log errors */
                    119: 
                    120:     if (write (2, fname, 0)) 
                    121:     {
                    122:        long t; 
                    123: 
                    124:        char *ctime();
                    125:         close(stdin);
                    126:         close(stdout);
                    127:        strcpy (fname, "/usr/adm/X");
                    128:        strcat (fname, display);
                    129:        strcat (fname, "msgs");
                    130:        freopen (fname, "a+", stderr);
                    131:        time (&t);
                    132:        fprintf (stderr, "start %s", ctime(&t));
                    133:     }
                    134:        if (getpgrp (0) == 0)
                    135:            setpgrp (0, getpid ());
                    136: 
                    137:     WellKnownConnections = 0;
                    138:     whichbyte = 1;
                    139:     
                    140:     if (*(char *) &whichbyte)
                    141:         whichByteIsFirst = 'l';
                    142:     else
                    143:         whichByteIsFirst = 'B';
                    144: 
                    145: 
                    146:     retry = 10;
                    147:     sprintf(port, "/cs/tcp.%d", atoi (display) + X_TCP_PORT);
                    148:     while ((request = ipccreat(port, "heavy")) < 0) 
                    149:     {
                    150:         if (--retry == 0)
                    151:                Notice ("Binding TCP socket");
                    152:         sleep (10);
                    153:     }
                    154:     WellKnownConnections |= (1 << request);
                    155:     DefineSelf (request);
                    156: 
                    157:     if (WellKnownConnections == 0)
                    158:         Error ("No Listeners, nothing to do");
                    159:     signal (SIGPIPE, SIG_IGN);
1.1.1.2 ! root      160:     signal (SIGHUP, GiveUp);
1.1       root      161:     signal (SIGINT, GiveUp);
                    162:     signal (SIGTERM, GiveUp);
                    163:     FirstClient = request + 1;
                    164:     AllSockets[0] = WellKnownConnections;
                    165:     ResetHosts(display);
                    166: 
                    167:     for (i=0; i<MaxClients; i++)
                    168:     {
                    169:        inputBuffers[i].buffer = (char *) NULL;
                    170:        inputBuffers[i].bufptr = (char *) NULL;
                    171:        inputBuffers[i].bufcnt = 0;
                    172:        inputBuffers[i].lenLastReq = 0;
                    173:        inputBuffers[i].size = 0;
                    174:     }
                    175: }
                    176: 
                    177: /* We want to read the connection information.  If the client doesn't
                    178:  * send us enough data, however, we want to time out eventually.
                    179:  * The scheme is to clear a flag, set an alarm, and keep doing non-blocking
                    180:  * reads until we get all the data we want. If the alarm goes
                    181:  * off, the handler will clear the flag.  If we see that the flag is
                    182:  * cleared, we know we've timed out and return with an error.
                    183:  *
                    184:  * there remains one problem with this code:
                    185:  * there is a window of vulnerability in which we might get an alarm
                    186:  * even though all the data has come in properly.  This is because I
                    187:  * can't atomically clear the alarm.
                    188:  * 
                    189:  * Anyone who sees how to fix this problem should do so and
                    190:  * submit a fix.
                    191:  */
                    192: 
                    193: jmp_buf        env;
                    194: void TimeOut()
                    195: {
                    196:     longjmp(env, 1);
                    197: }
                    198: static Bool 
                    199: ReadBuffer(conn, buffer, charsWanted)
                    200:     long conn;
                    201:     char *buffer;
                    202:     int charsWanted;
                    203: {
                    204:     char *bptr = buffer;
                    205:     int got, fTimeOut;
                    206: 
                    207:     signal(SIGALRM, TimeOut);
                    208:     fTimeOut = FALSE;
                    209:     /* only 1 alarm, please, not 1 per minute */
                    210:     alarm(TimeOutValue);
                    211:     /* It better not take a full minute to get to the read call */
                    212: 
                    213:     while (charsWanted && (fTimeOut = setjmp(env)) == FALSE)
                    214:     {
                    215:        got = read(conn, bptr, charsWanted);    
                    216:        if (got <= 0)
                    217:            return FALSE;
                    218:        if(got > 0)
                    219:        {
                    220:            charsWanted -= got;
                    221:            bptr += got;
                    222:            /* Ok, we got something, reset the timer */
                    223:            alarm(TimeOutValue);
                    224:        }
                    225:     }
                    226:     /* disable the timer */
                    227:     alarm(0);
                    228:     /* If we got here and we didn't time out, then return TRUE, because
                    229:      * we must have read what we wanted. If we timed out, return FALSE */
                    230:     if(fTimeOut && debug_conns)
                    231:        ErrorF("Timed out on connection %d\n", conn);
                    232:     return (!fTimeOut);
                    233: }
                    234: 
                    235: /*****************************************************************
                    236:  * ClientAuthorized
                    237:  *
                    238:  *    Sent by the client at connection setup:
                    239:  *                typedef struct _xConnClientPrefix {
                    240:  *                   CARD8     byteOrder;
                    241:  *                   BYTE      pad;
                    242:  *                   CARD16    majorVersion, minorVersion;
                    243:  *                   CARD16    nbytesAuthProto;    
                    244:  *                   CARD16    nbytesAuthString;   
                    245:  *                 } xConnClientPrefix;
                    246:  *
                    247:  *             It is hoped that eventually one protocol will be agreed upon.  In the
                    248:  *        mean time, a server that implements a different protocol than the
                    249:  *        client expects, or a server that only implements the host-based
                    250:  *        mechanism, will simply ignore this information.
                    251:  *
                    252:  *****************************************************************/
                    253: 
                    254: int 
                    255: ClientAuthorized(conn, pswapped, reason)
                    256:     long conn;
                    257:     int  *pswapped;
                    258:     char **reason;   /* if authorization fails, put reason in here */
                    259: {
                    260:     short slen;
                    261:     xConnClientPrefix xccp;
                    262:     char auth_proto[100];
                    263:     char auth_string[100];
                    264: 
                    265:     if (!ReadBuffer(conn, &xccp, sizeof(xConnClientPrefix)))
                    266:     {
                    267:        /* If they can't even give us this much, just blow them off
                    268:         * without an error message */
                    269:        *reason = 0;
                    270:         return 0;
                    271:     }
                    272:     if (xccp.byteOrder != whichByteIsFirst)
                    273:     {        
                    274:        SwapConnClientPrefix(&xccp);
                    275:        *pswapped = TRUE;
                    276:     }
                    277:     else
                    278:         *pswapped = FALSE;
                    279:     if ((xccp.majorVersion != X_PROTOCOL) ||
                    280:        (xccp.minorVersion != X_PROTOCOL_REVISION))
                    281:     {        
                    282: #define STR "Protocol version mismatch"
                    283:         *reason = (char *)Xalloc(strlen(STR) + 1);
                    284:         strcpy(*reason, STR);
                    285:        if (debug_conns)
                    286:            ErrorF("%s\n", STR);
                    287: #undef STR
                    288:         return 0;
                    289:     }
                    290:     
                    291:    slen = (xccp.nbytesAuthProto + 3) & ~3;  
                    292:     if ( slen )
                    293:         if (!ReadBuffer(conn, auth_proto, slen))
                    294:         {
                    295: #define STR "Length error in xConnClientPrefix for protocol authorization "
                    296:             *reason = (char *)Xalloc(strlen(STR));
                    297:             strcpy(*reason, STR);
                    298:             return 0;
                    299: #undef STR
                    300:        }
                    301:     auth_proto[slen] = '\0';
                    302: 
                    303:     slen = (xccp.nbytesAuthString + 3) & ~3;   
                    304:     if ( slen)
                    305:         if (!ReadBuffer(conn, auth_string, slen))
                    306:         {
                    307: #define STR "Length error in xConnClientPrefix for protocol string"
                    308:             *reason = (char *)Xalloc(strlen(STR));
                    309:             strcpy(*reason, STR);
                    310:             return 0;
                    311: #undef STR
                    312:        }
                    313:     auth_string[slen] = '\0';
                    314: 
                    315:     /* At this point, if the client is authorized to change the access control
                    316:      * list, we should getpeername() information, and add the client to
                    317:      * the selfhosts list.  It's not really the host machine, but the
                    318:      * true purpose of the selfhosts list is to see who may change the
                    319:      * access control list.
                    320:      */
                    321:     return(1);
                    322: }    
                    323: 
                    324: static int padlength[4] = {0, 3, 2, 1};
                    325: 
                    326: /*****************
                    327:  * EstablishNewConnections
                    328:  *    If anyone is waiting on listened sockets, accept them.
                    329:  *    Returns a mask with indices of new clients.  Updates AllClients
                    330:  *    and AllSockets.
                    331:  *****************/
                    332: 
                    333: void
                    334: EstablishNewConnections(newclients, nnew)
                    335:     ClientPtr          *newclients;
                    336:     int                *nnew;
                    337: {
                    338:     long readyconnections;     /* mask of listeners that are ready */
                    339:     long curconn;                  /* fd of listener that's ready */
                    340:     long newconn;                  /* fd of new client */
                    341:     int         swapped;               /* set by ClientAuthorized if connection is
                    342:                                 * swapped */
                    343:     char *reason;
                    344:     ipcinfo *ip;
                    345: 
                    346:     *nnew = 0;
                    347:     if (readyconnections = (LastSelectMask[0] & WellKnownConnections)) 
                    348:     {
                    349:        while (readyconnections) 
                    350:        {
                    351:            curconn = ffs (readyconnections) - 1;
                    352:            if ((ip = ipclisten(curconn)) && (newconn = ipcaccept(ip)) >= 0)
                    353:            {
                    354:                if (newconn >= lastfdesc)
                    355:                {
                    356:                    if (debug_conns)
                    357: ErrorF("Didn't make connection: Out of file descriptors for connections\n");
                    358:                    close (newconn);
                    359:                } 
                    360:                else 
                    361:                {
                    362:                    if (ClientAuthorized(newconn, &swapped, &reason))
                    363:                    {
                    364:                        ClientPtr next;
                    365: 
                    366:                        (void) ioctl(newconn, FIOWNBLK, 0);
                    367:                        inputBuffers[newconn].used = 1; 
                    368:                         if (! inputBuffers[newconn].size) 
                    369:                        {
                    370:                            inputBuffers[newconn].buffer = 
                    371:                                        (char *)Xalloc(BUFSIZE);
                    372:                            inputBuffers[newconn].size = BUFSIZE;
                    373:                            inputBuffers[newconn].bufptr =      
                    374:                                        inputBuffers[newconn].buffer;
                    375:                        }
                    376:                        if (GrabDone)
                    377:                        {
                    378:                            BITSET(SavedAllClients, newconn);
                    379:                            BITSET(SavedAllSockets, newconn);
                    380:                        }
                    381:                        else
                    382:                        {
                    383:                            BITSET(AllClients, newconn);
                    384:                            BITSET(AllSockets, newconn);
                    385:                        }
                    386:                        next = NextAvailableClient();
                    387:                        if (next != (ClientPtr)NULL)
                    388:                        {
                    389:                           osPrivPtr priv;
                    390: 
                    391:                           newclients[(*nnew)++] = next;
                    392:                           next->swapped = swapped;
                    393:                           ConnectionTranslation[newconn] = next;
                    394:                           priv =  (osPrivPtr)Xalloc(sizeof(osPrivRec));
                    395:                           priv->fd = newconn;
                    396:                           next->osPrivate = (pointer)priv;
                    397:                        }
                    398:                    }
                    399:                    else
                    400:                    {
                    401:                        xConnSetupPrefix c;
                    402: 
                    403:                        if(reason)
                    404:                        {
                    405:                            c.success = xFalse;
                    406:                            c.lengthReason = strlen(reason);
                    407:                            c.length = (c.lengthReason + 3) >> 2;
                    408:                            c.majorVersion = X_PROTOCOL;
                    409:                            c.minorVersion = X_PROTOCOL_REVISION;
                    410:                            if(swapped)
                    411:                            {
                    412:                                int     n;
                    413: 
                    414:                                swaps(&c.majorVersion, n);
                    415:                                swaps(&c.minorVersion, n);
                    416:                                swaps(&c.length, n);
                    417:                            }
                    418: 
                    419:                            write(newconn, &c, sizeof(xConnSetupPrefix)); 
                    420:                            write(newconn, reason,
                    421:                                c.lengthReason+padlength[strlen(reason) & 3]);
                    422:                            if (debug_conns)
                    423:                                ErrorF("Didn't make connection:%s\n", reason);
                    424:                        }
                    425:                        close(newconn);
                    426:                        Xfree(reason);
                    427:                    }
                    428: 
                    429:                }
                    430:            }
                    431:            readyconnections &= ~(1 << curconn);
                    432:        }
                    433:     }
                    434: }
                    435: 
                    436: /************
                    437:  *   CloseDwonFileDescriptor:
                    438:  *     Remove this file descriptor and it's inputbuffers, etc.
                    439:  ************/
                    440: 
                    441: void
                    442: CloseDownFileDescriptor(connection)
                    443:     long connection;
                    444: {
                    445:     close(connection);
                    446: 
                    447:     inputBuffers[connection].bufptr = inputBuffers[connection].buffer;
                    448:     inputBuffers[connection].bufcnt = 0;
                    449:     inputBuffers[connection].lenLastReq = 0;
                    450:     inputBuffers[connection].used = 0;
                    451: 
                    452:     BITCLEAR(AllSockets, connection);
                    453:     BITCLEAR(AllClients, connection);
                    454:     BITCLEAR(ClientsWithInput, connection);
                    455: 
                    456: }
                    457: 
                    458: /*****************
                    459:  * CheckConections
                    460:  *    Some connection has died, go find which one and shut it down 
                    461:  *    The file descriptor has been closed, but is still in AllClients.
                    462:  *    If would truly be wonderful if select() would put the bogus
                    463:  *    file descriptors in the exception mask, but nooooo.  So we have
                    464:  *    to check each and every socket individually.
                    465:  *****************/
                    466: 
                    467: void
                    468: CheckConnections()
                    469: {
                    470:     long               mask[mskcnt];
                    471:     long               tmask[mskcnt]; 
                    472:     register int       curclient;
                    473:     int                        i;
                    474:     ClientPtr           bad;
                    475:     int r;
                    476: 
                    477:     COPYBITS(AllClients, mask);
                    478:     for (i=0; i<mskcnt; i++)
                    479:     {
                    480:         while (mask[i])
                    481:        {
                    482:            curclient = ffs (mask[i]) - 1 + (i << 5);
                    483:             CLEARBITS(tmask);
                    484:             BITSET(tmask, curclient);
                    485:             r = select (curclient + 1, tmask, (int *)NULL, 0);
                    486:             if (r < 0)
                    487:             {
                    488:                if (bad = ConnectionTranslation[curclient])
                    489:                    CloseDownClient(bad);
                    490:                 else
                    491:                     CloseDownFileDescriptor(curclient);
                    492:             }
                    493:            BITCLEAR(mask, curclient);
                    494:        }
                    495:     }  
                    496: }
                    497: 
                    498: 
                    499: /*****************
                    500:  * CloseDownConnection
                    501:  *    Delete client from AllClients and free resources 
                    502:  *****************/
                    503: 
                    504: CloseDownConnection(client)
                    505:     ClientPtr client;
                    506: {
                    507:     int connection = ((osPrivPtr)client->osPrivate)->fd;
                    508: 
                    509:     ConnectionTranslation[connection] = (ClientPtr)NULL;
                    510:     CloseDownFileDescriptor(connection);
                    511:     Xfree(client->osPrivate);
                    512: }
                    513: 
                    514: 
                    515: AddEnabledDevice(fd)
                    516:     int fd;
                    517: {
                    518:     EnabledDevices |= (1<<fd);
                    519:     BITSET(AllSockets, fd);
                    520: }
                    521: 
                    522: 
                    523: RemoveEnabledDevice(fd)
                    524:     int fd;
                    525: {
                    526:     EnabledDevices &= ~(1<<fd);
                    527:     BITCLEAR(AllSockets, fd);
                    528: }
                    529: 
                    530: /*****************
                    531:  * OnlyListenToOneClient:
                    532:  *    Only accept requests from  one client.  Continue to handle new
                    533:  *    connections, but don't take any protocol requests from the new
                    534:  *    ones.  Note that if GrabDone is set, EstablishNewConnections
                    535:  *    needs to put new clients into SavedAllSockets and SavedAllClients.
                    536:  *    Note also that there is no timeout for this in the protocol.
                    537:  *    This routine is "undone" by ListenToAllClients()
                    538:  *****************/
                    539: 
                    540: OnlyListenToOneClient(client)
                    541:     ClientPtr client;
                    542: {
                    543:     int connection = ((osPrivPtr)client->osPrivate)->fd;
                    544: 
                    545:     if (! GrabDone)
                    546:     {
                    547:        COPYBITS (ClientsWithInput, SavedClientsWithInput);
                    548:         BITCLEAR (SavedClientsWithInput, connection);
                    549:        if (GETBIT(ClientsWithInput, connection))
                    550:        {
                    551:            CLEARBITS(ClientsWithInput);            
                    552:            BITSET(ClientsWithInput, connection);
                    553:        }
                    554:        else
                    555:         {
                    556:            CLEARBITS(ClientsWithInput);            
                    557:        }
                    558:        COPYBITS(AllSockets, SavedAllSockets);
                    559:        COPYBITS(AllClients, SavedAllClients);
                    560: 
                    561:        UNSETBITS(AllSockets, AllClients);
                    562:        BITSET(AllSockets, connection);
                    563:        CLEARBITS(AllClients);
                    564:        BITSET(AllClients, connection);
                    565:        GrabDone = TRUE;
                    566:     }
                    567: }
                    568: 
                    569: /****************
                    570:  * ListenToAllClients:
                    571:  *    Undoes OnlyListentToOneClient()
                    572:  ****************/
                    573: 
                    574: ListenToAllClients()
                    575: {
                    576:     if (GrabDone)
                    577:     {
                    578:        ORBITS(AllSockets, AllSockets, SavedAllSockets);
                    579:        ORBITS(AllClients, AllClients, SavedAllClients);
                    580:        ORBITS(ClientsWithInput, ClientsWithInput, SavedClientsWithInput);
                    581:        GrabDone = FALSE;
                    582:     }  
                    583: }
                    584: 
                    585: 

unix.superglobalmegacorp.com

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