Annotation of lucent/sys/src/9/port/devip.c, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "../port/lib.h"
                      3: #include       "mem.h"
                      4: #include       "dat.h"
                      5: #include       "fns.h"
                      6: #include       "../port/error.h"
                      7: #include       "arp.h"
                      8: #include       "../port/ipdat.h"
                      9: 
                     10: #include       "devtab.h"
                     11: 
                     12: enum
                     13: {
                     14:        Nrprotocol      = 4,    /* Number of protocols supported by this driver */
                     15:        Nipsubdir       = 4,    /* Number of subdirectory entries per connection */
                     16:        Nfrag           = 32,   /* Ip reassembly queue entries */
                     17:        Nifc            = 4,    /* max interfaces */
                     18: };
                     19: 
                     20: int    udpsum = 1;
                     21: Ipifc  *ipifc[Nrprotocol+1];
                     22: QLock  ipalloc;                        /* Protocol port allocation lock */
                     23: Ipconv **tcpbase;
                     24: 
                     25: Streamput      udpstiput, udpstoput, tcpstiput, tcpstoput;
                     26: Streamput      iliput, iloput, bsdiput, bsdoput;
                     27: Streamopen     udpstopen, tcpstopen, ilopen, bsdopen;
                     28: Streamclose    udpstclose, tcpstclose, ilclose, bsdclose;
                     29: 
                     30: Qinfo tcpinfo = { tcpstiput, tcpstoput, tcpstopen, tcpstclose, "tcp", 0, 1 };
                     31: Qinfo udpinfo = { udpstiput, udpstoput, udpstopen, udpstclose, "udp" };
                     32: Qinfo ilinfo  = { iliput,    iloput,    ilopen,    ilclose,    "il"  };
                     33: Qinfo bsdinfo = { bsdiput,   bsdoput,  bsdopen,   bsdclose,   "bsd", 0, 1 };
                     34: 
                     35: Qinfo *protocols[] = { &tcpinfo, &udpinfo, &ilinfo, 0 };
                     36: 
                     37: void
                     38: ipinitifc(Ipifc *ifc, Qinfo *stproto)
                     39: {
                     40:        ifc->conv = xalloc(Nipconv * sizeof(Ipconv*));
                     41:        ifc->protop = stproto;
                     42:        ifc->nconv = Nipconv;
                     43:        ifc->devp = &ipconvinfo;
                     44:        if(stproto != &udpinfo)
                     45:                ifc->listen = iplisten;
                     46:        ifc->clone = ipclonecon;
                     47:        ifc->ninfo = 3;
                     48:        ifc->info[0].name = "remote";
                     49:        ifc->info[0].fill = ipremotefill;
                     50:        ifc->info[1].name = "local";
                     51:        ifc->info[1].fill = iplocalfill;
                     52:        ifc->info[2].name = "status";
                     53:        ifc->info[2].fill = ipstatusfill;
                     54:        ifc->name = stproto->name;
                     55: }
                     56: 
                     57: void
                     58: ipreset(void)
                     59: {
                     60:        int i;
                     61: 
                     62:        for(i = 0; protocols[i]; i++) {
                     63:                ipifc[i] = xalloc(sizeof(Ipifc));
                     64:                ipinitifc(ipifc[i], protocols[i]);
                     65:                newqinfo(protocols[i]);
                     66:        }
                     67: 
                     68:        initfrag(Nfrag);
                     69: }
                     70: 
                     71: void
                     72: ipinit(void)
                     73: {
                     74: }
                     75: 
                     76: Chan *
                     77: ipattach(char *spec)
                     78: {
                     79:        int i;
                     80:        Chan *c;
                     81: 
                     82:        if(ipd[0].q == 0)
                     83:                error("no ip multiplexor");
                     84: 
                     85:        for(i = 0; protocols[i]; i++) {
                     86:                if(strcmp(spec, protocols[i]->name) == 0) {
                     87:                        c = devattach('I', spec);
                     88:                        c->dev = i;
                     89: 
                     90:                        return (c);
                     91:                }
                     92:        }
                     93: 
                     94:        error(Enoproto);
                     95:        return 0;               /* not reached */
                     96: }
                     97: 
                     98: Chan *
                     99: ipclone(Chan *c, Chan *nc)
                    100: {
                    101:        return devclone(c, nc);
                    102: }
                    103: 
                    104: int
                    105: ipwalk(Chan *c, char *name)
                    106: {
                    107:        return netwalk(c, name, ipifc[c->dev]);
                    108: }
                    109: 
                    110: void
                    111: ipstat(Chan *c, char *db)
                    112: {
                    113:        netstat(c, db, ipifc[c->dev]);
                    114: }
                    115: 
                    116: Chan *
                    117: ipopen(Chan *c, int omode)
                    118: {
                    119:        return netopen(c, omode, ipifc[c->dev]);
                    120: }
                    121: 
                    122: int
                    123: ipclonecon(Chan *c)
                    124: {
                    125:        Ipconv *new;
                    126: 
                    127:        new = ipincoming(ipifc[c->dev], 0);
                    128:        if(new == 0)
                    129:                error(Enodev);
                    130:        return new->id;
                    131: }
                    132: 
                    133: /*
                    134:  *  create a new conversation structure if none exists for this conversation slot
                    135:  */
                    136: Ipconv*
                    137: ipcreateconv(Ipifc *ifc, int id)
                    138: {
                    139:        Ipconv **p;
                    140:        Ipconv *new;
                    141: 
                    142:        p = &ifc->conv[id];
                    143:        if(*p)
                    144:                return *p;
                    145:        qlock(ifc);
                    146:        p = &ifc->conv[id];
                    147:        if(*p){
                    148:                qunlock(ifc);
                    149:                return *p;
                    150:        }
                    151:        if(waserror()){
                    152:                qunlock(ifc);
                    153:                nexterror();
                    154:        }
                    155:        new = smalloc(sizeof(Ipconv));
                    156:        new->ifc = ifc;
                    157:        netadd(ifc, new, p - ifc->conv);
                    158:        new->ref = 1;
                    159:        *p = new;
                    160:        qunlock(ifc);
                    161:        poperror();
                    162:        return new;
                    163: }
                    164: 
                    165: /*
                    166:  *  allocate a conversation structure.
                    167:  */
                    168: Ipconv*
                    169: ipincoming(Ipifc *ifc, Ipconv *from)
                    170: {
                    171:        Ipconv *new;
                    172:        Ipconv **p, **etab;
                    173: 
                    174:        /* look for an unused existing conversation */
                    175:        etab = &ifc->conv[Nipconv];
                    176:        for(p = ifc->conv; p < etab; p++) {
                    177:                new = *p;
                    178:                if(new == 0)
                    179:                        break;
                    180:                if(new->ref == 0 && canqlock(new)) {
                    181:                        if(new->ref || ipconbusy(new)) {
                    182:                                qunlock(new);
                    183:                                continue;
                    184:                        }
                    185:                        if(from)        /* copy ownership from listening channel */
                    186:                                netown(new, from->owner, 0);
                    187:                        else            /* current user becomes owner */
                    188:                                netown(new, u->p->user, 0);
                    189: 
                    190:                        new->ref = 1;
                    191:                        qunlock(new);
                    192:                        return new;
                    193:                }       
                    194:        }
                    195: 
                    196:        /* create one */
                    197:        qlock(ifc);
                    198:        etab = &ifc->conv[Nipconv];
                    199:        for(p = ifc->conv; ; p++){
                    200:                if(p == etab){
                    201:                        qunlock(ifc);
                    202:                        return 0;
                    203:                }
                    204:                if(*p == 0)
                    205:                        break;
                    206:        }
                    207:        if(waserror()){
                    208:                qunlock(ifc);
                    209:                nexterror();
                    210:        }
                    211:        new = smalloc(sizeof(Ipconv));
                    212:        new->ifc = ifc;
                    213:        netadd(ifc, new, p - ifc->conv);
                    214:        qlock(new);
                    215:        *p = new;
                    216:        qunlock(ifc);
                    217:        poperror();
                    218:        if(from)        /* copy ownership from listening channel */
                    219:                netown(new, from->owner, 0);
                    220:        else            /* current user becomes owner */
                    221:                netown(new, u->p->user, 0);
                    222:        new->ref = 1;
                    223:        qunlock(new);
                    224:        return new;
                    225: }
                    226: 
                    227: void
                    228: ipcreate(Chan *c, char *name, int omode, ulong perm)
                    229: {
                    230:        USED(c, name, omode, perm);
                    231:        error(Eperm);
                    232: }
                    233: 
                    234: void
                    235: ipremove(Chan *c)
                    236: {
                    237:        USED(c);
                    238:        error(Eperm);
                    239: }
                    240: 
                    241: void
                    242: ipwstat(Chan *c, char *dp)
                    243: {
                    244:        netwstat(c, dp, ipifc[c->dev]);
                    245: }
                    246: 
                    247: void
                    248: ipclose(Chan *c)
                    249: {
                    250:        if(c->stream)
                    251:                streamclose(c);
                    252: }
                    253: 
                    254: long
                    255: ipread(Chan *c, void *a, long n, ulong offset)
                    256: {
                    257:        return netread(c, a, n, offset, ipifc[c->dev]);
                    258: }
                    259: 
                    260: long
                    261: ipwrite(Chan *c, char *a, long n, ulong offset)
                    262: {
                    263:        int     m, backlog, type, priv;
                    264:        char    *field[5], *ctlarg[5], buf[256];
                    265:        Port    port;
                    266:        Ipconv  *cp;
                    267:        uchar   dst[4];
                    268: 
                    269:        USED(offset);
                    270:        type = STREAMTYPE(c->qid.path);
                    271:        if (type == Sdataqid)
                    272:                return streamwrite(c, a, n, 0); 
                    273: 
                    274:        if (type != Sctlqid)
                    275:                error(Eperm);
                    276: 
                    277:        cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
                    278: 
                    279:        m = n;
                    280:        if(m > sizeof(buf)-1)
                    281:                m = sizeof(buf)-1;
                    282:        strncpy(buf, a, m);
                    283:        buf[m] = '\0';
                    284: 
                    285:        m = getfields(buf, field, 5, " ");
                    286:        if(m < 1)
                    287:                error(Ebadarg);
                    288: 
                    289:        if(strncmp(field[0], "connect", 7) == 0) {
                    290:                if(ipconbusy(cp))
                    291:                        error(Enetbusy);
                    292: 
                    293:                if(m < 2)
                    294:                        error(Ebadarg);
                    295: 
                    296:                switch(getfields(field[1], ctlarg, 5, "!")) {
                    297:                default:
                    298:                        error(Eneedservice);
                    299:                case 2:
                    300:                        priv = 0;
                    301:                        break;
                    302:                case 3:
                    303:                        if(strcmp(ctlarg[2], "r") != 0)
                    304:                                error(Eperm);
                    305:                        priv = 1;
                    306:                        break;
                    307:                }
                    308:                cp->dst = ipparse(ctlarg[0]);
                    309:                hnputl(dst, cp->dst);
                    310:                cp->src = ipgetsrc(dst);
                    311:                cp->pdst = atoi(ctlarg[1]);
                    312: 
                    313:                /* If we have no local port assign one */
                    314:                qlock(&ipalloc);
                    315:                if(m == 3){
                    316:                        port = atoi(field[2]);
                    317:                        if(portused(ipifc[c->dev], cp->psrc)){
                    318:                                qunlock(&ipalloc);      
                    319:                                error(Einuse);
                    320:                        }
                    321:                        cp->psrc = port;
                    322:                }
                    323:                if(cp->psrc == 0)
                    324:                        cp->psrc = nextport(ipifc[c->dev], priv);
                    325:                qunlock(&ipalloc);
                    326: 
                    327:                if(cp->ifc->protop == &tcpinfo)
                    328:                        tcpstart(cp, TCP_ACTIVE, Streamhi, 0);
                    329:                else if(cp->ifc->protop == &ilinfo)
                    330:                        ilstart(cp, IL_ACTIVE, 20);
                    331: 
                    332:                /*
                    333:                 *  stupid hack for BSD port's 512, 513, & 514
                    334:                 *  to make it harder for user to lie about his
                    335:                 *  identity. -- presotto
                    336:                 */
                    337:                switch(cp->pdst){
                    338:                case 512:
                    339:                case 513:
                    340:                case 514:
                    341:                        pushq(c->stream, &bsdinfo);
                    342:                        break;
                    343:                }
                    344: 
                    345:                memmove(cp->text, u->p->text, NAMELEN);
                    346:        }
                    347:        else if(strncmp(field[0], "disconnect", 10) == 0) {
                    348:                if(cp->ifc->protop != &udpinfo)
                    349:                        error(Eperm);
                    350: 
                    351:                cp->dst = 0;
                    352:                cp->pdst = 0;
                    353:        }
                    354:        else if(strncmp(field[0], "bind", 4) == 0) {
                    355:                if(ipconbusy(cp))
                    356:                        error(Enetbusy);
                    357: 
                    358:                port = atoi(field[1]);
                    359: 
                    360:                if(port){
                    361:                        qlock(&ipalloc);
                    362:                        if(portused(ipifc[c->dev], port)) {
                    363:                                qunlock(&ipalloc);      
                    364:                                error(Einuse);
                    365:                        }
                    366:                        cp->psrc = port;
                    367:                        qunlock(&ipalloc);
                    368:                } else if(*field[1] != '*'){
                    369:                        qlock(&ipalloc);
                    370:                        cp->psrc = nextport(ipifc[c->dev], 0);
                    371:                        qunlock(&ipalloc);
                    372:                } else
                    373:                        cp->psrc = 0;
                    374:        }
                    375:        else if(strncmp(field[0], "announce", 8) == 0) {
                    376:                if(ipconbusy(cp))
                    377:                        error(Enetbusy);
                    378: 
                    379:                if(m != 2)
                    380:                        error(Ebadarg);
                    381: 
                    382:                port = atoi(field[1]);
                    383: 
                    384:                if(port){
                    385:                        qlock(&ipalloc);
                    386:                        if(portused(ipifc[c->dev], port)) {
                    387:                                qunlock(&ipalloc);      
                    388:                                error(Einuse);
                    389:                        }
                    390:                        cp->psrc = port;
                    391:                        qunlock(&ipalloc);
                    392:                } else if(*field[1] != '*'){
                    393:                        qlock(&ipalloc);
                    394:                        cp->psrc = nextport(ipifc[c->dev], 0);
                    395:                        qunlock(&ipalloc);
                    396:                } else
                    397:                        cp->psrc = 0;
                    398: 
                    399:                if(cp->ifc->protop == &tcpinfo)
                    400:                        tcpstart(cp, TCP_PASSIVE, Streamhi, 0);
                    401:                else if(cp->ifc->protop == &ilinfo)
                    402:                        ilstart(cp, IL_PASSIVE, 10);
                    403: 
                    404:                if(cp->backlog == 0)
                    405:                        cp->backlog = 3;
                    406: 
                    407:                memmove(cp->text, u->p->text, NAMELEN);
                    408:        }
                    409:        else if(strncmp(field[0], "backlog", 7) == 0) {
                    410:                if(m != 2)
                    411:                        error(Ebadarg);
                    412:                backlog = atoi(field[1]);
                    413:                if(backlog == 0)
                    414:                        error(Ebadarg);
                    415:                if(backlog > 5)
                    416:                        backlog = 5;
                    417:                cp->backlog = backlog;
                    418:        }
                    419:        else if(strncmp(field[0], "headers", 7) == 0) {
                    420:                cp->headers = 1;        /* include addr/port in user packet */
                    421:        }
                    422:        else
                    423:                return streamwrite(c, a, n, 0);
                    424: 
                    425:        return n;
                    426: }
                    427: 
                    428: int
                    429: ipconbusy(Ipconv  *cp)
                    430: {
                    431:        if(cp->ifc->protop == &tcpinfo)
                    432:        if(cp->tcpctl.state != Closed)
                    433:                return 1;
                    434: 
                    435:        if(cp->ifc->protop == &ilinfo)
                    436:        if(cp->ilctl.state != Ilclosed)
                    437:                return 1;
                    438: 
                    439:        return 0;
                    440: }
                    441: 
                    442: void
                    443: udpstiput(Queue *q, Block *bp)
                    444: {
                    445:        PUTNEXT(q, bp);
                    446: }
                    447: 
                    448: /*
                    449:  * udprcvmsg - called by stip to multiplex udp ports onto conversations
                    450:  */
                    451: void
                    452: udprcvmsg(Ipifc *ifc, Block *bp)
                    453: {
                    454:        Ipconv *cp, **p, **etab;
                    455:        Udphdr *uh;
                    456:        Port   dport, sport;
                    457:        ushort sum, len;
                    458:        Ipaddr addr;
                    459:        Block *nbp;
                    460: 
                    461:        uh = (Udphdr *)(bp->rptr);
                    462: 
                    463:        /* Put back pseudo header for checksum */
                    464:        uh->Unused = 0;
                    465:        len = nhgets(uh->udplen);
                    466:        hnputs(uh->udpplen, len);
                    467: 
                    468:        addr = nhgetl(uh->udpsrc);
                    469: 
                    470:        if(udpsum && nhgets(uh->udpcksum)) {
                    471:                if(sum = ptcl_csum(bp, UDP_EHSIZE, len+UDP_PHDRSIZE)) {
                    472:                        print("udp: checksum error %x (%d.%d.%d.%d)\n",
                    473:                              sum, fmtaddr(addr));
                    474:                        
                    475:                        freeb(bp);
                    476:                        return;
                    477:                }
                    478:        }
                    479: 
                    480:        dport = nhgets(uh->udpdport);
                    481:        sport = nhgets(uh->udpsport);
                    482: 
                    483:        /* Look for a conversation structure for this port */
                    484:        etab = &ifc->conv[Nipconv];
                    485:        for(p = ifc->conv; p < etab; p++) {
                    486:                cp = *p;
                    487:                if(cp == 0)
                    488:                        break;
                    489:                if(cp->ref)
                    490:                if(cp->psrc == dport)
                    491:                if(cp->pdst == 0 || cp->pdst == sport) {
                    492:                        /* Trim the packet down to data size */
                    493:                        len = len - (UDP_HDRSIZE-UDP_PHDRSIZE);
                    494:                        bp = btrim(bp, UDP_EHSIZE+UDP_HDRSIZE, len);
                    495:                        if(bp == 0)
                    496:                                return;
                    497: 
                    498:                        if(cp->headers){
                    499:                                /* pass the src address to the stream head */
                    500:                                nbp = allocb(Udphdrsize);
                    501:                                nbp->next = bp;
                    502:                                bp = nbp;
                    503:                                hnputl(bp->wptr, addr);
                    504:                                bp->wptr += 4;
                    505:                                hnputs(bp->wptr, sport);
                    506:                                bp->wptr += 2;
                    507:                        } else {
                    508:                                /* save the src address in the conversation struct */
                    509:                                cp->dst = addr;
                    510:                                cp->pdst = sport;
                    511:                        }
                    512:                        cp->src = 0;
                    513:                        PUTNEXT(cp->readq, bp);
                    514:                        return;
                    515:                }
                    516:        }
                    517: 
                    518:        freeb(bp);
                    519: }
                    520: 
                    521: void
                    522: udpstoput(Queue *q, Block *bp)
                    523: {
                    524:        Ipconv *cp;
                    525:        Udphdr *uh;
                    526:        int dlen, ptcllen, newlen;
                    527:        Ipaddr addr;
                    528:        Port port;
                    529:        if(bp->type == M_CTL) {
                    530:                PUTNEXT(q, bp);
                    531:                return;
                    532:        }
                    533: 
                    534:        cp = (Ipconv *)(q->ptr);
                    535:        if(cp->psrc == 0){
                    536:                freeb(bp);
                    537:                error(Enoport);
                    538:        }
                    539: 
                    540:        if(bp->type != M_DATA) {
                    541:                freeb(bp);
                    542:                error(Ebadctl);
                    543:        }
                    544: 
                    545:        /* Only allow atomic udp writes to form datagrams */
                    546:        if(!(bp->flags & S_DELIM)) {
                    547:                freeb(bp);
                    548:                error(Emsgsize);
                    549:        }
                    550: 
                    551:        /*
                    552:         *  if we're in header mode, rip off the first 64 bytes as the
                    553:         *  destination.  The destination is in ascii in the form
                    554:         *      %d.%d.%d.%d!%d
                    555:         */
                    556:        if(cp->headers){
                    557:                /* get user specified addresses */
                    558:                bp = pullup(bp, Udphdrsize);
                    559:                if(bp == 0){
                    560:                        freeb(bp);
                    561:                        error(Emsgsize);
                    562:                }
                    563:                addr = nhgetl(bp->rptr);
                    564:                bp->rptr += 4;
                    565:                port = nhgets(bp->rptr);
                    566:                bp->rptr += 2;
                    567:        } else
                    568:                addr = port = 0;
                    569: 
                    570:        /* Round packet up to even number of bytes and check we can
                    571:         * send it
                    572:         */
                    573:        dlen = blen(bp);
                    574:        if(dlen > UDP_DATMAX) {
                    575:                freeb(bp);
                    576:                error(Emsgsize);
                    577:        }
                    578:        newlen = dlen /*bround(bp, 1)*/;
                    579: 
                    580:        /* Make space to fit udp & ip & ethernet header */
                    581:        bp = padb(bp, UDP_EHSIZE + UDP_HDRSIZE);
                    582: 
                    583:        uh = (Udphdr *)(bp->rptr);
                    584: 
                    585:        ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
                    586:        uh->Unused = 0;
                    587:        uh->udpproto = IP_UDPPROTO;
                    588:        uh->frag[0] = 0;
                    589:        uh->frag[1] = 0;
                    590:        hnputs(uh->udpplen, ptcllen);
                    591:        hnputs(uh->udpsport, cp->psrc);
                    592:        if(cp->headers) {
                    593:                hnputl(uh->udpdst, addr);
                    594:                hnputs(uh->udpdport, port);
                    595:        }
                    596:        else {
                    597:                hnputl(uh->udpdst, cp->dst);
                    598:                hnputs(uh->udpdport, cp->pdst);
                    599:        }
                    600:        if(cp->src == 0)
                    601:                cp->src = ipgetsrc(uh->udpdst);
                    602:        hnputl(uh->udpsrc, cp->src);
                    603:        hnputs(uh->udplen, ptcllen);
                    604:        uh->udpcksum[0] = 0;
                    605:        uh->udpcksum[1] = 0;
                    606: 
                    607:        hnputs(uh->udpcksum, ptcl_csum(bp, UDP_EHSIZE, newlen+UDP_HDRSIZE));
                    608:        PUTNEXT(q, bp);
                    609: }
                    610: 
                    611: void
                    612: udpstclose(Queue *q)
                    613: {
                    614:        Ipconv *ipc;
                    615: 
                    616:        ipc = (Ipconv *)(q->ptr);
                    617: 
                    618:        ipc->headers = 0;
                    619:        ipc->psrc = 0;
                    620:        ipc->pdst = 0;
                    621:        ipc->dst = 0;
                    622: }
                    623: 
                    624: void
                    625: udpstopen(Queue *q, Stream *s)
                    626: {
                    627:        Ipconv *ipc;
                    628: 
                    629:        ipc = ipcreateconv(ipifc[s->dev], s->id);
                    630:        initipifc(ipifc[s->dev], IP_UDPPROTO, udprcvmsg);
                    631: 
                    632:        ipc->readq = RD(q);     
                    633:        RD(q)->ptr = (void *)ipc;
                    634:        WR(q)->next->ptr = (void *)ipc->ifc;
                    635:        WR(q)->ptr = (void *)ipc;
                    636: }
                    637: 
                    638: void
                    639: tcpstiput(Queue *q, Block *bp)
                    640: {
                    641:        PUTNEXT(q, bp);
                    642: }
                    643: 
                    644: tcproominq(void *a)
                    645: {
                    646:        return !((Tcpctl *)a)->sndfull;
                    647: }
                    648: 
                    649: void
                    650: tcpstoput(Queue *q, Block *bp)
                    651: {
                    652:        Ipconv *s;
                    653:        Tcpctl *tcb; 
                    654:        Block *f;
                    655: 
                    656:        s = (Ipconv *)(q->ptr);
                    657:        tcb = &s->tcpctl;
                    658: 
                    659:        if(bp->type == M_CTL) {
                    660:                PUTNEXT(q, bp);
                    661:                return;
                    662:        }
                    663: 
                    664:        if(s->psrc == 0)
                    665:                error(Enoport);
                    666: 
                    667:        /* Report asynchronous errors */
                    668:        if(s->err)
                    669:                error(s->err);
                    670: 
                    671:        switch(tcb->state) {
                    672:        case Listen:
                    673:                tcb->flags |= ACTIVE;
                    674:                tcpsndsyn(tcb);
                    675:                tcpsetstate(s, Syn_sent);
                    676: 
                    677:                /* No break */
                    678:        case Syn_sent:
                    679:        case Syn_received:
                    680:        case Established:
                    681:                /*
                    682:                 * Process flow control
                    683:                 */
                    684:                if(tcb->sndfull){
                    685:                        qlock(&tcb->sndrlock);
                    686:                        if(waserror()) {
                    687:                                qunlock(&tcb->sndrlock);
                    688:                                freeb(bp);
                    689:                                nexterror();
                    690:                        }
                    691:                        sleep(&tcb->sndr, tcproominq, tcb);
                    692:                        poperror();
                    693:                        qunlock(&tcb->sndrlock);
                    694:                }
                    695: 
                    696:                /*
                    697:                 * Push data
                    698:                 */
                    699:                qlock(tcb);
                    700:                if(waserror()) {
                    701:                        qunlock(tcb);
                    702:                        nexterror();
                    703:                }
                    704: 
                    705:                /* make sure we don't queue onto something that just closed */
                    706:                switch(tcb->state) {
                    707:                case Syn_sent:
                    708:                case Syn_received:
                    709:                case Established:
                    710:                        break;
                    711:                default:
                    712:                        freeb(bp);
                    713:                        error(Ehungup);
                    714:                }
                    715: 
                    716:                tcb->sndcnt += blen(bp);
                    717:                if(tcb->sndcnt > Streamhi)
                    718:                        tcb->sndfull = 1;
                    719:                if(tcb->sndq == 0)
                    720:                        tcb->sndq = bp;
                    721:                else {
                    722:                        for(f = tcb->sndq; f->next; f = f->next)
                    723:                                ;
                    724:                        f->next = bp;
                    725:                }
                    726:                tcprcvwin(s);
                    727:                tcpoutput(s);
                    728:                poperror();
                    729:                qunlock(tcb);
                    730:                break;
                    731: 
                    732:        case Close_wait:
                    733:        default:
                    734:                freeb(bp);
                    735:                error(Ehungup);
                    736:        }       
                    737: }
                    738: 
                    739: void
                    740: tcpstopen(Queue *q, Stream *s)
                    741: {
                    742:        Ipconv *ipc;
                    743:        Ipifc *ifc;
                    744:        Tcpctl *tcb;
                    745:        Block *bp;      
                    746:        static int tcpkprocs;
                    747: 
                    748:        /* Flow control and tcp timer processes */
                    749:        if(tcpkprocs == 0) {
                    750:                tcpkprocs = 1;
                    751:                kproc("tcpack", tcpackproc, 0);
                    752:                kproc("tcpflow", tcpflow, ipifc[s->dev]);
                    753: 
                    754:        }
                    755: 
                    756:        if(tcpbase == 0)
                    757:                tcpbase = ipifc[s->dev]->conv;
                    758:        ifc = ipifc[s->dev];
                    759:        initipifc(ifc, IP_TCPPROTO, tcpinput);
                    760:        ipc = ipcreateconv(ifc, s->id);
                    761: 
                    762:        ipc->readq = RD(q);
                    763:        ipc->readq->rp = &tcpflowr;
                    764:        ipc->err = 0;
                    765: 
                    766:        RD(q)->ptr = (void *)ipc;
                    767:        WR(q)->ptr = (void *)ipc;
                    768: 
                    769:        /* pass any waiting data upstream */
                    770:        tcb = &ipc->tcpctl;
                    771:        qlock(tcb);
                    772:        while(bp = getb(&tcb->rcvq))
                    773:                PUTNEXT(ipc->readq, bp);
                    774:        qunlock(tcb);
                    775: }
                    776: 
                    777: void
                    778: ipremotefill(Chan *c, char *buf, int len)
                    779: {
                    780:        Ipconv *cp;
                    781: 
                    782:        if(len < 24)
                    783:                error(Ebadarg);
                    784:        cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
                    785:        sprint(buf, "%d.%d.%d.%d!%d\n", fmtaddr(cp->dst), cp->pdst);
                    786: }
                    787: 
                    788: void
                    789: iplocalfill(Chan *c, char *buf, int len)
                    790: {
                    791:        Ipconv *cp;
                    792: 
                    793:        if(len < 24)
                    794:                error(Ebadarg);
                    795:        cp = ipcreateconv(ipifc[c->dev], STREAMID(c->qid.path));
                    796:        sprint(buf, "%d.%d.%d.%d!%d\n", fmtaddr(ipd[0].Myip[Myself]), cp->psrc);
                    797: }
                    798: 
                    799: void
                    800: ipstatusfill(Chan *c, char *buf, int len)
                    801: {
                    802:        Ipconv *cp;
                    803:        int connection;
                    804: 
                    805:        if(len < 64)
                    806:                error(Ebadarg);
                    807:        connection = STREAMID(c->qid.path);
                    808:        cp = ipcreateconv(ipifc[c->dev], connection);
                    809:        if(cp->ifc->protop == &tcpinfo)
                    810:                sprint(buf, "tcp/%d %d %s %s %s %d+%d\n", connection, cp->ref,
                    811:                        tcpstate[cp->tcpctl.state],
                    812:                        cp->tcpctl.flags & CLONE ? "listen" : "connect",
                    813:                        cp->text,
                    814:                        cp->tcpctl.srtt, cp->tcpctl.mdev);
                    815:        else if(cp->ifc->protop == &ilinfo)
                    816:                sprint(buf, "il/%d %d %s rtt %d ms %d csum\n", connection, cp->ref,
                    817:                        ilstate[cp->ilctl.state], cp->ilctl.rtt,
                    818:                        cp->ifc ? cp->ifc->chkerrs : 0);
                    819:        else
                    820:                sprint(buf, "%s/%d %d Datagram\n",
                    821:                                cp->ifc->protop->name, connection, cp->ref);
                    822: }
                    823: 
                    824: int
                    825: iphavecon(Ipconv *s)
                    826: {
                    827:        return s->curlog;
                    828: }
                    829: 
                    830: int
                    831: iplisten(Chan *c)
                    832: {
                    833:        Ipconv *s;
                    834:        int connection;
                    835:        Ipconv **p, **etab, *new;
                    836: 
                    837:        connection = STREAMID(c->qid.path);
                    838:        s = ipcreateconv(ipifc[c->dev], connection);
                    839: 
                    840:        if(s->ifc->protop == &tcpinfo)
                    841:        if(s->tcpctl.state != Listen)
                    842:                error(Enolisten);
                    843: 
                    844:        if(s->ifc->protop == &ilinfo)
                    845:        if(s->ilctl.state != Illistening)
                    846:                error(Enolisten);
                    847: 
                    848:        for(;;) {
                    849:                qlock(&s->listenq);     /* single thread for the sleep */
                    850:                if(waserror()) {
                    851:                        qunlock(&s->listenq);
                    852:                        nexterror();
                    853:                }
                    854:                sleep(&s->listenr, iphavecon, s);
                    855:                poperror();
                    856:                etab = &ipifc[c->dev]->conv[Nipconv];
                    857:                for(p = ipifc[c->dev]->conv; p < etab; p++) {
                    858:                        new = *p;
                    859:                        if(new == 0)
                    860:                                break;
                    861:                        if(new->newcon == s) {
                    862:                                qlock(s);
                    863:                                s->curlog--;
                    864:                                qunlock(s);
                    865:                                new->newcon = 0;
                    866:                                qunlock(&s->listenq);
                    867:                                return new->id;
                    868:                        }
                    869:                }
                    870:                qunlock(&s->listenq);
                    871:                print("iplisten: no newcon\n");
                    872:        }
                    873:        return -1;              /* not reached */
                    874: }
                    875: 
                    876: void
                    877: tcpstclose(Queue *q)
                    878: {
                    879:        Ipconv *s, *new;
                    880:        Ipconv **etab, **p;
                    881:        Tcpctl *tcb;
                    882: 
                    883:        s = (Ipconv *)(q->ptr);
                    884:        tcb = &s->tcpctl;
                    885: 
                    886:        /* Not interested in data anymore */
                    887:        qlock(s);
                    888:        s->readq = 0;
                    889:        qunlock(s);
                    890: 
                    891:        switch(tcb->state){
                    892:        case Listen:
                    893:                /*
                    894:                 *  reset any incoming calls to this listener
                    895:                 */
                    896:                qlock(s);
                    897:                s->backlog = 0;
                    898:                s->curlog = 0;
                    899:                etab = &tcpbase[Nipconv];
                    900:                for(p = tcpbase; p < etab; p++){
                    901:                        new = *p;
                    902:                        if(new == 0)
                    903:                                break;
                    904:                        if(new->newcon == s){
                    905:                                new->newcon = 0;
                    906:                                tcpflushincoming(new);
                    907:                                new->ref = 0;
                    908:                        }
                    909:                }
                    910:                qunlock(s);
                    911: 
                    912:                qlock(tcb);
                    913:                localclose(s, 0);
                    914:                qunlock(tcb);
                    915:                break;
                    916: 
                    917:        case Closed:
                    918:        case Syn_sent:
                    919:                qlock(tcb);
                    920:                localclose(s, 0);
                    921:                qunlock(tcb);
                    922:                break;
                    923: 
                    924:        case Syn_received:
                    925:        case Established:
                    926:                tcb->sndcnt++;
                    927:                tcb->snd.nxt++;
                    928:                tcpsetstate(s, Finwait1);
                    929:                goto output;
                    930: 
                    931:        case Close_wait:
                    932:                tcb->sndcnt++;
                    933:                tcb->snd.nxt++;
                    934:                tcpsetstate(s, Last_ack);
                    935:        output:
                    936:                qlock(tcb);
                    937:                if(waserror()) {
                    938:                        qunlock(tcb);
                    939:                        nexterror();
                    940:                }
                    941:                tcpoutput(s);
                    942:                poperror();
                    943:                qunlock(tcb);
                    944:                break;
                    945:        }
                    946: }
                    947: 
                    948: 
                    949: static short   endian  = 1;
                    950: static char*   aendian = (char*)&endian;
                    951: #define        LITTLE  *aendian
                    952: 
                    953: ushort
                    954: ptcl_bsum(uchar *addr, int len)
                    955: {
                    956:        ulong losum, hisum, mdsum, x;
                    957:        ulong t1, t2;
                    958: 
                    959:        losum = 0;
                    960:        hisum = 0;
                    961:        mdsum = 0;
                    962: 
                    963:        x = 0;
                    964:        if((ulong)addr & 1) {
                    965:                if(len) {
                    966:                        hisum += addr[0];
                    967:                        len--;
                    968:                        addr++;
                    969:                }
                    970:                x = 1;
                    971:        }
                    972:        while(len >= 16) {
                    973:                t1 = *(ushort*)(addr+0);
                    974:                t2 = *(ushort*)(addr+2);        mdsum += t1;
                    975:                t1 = *(ushort*)(addr+4);        mdsum += t2;
                    976:                t2 = *(ushort*)(addr+6);        mdsum += t1;
                    977:                t1 = *(ushort*)(addr+8);        mdsum += t2;
                    978:                t2 = *(ushort*)(addr+10);       mdsum += t1;
                    979:                t1 = *(ushort*)(addr+12);       mdsum += t2;
                    980:                t2 = *(ushort*)(addr+14);       mdsum += t1;
                    981:                mdsum += t2;
                    982:                len -= 16;
                    983:                addr += 16;
                    984:        }
                    985:        while(len >= 2) {
                    986:                mdsum += *(ushort*)addr;
                    987:                len -= 2;
                    988:                addr += 2;
                    989:        }
                    990:        if(x) {
                    991:                if(len)
                    992:                        losum += addr[0];
                    993:                if(LITTLE)
                    994:                        losum += mdsum;
                    995:                else
                    996:                        hisum += mdsum;
                    997:        } else {
                    998:                if(len)
                    999:                        hisum += addr[0];
                   1000:                if(LITTLE)
                   1001:                        hisum += mdsum;
                   1002:                else
                   1003:                        losum += mdsum;
                   1004:        }
                   1005: 
                   1006:        losum += hisum >> 8;
                   1007:        losum += (hisum & 0xff) << 8;
                   1008:        while(hisum = losum>>16)
                   1009:                losum = hisum + (losum & 0xffff);
                   1010: 
                   1011:        return losum & 0xffff;
                   1012: }
                   1013: 
                   1014: ushort
                   1015: ptcl_csum(Block *bp, int offset, int len)
                   1016: {
                   1017:        uchar *addr;
                   1018:        ulong losum, hisum;
                   1019:        ushort csum;
                   1020:        int odd, blen, x;
                   1021: 
                   1022:        /* Correct to front of data area */
                   1023:        while(bp && offset && offset >= BLEN(bp)) {
                   1024:                offset -= BLEN(bp);
                   1025:                bp = bp->next;
                   1026:        }
                   1027:        if(bp == 0)
                   1028:                return 0;
                   1029: 
                   1030:        addr = bp->rptr + offset;
                   1031:        blen = BLEN(bp) - offset;
                   1032: 
                   1033:        if(bp->next == 0)
                   1034:                return ~ptcl_bsum(addr, MIN(len, blen)) & 0xffff;
                   1035: 
                   1036:        losum = 0;
                   1037:        hisum = 0;
                   1038: 
                   1039:        odd = 0;
                   1040:        while(len) {
                   1041:                x = MIN(len, blen);
                   1042:                csum = ptcl_bsum(addr, x);
                   1043:                if(odd)
                   1044:                        hisum += csum;
                   1045:                else
                   1046:                        losum += csum;
                   1047:                odd = (odd+x) & 1;
                   1048:                len -= x;
                   1049: 
                   1050:                bp = bp->next;
                   1051:                if(bp == 0)
                   1052:                        break;
                   1053:                blen = BLEN(bp);
                   1054:                addr = bp->rptr;
                   1055:        }
                   1056: 
                   1057:        losum += hisum>>8;
                   1058:        losum += (hisum&0xff)<<8;
                   1059:        while((csum = losum>>16) != 0)
                   1060:                losum = csum + (losum & 0xffff);
                   1061: 
                   1062:        return ~losum & 0xffff;
                   1063: }
                   1064: 
                   1065: Block *
                   1066: btrim(Block *bp, int offset, int len)
                   1067: {
                   1068:        Block *nb, *startb;
                   1069:        ulong l;
                   1070: 
                   1071:        if(blen(bp) < offset+len) {
                   1072:                freeb(bp);
                   1073:                return 0;
                   1074:        }
                   1075: 
                   1076:        while((l = BLEN(bp)) < offset) {
                   1077:                offset -= l;
                   1078:                nb = bp->next;
                   1079:                bp->next = 0;
                   1080:                freeb(bp);
                   1081:                bp = nb;
                   1082:        }
                   1083: 
                   1084:        startb = bp;
                   1085:        bp->rptr += offset;
                   1086: 
                   1087:        while((l = BLEN(bp)) < len) {
                   1088:                len -= l;
                   1089:                bp = bp->next;
                   1090:        }
                   1091: 
                   1092:        bp->wptr -= (BLEN(bp) - len);
                   1093:        bp->flags |= S_DELIM;
                   1094: 
                   1095:        if(bp->next) {
                   1096:                freeb(bp->next);
                   1097:                bp->next = 0;
                   1098:        }
                   1099: 
                   1100:        return(startb);
                   1101: }
                   1102: 
                   1103: Ipconv *
                   1104: portused(Ipifc *ifc, Port port)
                   1105: {
                   1106:        Ipconv **p, **etab;
                   1107:        Ipconv *cp;
                   1108: 
                   1109:        if(port == 0)
                   1110:                return 0;
                   1111: 
                   1112:        etab = &ifc->conv[Nipconv];
                   1113:        for(p = ifc->conv; p < etab; p++){
                   1114:                cp = *p;
                   1115:                if(cp == 0)
                   1116:                        break;
                   1117:                if(cp->psrc == port) 
                   1118:                        return cp;
                   1119:        }
                   1120: 
                   1121:        return 0;
                   1122: }
                   1123: 
                   1124: static Port lastport[2] = { PORTALLOC-1, PRIVPORTALLOC-1 };
                   1125: 
                   1126: Port
                   1127: nextport(Ipifc *ifc, int priv)
                   1128: {
                   1129:        Port base;
                   1130:        Port max;
                   1131:        Port *p;
                   1132:        Port i;
                   1133: 
                   1134:        if(priv){
                   1135:                base = PRIVPORTALLOC;
                   1136:                max = UNPRIVPORTALLOC;
                   1137:                p = &lastport[1];
                   1138:        } else {
                   1139:                base = PORTALLOC;
                   1140:                max = PORTMAX;
                   1141:                p = &lastport[0];
                   1142:        }
                   1143:        
                   1144:        for(i = *p + 1; i < max; i++)
                   1145:                if(!portused(ifc, i))
                   1146:                        return(*p = i);
                   1147:        for(i = base ; i <= *p; i++)
                   1148:                if(!portused(ifc, i))
                   1149:                        return(*p = i);
                   1150: 
                   1151:        return(0);
                   1152: }
                   1153: 
                   1154: /* NEEDS HASHING ! */
                   1155: 
                   1156: Ipconv*
                   1157: ip_conn(Ipifc *ifc, Port dst, Port src, Ipaddr dest)
                   1158: {
                   1159:        Ipconv **p, *s, **etab;
                   1160: 
                   1161:        /* Look for a conversation structure for this port */
                   1162:        etab = &ifc->conv[Nipconv];
                   1163:        for(p = ifc->conv; p < etab; p++) {
                   1164:                s = *p;
                   1165:                if(s == 0)
                   1166:                        break;
                   1167:                if(s->psrc == dst)
                   1168:                if(s->pdst == src)
                   1169:                if(s->dst == dest || dest == 0)
                   1170:                        return s;
                   1171:        }
                   1172: 
                   1173:        return 0;
                   1174: }
                   1175: 
                   1176: /*
                   1177:  *
                   1178:  *  BSD authentication protocol, used on ports 512, 513, & 514.
                   1179:  *  This makes sure that a user can only write the REAL user id.
                   1180:  *
                   1181:  *  q->ptr is number of nulls seen
                   1182:  */
                   1183: void
                   1184: bsdopen(Queue *q, Stream *s)
                   1185: {
                   1186:        USED(s);
                   1187:        RD(q)->ptr = q;
                   1188:        WR(q)->ptr = q;
                   1189: }
                   1190: void
                   1191: bsdclose(Queue *q)
                   1192: {
                   1193:        Block *bp;
                   1194: 
                   1195:        bp = allocb(0);
                   1196:        bp->type = M_HANGUP;
                   1197:        PUTNEXT(q->other, bp);
                   1198: }
                   1199: void
                   1200: bsdiput(Queue *q, Block *bp)
                   1201: {
                   1202:        PUTNEXT(q, bp);
                   1203: }
                   1204: void
                   1205: bsdoput(Queue *q, Block *bp)
                   1206: {
                   1207:        uchar *luser;
                   1208:        Block *nbp;
                   1209: 
                   1210:        /* just pass it on if we've done authentication */
                   1211:        if(q->ptr == 0 || bp->type != M_DATA){
                   1212:                PUTNEXT(q, bp);
                   1213:                return;
                   1214:        }
                   1215: 
                   1216:        /* collect into a single block */
                   1217:        qlock(&q->rlock);
                   1218:        if(q->first == 0)
                   1219:                q->first = pullup(bp, blen(bp));
                   1220:        else{
                   1221:                nbp = q->first;
                   1222:                nbp->next = bp;
                   1223:                q->first = pullup(nbp, blen(nbp));
                   1224:        }
                   1225:        bp = q->first;
                   1226:        if(bp == 0){
                   1227:                qunlock(&q->rlock);
                   1228:                bsdclose(q);
                   1229:                return;
                   1230:        }
                   1231: 
                   1232:        /* look for 2 nulls to indicate stderr port and local user */
                   1233:        luser = memchr(bp->rptr, 0, BLEN(bp));
                   1234:        if(luser == 0){
                   1235:                qunlock(&q->rlock);
                   1236:                return;
                   1237:        }
                   1238:        luser++;
                   1239:        if(memchr(luser, 0, bp->wptr - luser) == 0){
                   1240:                qunlock(&q->rlock);
                   1241:                return;
                   1242:        }
                   1243: 
                   1244:        /* if luser is a lie, hangup */
                   1245:        if(memcmp(luser, u->p->user, strlen(u->p->user)+1) != 0)
                   1246:                bsdclose(q);
                   1247: 
                   1248:        /* mark queue as authenticated and pass data to remote side */
                   1249:        q->ptr = 0;
                   1250:        q->first = 0;
                   1251:        bp->flags |= S_DELIM;
                   1252:        PUTNEXT(q, bp);
                   1253:        qunlock(&q->rlock);
                   1254: }

unix.superglobalmegacorp.com

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