plan 9 kernel history: overview | file list | diff list

1991/1027/port/devarp.c (diff list | history)

1991/0424/sys/src/9/port/devarp.c:81,921991/0427/sys/src/9/port/devarp.c:81,86 (short | long)
1991/0424    
	return devwalk(c, name, arptab, (long)Narptab, devgen); 
} 
 
Chan* 
arpclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
                 
void 
arpstat(Chan *c, char *db) 
{ 
1991/0427/sys/src/9/port/devarp.c:17,231991/1026/sys/src/9/port/devarp.c:17,22 (short | long)
1991/0424    
#define ARP_ENTRYLEN	50 
char *padstr = "                                           "; 
 
                 
extern Arpcache *arplruhead; 
extern Arpcache *arplrutail; 
 
1991/1026/sys/src/9/port/devarp.c:9,251991/1027/sys/src/9/port/devarp.c:9,49 (short | long)
1991/0424    
 
#include	"devtab.h" 
 
Arpcache 	*arp; 
Arpcache	**arphash; 
Arpstats	arpstats; 
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 = "                                           "; 
 
extern Arpcache *arplruhead; 
extern Arpcache *arplrutail; 
                 
enum{ 
	arpdirqid, 
	arpstatqid, 
1991/1026/sys/src/9/port/devarp.c:55,601991/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,2141991/1027/sys/src/9/port/devarp.c:228,239
1991/0424    
		m = getfields(buf, field, 5, ' '); 
 
		if(strncmp(field[0], "flush", 5) == 0) 
			arp_flush(); 
1991/1027    
			arpflush(); 
1991/0424    
		else if(strcmp(field[0], "delete") == 0) { 
			if(m != 2) 
				error(Ebadarg); 
 
			if(arp_delete(field[1]) < 0) 
1991/1027    
			if(arpdelete(field[1]) < 0) 
1991/0424    
				error(Eaddrnotfound); 
		} 
	case arpdataqid: 
1991/1026/sys/src/9/port/devarp.c:215,2211991/1027/sys/src/9/port/devarp.c:240,246
1991/0424    
		if(n != sizeof(Arpentry)) 
			error(Emsgsize); 
		memmove(&entry, a, sizeof(Arpentry)); 
		arp_enter(&entry, ARP_TEMP); 
1991/1027    
		arpenter(&entry, ARP_TEMP); 
1991/0424    
		break; 
	default: 
		error(Ebadusefd); 
1991/1026/sys/src/9/port/devarp.c:224,2261991/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; 
	} 
} 
1991/1027/sys/src/9/port/devarp.c:310,3181991/1028/sys/src/9/port/devarp.c:310,320 (short | long)
1991/1027    
 
	iproute(unroutedip, ip); 
	if(arplookup(ip, ether)) { 
1991/1028    
print("hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); 
1991/1027    
		PUTNEXT(put, bp); 
		return; 
	} 
1991/1028    
print("miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); 
1991/1027    
 
	/* Send the request out to the user level arp daemon */ 
	nbp = allocb(sizeof(ip)); 
1991/1028/sys/src/9/port/devarp.c:9,441991/1029/sys/src/9/port/devarp.c:9,50 (short | long)
1991/0424    
 
#include	"devtab.h" 
 
1991/1029    
#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; 
}; 
 
1991/0424    
Arpstats	arpstats; 
1991/1027    
Arpcache 	*arplruhead, *arplrutail; 
Arpcache 	*arp, **arphash; 
1991/0424    
Queue		*Servq; 
1991/1029    
Lock		larphash; 
1991/0424    
 
1991/1027    
typedef struct Arpq Arpq; 
struct Arpq 
{ 
	uchar	ip[4]; 
	uchar	*etheraddr; 
	Block	*bp; 
	Queue	*put; 
	ulong	time; 
	Arpq	*next; 
}; 
1991/1029    
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*); 
1991/1027    
 
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 
1991/1028/sys/src/9/port/devarp.c:253,2601991/1029/sys/src/9/port/devarp.c:259,264
1991/1027    
void 
arpopn(Queue *q, Stream *s) 
{ 
	if(!Servq) 
		Servq = RD(q); 
} 
 
