Annotation of researchv10dc/lsys/inet/ip_ld.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * ip line discipline, to be pushed on an ethernet controller.
        !             3:  * collects data till a delim, passes it to ip_input().
        !             4:  */
        !             5: 
        !             6: #include "sys/param.h"
        !             7: #include "sys/stream.h"
        !             8: #include "sys/conf.h"
        !             9: #include "sys/inet/in.h"
        !            10: #include "sys/inet/ip_var.h"
        !            11: #include "sys/inet/ethernet.h"
        !            12: 
        !            13: extern struct ipif ipif[];
        !            14: extern struct ipif *ipifsort[];
        !            15: extern int ipcnt;                      /* number of ip's */
        !            16: extern int arpcnt;
        !            17: 
        !            18: int     ipiput(), ipisrv(), ipclose();
        !            19: long   ipopen();
        !            20: int    iposrv();
        !            21: static struct qinit iprinit = { ipiput, ipisrv, ipopen, ipclose, IP_MSG_LIMIT, 64};
        !            22: static struct qinit ipwinit = { putq, iposrv, ipopen, ipclose, 2*IP_MSG_LIMIT, 64 };
        !            23: struct streamtab ipstream = { &iprinit, &ipwinit };
        !            24: 
        !            25: long
        !            26: ipopen(q, dev)
        !            27: register struct queue *q;
        !            28: {
        !            29:        static int timing;
        !            30:        register struct ipif *fp, *ifend;
        !            31: 
        !            32:        if (q->ptr)
        !            33:                return(1);
        !            34:        if(!timing){
        !            35:                timing = 1;
        !            36:                ip_slowtimo();
        !            37:        }
        !            38:        ifend = &ipif[ipcnt];
        !            39:        for (fp = ipif; fp < ifend; fp++)
        !            40:                if (fp->queue == NULL)
        !            41:                        break;
        !            42:        if (fp >= ifend)
        !            43:                return(0);
        !            44:        fp->queue = q;  /* that's the RD q */
        !            45:        fp->flags = IFF_UP;
        !            46:        fp->that = fp->thishost = 0;
        !            47:        fp->ipackets = fp->opackets = fp->ierrors = fp->oerrors = 0;
        !            48:        fp->mtu = 1500;
        !            49:        fp->arp = -1;
        !            50:        fp->dev = dev;
        !            51:        q->flag |= QDELIM;
        !            52:        WR(q)->flag |= QDELIM;
        !            53:        q->ptr = (caddr_t)fp;
        !            54:        WR(q)->ptr = (caddr_t)fp;
        !            55:        q->flag |= QNOENB;      /* ipiput calls qenable() */
        !            56:        return(1);
        !            57: }
        !            58: 
        !            59: ipclose(q)
        !            60: struct queue *q;
        !            61: {
        !            62:        register struct ipif *ifp;
        !            63: 
        !            64:        ifp = (struct ipif *)q->ptr;
        !            65:        ip_ifremove(ifp);
        !            66:        ifp->queue = 0;
        !            67:        ifp->flags = 0;
        !            68: }
        !            69: 
        !            70: ipisrv(q)
        !            71: register struct queue *q;
        !            72: {
        !            73:        register struct block *bp, *head, *tail;
        !            74:        register struct ipif *ifp;
        !            75: 
        !            76:        /* there is now a whole packet waiting
        !            77:         * on this queue; strip it off and pass to ip_input().
        !            78:         * things other than data or delims are forwarded directly
        !            79:         * by ipiput().
        !            80:         */
        !            81:        head = tail = (struct block *) 0;
        !            82:        ifp = (struct ipif *)q->ptr;
        !            83:        while(bp = getq(q)){
        !            84:                if (bp->type != M_DATA)
        !            85:                        panic("ipisrv");
        !            86:                bp->next = NULL;
        !            87:                if (head == NULL)
        !            88:                        head = bp;
        !            89:                else
        !            90:                        tail->next = bp;
        !            91:                tail = bp;
        !            92:                if (bp->class&S_DELIM) {
        !            93:                        bp->class &=~ S_DELIM;
        !            94:                        MCHECK(head);
        !            95:                        if((ifp->flags & IFF_ARP)
        !            96:                           && (head->wptr-head->rptr) >= sizeof(struct etherpup)){
        !            97:                                /* strip off ether header */
        !            98:                                head->rptr += sizeof(struct etherpup);
        !            99:                        }
        !           100:                        ip_input(head);
        !           101:                        ifp->ipackets++;
        !           102:                        head = tail = NULL;
        !           103:                }
        !           104:        }
        !           105:        if(head)
        !           106:                bp_putback(q, head);
        !           107: }
        !           108: 
        !           109: 
        !           110: ipiput(q, bp)
        !           111: register struct queue *q;
        !           112: register struct block *bp;
        !           113: {
        !           114:        switch(bp->type){
        !           115:        case M_DATA:
        !           116:                putq(q, bp);
        !           117:                if (bp->class&S_DELIM)
        !           118:                        qenable(q);
        !           119:                break;
        !           120:        default:
        !           121:                (*q->next->qinfo->putp)(q->next, bp);
        !           122:                break;
        !           123:        }
        !           124:                
        !           125: }
        !           126: 
        !           127: iposrv(q)
        !           128: register struct queue *q;
        !           129: {
        !           130:        struct x{
        !           131:                unsigned int in;
        !           132:                unsigned char en[6];
        !           133:        } *xp;
        !           134:        register struct block *bp;
        !           135:        register struct ipif *ifp;
        !           136:        register long *intp;
        !           137: 
        !           138:        ifp = (struct ipif *)q->ptr;
        !           139:        while(bp = getq(q)){
        !           140:                switch (bp->type) {
        !           141:                case M_IOCTL:
        !           142:                        switch(stiocom(bp)){
        !           143:                        case IPIOARP:
        !           144:                                ifp->flags |= IFF_ARP;
        !           145:                                bp->type = M_IOCACK;
        !           146:                                bp->wptr = bp->rptr;
        !           147:                                qreply(q, bp);
        !           148:                                break;
        !           149:                        case IPIORESOLVE:
        !           150:                                xp = (struct x *)(stiodata(bp));
        !           151:                                if (arpcnt > 0)
        !           152:                                        arp_install(xp->in, xp->en);
        !           153:                                bp->wptr = bp->rptr;
        !           154:                                bp->type = M_IOCACK;
        !           155:                                qreply(q, bp);
        !           156:                                break;
        !           157:                        case IPIOHOST:
        !           158:                                intp = (long *)(stiodata(bp));
        !           159:                                ifp->that = *intp;
        !           160:                                ifp->flags |= IFF_HOST;
        !           161:                                ifp->mask = 0xffffffff;
        !           162:                                ifp->broadcast = 0;
        !           163:                                ip_ifinsert(ifp);
        !           164:                                bp->type = M_IOCACK;
        !           165:                                qreply(q, bp);
        !           166:                                ip_doroute(ifp->that, 0);
        !           167:                                break;
        !           168:                        case IPIOMTU:
        !           169:                                intp = (long *)(stiodata(bp));
        !           170:                                ifp->mtu = *intp;
        !           171:                                bp->type = M_IOCACK;
        !           172:                                qreply(q, bp);
        !           173:                                break;
        !           174:                        case IPIONET:
        !           175:                                intp = (long *)(stiodata(bp));
        !           176:                                ifp->that = *intp;
        !           177:                                ifp->mask = IN_CLASS_NMASK(ifp->that);
        !           178:                                ifp->broadcast = ifp->that|~ifp->mask;
        !           179:                                ip_ifinsert(ifp);
        !           180:                                ifp->flags &= (~IFF_HOST);
        !           181:                                bp->type = M_IOCACK;
        !           182:                                qreply(q, bp);
        !           183:                                ip_doroute(ifp->that, 0);
        !           184:                                break;
        !           185:                        case IPIOMASK:
        !           186:                                intp = (long *)(stiodata(bp));
        !           187:                                /*
        !           188:                                 *  the mask has to be a superset of the class mask
        !           189:                                 */
        !           190:                                if((*intp&ifp->mask)==ifp->mask)
        !           191:                                        ifp->mask = *intp;
        !           192:                                ifp->broadcast = ifp->that|~ifp->mask;
        !           193:                                ip_ifinsert(ifp);
        !           194:                                bp->type = M_IOCACK;
        !           195:                                qreply(q, bp);
        !           196:                                break;
        !           197:                        case IPIOLOCAL:
        !           198:                                intp = (long *)(stiodata(bp));
        !           199:                                ifp->thishost = *intp;
        !           200:                                bp->type = M_IOCACK;
        !           201:                                qreply(q, bp);
        !           202:                                break;
        !           203:                        default:
        !           204:                                (*q->next->qinfo->putp)(q->next, bp);
        !           205:                                break;
        !           206:                        }
        !           207:                        continue;
        !           208: 
        !           209:                default:
        !           210:                        if (q->next->flag & QFULL) {
        !           211:                                putbq(q, bp);
        !           212:                                return;
        !           213:                        }
        !           214:                        if(bp->class&S_DELIM)
        !           215:                                ifp->opackets++;
        !           216:                        (*q->next->qinfo->putp)(q->next, bp);
        !           217:                        continue;
        !           218:                }
        !           219:        }
        !           220: }
        !           221: 
        !           222: /*
        !           223:  *  Insert an entry into ipifsort.  Entries are sorted by mask length,
        !           224:  *  longest first.
        !           225:  */
        !           226: ip_ifinsert(ifp)
        !           227:        struct ipif *ifp;
        !           228: {
        !           229:        int s = spl6();
        !           230:        register int i, j;
        !           231: 
        !           232:        /*
        !           233:         *  First try to remove it.  This may be a reordering.
        !           234:         */
        !           235:        ip_ifremove(ifp);
        !           236: 
        !           237:        /*
        !           238:         *  Now (re)insert it in the correct place
        !           239:         */
        !           240:        for(i=0; i<ipcnt; i++){
        !           241:                if(ipifsort[i]==ifp)
        !           242:                        panic("ip_ifinsert duplcate");
        !           243:                if(ipifsort[i]==0 || (ifp->mask & ipifsort[i]->mask)!=ifp->mask)
        !           244:                        break;
        !           245:        }
        !           246:        if(i>=ipcnt)
        !           247:                panic("ip_ifinsert no room");
        !           248:        for(j=ipcnt-1; j>i; j--)
        !           249:                ipifsort[j] = ipifsort[j-1];
        !           250:        ipifsort[i] = ifp;
        !           251:        splx(s);
        !           252: }
        !           253: 
        !           254: /*
        !           255:  *  Remove an entry from ipifsort.  Compress list to fill gap.
        !           256:  *  It may not already be there.
        !           257:  */
        !           258: ip_ifremove(ifp)
        !           259:        struct ipif *ifp;
        !           260: {
        !           261:        int s = spl6();
        !           262:        register int i;
        !           263: 
        !           264:        for(i=0; i<ipcnt; i++)
        !           265:                if(ipifsort[i]==ifp)
        !           266:                        break;
        !           267:        if(i<ipcnt){
        !           268:                for(; i<ipcnt-1; i++)
        !           269:                        ipifsort[i] = ipifsort[i+1];
        !           270:                ipifsort[i] = 0;
        !           271:        }
        !           272:        splx(s);
        !           273: }
        !           274: 
        !           275: /*
        !           276:  *  Find the interface to use for sending messages to `dst'.
        !           277:  *  ipifsort is sorted into priority order;
        !           278:  *  first match found is best.
        !           279:  */
        !           280: struct ipif *
        !           281: ip_ifonnetof(dst)
        !           282:        register unsigned long dst;
        !           283: {
        !           284:        extern ipprintfs;
        !           285:        register struct ipif *ifp;
        !           286:        register int i;
        !           287:        register int Ipcnt = ipcnt;     /* optimization */
        !           288: 
        !           289:        /*
        !           290:         *  first look for a match against addresses
        !           291:         */
        !           292:        for(i=0; i < Ipcnt; i++){
        !           293:                if((ifp = ipifsort[i])==0)
        !           294:                        break;
        !           295:                if(ifp->flags & IFF_UP)
        !           296:                        if((dst & ifp->mask) == ifp->that)
        !           297:                                return(ifp);
        !           298:        }
        !           299: 
        !           300:        /*
        !           301:         *  now try to match against the local host's addresses
        !           302:         */
        !           303:        ifp = ip_ifwithaddr(dst);
        !           304:        if(ifp)
        !           305:                return(ifp);
        !           306: 
        !           307:        /*
        !           308:         *  no match
        !           309:         */
        !           310:        if(ipprintfs)
        !           311:                printf("ifonnetof %x?\n", dst);
        !           312:        return(0);
        !           313: }
        !           314: 
        !           315: /*
        !           316:  *  return the interface for which addr is a local address.  if non
        !           317:  *  such exists, return 0.
        !           318:  *
        !           319:  *  This routine assumes that ipifsort is sorted in priority order
        !           320:  *  so that the first match found is the best match.
        !           321:  */
        !           322: struct ipif *
        !           323: ip_ifwithaddr(addr)
        !           324:        register u_long addr;
        !           325: {
        !           326:        register int i;
        !           327:        register u_long net, mask;
        !           328:        register struct ipif *ifp;
        !           329:        register int Ipcnt = ipcnt;     /* optimization */
        !           330: 
        !           331:        net = in_netof(addr);
        !           332:        for(i=0; i < Ipcnt; i++){
        !           333:                if((ifp = ipifsort[i])==0)
        !           334:                        break;
        !           335:                if(ifp->flags & IFF_UP) {
        !           336: 
        !           337:                        /* address of this host */
        !           338:                        if(addr == ifp->thishost)
        !           339:                                return(ifp);
        !           340: 
        !           341:                        /* standard IP broadcast address */
        !           342:                        if(addr == ifp->broadcast)
        !           343:                                return(ifp);
        !           344: 
        !           345:                        /* old style BSD IP broadcast address */
        !           346:                        if(addr == in_netof(ifp->thishost))
        !           347:                                return(ifp);
        !           348: 
        !           349:                        /* address on a network simulated by this node */
        !           350:                        if(net == ifp->thishost)
        !           351:                                return(ifp);
        !           352: 
        !           353:                        /* finally, try unsubnetted broadcast addresses */
        !           354:                        mask = IN_CLASS_NMASK(ifp->thishost);
        !           355:                        if((mask&ifp->thishost | ~mask) == addr)
        !           356:                                return(ifp);
        !           357: 
        !           358:                        /* finally, try unsubnetted broadcast addresses */
        !           359:                        if((mask&ifp->thishost) == addr)
        !           360:                                return(ifp);
        !           361:                }
        !           362:        }
        !           363:        return(0);
        !           364: }
        !           365: 
        !           366: /*
        !           367:  * output list bp onto interface ifp
        !           368:  * for better buffering, put it on ip's queue first;
        !           369:  * iposrv will dribble it out as there's room
        !           370:  */
        !           371: ip_ldout(bp, dst, ifp)
        !           372: register struct block *bp;
        !           373: unsigned long dst;             /* host byte order */
        !           374: register struct ipif *ifp;
        !           375: {
        !           376:        extern struct block *arp_resolve();
        !           377:        register struct block *bp1;
        !           378:        register struct queue *q;
        !           379: 
        !           380:        if(ifp->queue == 0){
        !           381:                printf("ifp but no queue in ip_ldout\n");
        !           382:                bp_free(bp);
        !           383:                return(0);
        !           384:        }
        !           385:        q = WR(ifp->queue);
        !           386:        if(q->flag & QFULL){
        !           387:                bp_free(bp);
        !           388:                ifp->oerrors++;
        !           389:                return(1);
        !           390:        }
        !           391:        if(arpcnt > 0 && (ifp->flags & IFF_ARP)){
        !           392:                bp = arp_resolve(ifp->queue, bp, dst);
        !           393:                if(bp == 0)
        !           394:                        return(1);
        !           395:        }
        !           396:        MCHECK(bp);
        !           397:        while(bp){
        !           398:                bp1 = bp->next;
        !           399:                if (bp1==NULL)
        !           400:                        bp->class |= S_DELIM;
        !           401:                (*q->qinfo->putp)(q, bp);
        !           402:                bp = bp1;
        !           403:        }
        !           404:        return(0);
        !           405: }

unix.superglobalmegacorp.com

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