Annotation of researchv10dc/lsys/inet/ip_ld.c, revision 1.1.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.