void 
1991/1028/sys/src/9/port/devarp.c:273,2791991/1029/sys/src/9/port/devarp.c:277,316
1991/1027    
void 
arpoput(Queue *q, Block *bp) 
{ 
	PUTNEXT(q, bp); 
1991/1029    
	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); 
1991/1027    
} 
 
int 
1991/1028/sys/src/9/port/devarp.c:281,3601991/1029/sys/src/9/port/devarp.c:318,339
1991/1027    
{ 
	Arpcache *ap; 
 
	lock(&arpalloc.hash); 
1991/1029    
	lock(&larphash); 
1991/1027    
	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); 
1991/1029    
			unlock(&larphash); 
1991/1027    
			arpstats.hit++; 
			return 1; 
		} 
	} 
	unlock(&arpalloc.hash); 
1991/1029    
	arpstats.miss++; 
	unlock(&larphash); 
1991/1027    
	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)) { 
1991/1028    
print("hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); 
1991/1027    
		PUTNEXT(put, bp); 
		return; 
	} 
1991/1028    
print("miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); 
1991/1027    
                 
	/* 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; 
1991/1028/sys/src/9/port/devarp.c:371,3771991/1029/sys/src/9/port/devarp.c:350,356
1991/1027    
 
	/* Update an entry if we have one already */ 
	l = &ARPHASH(ape->ipaddr); 
	lock(&arpalloc.hash); 
1991/1029    
	lock(&larphash); 
1991/1027    
	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) { 
1991/1028/sys/src/9/port/devarp.c:379,3851991/1029/sys/src/9/port/devarp.c:358,364
1991/1027    
				memmove(ap->et, ape->etaddr, sizeof(ap->et)); 
				ap->status = ARP_OK; 
			} 
			unlock(&arpalloc.hash); 
1991/1029    
			unlock(&larphash); 
1991/1027    
			return; 
		} 
	} 
1991/1028/sys/src/9/port/devarp.c:390,3961991/1029/sys/src/9/port/devarp.c:369,375
1991/1027    
 
	if(!ap) { 
		print("arp: too many permanent entries\n"); 
		unlock(&arpalloc.hash); 
1991/1029    
		unlock(&larphash); 
1991/1027    
		return; 
	} 
 
1991/1028/sys/src/9/port/devarp.c:408,4521991/1029/sys/src/9/port/devarp.c:387,399
1991/1027    
	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(); 
1991/1029    
	unlock(&larphash); 
1991/1027    
} 
 
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) 
{ 
1991/1028/sys/src/9/port/devarp.c:464,4701991/1029/sys/src/9/port/devarp.c:411,417
1991/1027    
		ptr = strchr(ptr, ':')+1; 
	} 
 
	lock(&arpalloc.hash); 
1991/1029    
	lock(&larphash); 
1991/1027    
	for(ap = arplruhead; ap; ap = ap->frwd) { 
		if(memcmp(ap->et, ptr, sizeof(ap->et)) == 0) { 
			ap->status = ARP_FREE; 
1991/1028/sys/src/9/port/devarp.c:471,4771991/1029/sys/src/9/port/devarp.c:418,424
1991/1027    
			break; 
		} 
	} 
	unlock(&arpalloc.hash); 
1991/1029    
	unlock(&larphash); 
1991/1027    
} 
 
void 
1991/1029/sys/src/9/port/devarp.c:282,2881991/1030/sys/src/9/port/devarp.c:282,287 (short | long)
1991/1029    
 
	if(bp->type != M_DATA) { 
		if(Servq == 0 && streamparse("arpd", bp)) { 
print("setting arp channel\n"); 
			Servq = RD(q); 
			freeb(bp); 
		} 
1991/1029/sys/src/9/port/devarp.c:298,3141991/1030/sys/src/9/port/devarp.c:297,316
1991/1029    
	} 
 
	eh = (Etherhdr *)bp->rptr; 
1991/1030    
	if(nhgets(eh->type) != ET_IP) { 
		PUTNEXT(q, bp);	 
		return; 
	} 
 
