⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "all.h"#include "../ip/ip.h"#define	DEBUG	if(cons.flags&arpcache.flag)print#define	ORDER	1	/* 1 send last frag first, faster */typedef struct	Arpentry	Arpentry;typedef struct	Arpstats	Arpstats;typedef	struct	Arpe		Arpe;struct	Arpe{	uchar	tpa[Pasize];	uchar	tha[Easize];};static	int	ipahash(uchar*);static	void	cmd_arp(int, char*[]);staticstruct{	Lock;	uchar	null[Pasize];	int	start;	int	idgen;	ulong	flag;	Msgbuf*	unresol;	struct	{		int	laste;		Arpe	arpe[Ne];	} abkt[Nb];} arpcache;intnhgets(uchar *p){	return (p[0]<<8) | p[1];}longnhgetl(uchar *p){	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];}voidhnputs(uchar *p, int x){	p[0] = x>>8;	p[1] = x;}voidhnputl(uchar *p, long x){	p[0] = x>>24;	p[1] = x>>16;	p[2] = x>>8;	p[3] = x;}voidarpstart(void){	if(arpcache.start == 0) {		lock(&arpcache);		if(arpcache.start == 0) {			cmd_install("arp", "subcommand -- arp protocol", cmd_arp);			arpcache.flag = flag_install("arp", "-- verbose");			arpcache.start = 1;			iprouteinit();		}		unlock(&arpcache);	}}voidarpreceive(Enpkt *ep, int l, Ifc *ifc){	Ilp* ilp;	Arppkt *p, *q;	Msgbuf *mb, **mbp;	Arpe *a;	uchar *tpa;	int type, i, h;	Timet t;	if(l < Ensize+Arpsize)		return;	p = (Arppkt*)ep;	if(nhgets(p->pro) != Iptype ||	   nhgets(p->hrd) != 1 ||	   p->pln != Pasize ||	   p->hln != Easize)		return;	type = nhgets(p->op);	switch(type) {	case Arprequest:		/* update entry for this source */		h = ipahash(p->spa);		a = arpcache.abkt[h].arpe;		lock(&arpcache);		for(i=0; i<Ne; i++,a++) {			if(memcmp(a->tpa, p->spa, Pasize) == 0) {				memmove(a->tha, p->sha, Easize);				break;			}		}		unlock(&arpcache);		if(memcmp(p->tpa, ifc->ipa, Pasize) != 0)			break;		DEBUG("rcv arp req for %I from %I\n", p->tpa, p->spa);		mb = mballoc(Ensize+Arpsize, 0, Mbarp1);		q = (Arppkt*)mb->data;		memmove(q, p, Ensize+Arpsize);		hnputs(q->op, Arpreply);		memmove(q->tha, p->sha, Easize);		memmove(q->tpa, p->spa, Pasize);		memmove(q->sha, ifc->ea, Easize);		memmove(q->spa, ifc->ipa, Pasize);		memmove(q->d, q->s, Easize);		send(ifc->reply, mb);		break;	case Arpreply:		DEBUG("rcv arp rpl for %I is %E\n", p->spa, p->sha);		h = ipahash(p->spa);		a = arpcache.abkt[h].arpe;		lock(&arpcache);		for(i=0; i<Ne; i++,a++) {			if(memcmp(a->tpa, p->spa, Pasize) == 0) {				memmove(a->tha, p->sha, Easize);				goto out;			}		}		i = arpcache.abkt[h].laste + 1;		if(i < 0 || i >= Ne)			i = 0;		arpcache.abkt[h].laste = i;		a = &arpcache.abkt[h].arpe[i];		memmove(a->tpa, p->spa, Pasize);		memmove(a->tha, p->sha, Easize);		/*		 * go thru unresolved queue		 */	out:		t = toytime();		mbp = &arpcache.unresol;		for(mb = *mbp; mb; mb = *mbp) {			if(t >= mb->param) {				*mbp = mb->next;				unlock(&arpcache);				mbfree(mb);				lock(&arpcache);				goto out;			}			ilp = mb->chan->pdata;			tpa = ilp->ipgate;			if(memcmp(a->tpa, tpa, Pasize) == 0) {				*mbp = mb->next;				mb->next = 0;				unlock(&arpcache);				ipsend(mb);				lock(&arpcache);				goto out;			}			mbp = &mb->next;		}		unlock(&arpcache);		break;	}}staticintipahash(uchar *p){	ulong h;	h = p[0];	h = h*7 + p[1];	h = h*7 + p[2];	h = h*7 + p[3];	return h%Nb;}voidipsend1(Msgbuf *mb, Ifc *ifc, uchar *ipgate){	Msgbuf **mbp, *m;	Ippkt *p;	Arppkt *q;	Arpe *a;	int i, id, len, dlen, off;	Timet t;	p = (Ippkt*)mb->data;	a = arpcache.abkt[ipahash(ipgate)].arpe;	lock(&arpcache);	for(i=0; i<Ne; i++,a++)		if(memcmp(a->tpa, ipgate, Pasize) == 0)			goto found;	/*	 * queue ip pkt to be resolved later	 */again:	i = 0;		// q length	t = toytime();	mbp = &arpcache.unresol;	for(m = *mbp; m; m = *mbp) {		if(t >= m->param) {			*mbp = m->next;			unlock(&arpcache);			mbfree(m);			lock(&arpcache);			goto again;		}		mbp = &m->next;		i++;	}	if(mb->chan && i < 10) {		mb->param = t + SECOND(10);		mb->next = 0;		*mbp = mb;		unlock(&arpcache);	} else {		unlock(&arpcache);		mbfree(mb);	}	/*	 * send an arp request	 */	m = mballoc(Ensize+Arpsize, 0, Mbarp2);	q = (Arppkt*)m->data;	DEBUG("snd arp req target %I ip dest %I\n", ipgate, p->dst);	memset(q->d, 0xff, Easize);		/* broadcast */	hnputs(q->type, Arptype);	hnputs(q->hrd, 1);	hnputs(q->pro, Iptype);	q->hln = Easize;	q->pln = Pasize;	hnputs(q->op, Arprequest);	memmove(q->sha, ifc->ea, Easize);	memmove(q->spa, ifc->ipa, Pasize);	memset(q->tha, 0, Easize);	memmove(q->tpa, ipgate, Pasize);	send(ifc->reply, m);	return;found:	len = mb->count;		/* includes Ensize+Ipsize+Ilsize */	memmove(p->d, a->tha, Easize);	p->vihl = IP_VER|IP_HLEN;	p->tos = 0;	p->ttl = 255;	id = arpcache.idgen;	if(id == 0)		id = toytime() * 80021;	arpcache.idgen = id+1;	unlock(&arpcache);	hnputs(p->id, id);	hnputs(p->type, Iptype);	/*	 * If we dont need to fragment just send it	 */	if(len <= ETHERMAXTU) {		hnputs(p->length, len-Ensize);		p->frag[0] = 0;		p->frag[1] = 0;		p->cksum[0] = 0;		p->cksum[1] = 0;		hnputs(p->cksum, ipcsum(&p->vihl));		send(ifc->reply, mb);		return;	}	off = 0;	len -= Ensize+Ipsize;		/* just ip data */	while(len > 0) {		dlen = (ETHERMAXTU-(Ensize+Ipsize)) & ~7;		if(dlen > len)			dlen = len;		len -= dlen;		/*		 * use first frag in place,		 * make copies of subsequent frags		 * this saves a copy of a MTU-size buffer		 */		if(ORDER && off == 0) {			m = 0;			mb->count = (Ensize+Ipsize)+dlen;			p = (Ippkt*)mb->data;		} else {			m = mballoc((Ensize+Ipsize)+dlen, 0, Mbip1);			p = (Ippkt*)m->data;			memmove(m->data, mb->data, Ensize+Ipsize);			memmove(m->data+(Ensize+Ipsize),				mb->data+(Ensize+Ipsize)+off, dlen);		}		hnputs(p->length, dlen+Ipsize);		if(len == 0)			hnputs(p->frag, off>>3);		else			hnputs(p->frag, (off>>3)|IP_MF);		p->cksum[0] = 0;		p->cksum[1] = 0;		hnputs(p->cksum, ipcsum(&p->vihl));		if(m)			send(ifc->reply, m);		off += dlen;	}	if(ORDER)		send(ifc->reply, mb);	else		mbfree(mb);}voidipsend(Msgbuf *mb){	Ilp *ilp;	Chan *cp;	cp = mb->chan;	if(cp == 0) {		print("cp = 0\n");		mbfree(mb);		return;	}	ilp = cp->pdata;	ipsend1(mb, cp->ifc, ilp->ipgate);}intipforme(uchar addr[Pasize], Ifc *ifc){	ulong haddr;	if(memcmp(addr, ifc->ipa, Pasize) == 0)		return 1;	haddr = nhgetl(addr);	/* My subnet broadcast */	if((haddr&ifc->mask) == (ifc->ipaddr&ifc->mask))		return 1;	/* Real ip broadcast */	if(haddr == 0)		return 1;	/* Old style 255.255.255.255 address */	if(haddr == ~0)		return 1;	return 0;}/* * ipcsum - Compute internet header checksums */intipcsum(uchar *addr){	int len;	ulong sum = 0;	len = (addr[0]&0xf) << 2;	while(len > 0) {		sum += (addr[0]<<8) | addr[1] ;		len -= 2;		addr += 2;	}	sum = (sum & 0xffff) + (sum >> 16);	sum = (sum & 0xffff) + (sum >> 16);	return sum^0xffff;}/*  * protcol checksum routine */static	short	endian	= 1;static	char*	aendian	= (char*)&endian;#define	LITTLE	*aendianintptclcsum(uchar *addr, int len){	ulong losum, hisum, mdsum, x;	ulong t1, t2;	losum = 0;	hisum = 0;	mdsum = 0;	x = 0;	if((ulong)addr & 1) {		if(len) {			hisum += addr[0];			len--;			addr++;		}		x = 1;	}	while(len >= 16) {		t1 = *(ushort*)(addr+0);		t2 = *(ushort*)(addr+2);	mdsum += t1;		t1 = *(ushort*)(addr+4);	mdsum += t2;		t2 = *(ushort*)(addr+6);	mdsum += t1;		t1 = *(ushort*)(addr+8);	mdsum += t2;		t2 = *(ushort*)(addr+10);	mdsum += t1;		t1 = *(ushort*)(addr+12);	mdsum += t2;		t2 = *(ushort*)(addr+14);	mdsum += t1;		mdsum += t2;		len -= 16;		addr += 16;	}	while(len >= 2) {		mdsum += *(ushort*)addr;		len -= 2;		addr += 2;	}	if(x) {		if(len)			losum += addr[0];		if(LITTLE)			losum += mdsum;		else			hisum += mdsum;	} else {		if(len)			hisum += addr[0];		if(LITTLE)			hisum += mdsum;		else			losum += mdsum;	}	losum += hisum >> 8;	losum += (hisum & 0xff) << 8;	while(hisum = losum>>16)		losum = hisum + (losum & 0xffff);	return ~losum & 0xffff;}staticvoidcmd_arp(int argc, char *argv[]){	int h, i, j;	Arpe *a;	if(argc <= 1) {		print("arp flush -- clear cache\n");		print("arp print -- print cache\n");		return;	}	for(i=1; i<argc; i++) {		if(strcmp(argv[i], "flush") == 0) {			lock(&arpcache);			for(h=0; h<Nb; h++)				memset(&arpcache.abkt[h], 0, sizeof(arpcache.abkt[0]));			unlock(&arpcache);			continue;		}		if(strcmp(argv[i], "print") == 0) {			for(h=0; h<Nb; h++) {				a = arpcache.abkt[h].arpe;				for(j=0; j<Ne; j++,a++) {					if(memcmp(arpcache.null, a->tpa, Pasize) == 0)						continue;					print("%-15I %E\n", a->tpa, a->tha);					prflush();				}			}			continue;		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -