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

📄 iproute.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "all.h"#include "../ip/ip.h"#define	DEBUG	if(cons.flags&ralloc.flag)printenum{	Version=	1,	/*	 *  definitions that are innately tied to BSD	 */	AF_INET=	2,	AF_UNSPEC=	0,	/*	 *  Packet types.	 */	Request=	1,	Response=	2,	Traceon=	3,	Traceoff=	4,	Infinity=	16,	/* infinite hop count */	Maxpacket=	488,	/* largest packet body */};/* *  network info */typedef struct Rip	Rip;struct Rip{	uchar	family[2];	uchar	port[2];	uchar	addr[Pasize];	uchar	pad[8];	uchar	metric[4];};typedef struct Ripmsg	Ripmsg;struct Ripmsg{	uchar	type;	uchar	vers;	uchar	pad[2];	Rip	rip[1];		/* the rest of the packet consists of routes */};enum{	Maxroutes=	(Maxpacket-4)/sizeof(Ripmsg),};/* *  internal route info */enum{	Nroute	= 2*1024,	Nhash	= 256,		/* routing hash buckets */	Nifc	= 16,};typedef struct Route	Route;struct Route{	Route	*next;	uchar	dest[Pasize];	uchar	mask[Pasize];	uchar	gate[Pasize];	int	metric;	int	inuse;	Timet	time;};struct{	Lock;	Route	route[Nroute];	Route	*hash[Nhash];	int	nroute;	ulong	flag;	int 	dorip;} ralloc;uchar classmask[4][4] ={	0xff, 0x00, 0x00, 0x00,	0xff, 0x00, 0x00, 0x00,	0xff, 0xff, 0x00, 0x00,	0xff, 0xff, 0xff, 0x00,};#define CLASS(p) ((*(uchar*)(p))>>6)static void	considerroute(Route*);static void	deleteroute(Route*);static void	printroute(Route*);static void	printroutes(void);static void	installroute(Route*);static void	getmask(uchar*, uchar*);static void	maskip(uchar*, uchar*, uchar*);static int	equivip(uchar*, uchar*);static void	cmd_route(int, char*[]);static ulong	rhash(uchar*);voidiprouteinit(void){	cmd_install("route", "subcommand -- ip routes", cmd_route);	ralloc.flag = flag_install("route", "-- verbose");	if(!conf.ripoff)		ralloc.dorip = 1;}static voidcmd_route(int argc, char *argv[]){	Route r;	if(argc < 2) {usage:		print("route add dest gate [mask] -- add a route\n");		print("route delete dest -- remote a route\n");		print("route print [dest] -- print routes\n");		print("route ripon -- listen to RIP packets\n");		print("route ripoff -- ignore RIP packets\n");		return;	}	if(strcmp(argv[1], "ripoff") == 0)		ralloc.dorip = 0;	else	if(strcmp(argv[1], "ripon") == 0)		ralloc.dorip = 1;	else	if(strcmp(argv[1], "add") == 0) {		switch(argc){		default:			goto usage;		case 4:			memmove(r.mask, classmask[CLASS(r.dest)], Pasize);			break;		case 5:			if(chartoip(r.mask, argv[4]))				goto usage;			break;		}		if(chartoip(r.dest, argv[2]) || chartoip(r.gate, argv[3]))			goto usage;		r.metric = 0;			/* rip can't nuke these */		deleteroute(&r);		considerroute(&r);	} else	if(strcmp(argv[1], "delete") == 0) {		if(argc != 3 || chartoip(r.dest, argv[2]))			goto usage;		deleteroute(&r);	} else	if(strcmp(argv[1], "print") == 0) {		if(argc == 3) {			if(chartoip(r.dest, argv[2]))				goto usage;			printroute(&r);		} else			printroutes();	}}/* *  consider installing a route.  Do so only if it is better than what *  we have. */static voidconsiderroute(Route *r){	ulong h, i;	ulong m, nm;	Route *hp, **l;	r->next = 0;	r->time = time();	r->inuse = 1;	lock(&ralloc);	h = rhash(r->dest);	for(hp = ralloc.hash[h]; hp; hp = hp->next) {		if(equivip(hp->dest, r->dest) && equivip(hp->mask, r->mask)) {			/*			 *  found a match, replace if better (or much newer)			 */			if(r->metric < hp->metric || time()-hp->time > 10*60) {				memmove(hp->gate, r->gate, Pasize);				hp->metric = r->metric;				DEBUG("route: replacement %I & %I -> %I (%d)\n",					hp->dest, hp->mask, hp->dest, hp->metric);			}			if(equivip(r->gate, hp->gate))				hp->time = time();			goto done;		}	}	/*	 *  no match, look for space	 */	for(hp = ralloc.route; hp < &ralloc.route[Nroute]; hp++)		if(hp->inuse == 0)			break;	if(hp == &ralloc.route[Nroute])		hp = 0;	/*	 *  look for an old entry	 */	for(i = 0; hp == 0 && i < Nhash; i++) {		l = &ralloc.hash[i];		for(hp = *l; hp; hp = *l) {			if(time() - hp->time > 10*60 && hp->metric > 0){				*l = hp->next;				break;			}			l = &hp->next;		}	}	if(hp == 0) {		print("no more routes");		goto done;	}	memmove(hp, r, sizeof(Route));	/*	 *  insert largest mask first	 */	m = nhgetl(hp->mask);	for(l = &ralloc.hash[h]; *l; l = &(*l)->next){		nm = nhgetl((*l)->mask);		if(nm < m)			break;	}	hp->next = *l;	*l = hp;	DEBUG("route: new %I & %I -> %I (%d)\n", hp->dest, hp->mask,		hp->dest, hp->metric);done:	unlock(&ralloc);}static voiddeleteroute(Route *r){	int h;	Route *hp, **l;	lock(&ralloc);	for(h = 0; h < Nhash; h++) {		l = &ralloc.hash[h];		for(hp = *l; hp; hp = *l){			if(equivip(r->dest, hp->dest)) {				*l = hp->next;				hp->next = 0;				hp->inuse = 0;				break;			}			l = &hp->next;		}	}	unlock(&ralloc);}static voidprintroutes(void){	Ifc *i;	int h;	Route *hp;	uchar mask[Pasize];	lock(&ralloc);	for(h = 0; h < Nhash; h++)		for(hp = ralloc.hash[h]; hp; hp = hp->next)			print("%I & %I -> %I\n", hp->dest, hp->mask, hp->gate);	unlock(&ralloc);	print("\nifc's\n");	for(i = enets; i; i = i->next) {		hnputl(mask, i->mask);		print("addr %I mask %I defgate %I\n", i->ipa, mask, i->netgate);	}}static voidprintroute(Route *r){	int h;	Route *hp;	uchar net[Pasize];	h = rhash(r->dest);	for(hp = ralloc.hash[h]; hp; hp = hp->next){		maskip(r->dest, hp->mask, net);		if(equivip(hp->dest, net)){			print("%I & %I -> %I\n", hp->dest, hp->mask, hp->gate);			return;		}	}	print("default * -> %I\n", enets[0].netgate);}voidiproute(uchar *to, uchar *dst, uchar *def){	int h;	Route *hp;	uchar net[Pasize];	h = rhash(dst);	for(hp = ralloc.hash[h]; hp; hp = hp->next) {		maskip(dst, hp->mask, net);		if(equivip(hp->dest, net)) {			def = hp->gate;			break;		}	}	memmove(to, def, Pasize);}voidriprecv(Msgbuf *mb, Ifc*){	int n;	Rip *r;	Ripmsg *m;	Udppkt *uh;	Route route;	if(ralloc.dorip == 0)		goto drop;	uh = (Udppkt*)mb->data;	m = (Ripmsg*)(mb->data + Ensize + Ipsize + Udpsize);	if(m->type != Response || m->vers != Version)		goto drop;	n = nhgets(uh->udplen);	n -= Udpsize;	n = n/sizeof(Rip);	DEBUG("%d routes from %I\n", n, uh->src);	memmove(route.gate, uh->src, Pasize);	for(r = m->rip; r < &m->rip[n]; r++){		getmask(route.mask, r->addr);		maskip(r->addr, route.mask, route.dest);		route.metric = nhgetl(r->metric) + 1;		if(route.metric < 1)			continue;		considerroute(&route);	}drop:	mbfree(mb);}/* *  route's hashed by net, not subnet */static ulongrhash(uchar *d){	ulong h;	uchar net[Pasize];	maskip(d, classmask[CLASS(d)], net);	h = net[0] + net[1] + net[2];	return h % Nhash;}/* *  figure out what mask to use, if we have a direct connected network *  with the same class net use its subnet mask. */static voidgetmask(uchar *mask, uchar *dest){	Ifc *i;	long ip;	ip = nhgetl(dest);	for(i = enets; i; i = i->next)		if((i->ipaddr & i->cmask) == (ip & i->cmask)) {			hnputl(mask, i->mask);			return;		}	memmove(mask, classmask[CLASS(dest)], Pasize);}static voidmaskip(uchar *a, uchar *m, uchar *n){	int i;	for(i = 0; i < 4; i++)		n[i] = a[i] & m[i];}static intequivip(uchar *a, uchar *b){	int i;	for(i = 0; i < 4; i++)		if(a[i] != b[i])			return 0;	return 1;}longipclassmask(uchar *ip){	return nhgetl(classmask[CLASS(ip)]);}

⌨️ 快捷键说明

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