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