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

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

1991/1028/sys/src/9/port/devarp.c:9,441991/1029/sys/src/9/port/devarp.c:9,50 (short | long | prev | next)
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 


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