| plan 9 kernel history: overview | file list | diff list |
1991/1027/port/devarp.c (diff list | history)
| 1991/1026/sys/src/9/port/devarp.c:9,25 – 1991/1027/sys/src/9/port/devarp.c:9,49 (short | long | prev | next) | ||
| 1991/0424 | #include "devtab.h" | |
| 1991/1027 | Arpcache *arplruhead, *arplrutail; Arpcache *arp, **arphash; | |
| 1991/0424 | Queue *Servq; | |
| 1991/1027 | 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" }; | |
| 1991/0424 | #define ARP_ENTRYLEN 50 char *padstr = " "; | |
| 1991/1026/sys/src/9/port/devarp.c:55,60 – 1991/1027/sys/src/9/port/devarp.c:79,85 | ||
| 1991/0424 | ap = &arp[conf.arp-1]; ap->frwd = 0; arplrutail = ap; | |
| 1991/1027 | newqinfo(&arpinfo); | |
| 1991/0424 | } void | |
| 1991/1026/sys/src/9/port/devarp.c:203,214 – 1991/1027/sys/src/9/port/devarp.c:228,239 | ||
| 1991/0424 | m = getfields(buf, field, 5, ' '); if(strncmp(field[0], "flush", 5) == 0) | |
| 1991/1027 | arpflush(); | |
| 1991/0424 | else if(strcmp(field[0], "delete") == 0) { if(m != 2) error(Ebadarg); | |
| 1991/1027 | if(arpdelete(field[1]) < 0) | |
| 1991/0424 | error(Eaddrnotfound); } case arpdataqid: | |
| 1991/1026/sys/src/9/port/devarp.c:215,221 – 1991/1027/sys/src/9/port/devarp.c:240,246 | ||
| 1991/0424 | if(n != sizeof(Arpentry)) error(Emsgsize); memmove(&entry, a, sizeof(Arpentry)); | |
| 1991/1027 | arpenter(&entry, ARP_TEMP); | |
| 1991/0424 | break; default: error(Ebadusefd); | |
| 1991/1026/sys/src/9/port/devarp.c:224,226 – 1991/1027/sys/src/9/port/devarp.c:249,493 | ||
| 1991/0424 | return n; } | |
| 1991/1027 | 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; } } | |