Annotation of lucent/sys/src/9/port/devarp.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: #define ARP_FREE       0
        !            13: #define ARP_OK         1
        !            14: #define ARP_ASKED      2
        !            15: #define ARP_TEMP       0
        !            16: #define ARP_PERM       1
        !            17: #define Arphashsize    32
        !            18: #define ARPHASH(p)     arphash[((p[2]^p[3])%Arphashsize)]
        !            19: 
        !            20: typedef struct Arpcache Arpcache;
        !            21: struct Arpcache
        !            22: {
        !            23:        uchar   status;
        !            24:        uchar   type;
        !            25:        uchar   eip[4];
        !            26:        uchar   et[6];
        !            27:        Arpcache *hash;
        !            28:        Arpcache **hashhd;
        !            29:        Arpcache *frwd;
        !            30:        Arpcache *prev;
        !            31: };
        !            32: 
        !            33: Arpstats       arpstats;
        !            34: Arpcache       *arplruhead, *arplrutail;
        !            35: Arpcache       *arp, **arphash;
        !            36: Queue          *Servq;
        !            37: Lock           larphash;
        !            38: 
        !            39: void   arpiput(Queue *, Block *);
        !            40: void   arpoput(Queue *, Block *);
        !            41: void   arpopn(Queue *, Stream *);
        !            42: void   arpcls(Queue *);
        !            43: void   arpenter(Arpentry*, int);
        !            44: void   arpflush(void);
        !            45: int    arpperm(char*);
        !            46: int    arpdelete(char*);
        !            47: void   arplinkhead(Arpcache*);
        !            48: int    arplookup(uchar*, uchar*);
        !            49: 
        !            50: Qinfo arpinfo = { arpiput, arpoput, arpopn, arpcls, "arp" };
        !            51: 
        !            52: #define ARP_ENTRYLEN   50
        !            53: char *padstr = "                                           ";
        !            54: 
        !            55: enum{
        !            56:        arpdirqid,
        !            57:        arpdir2qid,
        !            58:        arpstatqid,
        !            59:        arpctlqid,
        !            60:        arpdataqid,
        !            61: };
        !            62: 
        !            63: Dirtab arptab[]={
        !            64:        "stats",        {arpstatqid},           0,      0444,
        !            65:        "ctl",          {arpctlqid},            0,      0664,
        !            66:        "data",         {arpdataqid},           0,      0664,
        !            67: };
        !            68: #define Narptab (sizeof(arptab)/sizeof(Dirtab))
        !            69: 
        !            70: enum
        !            71: {
        !            72:        Narp=   64,     /* size of arp cache */
        !            73: };
        !            74: 
        !            75: /*
        !            76:  *  create a 2-level directory
        !            77:  */
        !            78: int
        !            79: arpgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
        !            80: {
        !            81:        Qid q;
        !            82: 
        !            83:        USED(vp);
        !            84:        USED(ntab);
        !            85: 
        !            86:        q.vers = 0;
        !            87: 
        !            88:        /* top level directory contains the directory arp */
        !            89:        if(c->qid.path == CHDIR){
        !            90:                if(i)
        !            91:                        return -1;
        !            92:                q.path = CHDIR | arpdir2qid;
        !            93:                devdir(c, q, "arp", 0, eve, 0555, dp);
        !            94:                return 1;
        !            95:        }
        !            96: 
        !            97:        /* next level uses table */
        !            98:        return devgen(c, arptab, Narptab, i, dp);
        !            99: }
        !           100: 
        !           101: void
        !           102: arpreset(void)
        !           103: {
        !           104:        Arpcache *ap, *ep;
        !           105: 
        !           106:        arp = xalloc(sizeof(Arpcache) * Narp);
        !           107:        arphash = (Arpcache **)xalloc(sizeof(Arpcache *) * Arphashsize);
        !           108: 
        !           109:        ep = &arp[Narp];
        !           110:        for(ap = arp; ap < ep; ap++) {
        !           111:                ap->frwd = ap+1;
        !           112:                ap->prev = ap-1;
        !           113:                ap->type = ARP_FREE;
        !           114:                ap->status = ARP_TEMP;
        !           115:        }
        !           116: 
        !           117:        arp[0].prev = 0;
        !           118:        arplruhead = arp;
        !           119:        ap = &arp[Narp-1];
        !           120:        ap->frwd = 0;
        !           121:        arplrutail = ap;
        !           122:        newqinfo(&arpinfo);
        !           123: }
        !           124: 
        !           125: void
        !           126: arpinit(void)
        !           127: {
        !           128: }
        !           129: 
        !           130: Chan *
        !           131: arpattach(char *spec)
        !           132: {
        !           133:        return devattach('a', spec);
        !           134: }
        !           135: 
        !           136: Chan *
        !           137: arpclone(Chan *c, Chan *nc)
        !           138: {
        !           139:        return devclone(c, nc);
        !           140: }
        !           141: 
        !           142: int
        !           143: arpwalk(Chan *c, char *name)
        !           144: {
        !           145:        return devwalk(c, name, 0, 0, arpgen);
        !           146: }
        !           147: 
        !           148: void
        !           149: arpstat(Chan *c, char *db)
        !           150: {
        !           151:        devstat(c, db, 0, 0, arpgen);
        !           152: }
        !           153: 
        !           154: Chan *
        !           155: arpopen(Chan *c, int omode)
        !           156: {
        !           157:        if(c->qid.path&CHDIR){
        !           158:                if(omode != OREAD)
        !           159:                        error(Eperm);
        !           160:        }
        !           161: 
        !           162:        switch(STREAMTYPE(c->qid.path)) {
        !           163:        case arpdataqid:
        !           164:                break;
        !           165:        case arpstatqid:
        !           166:                if(omode != OREAD)
        !           167:                        error(Ebadarg);
        !           168:                break;
        !           169:        case arpctlqid:
        !           170:                break;
        !           171:        }
        !           172: 
        !           173:        c->mode = openmode(omode);
        !           174:        c->flag |= COPEN;
        !           175:        c->offset = 0;
        !           176:        return c;
        !           177: }
        !           178: 
        !           179: void
        !           180: arpcreate(Chan *c, char *name, int omode, ulong perm)
        !           181: {
        !           182:        USED(c, name, omode, perm);
        !           183:        error(Eperm);
        !           184: }
        !           185: 
        !           186: void
        !           187: arpremove(Chan *c)
        !           188: {
        !           189:        USED(c);
        !           190:        error(Eperm);
        !           191: }
        !           192: 
        !           193: void
        !           194: arpwstat(Chan *c, char *dp)
        !           195: {
        !           196:        USED(c, dp);
        !           197:        error(Eperm);
        !           198: }
        !           199: 
        !           200: void
        !           201: arpclose(Chan *c)
        !           202: {
        !           203:        streamclose(c);
        !           204: }
        !           205: 
        !           206: long
        !           207: arpread(Chan *c, void *a, long n, ulong offset)
        !           208: {
        !           209:        char     buf[100];
        !           210:        Arpcache *ap;
        !           211:        int      part, bytes, size;
        !           212:        char     *ststr;
        !           213: 
        !           214:        if(c->qid.path&CHDIR)
        !           215:                return devdirread(c, a, n, arptab, Narptab, arpgen);
        !           216: 
        !           217:        switch((int)(c->qid.path&~CHDIR)){
        !           218:        case arpdataqid:
        !           219:                bytes = c->offset;
        !           220:                while(bytes < Narp*ARP_ENTRYLEN && n) {
        !           221:                        ap = &arp[bytes/ARP_ENTRYLEN];
        !           222:                        part = bytes%ARP_ENTRYLEN;
        !           223: 
        !           224:                        if(ap->status != ARP_OK)
        !           225:                                ststr = "invalid";
        !           226:                        else
        !           227:                                ststr = (ap->type == ARP_TEMP ? "temp" : "perm");
        !           228: 
        !           229:                        sprint(buf,"%d.%d.%d.%d to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s%s",
        !           230:                                ap->eip[0], ap->eip[1], ap->eip[2], ap->eip[3],
        !           231:                                ap->et[0], ap->et[1], ap->et[2], ap->et[3],
        !           232:                                ap->et[4], ap->et[5],
        !           233:                                ststr, padstr); 
        !           234:                        
        !           235:                        buf[ARP_ENTRYLEN-1] = '\n';
        !           236: 
        !           237:                        size = ARP_ENTRYLEN - part;
        !           238:                        size = MIN(n, size);
        !           239:                        memmove(a, buf+part, size);
        !           240: 
        !           241:                        a = (void *)((int)a + size);
        !           242:                        n -= size;
        !           243:                        bytes += size;
        !           244:                }
        !           245:                return bytes - c->offset;
        !           246:                break;
        !           247:        case arpstatqid:
        !           248:                sprint(buf, "hits: %d miss: %d failed: %d\n",
        !           249:                        arpstats.hit, arpstats.miss, arpstats.failed);
        !           250: 
        !           251:                return readstr(offset, a, n, buf);
        !           252:        default:
        !           253:                n=0;
        !           254:                break;
        !           255:        }
        !           256:        return n;
        !           257: }
        !           258: 
        !           259: long
        !           260: arpwrite(Chan *c, char *a, long n, ulong offset)
        !           261: {
        !           262:        int m;
        !           263:        Arpentry entry;
        !           264:        char buf[32], *field[5];
        !           265: 
        !           266:        USED(offset);
        !           267: 
        !           268:        switch(STREAMTYPE(c->qid.path)) {
        !           269:        case arpctlqid:
        !           270:                strncpy(buf, a, sizeof buf);
        !           271:                m = getfields(buf, field, 5, " ");
        !           272: 
        !           273:                if(strncmp(field[0], "flush", 5) == 0)
        !           274:                        arpflush();
        !           275:                else
        !           276:                if(strcmp(field[0], "delete") == 0) {
        !           277:                        if(m != 2)
        !           278:                                error(Ebadarg);
        !           279: 
        !           280:                        if(arpdelete(field[1]) < 0)
        !           281:                                error(Enetaddr);
        !           282:                }
        !           283:                else
        !           284:                if(strcmp(field[0], "perm") == 0) {
        !           285:                        if(m != 2)
        !           286:                                error(Ebadarg);
        !           287: 
        !           288:                        if(arpperm(field[1]) < 0)
        !           289:                                error(Enetaddr);
        !           290:                }
        !           291:                else
        !           292:                        error(Ebadctl);
        !           293:                break;
        !           294: 
        !           295:        case arpdataqid:
        !           296:                if(n != sizeof(Arpentry))
        !           297:                        error(Emsgsize);
        !           298:                memmove(&entry, a, sizeof(Arpentry));
        !           299:                arpenter(&entry, ARP_TEMP);
        !           300:                break;
        !           301: 
        !           302:        default:
        !           303:                error(Ebadusefd);
        !           304:        }
        !           305: 
        !           306:        return n;
        !           307: }
        !           308: 
        !           309: void
        !           310: arpopn(Queue *q, Stream *s)
        !           311: {
        !           312:        USED(q, s);
        !           313: }
        !           314: 
        !           315: void
        !           316: arpcls(Queue *q)
        !           317: {
        !           318:        if(q == Servq)
        !           319:                Servq = 0;
        !           320: }
        !           321: 
        !           322: void
        !           323: arpiput(Queue *q, Block *bp)
        !           324: {
        !           325:        PUTNEXT(q, bp);
        !           326: }
        !           327: 
        !           328: void
        !           329: arpoput(Queue *q, Block *bp)
        !           330: {
        !           331:        uchar ip[4];
        !           332:        Ipaddr addr;
        !           333:        Ipdevice *p;
        !           334:        Etherhdr *eh;
        !           335:        static int dropped;
        !           336: 
        !           337: 
        !           338:        if(bp->type != M_DATA) {
        !           339:                if(Servq == 0 && streamparse("arpd", bp)) {
        !           340:                        Servq = RD(q);
        !           341:                        freeb(bp);
        !           342:                }
        !           343:                else
        !           344:                        PUTNEXT(q, bp);
        !           345:                return;
        !           346:        }
        !           347: 
        !           348:        eh = (Etherhdr *)bp->rptr;
        !           349:        if(nhgets(eh->type) != ET_IP) {
        !           350:                PUTNEXT(q, bp); 
        !           351:                return;
        !           352:        }
        !           353: 
        !           354:        /*
        !           355:         * sleaze - we hid the next hop in the ethernet destination
        !           356:         *  and the interface in the first byte of the source
        !           357:         */
        !           358:        memmove(ip, eh->d, sizeof(ip));
        !           359:        p = &ipd[eh->s[0]];
        !           360:        if(p >= &ipd[Nipd] || p->q == 0)
        !           361:                p = ipd;
        !           362: 
        !           363:        /* if ip broadcast, use ether bcast address */
        !           364:        addr = nhgetl(eh->dst);
        !           365:        if(p->Myip[Myself] == 0 || addr == p->Myip[Mybcast] || addr == p->Myip[Mynet]
        !           366:        || ((addr & p->Mymask) == p->Myip[Mynet+1]
        !           367:            && (addr & ~p->Mynetmask) == ~p->Mynetmask)){
        !           368:                memset(eh->d, 0xff, sizeof(eh->d));
        !           369:                PUTNEXT(q, bp);
        !           370:                return;
        !           371:        }
        !           372: 
        !           373:        /* if a known ip addr, send downstream to the ethernet */
        !           374:        if(arplookup(ip, eh->d)) {
        !           375:                PUTNEXT(q, bp);
        !           376:                return;
        !           377:        }
        !           378: 
        !           379:        /* Push the packet up to the arp server for address resolution */
        !           380:        if(!Servq) {
        !           381:                if((dropped++ % 100) == 99)
        !           382:                        print("arp: No server, packet dropped %d.%d.%d.%d\n",
        !           383:                                eh->dst[0], eh->dst[1], eh->dst[2], eh->dst[3]);
        !           384:                freeb(bp);
        !           385:                return;
        !           386:        }
        !           387:        memmove(eh->d, ip, sizeof(ip));
        !           388:        PUTNEXT(Servq, bp);
        !           389: }
        !           390: 
        !           391: int
        !           392: arplookup(uchar *ip, uchar *et)
        !           393: {
        !           394:        Arpcache *ap;
        !           395: 
        !           396:        lock(&larphash);
        !           397:        for(ap = ARPHASH(ip); ap; ap = ap->hash) {
        !           398:                if(ap->status == ARP_OK && memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) {
        !           399:                        memmove(et, ap->et, sizeof(ap->et));
        !           400:                        arplinkhead(ap);
        !           401:                        arpstats.hit++;
        !           402:                        unlock(&larphash);
        !           403:                        return 1;
        !           404:                }
        !           405:        }
        !           406:        arpstats.miss++;
        !           407:        unlock(&larphash);
        !           408:        return 0;
        !           409: }
        !           410: 
        !           411: void
        !           412: arpflush(void)
        !           413: {
        !           414:        Arpcache *ap, *ep;
        !           415: 
        !           416:        ep = &arp[Narp];
        !           417:        for(ap = arp; ap < ep; ap++)
        !           418:                ap->status = ARP_FREE;
        !           419: }
        !           420: 
        !           421: void
        !           422: arpenter(Arpentry *ape, int type)
        !           423: {
        !           424:        Arpcache *ap, **l, *d;
        !           425: 
        !           426: 
        !           427:        /* Update an entry if we have one already */
        !           428:        l = &ARPHASH(ape->ipaddr);
        !           429:        lock(&larphash);
        !           430:        for(ap = *l; ap; ap = ap->hash) {
        !           431:                if(ap->status == ARP_OK && memcmp(ap->eip, ape->ipaddr, sizeof(ap->eip)) == 0) {
        !           432:                        if(ap->type != ARP_PERM) {
        !           433:                                ap->type = type;
        !           434:                                memmove(ap->et, ape->etaddr, sizeof(ap->et));
        !           435:                                ap->status = ARP_OK;
        !           436:                        }
        !           437:                        unlock(&larphash);
        !           438:                        return;
        !           439:                }
        !           440:        }
        !           441: 
        !           442:        /* Find an entry to replace */
        !           443:        ap = arplrutail;
        !           444:        while(ap) {
        !           445:                if(ap->type != ARP_PERM || ap->type == ARP_FREE)
        !           446:                        break;
        !           447:                 ap = ap->prev;
        !           448:        }
        !           449:        if(!ap) {
        !           450:                unlock(&larphash);
        !           451:                print("arp: too many permanent entries\n");
        !           452:                return;
        !           453:        }
        !           454: 
        !           455:        if(ap->hashhd) {
        !           456:                for(d = *ap->hashhd; d; d = d->hash) {
        !           457:                        if(d == ap) {
        !           458:                                *(ap->hashhd) = ap->hash;
        !           459:                                break;
        !           460:                        }
        !           461:                        ap->hashhd = &d->hash;
        !           462:                }
        !           463:        }
        !           464: 
        !           465:        ap->type = type;
        !           466:        ap->status = ARP_OK;
        !           467:        memmove(ap->eip, ape->ipaddr, sizeof(ape->ipaddr));
        !           468:        memmove(ap->et, ape->etaddr, sizeof(ape->etaddr));
        !           469:        ap->hashhd = l;
        !           470:        ap->hash = *l;
        !           471:        *l = ap;
        !           472:        arplinkhead(ap);
        !           473:        unlock(&larphash);
        !           474: }
        !           475: 
        !           476: int
        !           477: arpperm(char *addr)
        !           478: {
        !           479:        Arpcache *ap;
        !           480:        uchar ip[4];
        !           481:        Ipaddr i;
        !           482:        int rv;
        !           483: 
        !           484:        rv = -1;
        !           485:        i = ipparse(addr);
        !           486:        hnputl(ip, i);  
        !           487:        lock(&larphash);
        !           488:        for(ap = arplruhead; ap; ap = ap->frwd) {
        !           489:                if(memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) {
        !           490:                        ap->type = ARP_PERM;
        !           491:                        rv = 0;
        !           492:                        break;
        !           493:                }
        !           494:        }
        !           495:        unlock(&larphash);
        !           496:        return rv;
        !           497: }
        !           498: 
        !           499: int
        !           500: arpdelete(char *addr)
        !           501: {
        !           502:        Arpcache *ap;
        !           503:        uchar ip[4];
        !           504:        Ipaddr i;
        !           505:        int rv;
        !           506: 
        !           507:        rv = -1;
        !           508:        i = ipparse(addr);
        !           509:        hnputl(ip, i);  
        !           510:        lock(&larphash);
        !           511:        for(ap = arplruhead; ap; ap = ap->frwd) {
        !           512:                if(memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) {
        !           513:                        ap->status = ARP_FREE;
        !           514:                        rv = 0;
        !           515:                        break;
        !           516:                }
        !           517:        }
        !           518:        unlock(&larphash);
        !           519:        return rv;
        !           520: }
        !           521: 
        !           522: void
        !           523: arplinkhead(Arpcache *ap)
        !           524: {
        !           525:        if(ap == arplruhead)
        !           526:                return;
        !           527: 
        !           528:        if(ap->prev)
        !           529:                ap->prev->frwd = ap->frwd;
        !           530:        else
        !           531:                arplruhead = ap->frwd;
        !           532:        
        !           533:        if(ap->frwd)
        !           534:                ap->frwd->prev = ap->prev;
        !           535:        else
        !           536:                arplrutail = ap->prev;
        !           537:                
        !           538:        ap->frwd = arplruhead;
        !           539:        ap->prev = 0;
        !           540:        arplruhead->prev = ap;
        !           541:        arplruhead = ap;
        !           542: }

unix.superglobalmegacorp.com

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