Annotation of researchv10no/sys/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: 
                    128: /*
                    129:  *  set our many broadcast addresses
                    130:  */
                    131: static
                    132: setbcast(ifp)
                    133:        struct ipif *ifp;
                    134: {
                    135:        int i;
                    136: 
                    137:        /* official style */
                    138:        ifp->bcast[0] = ifp->that|~ifp->mask;                   /* subnet */
                    139:        ifp->bcast[1] = ifp->that|~IN_CLASS_NMASK(ifp->that);   /* net */
                    140:        ifp->bcast[2] = 0xffffffff;                             /* undirected */
                    141: 
                    142:        /* old BSD style */
                    143:        ifp->bcast[3] = ifp->that&ifp->mask;                    /* subnet */
                    144:        ifp->bcast[4] = ifp->that&IN_CLASS_NMASK(ifp->that);    /* net */
                    145:        ifp->bcast[5] = 0;                                      /* undirected */
                    146: 
                    147:        if(ifp->flags & IFF_HOST)
                    148:                for(i = 0; i < 6; i++)
                    149:                        ifp->bcast[i] = 0;
                    150: }
                    151: 
                    152: iposrv(q)
                    153: register struct queue *q;
                    154: {
                    155:        struct x{
                    156:                unsigned int in;
                    157:                unsigned char en[6];
                    158:        } *xp;
                    159:        register struct block *bp;
                    160:        register struct ipif *ifp;
                    161:        register long *intp;
                    162: 
                    163:        ifp = (struct ipif *)q->ptr;
                    164:        while(bp = getq(q)){
                    165:                switch (bp->type) {
                    166:                case M_IOCTL:
                    167:                        switch(stiocom(bp)){
                    168:                        case IPIOARP:
                    169:                                ifp->flags |= IFF_ARP;
                    170:                                bp->type = M_IOCACK;
                    171:                                bp->wptr = bp->rptr;
                    172:                                qreply(q, bp);
                    173:                                break;
                    174:                        case IPIORESOLVE:
                    175:                                xp = (struct x *)(stiodata(bp));
                    176:                                if (arpcnt > 0)
                    177:                                        arp_install(xp->in, xp->en);
                    178:                                bp->wptr = bp->rptr;
                    179:                                bp->type = M_IOCACK;
                    180:                                qreply(q, bp);
                    181:                                break;
                    182:                        case IPIOHOST:
                    183:                                intp = (long *)(stiodata(bp));
                    184:                                ifp->that = *intp;
                    185:                                ifp->flags |= IFF_HOST;
                    186:                                ifp->mask = 0xffffffff;
                    187:                                setbcast(ifp);
                    188:                                ip_ifinsert(ifp);
                    189:                                bp->type = M_IOCACK;
                    190:                                qreply(q, bp);
                    191:                                ip_doroute(ifp->that, 0);
                    192:                                break;
                    193:                        case IPIOMTU:
                    194:                                intp = (long *)(stiodata(bp));
                    195:                                ifp->mtu = *intp;
                    196:                                bp->type = M_IOCACK;
                    197:                                qreply(q, bp);
                    198:                                break;
                    199:                        case IPIONET:
                    200:                                intp = (long *)(stiodata(bp));
                    201:                                ifp->that = *intp;
                    202:                                ifp->mask = IN_CLASS_NMASK(ifp->that);
                    203:                                setbcast(ifp);
                    204:                                ip_ifinsert(ifp);
                    205:                                ifp->flags &= (~IFF_HOST);
                    206:                                bp->type = M_IOCACK;
                    207:                                qreply(q, bp);
                    208:                                ip_doroute(ifp->that, 0);
                    209:                                break;
                    210:                        case IPIOMASK:
                    211:                                intp = (long *)(stiodata(bp));
                    212:                                /*
                    213:                                 *  the mask has to be a superset of the class mask
                    214:                                 */
                    215:                                if((*intp&ifp->mask)==ifp->mask)
                    216:                                        ifp->mask = *intp;
                    217:                                setbcast(ifp);
                    218:                                ip_ifinsert(ifp);
                    219:                                bp->type = M_IOCACK;
                    220:                                qreply(q, bp);
                    221:                                break;
                    222:                        case IPIOLOCAL:
                    223:                                intp = (long *)(stiodata(bp));
                    224:                                ifp->thishost = *intp;
                    225:                                setbcast(ifp);
                    226:                                bp->type = M_IOCACK;
                    227:                                qreply(q, bp);
                    228:                                break;
                    229:                        default:
                    230:                                (*q->next->qinfo->putp)(q->next, bp);
                    231:                                break;
                    232:                        }
                    233:                        continue;
                    234: 
                    235:                default:
                    236:                        if (q->next->flag & QFULL) {
                    237:                                putbq(q, bp);
                    238:                                return;
                    239:                        }
                    240:                        if(bp->class&S_DELIM)
                    241:                                ifp->opackets++;
                    242:                        (*q->next->qinfo->putp)(q->next, bp);
                    243:                        continue;
                    244:                }
                    245:        }
                    246: }
                    247: 
                    248: /*
                    249:  *  Insert an entry into ipifsort.  Entries are sorted by mask length,
                    250:  *  longest first.
                    251:  */
                    252: ip_ifinsert(ifp)
                    253:        struct ipif *ifp;
                    254: {
                    255:        int s = spl6();
                    256:        register int i, j;
                    257: 
                    258:        /*
                    259:         *  First try to remove it.  This may be a reordering.
                    260:         */
                    261:        ip_ifremove(ifp);
                    262: 
                    263:        /*
                    264:         *  Now (re)insert it in the correct place
                    265:         */
                    266:        for(i=0; i<ipcnt; i++){
                    267:                if(ipifsort[i]==ifp)
                    268:                        panic("ip_ifinsert duplcate");
                    269:                if(ipifsort[i]==0 || (ifp->mask & ipifsort[i]->mask)!=ifp->mask)
                    270:                        break;
                    271:        }
                    272:        if(i>=ipcnt)
                    273:                panic("ip_ifinsert no room");
                    274:        for(j=ipcnt-1; j>i; j--)
                    275:                ipifsort[j] = ipifsort[j-1];
                    276:        ipifsort[i] = ifp;
                    277:        splx(s);
                    278: }
                    279: 
                    280: /*
                    281:  *  Remove an entry from ipifsort.  Compress list to fill gap.
                    282:  *  It may not already be there.
                    283:  */
                    284: ip_ifremove(ifp)
                    285:        struct ipif *ifp;
                    286: {
                    287:        int s = spl6();
                    288:        register int i;
                    289: 
                    290:        for(i=0; i<ipcnt; i++)
                    291:                if(ipifsort[i]==ifp)
                    292:                        break;
                    293:        if(i<ipcnt){
                    294:                for(; i<ipcnt-1; i++)
                    295:                        ipifsort[i] = ipifsort[i+1];
                    296:                ipifsort[i] = 0;
                    297:        }
                    298:        splx(s);
                    299: }
                    300: 
                    301: /*
                    302:  *  Find the interface to use for sending messages to `dst'.
                    303:  *  ipifsort is sorted into priority order;
                    304:  *  first match found is best.
                    305:  */
                    306: struct ipif *
                    307: ip_ifonnetof(dst)
                    308:        register unsigned long dst;
                    309: {
                    310:        extern ipprintfs;
                    311:        register struct ipif *ifp;
                    312:        register int i;
                    313:        register int Ipcnt = ipcnt;     /* optimization */
                    314: 
                    315:        /*
                    316:         *  first look for a match against addresses
                    317:         */
                    318:        for(i=0; i < Ipcnt; i++){
                    319:                if((ifp = ipifsort[i])==0)
                    320:                        break;
                    321:                if(ifp->flags & IFF_UP)
                    322:                        if((dst & ifp->mask) == ifp->that)
                    323:                                return(ifp);
                    324:        }
                    325: 
                    326:        /*
                    327:         *  now try to match against the local host's addresses
                    328:         */
                    329:        ifp = ip_ifwithaddr(dst);
                    330:        if(ifp)
                    331:                return(ifp);
                    332: 
                    333:        /*
                    334:         *  no match
                    335:         */
                    336:        if(ipprintfs)
                    337:                printf("ifonnetof %x?\n", dst);
                    338:        return(0);
                    339: }
                    340: 
                    341: /*
                    342:  *  return the interface for which addr is a local address.  if non
                    343:  *  such exists, return 0.
                    344:  *
                    345:  *  This routine assumes that ipifsort is sorted in priority order
                    346:  *  so that the first match found is the best match.
                    347:  */
                    348: struct ipif *
                    349: ip_ifwithaddr(addr)
                    350:        register u_long addr;
                    351: {
                    352:        register int i, j;
                    353:        register u_long net, mask;
                    354:        register struct ipif *ifp;
                    355:        register int Ipcnt = ipcnt;     /* optimization */
                    356: 
                    357:        net = in_netof(addr);
                    358:        for(i=0; i < Ipcnt; i++){
                    359:                if((ifp = ipifsort[i])==0)
                    360:                        break;
                    361:                if(ifp->flags & IFF_UP) {
                    362: 
                    363:                        /* address of this host */
                    364:                        if(addr == ifp->thishost)
                    365:                                return(ifp);
                    366: 
                    367:                        for(j = 0; j < 6; j++)
                    368:                                if(addr == ifp->bcast[j])
                    369:                                        return(ifp);
                    370: 
                    371:                        /* address on a network simulated by this node */
                    372:                        if(net == ifp->thishost)
                    373:                                return(ifp);
                    374:                }
                    375:        }
                    376:        return(0);
                    377: }
                    378: 
                    379: /*
                    380:  * output list bp onto interface ifp
                    381:  * for better buffering, put it on ip's queue first;
                    382:  * iposrv will dribble it out as there's room
                    383:  */
                    384: ip_ldout(bp, dst, ifp)
                    385: register struct block *bp;
                    386: unsigned long dst;             /* host byte order */
                    387: register struct ipif *ifp;
                    388: {
                    389:        extern struct block *arp_resolve();
                    390:        register struct block *bp1;
                    391:        register struct queue *q;
                    392: 
                    393:        if(ifp->queue == 0){
                    394:                printf("ifp but no queue in ip_ldout\n");
                    395:                bp_free(bp);
                    396:                return(0);
                    397:        }
                    398:        q = WR(ifp->queue);
                    399:        if(q->flag & QFULL){
                    400:                bp_free(bp);
                    401:                ifp->oerrors++;
                    402:                return(1);
                    403:        }
                    404:        if(arpcnt > 0 && (ifp->flags & IFF_ARP)){
                    405:                bp = arp_resolve(ifp->queue, bp, dst);
                    406:                if(bp == 0)
                    407:                        return(1);
                    408:        }
                    409:        MCHECK(bp);
                    410:        while(bp){
                    411:                bp1 = bp->next;
                    412:                if (bp1==NULL)
                    413:                        bp->class |= S_DELIM;
                    414:                (*q->qinfo->putp)(q, bp);
                    415:                bp = bp1;
                    416:        }
                    417:        return(0);
                    418: }

unix.superglobalmegacorp.com

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