1991/1029    
	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 */ 
1991/1030    
	/* Push the packet up to the arp server for address resolution */ 
1991/1029    
	memmove(eh->d, ip, sizeof(ip)); 
	PUTNEXT(Servq, bp); 
1991/1027    
} 
1991/1030/sys/src/9/port/devarp.c:58,661991/1112/sys/src/9/port/devarp.c:58,66 (short | long)
1991/0424    
}; 
 
Dirtab arptab[]={ 
	"stats",	{arpstatqid},		0,	0600, 
	"ctl",		{arpctlqid},		0,	0600, 
	"data",		{arpdataqid},		0,	0600, 
1991/1112    
	"stats",	{arpstatqid},		0,	0666, 
	"ctl",		{arpctlqid},		0,	0666, 
	"data",		{arpdataqid},		0,	0666, 
1991/0424    
}; 
#define Narptab (sizeof(arptab)/sizeof(Dirtab)) 
 
1991/1112/sys/src/9/port/devarp.c:147,1521991/1115/sys/src/9/port/devarp.c:147,153 (short | long)
1991/0424    
void 
arpcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	USED(c, name, omode, perm); 
1991/0424    
	error(Eperm); 
} 
 
1991/1112/sys/src/9/port/devarp.c:153,1581991/1115/sys/src/9/port/devarp.c:154,160
1991/0424    
void 
arpremove(Chan *c) 
{ 
1991/1115    
	USED(c); 
1991/0424    
	error(Eperm); 
} 
 
1991/1112/sys/src/9/port/devarp.c:159,1641991/1115/sys/src/9/port/devarp.c:161,167
1991/0424    
void 
arpwstat(Chan *c, char *dp) 
{ 
1991/1115    
	USED(c, dp); 
1991/0424    
	error(Eperm); 
} 
 
1991/1112/sys/src/9/port/devarp.c:212,2181991/1115/sys/src/9/port/devarp.c:215,221
1991/0424    
		sprint(buf, "hits: %d miss: %d failed: %d\n", 
			arpstats.hit, arpstats.miss, arpstats.failed); 
 
		return stringread(c, a, n, buf, offset); 
1991/1115    
		return stringread(a, n, buf, offset); 
1991/0424    
	default: 
		n=0; 
		break; 
1991/1112/sys/src/9/port/devarp.c:255,2641991/1115/sys/src/9/port/devarp.c:258,267
1991/0424    
	return n; 
} 
 
1991/1027    
                 
void 
arpopn(Queue *q, Stream *s) 
{ 
1991/1115    
	USED(q, s); 
1991/1027    
} 
 
void 
1991/1115/sys/src/9/port/devarp.c:18,241991/1203/sys/src/9/port/devarp.c:18,25 (short | long)
1991/1029    
#define ARPHASH(p)	arphash[((p[2]^p[3])%Arphashsize)] 
 
typedef struct Arpcache Arpcache; 
struct Arpcache { 
1991/1203    
struct Arpcache 
{ 
1991/1029    
	uchar	status; 
	uchar	type; 
	uchar	eip[4]; 
1991/1203/sys/src/9/port/devarp.c:3,91992/0111/sys/src/9/port/devarp.c:3,9 (short | long)
Move error.h to ../port. Change errors to actual strings.
rsc Fri Mar 4 12:44:25 2005
1991/0424    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1991/0424    
#include	"arp.h" 
#include 	"ipdat.h" 
 
1992/0111/sys/src/9/port/devarp.c:244,2501992/0112/sys/src/9/port/devarp.c:244,250 (short | long)
1991/0424    
				error(Ebadarg); 
 
1991/1027    
			if(arpdelete(field[1]) < 0) 
1991/0424    
				error(Eaddrnotfound); 
1992/0112    
				error(Ebadaddr); 
1991/0424    
		} 
	case arpdataqid: 
		if(n != sizeof(Arpentry)) 
1992/0112/sys/src/9/port/devarp.c:244,2501992/0114/sys/src/9/port/devarp.c:244,250 (short | long)
1991/0424    
				error(Ebadarg); 
 
1991/1027    
			if(arpdelete(field[1]) < 0) 
1992/0112    
				error(Ebadaddr); 
1992/0114    
				error(Enetaddr); 
1991/0424    
		} 
	case arpdataqid: 
		if(n != sizeof(Arpentry)) 
