Annotation of lucent/sys/src/9/port/devip.c, revision 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.