## diffname port/devarp.c 1991/0424 ## diff -e /dev/null /n/bootesdump/1991/0424/sys/src/9/port/devarp.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "arp.h" #include "ipdat.h" #include "devtab.h" Arpcache *arp; Arpcache **arphash; Arpstats arpstats; Queue *Servq; #define ARP_ENTRYLEN 50 char *padstr = " "; extern Arpcache *arplruhead; extern Arpcache *arplrutail; enum{ arpdirqid, arpstatqid, arpctlqid, arpdataqid, }; Dirtab arptab[]={ "stats", {arpstatqid}, 0, 0600, "ctl", {arpctlqid}, 0, 0600, "data", {arpdataqid}, 0, 0600, }; #define Narptab (sizeof(arptab)/sizeof(Dirtab)) void arpreset(void) { Arpcache *ap, *ep; arp = (Arpcache *)ialloc(sizeof(Arpcache) * conf.arp, 0); arphash = (Arpcache **)ialloc(sizeof(Arpcache *) * Arphashsize, 0); ep = &arp[conf.arp]; for(ap = arp; ap < ep; ap++) { ap->frwd = ap+1; ap->prev = ap-1; ap->type = ARP_FREE; ap->status = ARP_TEMP; } arp[0].prev = 0; arplruhead = arp; ap = &arp[conf.arp-1]; ap->frwd = 0; arplrutail = ap; } void arpinit(void) { } Chan * arpattach(char *spec) { return devattach('a', spec); } Chan * arpclone(Chan *c, Chan *nc) { return devclone(c, nc); } int arpwalk(Chan *c, char *name) { return devwalk(c, name, arptab, (long)Narptab, devgen); } Chan* arpclwalk(Chan *c, char *name) { return devclwalk(c, name); } void arpstat(Chan *c, char *db) { devstat(c, db, arptab, (long)Narptab, devgen); } Chan * arpopen(Chan *c, int omode) { if(c->qid.path == CHDIR){ if(omode != OREAD) error(Eperm); } switch(STREAMTYPE(c->qid.path)) { case arpdataqid: break; case arpstatqid: if(omode != OREAD) error(Ebadarg); break; case arpctlqid: break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void arpcreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void arpremove(Chan *c) { error(Eperm); } void arpwstat(Chan *c, char *dp) { error(Eperm); } void arpclose(Chan *c) { streamclose(c); } long arpread(Chan *c, void *a, long n, ulong offset) { char buf[100]; Arpcache *ap, *ep; int part, bytes, size; char *ptr, *ststr; switch((int)(c->qid.path&~CHDIR)){ case arpdirqid: return devdirread(c, a, n, arptab, Narptab, devgen); case arpdataqid: bytes = c->offset; while(bytes < conf.arp*ARP_ENTRYLEN && n) { ap = &arp[bytes/ARP_ENTRYLEN]; part = bytes%ARP_ENTRYLEN; if(ap->status != ARP_OK) ststr = "invalid"; else ststr = (ap->type == ARP_TEMP ? "temp" : "perm"); sprint(buf,"%d.%d.%d.%d to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s%s", ap->eip[0], ap->eip[1], ap->eip[2], ap->eip[3], ap->et[0], ap->et[1], ap->et[2], ap->et[3], ap->et[4], ap->et[5], ststr, padstr); buf[ARP_ENTRYLEN-1] = '\n'; size = ARP_ENTRYLEN - part; size = MIN(n, size); memmove(a, buf+part, size); a = (void *)((int)a + size); n -= size; bytes += size; } return bytes - c->offset; break; case arpstatqid: sprint(buf, "hits: %d miss: %d failed: %d\n", arpstats.hit, arpstats.miss, arpstats.failed); return stringread(c, a, n, buf, offset); default: n=0; break; } return n; } long arpwrite(Chan *c, char *a, long n, ulong offset) { Arpentry entry; char buf[20], *field[5]; int m; switch(STREAMTYPE(c->qid.path)) { case arpctlqid: strncpy(buf, a, sizeof buf); m = getfields(buf, field, 5, ' '); if(strncmp(field[0], "flush", 5) == 0) arp_flush(); else if(strcmp(field[0], "delete") == 0) { if(m != 2) error(Ebadarg); if(arp_delete(field[1]) < 0) error(Eaddrnotfound); } case arpdataqid: if(n != sizeof(Arpentry)) error(Emsgsize); memmove(&entry, a, sizeof(Arpentry)); arp_enter(&entry, ARP_TEMP); break; default: error(Ebadusefd); } return n; } . ## diffname port/devarp.c 1991/0427 ## diff -e /n/bootesdump/1991/0424/sys/src/9/port/devarp.c /n/bootesdump/1991/0427/sys/src/9/port/devarp.c 84,89d ## diffname port/devarp.c 1991/1026 ## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devarp.c /n/bootesdump/1991/1026/sys/src/9/port/devarp.c 20d ## diffname port/devarp.c 1991/1027 ## diff -e /n/bootesdump/1991/1026/sys/src/9/port/devarp.c /n/bootesdump/1991/1027/sys/src/9/port/devarp.c 226a void arpopn(Queue *q, Stream *s) { if(!Servq) Servq = RD(q); } void arpcls(Queue *q) { if(q == Servq) Servq = 0; } void arpiput(Queue *q, Block *bp) { PUTNEXT(q, bp); } void arpoput(Queue *q, Block *bp) { PUTNEXT(q, bp); } int arplookup(uchar *ip, uchar *et) { Arpcache *ap; lock(&arpalloc.hash); for(ap = ARPHASH(ip); ap; ap = ap->hash) { if(ap->status == ARP_OK && memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) { memmove(et, ap->et, sizeof(ap->et)); arplinkhead(ap); unlock(&arpalloc.hash); arpstats.hit++; return 1; } } unlock(&arpalloc.hash); return 0; } void arpsendpkt(uchar *unroutedip, uchar *ether, Queue *put, Block *bp) { Arpq *aq; Block *nbp; uchar ip[4]; if(!Servq) { print("arp: No server\n"); freeb(bp); return; } iproute(unroutedip, ip); if(arplookup(ip, ether)) { PUTNEXT(put, bp); return; } /* Send the request out to the user level arp daemon */ nbp = allocb(sizeof(ip)); memmove(nbp->rptr, ip, sizeof(ip)); nbp->wptr += sizeof(ip); nbp->flags |= S_DELIM; PUTNEXT(Servq, nbp); arpstats.miss++; lock(&arpalloc); if(aq = arpalloc.free) arpalloc.free = aq->next; unlock(&arpalloc); if(aq == 0) { freeb(bp); return; } /* Stash the work away until the arp completes or times out */ memmove(aq->ip, ip, sizeof(aq->ip)); aq->etheraddr = ether; aq->bp = bp; aq->put = put; aq->time = MACHP(0)->ticks; lock(&arpalloc.list); if(arpalloc.head) { arpalloc.tail->next = aq; arpalloc.tail = aq; } else { arpalloc.tail = aq; arpalloc.head = aq; } aq->next = 0; unlock(&arpalloc.list); } void arpflush(void) { Arpcache *ap; for(ap = arplruhead; ap; ap = ap->frwd) ap->status = ARP_FREE; } void arpenter(Arpentry *ape, int type) { Arpcache *ap, **l, *d; /* Update an entry if we have one already */ l = &ARPHASH(ape->ipaddr); lock(&arpalloc.hash); for(ap = *l; ap; ap = ap->hash) { if(ap->status == ARP_OK && memcmp(ap->eip, ape->ipaddr, sizeof(ap->eip)) == 0) { if(ap->type != ARP_PERM) { ap->type = type; memmove(ap->et, ape->etaddr, sizeof(ap->et)); ap->status = ARP_OK; } unlock(&arpalloc.hash); return; } } /* Find an entry to replace */ for(ap = arplrutail; ap && ap->type == ARP_PERM; ap = ap->prev) ; if(!ap) { print("arp: too many permanent entries\n"); unlock(&arpalloc.hash); return; } if(ap->hashhd) { for(d = *ap->hashhd; d; d = d->hash) { if(d == ap) { *(ap->hashhd) = ap->hash; break; } ap->hashhd = &d->hash; } } ap->type = type; ap->status = ARP_OK; memmove(ap->eip, ape->ipaddr, sizeof(ape->ipaddr)); memmove(ap->et, ape->etaddr, sizeof(ape->etaddr)); ap->ip = nhgetl(ap->eip); ap->hashhd = l; ap->hash = *l; *l = ap; arplinkhead(ap); unlock(&arpalloc.hash); pusharpq(); } void pusharpq(void) { int sent; Arpq *aq, *prev; loop: prev = 0; lock(&arpalloc.list); for(aq = arpalloc.head; aq; aq = aq->next) { if(arplookup(aq->ip, aq->etheraddr)) { if(prev) prev->next = aq->next; else arpalloc.head = 0; if(aq->next == 0) arpalloc.tail = prev; unlock(&arpalloc.list); PUTNEXT(aq->put, aq->bp); lock(&arpalloc); aq->next = arpalloc.free; arpalloc.free = aq; unlock(&arpalloc); goto loop; } prev = aq; } unlock(&arpalloc.list); } int arpdelete(char *addr) { Arpcache *ap; char enetaddr[6], buf[20], *ptr; int i; ptr = buf + 2; strncpy(ptr, addr, (sizeof buf) - 2); for(i = 0; i < 6 && addr != (char *)1; i++) { ptr[-2] = '0'; ptr[-1] = 'x'; enetaddr[i] = atoi(ptr-2); ptr = strchr(ptr, ':')+1; } lock(&arpalloc.hash); for(ap = arplruhead; ap; ap = ap->frwd) { if(memcmp(ap->et, ptr, sizeof(ap->et)) == 0) { ap->status = ARP_FREE; break; } } unlock(&arpalloc.hash); } void arplinkhead(Arpcache *ap) { if(ap != arplruhead) { if(ap->prev) ap->prev->frwd = ap->frwd; else arplruhead = ap->frwd; if(ap->frwd) ap->frwd->prev = ap->prev; else arplrutail = ap->prev; ap->frwd = arplruhead; ap->prev = 0; arplruhead = ap; } } . 218c arpenter(&entry, ARP_TEMP); . 211c if(arpdelete(field[1]) < 0) . 206c arpflush(); . 57a newqinfo(&arpinfo); . 20,22d 16a typedef struct Arpq Arpq; struct Arpq { uchar ip[4]; uchar *etheraddr; Block *bp; Queue *put; ulong time; Arpq *next; }; struct arpalloc { Lock; Lock list; Lock hash; Arpq *free; Arpq *head; Arpq *tail; }arpalloc; void arpiput(Queue *, Block *); void arpoput(Queue *, Block *); void arpopn(Queue *, Stream *); void arpcls(Queue *); Qinfo arpinfo = { arpiput, arpoput, arpopn, arpcls, "arp" }; . 14a Arpcache *arplruhead, *arplrutail; Arpcache *arp, **arphash; . 12,13d ## diffname port/devarp.c 1991/1028 ## diff -e /n/bootesdump/1991/1027/sys/src/9/port/devarp.c /n/bootesdump/1991/1028/sys/src/9/port/devarp.c 315a print("miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); . 312a print("hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); . ## diffname port/devarp.c 1991/1029 ## diff -e /n/bootesdump/1991/1028/sys/src/9/port/devarp.c /n/bootesdump/1991/1029/sys/src/9/port/devarp.c 474c unlock(&larphash); . 467c lock(&larphash); . 420,449d 416,417c unlock(&larphash); . 411d 393c unlock(&larphash); . 382c unlock(&larphash); . 374c lock(&larphash); . 299,357d 294c arpstats.miss++; unlock(&larphash); . 289c unlock(&larphash); . 284c lock(&larphash); . 276c uchar ip[4]; Etherhdr *eh; if(bp->type != M_DATA) { if(Servq == 0 && streamparse("arpd", bp)) { print("setting arp channel\n"); Servq = RD(q); freeb(bp); } else PUTNEXT(q, bp); return; } if(!Servq) { print("arp: No server, packet dropped\n"); freeb(bp); return; } eh = (Etherhdr *)bp->rptr; iproute(eh->dst, ip); /* Send downstream to the ethernet */ if(arplookup(ip, eh->d)) { print("arp hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); PUTNEXT(q, bp); return; } print("arp miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); /* Return the packet to the arp server for address resolution */ memmove(eh->d, ip, sizeof(ip)); PUTNEXT(Servq, bp); . 256,257d 28,41d 17,26c void arpiput(Queue *, Block *); void arpoput(Queue *, Block *); void arpopn(Queue *, Stream *); void arpcls(Queue *); void arpenter(Arpentry*, int); void arpflush(void); int arpdelete(char*); void arplinkhead(Arpcache*); int arplookup(uchar*, uchar*); . 15a Lock larphash; . 11a #define ARP_FREE 0 #define ARP_OK 1 #define ARP_ASKED 2 #define ARP_TEMP 0 #define ARP_PERM 1 #define Arphashsize 32 #define ARPHASH(p) arphash[((p[2]^p[3])%Arphashsize)] typedef struct Arpcache Arpcache; struct Arpcache { uchar status; uchar type; uchar eip[4]; uchar et[6]; Arpcache *hash; Arpcache **hashhd; Arpcache *frwd; Arpcache *prev; }; . ## diffname port/devarp.c 1991/1030 ## diff -e /n/bootesdump/1991/1029/sys/src/9/port/devarp.c /n/bootesdump/1991/1030/sys/src/9/port/devarp.c 311c /* Push the packet up to the arp server for address resolution */ . 309d 305d 300a if(nhgets(eh->type) != ET_IP) { PUTNEXT(q, bp); return; } . 285d ## diffname port/devarp.c 1991/1112 ## diff -e /n/bootesdump/1991/1030/sys/src/9/port/devarp.c /n/bootesdump/1991/1112/sys/src/9/port/devarp.c 61,63c "stats", {arpstatqid}, 0, 0666, "ctl", {arpctlqid}, 0, 0666, "data", {arpdataqid}, 0, 0666, . ## diffname port/devarp.c 1991/1115 ## diff -e /n/bootesdump/1991/1112/sys/src/9/port/devarp.c /n/bootesdump/1991/1115/sys/src/9/port/devarp.c 261a USED(q, s); . 258d 215c return stringread(a, n, buf, offset); . 161a USED(c, dp); . 155a USED(c); . 149a USED(c, name, omode, perm); . ## diffname port/devarp.c 1991/1203 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devarp.c /n/bootesdump/1991/1203/sys/src/9/port/devarp.c 21c struct Arpcache { . ## diffname port/devarp.c 1992/0111 ## diff -e /n/bootesdump/1991/1203/sys/src/9/port/devarp.c /n/bootesdump/1992/0111/sys/src/9/port/devarp.c 6c #include "../port/error.h" . ## diffname port/devarp.c 1992/0112 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devarp.c /n/bootesdump/1992/0112/sys/src/9/port/devarp.c 247c error(Ebadaddr); . ## diffname port/devarp.c 1992/0114 ## diff -e /n/bootesdump/1992/0112/sys/src/9/port/devarp.c /n/bootesdump/1992/0114/sys/src/9/port/devarp.c 247c error(Enetaddr); . ## diffname port/devarp.c 1992/0213 ## diff -e /n/bootesdump/1992/0114/sys/src/9/port/devarp.c /n/bootesdump/1992/0213/sys/src/9/port/devarp.c 445a . 316a /* if ip broadcast, use ether bcast address */ addr = nhgetl(eh->dst); if(addr == Myip[Mybcast] || addr == Myip[Mynet] || addr == Myip[Mysubnet]){ memset(eh->d, 0xff, sizeof(eh->d)); PUTNEXT(q, bp); return; } . 311c /* if a known ip addr, send downstream to the ethernet */ . 298c if((dropped++ % 1000) == 0) print("arp: No server, packet dropped\n"); . 285a Ipaddr addr; static int dropped; . 185c return devdirread(c, a, n, 0, 0, arpgen); . 118c devstat(c, db, 0, 0, arpgen); . 112c return devwalk(c, name, 0, 0, arpgen); . 67a /* * create a 2-level directory */ int arpgen(Chan *c, void *vp, int ntab, int i, Dir *dp) { Qid q; q.vers = 0; /* top level directory contains the directory arp */ if(c->qid.path == CHDIR){ if(i) return -1; q.path = CHDIR | arpdir2qid; devdir(c, q, "arp", 0, eve, 0555, dp); return 1; } /* next level uses table */ return devgen(c, arptab, Narptab, i, dp); } . 62,64c "stats", {arpstatqid}, 0, 0444, "ctl", {arpctlqid}, 0, 0664, "data", {arpdataqid}, 0, 0664, . 55a arpdir2qid, . ## diffname port/devarp.c 1992/0214 ## diff -e /n/bootesdump/1992/0213/sys/src/9/port/devarp.c /n/bootesdump/1992/0214/sys/src/9/port/devarp.c 351,352d 344,348c /* Push the packet up to the arp server for address resolution */ if(!Servq) { if((dropped++ % 1000) == 0) print("arp: No server, packet dropped %d.%d.%d.%d\n", eh->dst[0], eh->dst[1], eh->dst[2], eh->dst[3]); freeb(bp); . 335a /* if ip broadcast, use ether bcast address */ addr = nhgetl(eh->dst); if(addr == Myip[Mybcast] || addr == Myip[Mynet] || addr == Myip[Mysubnet]){ memset(eh->d, 0xff, sizeof(eh->d)); PUTNEXT(q, bp); return; } . 323,329d ## diffname port/devarp.c 1992/0304 ## diff -e /n/bootesdump/1992/0214/sys/src/9/port/devarp.c /n/bootesdump/1992/0304/sys/src/9/port/devarp.c 331c if(addr == Myip[Mybcast] || addr == Myip[Mynet] || ((addr & Mymask) == Myip[Mynet+1] && (addr & ~Mynetmask) == ~Mynetmask)){ . ## diffname port/devarp.c 1992/0319 ## diff -e /n/bootesdump/1992/0304/sys/src/9/port/devarp.c /n/bootesdump/1992/0319/sys/src/9/port/devarp.c 288a if(Myip[Myself]) error(Einuse); . ## diffname port/devarp.c 1992/0320 ## diff -e /n/bootesdump/1992/0319/sys/src/9/port/devarp.c /n/bootesdump/1992/0320/sys/src/9/port/devarp.c 289,290d 278a . 272a break; . 266c else if(strcmp(field[0], "delete") == 0) { . ## diffname port/devarp.c 1992/0321 ## diff -e /n/bootesdump/1992/0320/sys/src/9/port/devarp.c /n/bootesdump/1992/0321/sys/src/9/port/devarp.c 2c #include "../port/lib.h" . ## diffname port/devarp.c 1992/0325 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/devarp.c /n/bootesdump/1992/0325/sys/src/9/port/devarp.c 486d 462c if(memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) { . 450,459c i = ipparse(addr); hnputl(ip, i); . 447,448c uchar ip[4]; Ipaddr i; . 387c ep = &arp[conf.arp]; for(ap = arp; ap < ep; ap++) . 385c Arpcache *ap, *ep; . ## diffname port/devarp.c 1992/0520 ## diff -e /n/bootesdump/1992/0325/sys/src/9/port/devarp.c /n/bootesdump/1992/0520/sys/src/9/port/devarp.c 460a return rv; . 456a rv = 0; . 450a rv = -1; . 449a int rv; . ## diffname port/devarp.c 1992/0619 ## diff -e /n/bootesdump/1992/0520/sys/src/9/port/devarp.c /n/bootesdump/1992/0619/sys/src/9/port/devarp.c 335c if(Myip[Myself] == 0 || addr == Myip[Mybcast] || addr == Myip[Mynet] . ## diffname port/devarp.c 1992/0620 ## diff -e /n/bootesdump/1992/0619/sys/src/9/port/devarp.c /n/bootesdump/1992/0620/sys/src/9/port/devarp.c 97,98c arp = xalloc(sizeof(Arpcache) * conf.arp); arphash = (Arpcache **)xalloc(sizeof(Arpcache *) * Arphashsize); . ## diffname port/devarp.c 1992/0623 ## diff -e /n/bootesdump/1992/0620/sys/src/9/port/devarp.c /n/bootesdump/1992/0623/sys/src/9/port/devarp.c 243c return readstr(offset, a, n, buf); . ## diffname port/devarp.c 1992/0711 ## diff -e /n/bootesdump/1992/0623/sys/src/9/port/devarp.c /n/bootesdump/1992/0711/sys/src/9/port/devarp.c 256a USED(offset); . 205c char *ststr; . 203c Arpcache *ap; . 76a USED(vp); USED(ntab); . ## diffname port/devarp.c 1992/0819 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/devarp.c /n/bootesdump/1992/0819/sys/src/9/port/devarp.c 211,212d 209a if(c->qid.path&CHDIR) return devdirread(c, a, n, arptab, Narptab, arpgen); . 168d 151,152c if(c->qid.path&CHDIR){ . ## diffname port/devarp.c 1993/0206 ## diff -e /n/bootesdump/1992/0819/sys/src/9/port/devarp.c /n/bootesdump/1993/0206/sys/src/9/port/devarp.c 391c ep = &arp[Narp]; . 214c while(bytes < Narp*ARP_ENTRYLEN && n) { . 113c ap = &arp[Narp-1]; . 103c ep = &arp[Narp]; . 100c arp = xalloc(sizeof(Arpcache) * Narp); . 68a enum { Narp= 64, /* size of arp cache */ }; . ## diffname port/devarp.c 1993/0501 ## diff -e /n/bootesdump/1993/0206/sys/src/9/port/devarp.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devarp.c 396c ep = &arp[conf.arp]; . 219c while(bytes < conf.arp*ARP_ENTRYLEN && n) { . 118c ap = &arp[conf.arp-1]; . 108c ep = &arp[conf.arp]; . 105c arp = xalloc(sizeof(Arpcache) * conf.arp); . 69,73d ## diffname port/devarp.c 1993/0804 # deleted ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/devarp.c /n/fornaxdump/1993/0804/sys/src/brazil/port/devarp.c 1,489d