1992/0114/sys/src/9/port/devarp.c:53,581992/0213/sys/src/9/port/devarp.c:53,59 (short | long)
1991/0424    
 
enum{ 
	arpdirqid, 
1992/0213    
	arpdir2qid, 
1991/0424    
	arpstatqid, 
	arpctlqid, 
	arpdataqid, 
1992/0114/sys/src/9/port/devarp.c:59,701992/0213/sys/src/9/port/devarp.c:60,94
1991/0424    
}; 
 
Dirtab arptab[]={ 
1991/1112    
	"stats",	{arpstatqid},		0,	0666, 
	"ctl",		{arpctlqid},		0,	0666, 
	"data",		{arpdataqid},		0,	0666, 
1992/0213    
	"stats",	{arpstatqid},		0,	0444, 
	"ctl",		{arpctlqid},		0,	0664, 
	"data",		{arpdataqid},		0,	0664, 
1991/0424    
}; 
#define Narptab (sizeof(arptab)/sizeof(Dirtab)) 
 
1992/0213    
/* 
 *  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); 
} 
 
1991/0424    
void 
arpreset(void) 
{ 
1992/0114/sys/src/9/port/devarp.c:109,1211992/0213/sys/src/9/port/devarp.c:133,145
1991/0424    
int 
arpwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, arptab, (long)Narptab, devgen); 
1992/0213    
	return devwalk(c, name, 0, 0, arpgen); 
1991/0424    
} 
 
void 
arpstat(Chan *c, char *db) 
{ 
	devstat(c, db, arptab, (long)Narptab, devgen); 
1992/0213    
	devstat(c, db, 0, 0, arpgen); 
1991/0424    
} 
 
Chan * 
1992/0114/sys/src/9/port/devarp.c:182,1881992/0213/sys/src/9/port/devarp.c:206,212
1991/0424    
 
	switch((int)(c->qid.path&~CHDIR)){ 
	case arpdirqid: 
		return devdirread(c, a, n, arptab, Narptab, devgen); 
1992/0213    
		return devdirread(c, a, n, 0, 0, arpgen); 
1991/0424    
	case arpdataqid: 
		bytes = c->offset; 
		while(bytes < conf.arp*ARP_ENTRYLEN && n) { 
1992/0114/sys/src/9/port/devarp.c:283,2881992/0213/sys/src/9/port/devarp.c:307,314
1991/1027    
{ 
1991/1029    
	uchar ip[4]; 
	Etherhdr *eh; 
1992/0213    
	Ipaddr addr; 
	static int dropped; 
1991/1029    
 
	if(bp->type != M_DATA) { 
		if(Servq == 0 && streamparse("arpd", bp)) { 
1992/0114/sys/src/9/port/devarp.c:295,3011992/0213/sys/src/9/port/devarp.c:321,328
1991/1029    
	} 
 
	if(!Servq) { 
		print("arp: No server, packet dropped\n"); 
1992/0213    
		if((dropped++ % 1000) == 0) 
			print("arp: No server, packet dropped\n"); 
1991/1029    
		freeb(bp); 
		return; 
	} 
1992/0114/sys/src/9/port/devarp.c:308,3191992/0213/sys/src/9/port/devarp.c:335,354
1991/1030    
 
1991/1029    
	iproute(eh->dst, ip); 
 
	/* Send downstream to the ethernet */ 
1992/0213    
	/* if a known ip addr, send downstream to the ethernet */ 
1991/1029    
	if(arplookup(ip, eh->d)) { 
		PUTNEXT(q, bp); 
		return; 
	} 
 
1992/0213    
	/* 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; 
	} 
 
1991/1030    
	/* Push the packet up to the arp server for address resolution */ 
1991/1029    
	memmove(eh->d, ip, sizeof(ip)); 
	PUTNEXT(Servq, bp); 
