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

📄 iproute.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"static void	walkadd(Fs*, Route**, Route*);static void	addnode(Fs*, Route**, Route*);static void	calcd(Route*);/* these are used for all instances of IP */Route*	v4freelist;Route*	v6freelist;RWlock	routelock;ulong	v4routegeneration, v6routegeneration;static voidfreeroute(Route *r){	Route **l;	r->left = nil;	r->right = nil;	if(r->type & Rv4)		l = &v4freelist;	else		l = &v6freelist;	r->mid = *l;	*l = r;}static Route*allocroute(int type){	Route *r;	int n;	Route **l;	if(type & Rv4){		n = sizeof(RouteTree) + sizeof(V4route);		l = &v4freelist;	} else {		n = sizeof(RouteTree) + sizeof(V6route);		l = &v6freelist;	}	r = *l;	if(r != nil){		*l = r->mid;	} else {		r = malloc(n);		if(r == nil)			panic("out of routing nodes");	}	memset(r, 0, n);	r->type = type;	r->ifc = nil;	r->ref = 1;	return r;}static voidaddqueue(Route **q, Route *r){	Route *l;	if(r == nil)		return;	l = allocroute(r->type);	l->mid = *q;	*q = l;	l->left = r;}/* *   compare 2 v6 addresses */static intlcmp(ulong *a, ulong *b){	int i;	for(i = 0; i < IPllen; i++){		if(a[i] > b[i])			return 1;		if(a[i] < b[i])			return -1;	}	return 0;}/* *  compare 2 v4 or v6 ranges */enum{	Rpreceeds,	Rfollows,	Requals,	Rcontains,	Rcontained,};static intrangecompare(Route *a, Route *b){	if(a->type & Rv4){		if(a->v4.endaddress < b->v4.address)			return Rpreceeds;		if(a->v4.address > b->v4.endaddress)			return Rfollows;		if(a->v4.address <= b->v4.address		&& a->v4.endaddress >= b->v4.endaddress){			if(a->v4.address == b->v4.address			&& a->v4.endaddress == b->v4.endaddress)				return Requals;			return Rcontains;		}		return Rcontained;	}	if(lcmp(a->v6.endaddress, b->v6.address) < 0)		return Rpreceeds;	if(lcmp(a->v6.address, b->v6.endaddress) > 0)		return Rfollows;	if(lcmp(a->v6.address, b->v6.address) <= 0	&& lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){		if(lcmp(a->v6.address, b->v6.address) == 0		&& lcmp(a->v6.endaddress, b->v6.endaddress) == 0)				return Requals;		return Rcontains;	}	return Rcontained;}static voidcopygate(Route *old, Route *new){	if(new->type & Rv4)		memmove(old->v4.gate, new->v4.gate, IPv4addrlen);	else		memmove(old->v6.gate, new->v6.gate, IPaddrlen);}/* *  walk down a tree adding nodes back in */static voidwalkadd(Fs *f, Route **root, Route *p){	Route *l, *r;	l = p->left;	r = p->right;	p->left = 0;	p->right = 0;	addnode(f, root, p);	if(l)		walkadd(f, root, l);	if(r)		walkadd(f, root, r);}/* *  calculate depth */static voidcalcd(Route *p){	Route *q;	int d;	if(p) {		d = 0;		q = p->left;		if(q)			d = q->depth;		q = p->right;		if(q && q->depth > d)			d = q->depth;		q = p->mid;		if(q && q->depth > d)			d = q->depth;		p->depth = d+1;	}}/* *  balance the tree at the current node */static voidbalancetree(Route **cur){	Route *p, *l, *r;	int dl, dr;	/*	 * if left and right are	 * too out of balance,	 * rotate tree node	 */	p = *cur;	dl = 0; if(l = p->left) dl = l->depth;	dr = 0; if(r = p->right) dr = r->depth;	if(dl > dr+1) {		p->left = l->right;		l->right = p;		*cur = l;		calcd(p);		calcd(l);	} else	if(dr > dl+1) {		p->right = r->left;		r->left = p;		*cur = r;		calcd(p);		calcd(r);	} else		calcd(p);}/* *  add a new node to the tree */static voidaddnode(Fs *f, Route **cur, Route *new){	Route *p;	p = *cur;	if(p == 0) {		*cur = new;		new->depth = 1;		return;	}	switch(rangecompare(new, p)){	case Rpreceeds:		addnode(f, &p->left, new);		break;	case Rfollows:		addnode(f, &p->right, new);		break;	case Rcontains:		/*		 *  if new node is superset		 *  of tree node,		 *  replace tree node and		 *  queue tree node to be		 *  merged into root.		 */		*cur = new;		new->depth = 1;		addqueue(&f->queue, p);		break;	case Requals:		/*		 *  supercede the old entry if the old one isn't		 *  a local interface.		 */		if((p->type & Rifc) == 0){			p->type = new->type;			p->ifcid = -1;			copygate(p, new);		} else if(new->type & Rifc)			p->ref++;		freeroute(new);		break;	case Rcontained:		addnode(f, &p->mid, new);		break;	}		balancetree(cur);}#define	V4H(a)	((a&0x07ffffff)>>(32-Lroot-5))voidv4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type){	Route *p;	ulong sa;	ulong m;	ulong ea;	int h, eh;	m = nhgetl(mask);	sa = nhgetl(a) & m;	ea = sa | ~m;	eh = V4H(ea);	for(h=V4H(sa); h<=eh; h++) {		p = allocroute(Rv4 | type);		p->v4.address = sa;		p->v4.endaddress = ea;		memmove(p->v4.gate, gate, sizeof(p->v4.gate));		memmove(p->tag, tag, sizeof(p->tag));		wlock(&routelock);		addnode(f, &f->v4root[h], p);		while(p = f->queue) {			f->queue = p->mid;			walkadd(f, &f->v4root[h], p->left);			freeroute(p);		}		wunlock(&routelock);	}	v4routegeneration++;	ipifcaddroute(f, Rv4, a, mask, gate, type);}#define	V6H(a)	(((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))#define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))voidv6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type){	Route *p;	ulong sa[IPllen], ea[IPllen];	ulong x, y;	int h, eh;	/*	if(ISDFLT(a, mask, tag))		f->v6p->cdrouter = -1;	*/	for(h = 0; h < IPllen; h++){		x = nhgetl(a+4*h);		y = nhgetl(mask+4*h);		sa[h] = x & y;		ea[h] = x | ~y;	}	eh = V6H(ea);	for(h = V6H(sa); h <= eh; h++) {		p = allocroute(type);		memmove(p->v6.address, sa, IPaddrlen);		memmove(p->v6.endaddress, ea, IPaddrlen);		memmove(p->v6.gate, gate, IPaddrlen);		memmove(p->tag, tag, sizeof(p->tag));		wlock(&routelock);		addnode(f, &f->v6root[h], p);		while(p = f->queue) {			f->queue = p->mid;			walkadd(f, &f->v6root[h], p->left);			freeroute(p);		}		wunlock(&routelock);	}	v6routegeneration++;	ipifcaddroute(f, 0, a, mask, gate, type);}Route**looknode(Route **cur, Route *r){	Route *p;	for(;;){		p = *cur;		if(p == 0)			return 0;			switch(rangecompare(r, p)){		case Rcontains:			return 0;		case Rpreceeds:			cur = &p->left;			break;		case Rfollows:			cur = &p->right;			break;		case Rcontained:			cur = &p->mid;			break;		case Requals:			return cur;		}	}}voidv4delroute(Fs *f, uchar *a, uchar *mask, int dolock){	Route **r, *p;	Route rt;	int h, eh;	ulong m;	m = nhgetl(mask);	rt.v4.address = nhgetl(a) & m;	rt.v4.endaddress = rt.v4.address | ~m;	rt.type = Rv4;	eh = V4H(rt.v4.endaddress);	for(h=V4H(rt.v4.address); h<=eh; h++) {		if(dolock)			wlock(&routelock);		r = looknode(&f->v4root[h], &rt);		if(r) {			p = *r;			if(--(p->ref) == 0){				*r = 0;				addqueue(&f->queue, p->left);				addqueue(&f->queue, p->mid);				addqueue(&f->queue, p->right);				freeroute(p);				while(p = f->queue) {					f->queue = p->mid;					walkadd(f, &f->v4root[h], p->left);					freeroute(p);				}			}		}		if(dolock)			wunlock(&routelock);	}	v4routegeneration++;	ipifcremroute(f, Rv4, a, mask);}voidv6delroute(Fs *f, uchar *a, uchar *mask, int dolock){	Route **r, *p;	Route rt;	int h, eh;	ulong x, y;	for(h = 0; h < IPllen; h++){		x = nhgetl(a+4*h);		y = nhgetl(mask+4*h);		rt.v6.address[h] = x & y;		rt.v6.endaddress[h] = x | ~y;	}	rt.type = 0;	eh = V6H(rt.v6.endaddress);	for(h=V6H(rt.v6.address); h<=eh; h++) {		if(dolock)			wlock(&routelock);		r = looknode(&f->v6root[h], &rt);		if(r) {			p = *r;			if(--(p->ref) == 0){				*r = 0;				addqueue(&f->queue, p->left);				addqueue(&f->queue, p->mid);				addqueue(&f->queue, p->right);				freeroute(p);				while(p = f->queue) {					f->queue = p->mid;					walkadd(f, &f->v6root[h], p->left);					freeroute(p);				}			}		}		if(dolock)			wunlock(&routelock);	}	v6routegeneration++;	ipifcremroute(f, 0, a, mask);}Route*v4lookup(Fs *f, uchar *a, Conv *c){	Route *p, *q;	ulong la;	uchar gate[IPaddrlen];	Ipifc *ifc;	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration)		return c->r;	la = nhgetl(a);	q = nil;	for(p=f->v4root[V4H(la)]; p;)		if(la >= p->v4.address) {			if(la <= p->v4.endaddress) {				q = p;				p = p->mid;			} else				p = p->right;		} else			p = p->left;	if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){		if(q->type & Rifc) {			hnputl(gate+IPv4off, q->v4.address);			memmove(gate, v4prefix, IPv4off);		} else			v4tov6(gate, q->v4.gate);		ifc = findipifc(f, gate, q->type);		if(ifc == nil)			return nil;		q->ifc = ifc;		q->ifcid = ifc->ifcid;	}	if(c != nil){		c->r = q;		c->rgen = v4routegeneration;	}	return q;}Route*v6lookup(Fs *f, uchar *a, Conv *c){	Route *p, *q;	ulong la[IPllen];	int h;	ulong x, y;	uchar gate[IPaddrlen];	Ipifc *ifc;	if(memcmp(a, v4prefix, IPv4off) == 0){		q = v4lookup(f, a+IPv4off, c);		if(q != nil)			return q;	}	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration)		return c->r;	for(h = 0; h < IPllen; h++)		la[h] = nhgetl(a+4*h);	q = 0;	for(p=f->v6root[V6H(la)]; p;){		for(h = 0; h < IPllen; h++){			x = la[h];			y = p->v6.address[h];			if(x == y)				continue;			if(x < y){				p = p->left;				goto next;			}			break;		}		for(h = 0; h < IPllen; h++){			x = la[h];			y = p->v6.endaddress[h];			if(x == y)				continue;			if(x > y){				p = p->right;				goto next;			}			break;		}		q = p;		p = p->mid;next:		;	}	if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){		if(q->type & Rifc) {			for(h = 0; h < IPllen; h++)				hnputl(gate+4*h, q->v6.address[h]);			ifc = findipifc(f, gate, q->type);		} else			ifc = findipifc(f, q->v6.gate, q->type);		if(ifc == nil)			return nil;		q->ifc = ifc;		q->ifcid = ifc->ifcid;	}	if(c != nil){		c->r = q;		c->rgen = v6routegeneration;	}		return q;}voidroutetype(int type, char *p){	memset(p, ' ', 4);	p[4] = 0;	if(type & Rv4)		*p++ = '4';	else		*p++ = '6';	if(type & Rifc)		*p++ = 'i';	if(type & Runi)		*p++ = 'u';	else if(type & Rbcast)		*p++ = 'b';	else if(type & Rmulti)		*p++ = 'm';	if(type & Rptpt)		*p = 'p';}char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";voidconvroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc){	int i;	if(r->type & Rv4){		memmove(addr, v4prefix, IPv4off);		hnputl(addr+IPv4off, r->v4.address);		memset(mask, 0xff, IPv4off);		hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address));		memmove(gate, v4prefix, IPv4off);		memmove(gate+IPv4off, r->v4.gate, IPv4addrlen);	} else {		for(i = 0; i < IPllen; i++){			hnputl(addr + 4*i, r->v6.address[i]);			hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));		}		memmove(gate, r->v6.gate, IPaddrlen);	}	routetype(r->type, t);	if(r->ifc)		*nifc = r->ifc->conv->x;	else		*nifc = -1;}/* *  this code is not in rr to reduce stack size */static voidsprintroute(Route *r, Routewalk *rw){	int nifc, n;	char t[5], *iname, ifbuf[5];	uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];	char *p;	convroute(r, addr, mask, gate, t, &nifc);	iname = "-";	if(nifc != -1) {		iname = ifbuf;		sprint(ifbuf, "%d", nifc);	}	p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);	if(rw->o < 0){		n = p - rw->p;		if(n > -rw->o){			memmove(rw->p, rw->p-rw->o, n+rw->o);			rw->p = p + rw->o;		}		rw->o += n;	} else		rw->p = p;}/* *  recurse descending tree, applying the function in Routewalk */static intrr(Route *r, Routewalk *rw){	int h;	if(rw->e <= rw->p)		return 0;	if(r == nil)		return 1;	if(rr(r->left, rw) == 0)		return 0;	if(r->type & Rv4)		h = V4H(r->v4.address);	else		h = V6H(r->v6.address);	if(h == rw->h)		rw->walk(r, rw);	if(rr(r->mid, rw) == 0)		return 0;	return rr(r->right, rw);}voidipwalkroutes(Fs *f, Routewalk *rw){	rlock(&routelock);	if(rw->e > rw->p) {		for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++)			if(rr(f->v4root[rw->h], rw) == 0)				break;	}	if(rw->e > rw->p) {		for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++)			if(rr(f->v6root[rw->h], rw) == 0)				break;	}	runlock(&routelock);}longrouteread(Fs *f, char *p, ulong offset, int n){	Routewalk rw;	rw.p = p;	rw.e = p+n;	rw.o = -offset;	rw.walk = sprintroute;	ipwalkroutes(f, &rw);	return rw.p - p;}/* *  this code is not in routeflush to reduce stack size */voiddelroute(Fs *f, Route *r, int dolock){	uchar addr[IPaddrlen];	uchar mask[IPaddrlen];	uchar gate[IPaddrlen];	char t[5];	int nifc;	convroute(r, addr, mask, gate, t, &nifc);	if(r->type & Rv4)		v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);	else		v6delroute(f, addr, mask, dolock);}/* *  recurse until one route is deleted *    returns 0 if nothing is deleted, 1 otherwise */introuteflush(Fs *f, Route *r, char *tag){	if(r == nil)		return 0;	if(routeflush(f, r->mid, tag))		return 1;	if(routeflush(f, r->left, tag))		return 1;	if(routeflush(f, r->right, tag))		return 1;	if((r->type & Rifc) == 0){		if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0){			delroute(f, r, 0);			return 1;		}	}	return 0;}longroutewrite(Fs *f, Chan *c, char *p, int n){	int h, changed;	char *tag;	Cmdbuf *cb;	uchar addr[IPaddrlen];	uchar mask[IPaddrlen];	uchar gate[IPaddrlen];	IPaux *a, *na;	cb = parsecmd(p, n);	if(waserror()){		free(cb);		nexterror();	}	if(strcmp(cb->f[0], "flush") == 0){		tag = cb->f[1];		for(h = 0; h < nelem(f->v4root); h++)			for(changed = 1; changed;){				wlock(&routelock);				changed = routeflush(f, f->v4root[h], tag);				wunlock(&routelock);			}		for(h = 0; h < nelem(f->v6root); h++)			for(changed = 1; changed;){				wlock(&routelock);				changed = routeflush(f, f->v6root[h], tag);				wunlock(&routelock);			}	} else if(strcmp(cb->f[0], "remove") == 0){		if(cb->nf < 3)			error(Ebadarg);		parseip(addr, cb->f[1]);		parseipmask(mask, cb->f[2]);		if(memcmp(addr, v4prefix, IPv4off) == 0)			v4delroute(f, addr+IPv4off, mask+IPv4off, 1);		else			v6delroute(f, addr, mask, 1);	} else if(strcmp(cb->f[0], "add") == 0){		if(cb->nf < 4)			error(Ebadarg);		parseip(addr, cb->f[1]);		parseipmask(mask, cb->f[2]);		parseip(gate, cb->f[3]);		tag = "none";		if(c != nil){			a = c->aux;			tag = a->tag;		}		if(memcmp(addr, v4prefix, IPv4off) == 0)			v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);		else			v6addroute(f, tag, addr, mask, gate, 0);	} else if(strcmp(cb->f[0], "tag") == 0) {		if(cb->nf < 2)			error(Ebadarg);		a = c->aux;		na = newipaux(a->owner, cb->f[1]);		c->aux = na;		free(a);	}	poperror();	free(cb);	return n;}

⌨️ 快捷键说明

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