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

📄 ethermedium.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "ip.h"#include "ipv6.h"typedef struct Etherhdr Etherhdr;struct Etherhdr{	uchar	d[6];	uchar	s[6];	uchar	t[2];};static uchar ipbroadcast[IPaddrlen] = {	0xff,0xff,0xff,0xff,  	0xff,0xff,0xff,0xff,  	0xff,0xff,0xff,0xff,  	0xff,0xff,0xff,0xff,};static uchar etherbroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };static void	etherread4(void *a);static void	etherread6(void *a);static void	etherbind(Ipifc *ifc, int argc, char **argv);static void	etherunbind(Ipifc *ifc);static void	etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);static void	etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);static void	etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);static Block*	multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);static void	sendarp(Ipifc *ifc, Arpent *a);static void	sendgarp(Ipifc *ifc, uchar*);static int	multicastea(uchar *ea, uchar *ip);static void	recvarpproc(void*);static void	resolveaddr6(Ipifc *ifc, Arpent *a);static void	etherpref2addr(uchar *pref, uchar *ea);Medium ethermedium ={.name=		"ether",.hsize=		14,.mintu=		60,.maxtu=		1514,.maclen=	6,.bind=		etherbind,.unbind=	etherunbind,.bwrite=	etherbwrite,.addmulti=	etheraddmulti,.remmulti=	etherremmulti,.ares=		arpenter,.areg=		sendgarp,.pref2addr=	etherpref2addr,};Medium gbemedium ={.name=		"gbe",.hsize=		14,.mintu=		60,.maxtu=		9014,.maclen=	6,.bind=		etherbind,.unbind=	etherunbind,.bwrite=	etherbwrite,.addmulti=	etheraddmulti,.remmulti=	etherremmulti,.ares=		arpenter,.areg=		sendgarp,.pref2addr=	etherpref2addr,};typedef struct	Etherrock Etherrock;struct Etherrock{	Fs	*f;		/* file system we belong to */	Proc	*arpp;		/* arp process */	Proc	*read4p;	/* reading process (v4)*/	Proc	*read6p;	/* reading process (v6)*/	Chan	*mchan4;	/* Data channel for v4 */	Chan	*achan;		/* Arp channel */	Chan	*cchan4;	/* Control channel for v4 */	Chan	*mchan6;	/* Data channel for v6 */	Chan	*cchan6;	/* Control channel for v6 */};/* *  ethernet arp request */enum{	ETARP		= 0x0806,	ETIP4		= 0x0800,	ETIP6		= 0x86DD,	ARPREQUEST	= 1,	ARPREPLY	= 2,};typedef struct Etherarp Etherarp;struct Etherarp{	uchar	d[6];	uchar	s[6];	uchar	type[2];	uchar	hrd[2];	uchar	pro[2];	uchar	hln;	uchar	pln;	uchar	op[2];	uchar	sha[6];	uchar	spa[4];	uchar	tha[6];	uchar	tpa[4];};static char *nbmsg = "nonblocking";/* *  called to bind an IP ifc to an ethernet device *  called with ifc wlock'd */static voidetherbind(Ipifc *ifc, int argc, char **argv){	Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan;	char addr[Maxpath];	//char addr[2*KNAMELEN];	char dir[Maxpath];	//char dir[2*KNAMELEN];	char *buf;	int n;	char *ptr;	Etherrock *er;	if(argc < 2)		error(Ebadarg);	mchan4 = cchan4 = achan = mchan6 = cchan6 = nil;	buf = nil;	if(waserror()){		if(mchan4 != nil)			cclose(mchan4);		if(cchan4 != nil)			cclose(cchan4);		if(achan != nil)			cclose(achan);		if(mchan6 != nil)			cclose(mchan6);		if(cchan6 != nil)			cclose(cchan6);		if(buf != nil)			free(buf);		nexterror(); 	}	/*	 *  open ip converstation	 *	 *  the dial will fail if the type is already open on	 *  this device.	 */	snprint(addr, sizeof(addr), "%s!0x800", argv[2]);	mchan4 = chandial(addr, nil, dir, &cchan4);	/*	 *  make it non-blocking	 */	devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);	/*	 *  get mac address and speed	 */	snprint(addr, sizeof(addr), "%s/stats", argv[2]);	buf = smalloc(512);	schan = namec(addr, Aopen, OREAD, 0);	if(waserror()){		cclose(schan);		nexterror();	}	n = devtab[schan->type]->read(schan, buf, 511, 0);	cclose(schan);	poperror();	buf[n] = 0;	ptr = strstr(buf, "addr: ");	if(!ptr)		error(Eio);	ptr += 6;	parsemac(ifc->mac, ptr, 6);	ptr = strstr(buf, "mbps: ");	if(ptr){		ptr += 6;		ifc->mbps = atoi(ptr);	} else		ifc->mbps = 100;	/* 	 *  open arp conversation	 */	snprint(addr, sizeof(addr), "%s!0x806", argv[2]);	achan = chandial(addr, nil, nil, nil);	/*	 *  open ip conversation	 *	 *  the dial will fail if the type is already open on	 *  this device.	 */	snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]);	mchan6 = chandial(addr, nil, dir, &cchan6);	/*	 *  make it non-blocking	 */	devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);	er = smalloc(sizeof(*er));	er->mchan4 = mchan4;	er->cchan4 = cchan4;	er->achan = achan;	er->mchan6 = mchan6;	er->cchan6 = cchan6;	er->f = ifc->conv->p->f;	ifc->arg = er;	free(buf);	poperror();	kproc("etherread4", etherread4, ifc);	kproc("recvarpproc", recvarpproc, ifc);	kproc("etherread6", etherread6, ifc);}/* *  called with ifc wlock'd */static voidetherunbind(Ipifc *ifc){	Etherrock *er = ifc->arg;	if(er->read4p)		postnote(er->read4p, 1, "unbind", 0);	if(er->read6p)		postnote(er->read6p, 1, "unbind", 0);	if(er->arpp)		postnote(er->arpp, 1, "unbind", 0);	/* wait for readers to die */	while(er->arpp != 0 || er->read4p != 0 || er->read6p != 0)		tsleep(&up->sleep, return0, 0, 300);	if(er->mchan4 != nil)		cclose(er->mchan4);	if(er->achan != nil)		cclose(er->achan);	if(er->cchan4 != nil)		cclose(er->cchan4);	if(er->mchan6 != nil)		cclose(er->mchan6);	if(er->cchan6 != nil)		cclose(er->cchan6);	free(er);}/* *  called by ipoput with a single block to write with ifc rlock'd */static voidetherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip){	Etherhdr *eh;	Arpent *a;	uchar mac[6];	Etherrock *er = ifc->arg;	/* get mac address of destination */	a = arpget(er->f->arp, bp, version, ifc, ip, mac);	if(a){		/* check for broadcast or multicast */		bp = multicastarp(er->f, a, ifc->m, mac);		if(bp==nil){			switch(version){			case V4:				sendarp(ifc, a);				break;			case V6: 				resolveaddr6(ifc, a);				break;			default:				panic("etherbwrite: version %d", version);			}			return;		}	}	/* make it a single block with space for the ether header */	bp = padblock(bp, ifc->m->hsize);	if(bp->next)		bp = concatblock(bp);	if(BLEN(bp) < ifc->mintu)		bp = adjustblock(bp, ifc->mintu);	eh = (Etherhdr*)bp->rp;	/* copy in mac addresses and ether type */	memmove(eh->s, ifc->mac, sizeof(eh->s));	memmove(eh->d, mac, sizeof(eh->d)); 	switch(version){	case V4:		eh->t[0] = 0x08;		eh->t[1] = 0x00;		devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0);		break;	case V6:		eh->t[0] = 0x86;		eh->t[1] = 0xDD;		devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0);		break;	default:		panic("etherbwrite2: version %d", version);	}	ifc->out++;}/* *  process to read from the ethernet */static voidetherread4(void *a){	Ipifc *ifc;	Block *bp;	Etherrock *er;	ifc = a;	er = ifc->arg;	er->read4p = up;	/* hide identity under a rock for unbind */	if(waserror()){		er->read4p = 0;		pexit("hangup", 1);	}	for(;;){		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);		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			ipiput4(er->f, ifc, bp);		runlock(ifc);		poperror();	}}/* *  process to read from the ethernet, IPv6 */static voidetherread6(void *a){	Ipifc *ifc;	Block *bp;	Etherrock *er;	ifc = a;	er = ifc->arg;	er->read6p = up;	/* hide identity under a rock for unbind */	if(waserror()){		er->read6p = 0;		pexit("hangup", 1);	}	for(;;){		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);

⌨️ 快捷键说明

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