1992/0114/sys/src/9/port/devarp.c:443,4481992/0213/sys/src/9/port/devarp.c:478,484
1991/1027    
		 
		ap->frwd = arplruhead; 
		ap->prev = 0; 
1992/0213    
 
1991/1027    
		arplruhead = ap; 
	} 
} 
1992/0213/sys/src/9/port/devarp.c:320,3321992/0214/sys/src/9/port/devarp.c:320,325 (short | long)
1991/1029    
		return; 
	} 
 
	if(!Servq) { 
1992/0213    
		if((dropped++ % 1000) == 0) 
			print("arp: No server, packet dropped\n"); 
1991/1029    
		freeb(bp); 
		return; 
	} 
                 
	eh = (Etherhdr *)bp->rptr; 
1991/1030    
	if(nhgets(eh->type) != ET_IP) { 
		PUTNEXT(q, bp);	 
1992/0213/sys/src/9/port/devarp.c:333,3381992/0214/sys/src/9/port/devarp.c:326,339
1991/1030    
		return; 
	} 
 
1992/0214    
	/* 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; 
	} 
 
1991/1029    
	iproute(eh->dst, ip); 
 
1992/0213    
	/* if a known ip addr, send downstream to the ethernet */ 
1992/0213/sys/src/9/port/devarp.c:341,3551992/0214/sys/src/9/port/devarp.c:342,355
1991/1029    
		return; 
	} 
 
1992/0213    
	/* 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); 
1992/0214    
	/* 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); 
1992/0213    
		return; 
	} 
                 
1991/1030    
	/* Push the packet up to the arp server for address resolution */ 
1991/1029    
	memmove(eh->d, ip, sizeof(ip)); 
	PUTNEXT(Servq, bp); 
1991/1027    
} 
1992/0214/sys/src/9/port/devarp.c:328,3341992/0304/sys/src/9/port/devarp.c:328,335 (short | long)
1991/1030    
 
