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

📄 tripmedium.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "ip.h"#include "trip.h"static void	tripread(void *a);static void	tripbind(Ipifc *ifc, int argc, char **argv);static void	tripunbind(Ipifc *ifc);static void	tripbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);static void	tripaddmulti(Ipifc *ifc, uchar*, uchar*);static void	tripremmulti(Ipifc *ifc, uchar*, uchar*);static void	tripaddroute(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);static void	tripremroute(Ipifc *ifc, int, uchar*, uchar*);static void	tripares(Fs*, int, uchar*, uchar*, int, int);Medium tripmedium ={.name=		"trip",.mintu=	20,.maxtu=	64*1024,.maclen=	LCIMACSIZE,.bind=		tripbind,.unbind=	tripunbind,.bwrite=	tripbwrite,.addmulti=	tripaddmulti,.remmulti=	tripremmulti,.addroute=	tripaddroute,.remroute=	tripremroute,.ares=		tripares,};typedef struct	Tripinfo Tripinfo;struct Tripinfo{	Fs*	fs;		/* my instance of the IP stack */	Ipifc*	ifc;		/* IP interface */	Card*	dev;	Proc*	readp;		/* reading process */	Chan*	mchan;		/* Data channel */};/* *  called to bind an IP ifc to an ethernet device *  called with ifc qlock'd */static voidtripbind(Ipifc *ifc, int argc, char **argv){	int fd;	Chan *mchan;	Tripinfo *er;	if(argc < 2)		error(Ebadarg);	fd = kopen(argv[2], ORDWR);	if(fd < 0)		error("trip open failed");	mchan = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);	kclose(fd);	if(devtab[mchan->type]->dc != 'T') {		cclose(mchan);		error(Enoport);	}	er = smalloc(sizeof(*er));	er->mchan = mchan;	er->ifc = ifc;	er->dev = tripsetifc(mchan, ifc);	er->fs = ifc->conv->p->f;	ifc->arg = er;	kproc("tripread", tripread, ifc);}/* *  called with ifc qlock'd */static voidtripunbind(Ipifc *ifc){	Tripinfo *er = ifc->arg;/*	if(er->readp)		postnote(er->readp, 1, "unbind", 0);*/	tsleep(&up->sleep, return0, 0, 300);	if(er->mchan != nil)		cclose(er->mchan);	free(er);}/* *  called by ipoput with a single block to write */static voidtripbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip){	Tripinfo *er = ifc->arg;	/*	 * Packet is rerouted at linecard	 * so the gateway is ignored	 */	USED(ip);	USED(version);	if(waserror()) {		print("tripwrite failed\n");		return;	}	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);	poperror();	ifc->out++;}/* *  process to read from the trip interface */static voidtripread(void *a){	Ipifc *ifc;	Block *bp;	Tripinfo *er;	ifc = a;	er = ifc->arg;	er->readp = up;	/* hide identity under a rock for unbind */	for(;;) {		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);		ifc->in++;		ipiput4(er->fs, ifc, bp);	}	pexit("hangup", 1);}static voidtripaddroute(Ipifc *ifc, int v, uchar *addr, uchar *mask, uchar *gate, int t){	int alen;	MTroute mtr;	Tripinfo *tinfo;	tinfo = ifc->arg;	if(!tinfo->dev->routing)		return;	/*	 * Multicast addresses are handled on the linecard by	 * the multicast port driver, so the route load is dumped.	 *	loaded by addmulti/remmulti for SBC routes	 *		  joinmulti/leavemulti for inter LC	 */	if(ipismulticast(addr))		return;	mtr.type = T_ROUTEADMIN;	if(v & Rv4) {		mtr.op = RTADD4;		alen = IPv4addrlen;	}	else {		mtr.op = RTADD6;		alen = IPaddrlen;	}	mtr.rtype = t;	memmove(mtr.addr, addr, alen);	memmove(mtr.mask, mask, alen);	memmove(mtr.gate, gate, alen);	i2osend(tinfo->dev, &mtr, sizeof(mtr));}static voidtripremroute(Ipifc *ifc, int v, uchar *addr, uchar *mask){	int alen;	MTroute mtr;	Tripinfo *tinfo;	tinfo = ifc->arg;	if(!tinfo->dev->routing)		return;	if(ipismulticast(addr))		return;	mtr.type = T_ROUTEADMIN;	if(v & Rv4) {		mtr.op = RTDEL4;		alen = IPv4addrlen;	}	else {		mtr.op = RTDEL6;		alen = IPaddrlen;	}	memmove(mtr.addr, addr, alen);	memmove(mtr.mask, mask, alen);	i2osend(tinfo->dev, &mtr, sizeof(mtr));}static voidtripxmitroute(Route *r, Routewalk *rw){	int nifc;	char t[5];	uchar a[IPaddrlen], m[IPaddrlen], g[IPaddrlen];	convroute(r, a, m, g, t, &nifc);	if(!(r->type & Rv4)) {		tripaddroute(rw->state, 0, a, m, g, r->type);		return;	}	tripaddroute(rw->state, Rv4, a+IPv4off, m+IPv4off, g+IPv4off, r->type);}static voidsendifcinfo(Ipifc *dest){	Conv **cp, **e;	Iplifc *l;	Ipifc *ifc;	MTifctl mtc;	Tripinfo *tinfo, *oinfo;	Proto *p;	tinfo = dest->arg;	/* Install interfaces */	p = tinfo->fs->ipifc;	e = &p->conv[p->nc];	for(cp = p->conv; cp < e; cp++) {		if(*cp == nil)			continue;		ifc = (Ipifc*)(*cp)->ptcl;		if(dest == ifc)			continue;		mtc.type = T_CTLIFADMIN;		mtc.maxtu = ifc->maxtu;		mtc.mintu = ifc->mintu;		mtc.port = 0;		if(ifc->m == &tripmedium) {			oinfo = ifc->arg;			mtc.port = oinfo->dev->bar[0].bar;		}		for(l = ifc->lifc; l != nil; l = l->next) {			if(isv4(l->local)) {				mtc.op = IFADD4;				memmove(mtc.addr, l->local+IPv4off, IPv4addrlen);				memmove(mtc.mask, l->mask+IPv4off, IPv4addrlen);			}			else {				mtc.op = IFADD6;				memmove(mtc.addr, l->local, sizeof(mtc.addr));				memmove(mtc.mask, l->mask, sizeof(mtc.mask));			}			i2osend(tinfo->dev, &mtc, sizeof(mtc));		}	}}voidtripsync(Ipifc *ifc){	Routewalk rw;	if(ifc == nil) {		print("tripsync: interface not bound\n");		return;	}	/* Mirror the route table into the lincard */	rw.o = 0;	rw.n = (1<<22);	rw.state = ifc;	rw.walk = tripxmitroute;	ipwalkroutes(ifc->conv->p->f, &rw);	/*	 * Tell the linecard about interfaces that already	 * exist elsewhere	 */	sendifcinfo(ifc);}/* Tell a line card the SBC is interested in listening * to a multicast address */static voidtripaddmulti(Ipifc *ifc, uchar *addr, uchar *ifca){	MTmultiears mt;	Tripinfo *tinfo;	/* print("tripaddmulti %I %I\n", addr, ifca); /**/	tinfo = ifc->arg;	if(!tinfo->dev->routing)		return;	mt.type = T_MULTIEAR;	mt.op = ADDMULTI;	memmove(mt.addr, addr, sizeof(mt.addr));	memmove(mt.ifca, ifca, sizeof(mt.ifca));	i2osend(tinfo->dev, &mt, sizeof(mt));}/* Tell a line card the SBC is no longer interested in listening * to a multicast address */static voidtripremmulti(Ipifc *ifc, uchar *addr, uchar *ifca){	MTmultiears mt;	Tripinfo *tinfo;	tinfo = ifc->arg;	if(!tinfo->dev->routing)		return;	mt.type = T_MULTIEAR;	mt.op = REMMULTI;	memmove(mt.addr, addr, sizeof(mt.addr));	memmove(mt.ifca, ifca, sizeof(mt.ifca));	i2osend(tinfo->dev, &mt, sizeof(mt));}static voidtripares(Fs *fs, int vers, uchar *ip, uchar *mac, int l, int){	Route *r;	Ipifc *ifc;	MTaresenter ta;	Tripinfo *tinfo;	uchar v6ip[IPaddrlen];	if(vers == V4) {		r = v4lookup(fs, ip);		v4tov6(v6ip, ip);		ip = v6ip;	}	else		r = v6lookup(fs, ip);	if(r == nil) {		print("tripares: no route for entry\n");		return;	}	ifc = r->ifc;	tinfo = ifc->arg;	if(!tinfo->dev->routing)		return;	if(vers == V4) {		v4tov6(v6ip, ip);		ip = v6ip;	}	ta.type = T_ARESENTER;	ta.maclen = l;	memmove(ta.addr, ip, IPaddrlen);	memmove(ta.amac, mac, l);	i2osend(tinfo->dev, &ta, sizeof(ta));}voidtripmediumlink(void){	addipmedium(&tripmedium);}

⌨️ 快捷键说明

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