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

📄 ethermedium.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(!canrlock(ifc)){			freeb(bp);			continue;		}		if(waserror()){			runlock(ifc);			nexterror();		}		ifc->in++;		bp->rp += ifc->m->hsize;		if(ifc->lifc == nil)			freeb(bp);		else			ipiput6(er->f, ifc, bp);		runlock(ifc);		poperror();	}}static voidetheraddmulti(Ipifc *ifc, uchar *a, uchar *){	uchar mac[6];	char buf[64];	Etherrock *er = ifc->arg;	int version;	version = multicastea(mac, a);	sprint(buf, "addmulti %E", mac);	switch(version){	case V4:		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);		break;	case V6:		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);		break;	default:		panic("etheraddmulti: version %d", version);	}}static voidetherremmulti(Ipifc *ifc, uchar *a, uchar *){	uchar mac[6];	char buf[64];	Etherrock *er = ifc->arg;	int version;	version = multicastea(mac, a);	sprint(buf, "remmulti %E", mac);	switch(version){	case V4:		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);		break;	case V6:		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);		break;	default:		panic("etherremmulti: version %d", version);	}}/* *  send an ethernet arp *  (only v4, v6 uses the neighbor discovery, rfc1970) */static voidsendarp(Ipifc *ifc, Arpent *a){	int n;	Block *bp;	Etherarp *e;	Etherrock *er = ifc->arg;	/* don't do anything if it's been less than a second since the last */	if(NOW - a->ctime < 1000){		arprelease(er->f->arp, a);		return;	}	/* remove all but the last message */	while((bp = a->hold) != nil){		if(bp == a->last)			break;		a->hold = bp->list;		freeblist(bp);	}	/* try to keep it around for a second more */	a->ctime = NOW;	arprelease(er->f->arp, a);	n = sizeof(Etherarp);	if(n < a->type->mintu)		n = a->type->mintu;	bp = allocb(n);	memset(bp->rp, 0, n);	e = (Etherarp*)bp->rp;	memmove(e->tpa, a->ip+IPv4off, sizeof(e->tpa));	ipv4local(ifc, e->spa);	memmove(e->sha, ifc->mac, sizeof(e->sha));	memset(e->d, 0xff, sizeof(e->d));		/* ethernet broadcast */	memmove(e->s, ifc->mac, sizeof(e->s));	hnputs(e->type, ETARP);	hnputs(e->hrd, 1);	hnputs(e->pro, ETIP4);	e->hln = sizeof(e->sha);	e->pln = sizeof(e->spa);	hnputs(e->op, ARPREQUEST);	bp->wp += n;	n = devtab[er->achan->type]->bwrite(er->achan, bp, 0);	if(n < 0)		print("arp: send: %r\n");}static voidresolveaddr6(Ipifc *ifc, Arpent *a){	int sflag;	Block *bp;	Etherrock *er = ifc->arg;	uchar ipsrc[IPaddrlen];	/* don't do anything if it's been less than a second since the last */	if(NOW - a->ctime < ReTransTimer){		arprelease(er->f->arp, a);		return;	}	/* remove all but the last message */	while((bp = a->hold) != nil){		if(bp == a->last)			break;		a->hold = bp->list;		freeblist(bp);	}	/* try to keep it around for a second more */	a->ctime = NOW;	a->rtime = NOW + ReTransTimer;	if(a->rxtsrem <= 0) {		arprelease(er->f->arp, a);		return;	}	a->rxtsrem--;	arprelease(er->f->arp, a);	if(sflag = ipv6anylocal(ifc, ipsrc)) 		icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);}/* *  send a gratuitous arp to refresh arp caches */static voidsendgarp(Ipifc *ifc, uchar *ip){	int n;	Block *bp;	Etherarp *e;	Etherrock *er = ifc->arg;	/* don't arp for our initial non address */	if(ipcmp(ip, IPnoaddr) == 0)		return;	n = sizeof(Etherarp);	if(n < ifc->m->mintu)		n = ifc->m->mintu;	bp = allocb(n);	memset(bp->rp, 0, n);	e = (Etherarp*)bp->rp;	memmove(e->tpa, ip+IPv4off, sizeof(e->tpa));	memmove(e->spa, ip+IPv4off, sizeof(e->spa));	memmove(e->sha, ifc->mac, sizeof(e->sha));	memset(e->d, 0xff, sizeof(e->d));		/* ethernet broadcast */	memmove(e->s, ifc->mac, sizeof(e->s));	hnputs(e->type, ETARP);	hnputs(e->hrd, 1);	hnputs(e->pro, ETIP4);	e->hln = sizeof(e->sha);	e->pln = sizeof(e->spa);	hnputs(e->op, ARPREQUEST);	bp->wp += n;	n = devtab[er->achan->type]->bwrite(er->achan, bp, 0);	if(n < 0)		print("garp: send: %r\n");}static voidrecvarp(Ipifc *ifc){	int n;	Block *ebp, *rbp;	Etherarp *e, *r;	uchar ip[IPaddrlen];	static uchar eprinted[4];	Etherrock *er = ifc->arg;	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);	if(ebp == nil) {		print("arp: rcv: %r\n");		return;	}	e = (Etherarp*)ebp->rp;	switch(nhgets(e->op)) {	default:		break;	case ARPREPLY:		/* check for machine using my ip address */		v4tov6(ip, e->spa);		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){				print("arprep: 0x%E/0x%E also has ip addr %V\n",					e->s, e->sha, e->spa);				break;			}		}		/* make sure we're not entering broadcast addresses */		if(ipcmp(ip, ipbroadcast) == 0 ||			!memcmp(e->sha, etherbroadcast, sizeof(e->sha))){			print("arprep: 0x%E/0x%E cannot register broadcast address %I\n",				e->s, e->sha, e->spa);			break;		}		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0);		break;	case ARPREQUEST:		/* don't answer arps till we know who we are */		if(ifc->lifc == 0)			break;		/* check for machine using my ip or ether address */		v4tov6(ip, e->spa);		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){				if (memcmp(eprinted, e->spa, sizeof(e->spa))){					/* print only once */					print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa);					memmove(eprinted, e->spa, sizeof(e->spa));				}			}		} else {			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){				print("arpreq: %V also has ether addr %E\n", e->spa, e->sha);				break;			}		}		/* refresh what we know about sender */		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1);		/* answer only requests for our address or systems we're proxying for */		v4tov6(ip, e->tpa);		if(!iplocalonifc(ifc, ip))		if(!ipproxyifc(er->f, ifc, ip))			break;		n = sizeof(Etherarp);		if(n < ifc->mintu)			n = ifc->mintu;		rbp = allocb(n);		r = (Etherarp*)rbp->rp;		memset(r, 0, sizeof(Etherarp));		hnputs(r->type, ETARP);		hnputs(r->hrd, 1);		hnputs(r->pro, ETIP4);		r->hln = sizeof(r->sha);		r->pln = sizeof(r->spa);		hnputs(r->op, ARPREPLY);		memmove(r->tha, e->sha, sizeof(r->tha));		memmove(r->tpa, e->spa, sizeof(r->tpa));		memmove(r->sha, ifc->mac, sizeof(r->sha));		memmove(r->spa, e->tpa, sizeof(r->spa));		memmove(r->d, e->sha, sizeof(r->d));		memmove(r->s, ifc->mac, sizeof(r->s));		rbp->wp += n;		n = devtab[er->achan->type]->bwrite(er->achan, rbp, 0);		if(n < 0)			print("arp: write: %r\n");	}	freeb(ebp);}static voidrecvarpproc(void *v){	Ipifc *ifc = v;	Etherrock *er = ifc->arg;	er->arpp = up;	if(waserror()){		er->arpp = 0;		pexit("hangup", 1);	}	for(;;)		recvarp(ifc);}static intmulticastea(uchar *ea, uchar *ip){	int x;	switch(x = ipismulticast(ip)){	case V4:		ea[0] = 0x01;		ea[1] = 0x00;		ea[2] = 0x5e;		ea[3] = ip[13] & 0x7f;		ea[4] = ip[14];		ea[5] = ip[15];		break; 	case V6: 		ea[0] = 0x33; 		ea[1] = 0x33; 		ea[2] = ip[12];		ea[3] = ip[13]; 		ea[4] = ip[14]; 		ea[5] = ip[15]; 		break;	}	return x;}/* *  fill in an arp entry for broadcast or multicast *  addresses.  Return the first queued packet for the *  IP address. */static Block*multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac){	/* is it broadcast? */	switch(ipforme(f, a->ip)){	case Runi:		return nil;	case Rbcast:		memset(mac, 0xff, 6);		return arpresolve(f->arp, a, medium, mac);	default:		break;	}	/* if multicast, fill in mac */	switch(multicastea(mac, a->ip)){	case V4:	case V6:		return arpresolve(f->arp, a, medium, mac);	}	/* let arp take care of it */	return nil;}voidethermediumlink(void){	addipmedium(&ethermedium);	addipmedium(&gbemedium);}static void etherpref2addr(uchar *pref, uchar *ea){	pref[8]  = ea[0] | 0x2;	pref[9]  = ea[1];	pref[10] = ea[2];	pref[11] = 0xFF;	pref[12] = 0xFE;	pref[13] = ea[3];	pref[14] = ea[4];	pref[15] = ea[5];}

⌨️ 快捷键说明

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