1992/0214    
	/* if ip broadcast, use ether bcast address */ 
	addr = nhgetl(eh->dst); 
	if(addr == Myip[Mybcast] || addr == Myip[Mynet] || addr == Myip[Mysubnet]){ 
1992/0304    
	if(addr == Myip[Mybcast] || addr == Myip[Mynet] 
	|| ((addr & Mymask) == Myip[Mynet+1] && (addr & ~Mynetmask) == ~Mynetmask)){ 
1992/0214    
		memset(eh->d, 0xff, sizeof(eh->d)); 
		PUTNEXT(q, bp); 
		return; 
1992/0304/sys/src/9/port/devarp.c:286,2911992/0319/sys/src/9/port/devarp.c:286,293 (short | long)
1991/1027    
void 
arpopn(Queue *q, Stream *s) 
{ 
1992/0319    
	if(Myip[Myself]) 
		error(Einuse); 
1991/1115    
	USED(q, s); 
1991/1027    
} 
 
1992/0319/sys/src/9/port/devarp.c:263,2691992/0320/sys/src/9/port/devarp.c:263,270 (short | long)
1991/0424    
 
		if(strncmp(field[0], "flush", 5) == 0) 
1991/1027    
			arpflush(); 
1991/0424    
		else if(strcmp(field[0], "delete") == 0) { 
1992/0320    
		else 
		if(strcmp(field[0], "delete") == 0) { 
1991/0424    
			if(m != 2) 
				error(Ebadarg); 
 
1992/0319/sys/src/9/port/devarp.c:270,2751992/0320/sys/src/9/port/devarp.c:271,278
1991/1027    
			if(arpdelete(field[1]) < 0) 
1992/0114    
				error(Enetaddr); 
1991/0424    
		} 
1992/0320    
		break; 
 
1991/0424    
	case arpdataqid: 
		if(n != sizeof(Arpentry)) 
			error(Emsgsize); 
1992/0319/sys/src/9/port/devarp.c:276,2811992/0320/sys/src/9/port/devarp.c:279,285
1991/0424    
		memmove(&entry, a, sizeof(Arpentry)); 
1991/1027    
		arpenter(&entry, ARP_TEMP); 
1991/0424    
		break; 
1992/0320    
 
1991/0424    
	default: 
		error(Ebadusefd); 
	} 
1992/0319/sys/src/9/port/devarp.c:286,2931992/0320/sys/src/9/port/devarp.c:290,295
1991/1027    
void 
arpopn(Queue *q, Stream *s) 
{ 
1992/0319    
	if(Myip[Myself]) 
		error(Einuse); 
1991/1115    
	USED(q, s); 
1991/1027    
} 
 
1992/0320/sys/src/9/port/devarp.c:1,51992/0321/sys/src/9/port/devarp.c:1,5 (short | long)
Move lib.h to ../port.
rsc Fri Mar 4 12:44:25 2005
1991/0424    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0424    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/port/devarp.c:382,3901992/0325/sys/src/9/port/devarp.c:382,391 (short | long)
1991/1027    
void 
arpflush(void) 
{ 
	Arpcache *ap; 
1992/0325    
	Arpcache *ap, *ep; 
1991/1027    
 
	for(ap = arplruhead; ap; ap = ap->frwd) 
1992/0325    
	ep = &arp[conf.arp]; 
	for(ap = arp; ap < ep; ap++) 
1991/1027    
		ap->status = ARP_FREE; 
} 
 
1992/0321/sys/src/9/port/devarp.c:444,4651992/0325/sys/src/9/port/devarp.c:445,458
1991/1027    
arpdelete(char *addr) 
{ 
	Arpcache *ap; 
	char enetaddr[6], buf[20], *ptr; 
	int i; 
1992/0325    
	uchar ip[4]; 
	Ipaddr i; 
1991/1027    
 
	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; 
	} 
                 
1992/0325    
	i = ipparse(addr); 
	hnputl(ip, i);	 
1991/1029    
	lock(&larphash); 
1991/1027    
	for(ap = arplruhead; ap; ap = ap->frwd) { 
		if(memcmp(ap->et, ptr, sizeof(ap->et)) == 0) { 
1992/0325    
		if(memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) { 
1991/1027    
			ap->status = ARP_FREE; 
			break; 
		} 
1992/0321/sys/src/9/port/devarp.c:483,4891992/0325/sys/src/9/port/devarp.c:476,481
1991/1027    
		 
		ap->frwd = arplruhead; 
		ap->prev = 0; 
1992/0213    
                 
1991/1027    
		arplruhead = ap; 
	} 
} 
1992/0325/sys/src/9/port/devarp.c:447,4531992/0520/sys/src/9/port/devarp.c:447,455 (short | long)
1991/1027    
	Arpcache *ap; 
1992/0325    
	uchar ip[4]; 
	Ipaddr i; 
1992/0520    
	int rv; 
1991/1027    
 
1992/0520    
	rv = -1; 
1992/0325    
	i = ipparse(addr); 
	hnputl(ip, i);	 
1991/1029    
	lock(&larphash); 
1992/0325/sys/src/9/port/devarp.c:454,4631992/0520/sys/src/9/port/devarp.c:456,467
1991/1027    
	for(ap = arplruhead; ap; ap = ap->frwd) { 
1992/0325    
		if(memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) { 
1991/1027    
			ap->status = ARP_FREE; 
1992/0520    
			rv = 0; 
1991/1027    
			break; 
		} 
	} 
1991/1029    
	unlock(&larphash); 
1992/0520    
	return rv; 
1991/1027    
} 
 
void 
1992/0520/sys/src/9/port/devarp.c:332,3381992/0619/sys/src/9/port/devarp.c:332,338 (short | long)
1991/1030    
 
1992/0214    
	/* if ip broadcast, use ether bcast address */ 
	addr = nhgetl(eh->dst); 
1992/0304    
	if(addr == Myip[Mybcast] || addr == Myip[Mynet] 
1992/0619    
	if(Myip[Myself] == 0 || addr == Myip[Mybcast] || addr == Myip[Mynet] 
1992/0304    
	|| ((addr & Mymask) == Myip[Mynet+1] && (addr & ~Mynetmask) == ~Mynetmask)){ 
1992/0214    
		memset(eh->d, 0xff, sizeof(eh->d)); 
		PUTNEXT(q, bp); 
1992/0619/sys/src/9/port/devarp.c:94,1011992/0620/sys/src/9/port/devarp.c:94,101 (short | long)
1991/0424    
{ 
	Arpcache *ap, *ep; 
 
	arp = (Arpcache *)ialloc(sizeof(Arpcache) * conf.arp, 0); 
	arphash = (Arpcache **)ialloc(sizeof(Arpcache *) * Arphashsize, 0); 
1992/0620    
	arp = xalloc(sizeof(Arpcache) * conf.arp); 
	arphash = (Arpcache **)xalloc(sizeof(Arpcache *) * Arphashsize); 
1991/0424    
 
	ep = &arp[conf.arp]; 
	for(ap = arp; ap < ep; ap++) { 
1992/0620/sys/src/9/port/devarp.c:240,2461992/0623/sys/src/9/port/devarp.c:240,246 (short | long)
1991/0424    
		sprint(buf, "hits: %d miss: %d failed: %d\n", 
			arpstats.hit, arpstats.miss, arpstats.failed); 
 
1991/1115    
		return stringread(a, n, buf, offset); 
1992/0623    
		return readstr(offset, a, n, buf); 
1991/0424    
	default: 
		n=0; 
		break; 
1992/0623/sys/src/9/port/devarp.c:74,791992/0711/sys/src/9/port/devarp.c:74,82 (short | long)
1992/0213    
{ 
	Qid q; 
 
1992/0711    
	USED(vp); 
	USED(ntab); 
 
1992/0213    
	q.vers = 0; 
 
	/* top level directory contains the directory arp */ 
1992/0623/sys/src/9/port/devarp.c:200,2081992/0711/sys/src/9/port/devarp.c:203,211
1991/0424    
arpread(Chan *c, void *a, long n, ulong offset) 
{ 
	char	 buf[100]; 
	Arpcache *ap, *ep; 
1992/0711    
	Arpcache *ap; 
1991/0424    
	int	 part, bytes, size; 
	char	 *ptr, *ststr; 
1992/0711    
	char	 *ststr; 
1991/0424    
 
	switch((int)(c->qid.path&~CHDIR)){ 
	case arpdirqid: 
1992/0623/sys/src/9/port/devarp.c:254,2591992/0711/sys/src/9/port/devarp.c:257,264
1991/0424    
	Arpentry entry; 
	char	 buf[20], *field[5]; 
	int 	 m; 
1992/0711    
 
	USED(offset); 
1991/0424    
 
	switch(STREAMTYPE(c->qid.path)) { 
	case arpctlqid: 
1992/0711/sys/src/9/port/devarp.c:148,1551992/0819/sys/src/9/port/devarp.c:148,154 (short | long)
1991/0424    
Chan * 
arpopen(Chan *c, int omode) 
{ 
                 
	if(c->qid.path == CHDIR){ 
1992/0819    
	if(c->qid.path&CHDIR){ 
1991/0424    
		if(omode != OREAD) 
			error(Eperm); 
	} 
1992/0711/sys/src/9/port/devarp.c:165,1711992/0819/sys/src/9/port/devarp.c:164,169
1991/0424    
		break; 
	} 
 
                 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
1992/0711/sys/src/9/port/devarp.c:207,2151992/0819/sys/src/9/port/devarp.c:205,214
1991/0424    
	int	 part, bytes, size; 
1992/0711    
	char	 *ststr; 
1991/0424    
 
1992/0819    
	if(c->qid.path&CHDIR) 
		return devdirread(c, a, n, arptab, Narptab, arpgen); 
 
1991/0424    
	switch((int)(c->qid.path&~CHDIR)){ 
	case arpdirqid: 
1992/0213    
		return devdirread(c, a, n, 0, 0, arpgen); 
1991/0424    
	case arpdataqid: 
		bytes = c->offset; 
		while(bytes < conf.arp*ARP_ENTRYLEN && n) { 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)