plan 9 kernel history: overview | file list | diff list

1991/0330/port/deviproute.c (diff list | history)

1991/0330/sys/src/9/port/deviproute.c:1,61991/0331/sys/src/9/port/deviproute.c:1,12 (short | long)
1991/0330    
#include <u.h> 
#include <libc.h> 
1991/0331    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1991/0330    
 
1991/0331    
#include	"devtab.h" 
 
1991/0330    
typedef	struct Iproute	Iproute; 
typedef	struct Iprtab	Iprtab; 
 
1991/0330/sys/src/9/port/deviproute.c:20,251991/0331/sys/src/9/port/deviproute.c:26,34
1991/0330    
}; 
#define CLASSMASK(x)	classmask[(*x>>6) & 3] 
 
1991/0331    
uchar netbytes[4] = { 1, 1, 2, 3 }; 
#define NETBYTES(x)	netbytes[(*x>>6) & 3] 
 
1991/0330    
/* 
 *  routes 
 */ 
1991/0330/sys/src/9/port/deviproute.c:31,571991/0331/sys/src/9/port/deviproute.c:40,75
1991/0330    
	int	inuse; 
}; 
struct Iprtab { 
/*	Lock; */ 
	Iproute *first; 
	Iproute	r[Nroutes];	/* routings */ 
1991/0331    
	Lock; 
	int	n;		/* number of valid routes */ 
	Iproute *first;		/* list of valid routes */ 
	Iproute	r[Nroutes];	/* all routes */ 
1991/0330    
}; 
Iprtab	iprtab; 
 
#define lock(x) 
#define unlock(x) 
                 
1991/0331    
/* 
 *  Convert string to ip address.  This is rediculously difficult because 
 *  the designers of ip decided to allow any leading zero bytes in the 
 *  host part to be left out. 
 */ 
1991/0330    
void 
printroute(void) 
1991/0331    
strtoip(char *s, uchar *addr) 
1991/0330    
{ 
	Iproute *r; 
1991/0331    
	int i, off, first; 
	char *rptr = s; 
1991/0330    
 
	print("\n"); 
	for(r = iprtab.first; r; r = r->next) 
		print("%d.%d.%d.%d  %d.%d.%d.%d  %d.%d.%d.%d\n", 
			r->dst[0], r->dst[1], r->dst[2], r->dst[3], 
			r->mask[0], r->mask[1], r->mask[2], r->mask[3], 
			r->gate[0], r->gate[1], r->gate[2], r->gate[3]); 
	print("\n"); 
1991/0331    
	/* convert the bytes */ 
	for(i = 0; i<4 & *rptr; i++) 
		addr[i] = strtoul(rptr, &rptr, 0); 
 
	/* move host bytes to the right place */ 
	first = NETBYTES(addr); 
	off = 4 - i; 
	if(off) 
		while(i != first){ 
			--i; 
			addr[i+off] = addr[i]; 
		} 
1991/0330    
} 
 
/* 
1991/0330/sys/src/9/port/deviproute.c:128,1341991/0331/sys/src/9/port/deviproute.c:146,152
1991/0330    
	 */ 
	for(i = 0; i < 4; i++) 
		if((dst[i]&mask[i]) != dst[i]) 
			return; 
1991/0331    
			errors("bad ip route"); 
1991/0330    
 
	/* 
	 *  see if we already have a route for 
1991/0330/sys/src/9/port/deviproute.c:147,1521991/0331/sys/src/9/port/deviproute.c:165,172
1991/0330    
			return; 
		} 
	} 
1991/0331    
	if(free == 0) 
		errors("no free ip routes"); 
1991/0330    
 
	/* 
	 *  add the new route in sorted order 
1991/0330/sys/src/9/port/deviproute.c:165,1701991/0331/sys/src/9/port/deviproute.c:185,191
1991/0330    
		iprtab.first = free; 
	else 
		e->next = free; 
1991/0331    
	iprtab.n++; 
1991/0330    
	unlock(&iprtab); 
} 
 
1991/0330/sys/src/9/port/deviproute.c:184,1891991/0331/sys/src/9/port/deviproute.c:205,211
1991/0330    
			else 
				e->next = r->next; 
			r->inuse = 0; 
1991/0331    
			iprtab.n--; 
1991/0330    
			break; 
		} 
		e = r; 
1991/0330/sys/src/9/port/deviproute.c:203,2071991/0331/sys/src/9/port/deviproute.c:225,413
1991/0330    
	for(r = iprtab.first; r; r = r->next) 
		r->inuse = 0; 
	iprtab.first = 0; 
1991/0331    
	iprtab.n = 0; 
1991/0330    
	unlock(&iprtab); 
1991/0331    
} 
 
/* 
 *  device interface 
 */ 
enum{ 
	Qdir, 
	Qdata, 
}; 
Dirtab iproutetab[]={ 
	"iproute",		Qdata,		0,	0600, 
}; 
#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) 
 
void 
iproutereset(void) 
{ 
} 
 
void 
iprouteinit(void) 
{ 
} 
 
Chan * 
iprouteattach(char *spec) 
{ 
	return devattach('R', spec); 
} 
 
Chan * 
iprouteclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int 
iproutewalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); 
} 
 
void 
iproutestat(Chan *c, char *db) 
{ 
	devstat(c, db, iproutetab, (long)Niproutetab, devgen); 
} 
 
Chan * 
iprouteopen(Chan *c, int omode) 
{ 
	if(c->qid.path == CHDIR){ 
		if(omode != OREAD) 
			error(Eperm); 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
 
void 
iproutecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	error(Eperm); 
} 
 
void 
iprouteremove(Chan *c) 
{ 
	error(Eperm); 
} 
 
void 
iproutewstat(Chan *c, char *dp) 
{ 
	error(Eperm); 
} 
 
void 
iprouteclose(Chan *c) 
{ 
} 
 
#define IPR_ENTRYLEN 54 
#define PAD "                                                                  " 
 
long 
iprouteread(Chan *c, void *a, long n) 
{ 
	char	buf[IPR_ENTRYLEN*2]; 
	Iproute	*r; 
	int	part, bytes, size; 
 
	switch((int)(c->qid.path&~CHDIR)){ 
	case Qdir: 
		return devdirread(c, a, n, iproutetab, Niproutetab, devgen); 
	case Qdata: 
		lock(&iprtab); 
		part = c->offset/IPR_ENTRYLEN; 
		for(r = iprtab.first; part && r; r = r->next) 
			; 
		bytes = c->offset; 
		while(bytes < iprtab.n*IPR_ENTRYLEN && n){ 
			part = bytes%IPR_ENTRYLEN; 
 
			sprint(buf,"%d.%d.%d.%d & %d.%d.%d.%d -> %d.%d.%d.%d%s", 
				r->dst[0], r->dst[1], r->dst[2], r->dst[3], 
				r->mask[0], r->mask[1], r->mask[2], r->mask[3], 
				r->gate[0], r->gate[1], r->gate[2], r->gate[3], 
				PAD);  
			 
			buf[IPR_ENTRYLEN-1] = '\n'; 
 
			size = IPR_ENTRYLEN - part; 
			size = MIN(n, size); 
			memmove(a, buf+part, size); 
 
			a = (void *)((int)a + size); 
			n -= size; 
			bytes += size; 
		} 
		unlock(&iprtab); 
		return bytes - c->offset; 
		break; 
	default: 
		n=0; 
		break; 
	} 
	return n; 
} 
 
long 
iproutewrite(Chan *c, char *a, long n) 
{ 
	char buf[IPR_ENTRYLEN]; 
	char *field[4]; 
	uchar mask[4], dst[4], gate[4]; 
	int m; 
 
	switch((int)(c->qid.path&~CHDIR)){ 
	case Qdata: 
		strncpy(buf, a, sizeof buf); 
		m = getfields(buf, field, 4, ' '); 
 
		if(strncmp(field[0], "flush", 5) == 0) 
			ipflushroute(); 
		else if(strcmp(field[0], "add") == 0){ 
			switch(m){ 
			case 4: 
				strtoip(field[1], dst); 
				strtoip(field[2], mask); 
				strtoip(field[3], gate); 
				ipaddroute(dst, mask, gate); 
				break; 
			case 3: 
				strtoip(field[1], dst); 
				strtoip(field[2], gate); 
				ipaddroute(dst, 0, gate); 
				break; 
			default: 
				error(Ebadarg); 
			} 
		} else if(strcmp(field[0], "delete") == 0){ 
			switch(m){ 
			case 3: 
				strtoip(field[1], dst); 
				strtoip(field[2], mask); 
				ipremroute(dst, mask); 
				break; 
			case 2: 
				strtoip(field[1], dst); 
				ipremroute(dst, 0); 
				break; 
			default: 
				error(Ebadarg); 
			} 
		} 
		break; 
	default: 
		error(Ebadusefd); 
	} 
	return n; 
1991/0330    
} 
1991/0331/sys/src/9/port/deviproute.c:4,121991/0401/sys/src/9/port/deviproute.c:4,20 (short | long)
1991/0331    
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1991/0401    
#include	"arp.h" 
#include	"ipdat.h" 
1991/0330    
 
1991/0331    
#include	"devtab.h" 
 
1991/0401    
/* 
 *  All ip numbers and masks are stored as ulongs. 
 *  All interfaces to this code uses the standard byte 
 *  string representation. 
 */ 
 
1991/0330    
typedef	struct Iproute	Iproute; 
typedef	struct Iprtab	Iprtab; 
 
1991/0331/sys/src/9/port/deviproute.c:16,411991/0401/sys/src/9/port/deviproute.c:24,35
1991/0330    
}; 
 
/* 
 *  Standard ip masks for the 3 classes 
 */ 
uchar classmask[4][4] = { 
	0xff,	0,	0,	0, 
	0xff,	0,	0,	0, 
	0xff,	0xff,	0,	0, 
	0xff,	0xff,	0xff,	0, 
}; 
#define CLASSMASK(x)	classmask[(*x>>6) & 3] 
                 
1991/0331    
uchar netbytes[4] = { 1, 1, 2, 3 }; 
#define NETBYTES(x)	netbytes[(*x>>6) & 3] 
                 
1991/0330    
/* 
 *  routes 
 */ 
struct Iproute { 
	uchar	dst[4]; 
	uchar	gate[4]; 
	uchar	mask[4]; 
1991/0401    
	ulong	dst; 
	ulong	gate; 
	ulong	mask; 
1991/0330    
	Iproute	*next; 
	int	inuse; 
}; 
1991/0331/sys/src/9/port/deviproute.c:48,1301991/0401/sys/src/9/port/deviproute.c:42,85
1991/0330    
Iprtab	iprtab; 
 
1991/0331    
/* 
 *  Convert string to ip address.  This is rediculously difficult because 
 *  the designers of ip decided to allow any leading zero bytes in the 
 *  host part to be left out. 
 */ 
1991/0330    
void 
1991/0331    
strtoip(char *s, uchar *addr) 
1991/0330    
{ 
1991/0331    
	int i, off, first; 
	char *rptr = s; 
1991/0330    
                 
1991/0331    
	/* convert the bytes */ 
	for(i = 0; i<4 & *rptr; i++) 
		addr[i] = strtoul(rptr, &rptr, 0); 
                 
	/* move host bytes to the right place */ 
	first = NETBYTES(addr); 
	off = 4 - i; 
	if(off) 
		while(i != first){ 
			--i; 
			addr[i+off] = addr[i]; 
		} 
1991/0330    
} 
                 
/* 
 *  The chosen route is the one obeys the constraint 
 *		r->mask[x] & dst[x] == r->dst[x] for x in 0 1 2 3 
1991/0401    
 *		r->mask & dst == r->dst 
1991/0330    
 * 
 *  If there are several matches, the one whose mask has the most 
 *  leading ones (and hence is the most specific) wins. 
 * 
 *  If there is no match, the default gateway is chosen. 
1991/0401    
 *  leading ones (and hence is the most specific) wins.  This is 
 *  forced by storing the routes in decreasing number of ones order 
 *  and returning the first match.  The default gateway has no ones 
 *  in the mask and is thus the last matched. 
1991/0330    
 */ 
void 
iproute(uchar *dst, uchar *gate) 
{ 
	Iproute *r; 
1991/0401    
	ulong udst; 
1991/0330    
 
1991/0401    
	udst = nhgetl(dst); 
	if((udst&Mymask) == (Myip&Mymask)){ 
		memmove(gate, dst, 4); 
		return; 
	} 
 
1991/0330    
	/* 
	 *  first check routes 
	 */ 
	lock(&iprtab); 
	for(r = iprtab.first; r; r = r->next){ 
		if((r->mask[0]&dst[0]) == r->dst[0] 
		&& (r->mask[1]&dst[1]) == r->dst[1] 
		&& (r->mask[2]&dst[2]) == r->dst[2] 
		&& (r->mask[3]&dst[3]) == r->dst[3]){ 
			memmove(gate, r->gate, 4); 
			unlock(&iprtab); 
1991/0401    
		if((r->mask&udst) == r->dst){ 
			hnputl(gate, r->gate); 
1991/0330    
			return; 
		} 
	} 
	unlock(&iprtab); 
 
	/* 
	 *  else just return what we got 
1991/0401    
	 *  else just return the same address 
1991/0330    
	 */	 
	memmove(gate, dst, 4); 
} 
 
/* 
 *  Compares 2 subnet masks and returns an integer less than, equal to, 
 *  or greater than 0, according as m1 is numericly less than, 
 *  equal to, or greater than m2. 
 */ 
ipmaskcmp(uchar *m1, uchar *m2) 
{ 
	int a, i; 
                 
	for(i = 0; i < 4; i++){ 
		if(a = *m1++ - *m2++) 
			return a; 
	} 
	return 0; 
} 
                 
/* 
 *  Add a route, create a mask if the first mask is 0. 
 * 
 *  All routes are stored sorted by the length of leading 
1991/0331/sys/src/9/port/deviproute.c:133,1521991/0401/sys/src/9/port/deviproute.c:88,103
1991/0330    
 *  NOTE: A default route has an all zeroes mask and dst. 
 */ 
void 
ipaddroute(uchar *dst, uchar *mask, uchar *gate) 
1991/0401    
ipaddroute(ulong dst, ulong mask, ulong gate) 
1991/0330    
{ 
	Iproute *r, *e, *free; 
	int i; 
 
	if(mask==0) 
		mask = CLASSMASK(dst); 
                 
	/* 
	 *  filter out impossible requests 
	 */ 
	for(i = 0; i < 4; i++) 
		if((dst[i]&mask[i]) != dst[i]) 
1991/0331    
			errors("bad ip route"); 
1991/0401    
	if((dst&mask) != dst) 
		errors("bad ip route"); 
1991/0330    
 
	/* 
	 *  see if we already have a route for 
1991/0331/sys/src/9/port/deviproute.c:159,1821991/0401/sys/src/9/port/deviproute.c:110,135
1991/0330    
			free = r; 
			continue; 
		} 
		if(memcmp(dst, r->dst, 4)==0 && memcmp(mask, r->mask, 4)==0){ 
			memmove(r->gate, gate, 4); 
1991/0401    
		if(dst==r->dst && mask==r->mask){ 
			r->gate = gate; 
1991/0330    
			unlock(&iprtab); 
			return; 
		} 
	} 
1991/0331    
	if(free == 0) 
1991/0401    
	if(free == 0){ 
		unlock(&iprtab); 
1991/0331    
		errors("no free ip routes"); 
1991/0401    
	} 
1991/0330    
 
	/* 
	 *  add the new route in sorted order 
	 */ 
	memmove(free->dst, dst, 4); 
	memmove(free->mask, mask, 4); 
	memmove(free->gate, gate, 4); 
1991/0401    
	free->dst = dst; 
	free->mask = mask; 
	free->gate = gate; 
1991/0330    
	free->inuse = 1; 
	for(r = iprtab.first; r; r = r->next){ 
		if(ipmaskcmp(free->mask, r->mask) > 0) 
1991/0401    
	for(r = e = iprtab.first; r; r = r->next){ 
		if(mask > r->mask) 
1991/0330    
			break; 
		e = r; 
	} 
1991/0331/sys/src/9/port/deviproute.c:193,2051991/0401/sys/src/9/port/deviproute.c:146,158
1991/0330    
 *  remove a route 
 */ 
void 
ipremroute(uchar *dst, uchar *mask) 
1991/0401    
ipremroute(ulong dst, ulong mask) 
1991/0330    
{ 
	Iproute *r, *e; 
 
	lock(&iprtab); 
	for(r = iprtab.first; r; r = r->next){ 
		if(memcmp(dst, r->dst, 4)==0 && memcmp(mask, r->mask, 4)==0){ 
1991/0401    
	for(r = e = iprtab.first; r; r = r->next){ 
		if(dst==r->dst && mask==r->mask){ 
1991/0330    
			if(r == iprtab.first) 
				iprtab.first = r->next; 
			else 
1991/0331/sys/src/9/port/deviproute.c:317,3251991/0401/sys/src/9/port/deviproute.c:270,279
1991/0331    
long 
iprouteread(Chan *c, void *a, long n) 
{ 
	char	buf[IPR_ENTRYLEN*2]; 
1991/0401    
	char	buf[IPR_ENTRYLEN*3]; 
1991/0331    
	Iproute	*r; 
	int	part, bytes, size; 
1991/0401    
	uchar	dst[4], mask[4], gate[4]; 
1991/0331    
 
	switch((int)(c->qid.path&~CHDIR)){ 
	case Qdir: 
1991/0331/sys/src/9/port/deviproute.c:328,3531991/0401/sys/src/9/port/deviproute.c:282,312
1991/0331    
		lock(&iprtab); 
		part = c->offset/IPR_ENTRYLEN; 
		for(r = iprtab.first; part && r; r = r->next) 
			; 
1991/0401    
			part--; 
1991/0331    
		bytes = c->offset; 
		while(bytes < iprtab.n*IPR_ENTRYLEN && n){ 
1991/0401    
		while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){ 
1991/0331    
			part = bytes%IPR_ENTRYLEN; 
 
1991/0401    
			hnputl(dst, r->dst); 
			hnputl(mask, r->mask); 
			hnputl(gate, r->gate); 
1991/0331    
			sprint(buf,"%d.%d.%d.%d & %d.%d.%d.%d -> %d.%d.%d.%d%s", 
				r->dst[0], r->dst[1], r->dst[2], r->dst[3], 
				r->mask[0], r->mask[1], r->mask[2], r->mask[3], 
				r->gate[0], r->gate[1], r->gate[2], r->gate[3], 
1991/0401    
				dst[0], dst[1], dst[2], dst[3], 
				mask[0], mask[1], mask[2], mask[3], 
				gate[0], gate[1], gate[2], gate[3], 
1991/0331    
				PAD);  
			 
			buf[IPR_ENTRYLEN-1] = '\n'; 
 
			size = IPR_ENTRYLEN - part; 
			size = MIN(n, size); 
1991/0401    
			if(size > n) 
				size = n; 
1991/0331    
			memmove(a, buf+part, size); 
 
			a = (void *)((int)a + size); 
			n -= size; 
			bytes += size; 
1991/0401    
			r = r->next; 
1991/0331    
		} 
		unlock(&iprtab); 
		return bytes - c->offset; 
1991/0331/sys/src/9/port/deviproute.c:364,3701991/0401/sys/src/9/port/deviproute.c:323,329
1991/0331    
{ 
	char buf[IPR_ENTRYLEN]; 
	char *field[4]; 
	uchar mask[4], dst[4], gate[4]; 
1991/0401    
	Ipaddr mask, dst, gate; 
1991/0331    
	int m; 
 
	switch((int)(c->qid.path&~CHDIR)){ 
1991/0331/sys/src/9/port/deviproute.c:377,3911991/0401/sys/src/9/port/deviproute.c:336,350
1991/0331    
		else if(strcmp(field[0], "add") == 0){ 
			switch(m){ 
			case 4: 
				strtoip(field[1], dst); 
				strtoip(field[2], mask); 
				strtoip(field[3], gate); 
1991/0401    
				dst = ipparse(field[1]); 
				mask = ipparse(field[2]); 
				gate = ipparse(field[3]); 
1991/0331    
				ipaddroute(dst, mask, gate); 
				break; 
			case 3: 
				strtoip(field[1], dst); 
				strtoip(field[2], gate); 
				ipaddroute(dst, 0, gate); 
1991/0401    
				dst = ipparse(field[1]); 
				gate = ipparse(field[2]); 
				ipaddroute(dst, classmask[dst>>30], gate); 
1991/0331    
				break; 
			default: 
				error(Ebadarg); 
1991/0331/sys/src/9/port/deviproute.c:393,4051991/0401/sys/src/9/port/deviproute.c:352,364
1991/0331    
		} else if(strcmp(field[0], "delete") == 0){ 
			switch(m){ 
			case 3: 
				strtoip(field[1], dst); 
				strtoip(field[2], mask); 
1991/0401    
				dst = ipparse(field[1]); 
				mask = ipparse(field[2]); 
1991/0331    
				ipremroute(dst, mask); 
				break; 
			case 2: 
				strtoip(field[1], dst); 
				ipremroute(dst, 0); 
1991/0401    
				dst = ipparse(field[1]); 
				ipremroute(dst, classmask[dst>>30]); 
1991/0331    
				break; 
			default: 
				error(Ebadarg); 
1991/0401/sys/src/9/port/deviproute.c:268,2741991/0411/sys/src/9/port/deviproute.c:268,274 (short | long)
1991/0331    
#define PAD "                                                                  " 
 
long 
iprouteread(Chan *c, void *a, long n) 
1991/0411    
iprouteread(Chan *c, void *a, long n, ulong offset) 
1991/0331    
{ 
1991/0401    
	char	buf[IPR_ENTRYLEN*3]; 
1991/0331    
	Iproute	*r; 
1991/0401/sys/src/9/port/deviproute.c:280,2891991/0411/sys/src/9/port/deviproute.c:280,289
1991/0331    
		return devdirread(c, a, n, iproutetab, Niproutetab, devgen); 
	case Qdata: 
		lock(&iprtab); 
		part = c->offset/IPR_ENTRYLEN; 
1991/0411    
		part = offset/IPR_ENTRYLEN; 
1991/0331    
		for(r = iprtab.first; part && r; r = r->next) 
1991/0401    
			part--; 
1991/0331    
		bytes = c->offset; 
1991/0411    
		bytes = offset; 
1991/0401    
		while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){ 
1991/0331    
			part = bytes%IPR_ENTRYLEN; 
 
1991/0401/sys/src/9/port/deviproute.c:309,3151991/0411/sys/src/9/port/deviproute.c:309,315
1991/0401    
			r = r->next; 
1991/0331    
		} 
		unlock(&iprtab); 
		return bytes - c->offset; 
1991/0411    
		return bytes - offset; 
1991/0331    
		break; 
	default: 
		n=0; 
1991/0401/sys/src/9/port/deviproute.c:319,3251991/0411/sys/src/9/port/deviproute.c:319,325
1991/0331    
} 
 
long 
iproutewrite(Chan *c, char *a, long n) 
1991/0411    
iproutewrite(Chan *c, char *a, long n, ulong offset) 
1991/0331    
{ 
	char buf[IPR_ENTRYLEN]; 
	char *field[4]; 
1991/0411/sys/src/9/port/deviproute.c:207,2131991/0418/sys/src/9/port/deviproute.c:207,213 (short | long)
1991/0331    
Chan * 
iprouteattach(char *spec) 
{ 
	return devattach('R', spec); 
1991/0418    
	return devattach('P', spec); 
1991/0331    
} 
 
Chan * 
1991/0418/sys/src/9/port/deviproute.c:190,1961991/0419/sys/src/9/port/deviproute.c:190,196 (short | long)
1991/0331    
	Qdata, 
}; 
Dirtab iproutetab[]={ 
	"iproute",		Qdata,		0,	0600, 
1991/0419    
	"iproute",		{Qdata},		0,	0600, 
1991/0331    
}; 
#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) 
 
1991/0418/sys/src/9/port/deviproute.c:220,2251991/0419/sys/src/9/port/deviproute.c:220,231
1991/0331    
iproutewalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); 
1991/0419    
} 
 
Chan* 
iprouteclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
1991/0331    
} 
 
void 
1991/0419/sys/src/9/port/deviproute.c:222,2331991/0427/sys/src/9/port/deviproute.c:222,227 (short | long)
1991/0331    
	return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); 
1991/0419    
} 
 
Chan* 
iprouteclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
1991/0331    
} 
                 
void 
iproutestat(Chan *c, char *db) 
{ 
1991/0427/sys/src/9/port/deviproute.c:190,1961991/0629/sys/src/9/port/deviproute.c:190,196 (short | long)
1991/0331    
	Qdata, 
}; 
Dirtab iproutetab[]={ 
1991/0419    
	"iproute",		{Qdata},		0,	0600, 
1991/0629    
	"iproute",		{Qdata},		0,	0666, 
1991/0331    
}; 
#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) 
 
1991/0629/sys/src/9/port/deviproute.c:190,1961991/0705/sys/src/9/port/deviproute.c:190,196 (short | long)
1991/0331    
	Qdata, 
}; 
Dirtab iproutetab[]={ 
1991/0629    
	"iproute",		{Qdata},		0,	0666, 
1991/0705    
	"iproute",		{Qdata},		0,	0600, 
1991/0331    
}; 
#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) 
 
1991/0705/sys/src/9/port/deviproute.c:190,1961991/1112/sys/src/9/port/deviproute.c:190,196 (short | long)
1991/0331    
	Qdata, 
}; 
Dirtab iproutetab[]={ 
1991/0705    
	"iproute",		{Qdata},		0,	0600, 
1991/1112    
	"iproute",		{Qdata},		0,	0666, 
1991/0331    
}; 
#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) 
 
1991/1112/sys/src/9/port/deviproute.c:244,2491991/1115/sys/src/9/port/deviproute.c:244,250 (short | long)
1991/0331    
void 
iproutecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	USED(c, name, omode, perm); 
1991/0331    
	error(Eperm); 
} 
 
1991/1112/sys/src/9/port/deviproute.c:250,2551991/1115/sys/src/9/port/deviproute.c:251,257
1991/0331    
void 
iprouteremove(Chan *c) 
{ 
1991/1115    
	USED(c); 
1991/0331    
	error(Eperm); 
} 
 
1991/1112/sys/src/9/port/deviproute.c:256,2611991/1115/sys/src/9/port/deviproute.c:258,264
1991/0331    
void 
iproutewstat(Chan *c, char *dp) 
{ 
1991/1115    
	USED(c, dp); 
1991/0331    
	error(Eperm); 
} 
 
1991/1112/sys/src/9/port/deviproute.c:262,2671991/1115/sys/src/9/port/deviproute.c:265,271
1991/0331    
void 
iprouteclose(Chan *c) 
{ 
1991/1115    
	USED(c); 
1991/0331    
} 
 
#define IPR_ENTRYLEN 54 
1991/1115/sys/src/9/port/deviproute.c:3,91992/0111/sys/src/9/port/deviproute.c:3,9 (short | long)
Move error.h to ../port. Change errors to actual strings.
rsc Fri Mar 4 12:44:25 2005
1991/0331    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1991/0401    
#include	"arp.h" 
#include	"ipdat.h" 
1991/0330    
 
1992/0111/sys/src/9/port/deviproute.c:97,1031992/0112/sys/src/9/port/deviproute.c:97,103 (short | long)
1991/0330    
	 *  filter out impossible requests 
	 */ 
1991/0401    
	if((dst&mask) != dst) 
		errors("bad ip route"); 
1992/0112    
		error(Ebadaddr); 
1991/0330    
 
	/* 
	 *  see if we already have a route for 
1992/0111/sys/src/9/port/deviproute.c:118,1241992/0112/sys/src/9/port/deviproute.c:118,124
1991/0330    
	} 
1991/0401    
	if(free == 0){ 
		unlock(&iprtab); 
1991/0331    
		errors("no free ip routes"); 
1992/0112    
		error(Enoroute); 
1991/0401    
	} 
1991/0330    
 
	/* 
1992/0112/sys/src/9/port/deviproute.c:97,1031992/0114/sys/src/9/port/deviproute.c:97,103 (short | long)
1991/0330    
	 *  filter out impossible requests 
	 */ 
1991/0401    
	if((dst&mask) != dst) 
1992/0112    
		error(Ebadaddr); 
1992/0114    
		error(Enetaddr); 
1991/0330    
 
	/* 
	 *  see if we already have a route for 
1992/0112/sys/src/9/port/deviproute.c:118,1241992/0114/sys/src/9/port/deviproute.c:118,124
1991/0330    
	} 
1991/0401    
	if(free == 0){ 
		unlock(&iprtab); 
1992/0112    
		error(Enoroute); 
1992/0114    
		exhausted("routes"); 
1991/0401    
	} 
1991/0330    
 
	/* 
1992/0114/sys/src/9/port/deviproute.c:58,641992/0213/sys/src/9/port/deviproute.c:58,64 (short | long)
1991/0401    
	ulong udst; 
1991/0330    
 
1991/0401    
	udst = nhgetl(dst); 
	if((udst&Mymask) == (Myip&Mymask)){ 
1992/0213    
	if((udst&Mymask) == (Myip[Myself]&Mymask)){ 
1991/0401    
		memmove(gate, dst, 4); 
		return; 
	} 
1992/0213/sys/src/9/port/deviproute.c:58,641992/0304/sys/src/9/port/deviproute.c:58,64 (short | long)
1991/0401    
	ulong udst; 
1991/0330    
 
1991/0401    
	udst = nhgetl(dst); 
1992/0213    
	if((udst&Mymask) == (Myip[Myself]&Mymask)){ 
1992/0304    
	if((udst&Mynetmask) == (Myip[Myself]&Mynetmask)){ 
1991/0401    
		memmove(gate, dst, 4); 
		return; 
	} 
1992/0304/sys/src/9/port/deviproute.c:1,51992/0321/sys/src/9/port/deviproute.c:1,5 (short | long)
Move lib.h to ../port.
rsc Fri Mar 4 12:44:25 2005
1991/0331    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0331    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/port/deviproute.c:91,971992/0711/sys/src/9/port/deviproute.c:91,96 (short | long)
1991/0401    
ipaddroute(ulong dst, ulong mask, ulong gate) 
1991/0330    
{ 
	Iproute *r, *e, *free; 
	int i; 
 
	/* 
	 *  filter out impossible requests 
1992/0321/sys/src/9/port/deviproute.c:329,3341992/0711/sys/src/9/port/deviproute.c:328,335
1991/0331    
	char *field[4]; 
1991/0401    
	Ipaddr mask, dst, gate; 
1991/0331    
	int m; 
1992/0711    
 
	USED(offset); 
1991/0331    
 
	switch((int)(c->qid.path&~CHDIR)){ 
	case Qdata: 
1992/0711/sys/src/9/port/deviproute.c:1,3771993/0804/sys/src/9/port/deviproute.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:30:45 2005
1991/0331    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0331    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1991/0401    
#include	"arp.h" 
#include	"ipdat.h" 
1991/0330    
                 
1991/0331    
#include	"devtab.h" 
                 
1991/0401    
/* 
 *  All ip numbers and masks are stored as ulongs. 
 *  All interfaces to this code uses the standard byte 
 *  string representation. 
 */ 
                 
1991/0330    
typedef	struct Iproute	Iproute; 
typedef	struct Iprtab	Iprtab; 
                 
enum 
{ 
	Nroutes=	256, 
}; 
                 
/* 
 *  routes 
 */ 
struct Iproute { 
1991/0401    
	ulong	dst; 
	ulong	gate; 
	ulong	mask; 
1991/0330    
	Iproute	*next; 
	int	inuse; 
}; 
struct Iprtab { 
1991/0331    
	Lock; 
	int	n;		/* number of valid routes */ 
	Iproute *first;		/* list of valid routes */ 
	Iproute	r[Nroutes];	/* all routes */ 
1991/0330    
}; 
Iprtab	iprtab; 
                 
1991/0331    
/* 
1991/0330    
 *  The chosen route is the one obeys the constraint 
1991/0401    
 *		r->mask & dst == r->dst 
1991/0330    
 * 
 *  If there are several matches, the one whose mask has the most 
1991/0401    
 *  leading ones (and hence is the most specific) wins.  This is 
 *  forced by storing the routes in decreasing number of ones order 
 *  and returning the first match.  The default gateway has no ones 
 *  in the mask and is thus the last matched. 
1991/0330    
 */ 
void 
iproute(uchar *dst, uchar *gate) 
{ 
	Iproute *r; 
1991/0401    
	ulong udst; 
1991/0330    
                 
1991/0401    
	udst = nhgetl(dst); 
1992/0304    
	if((udst&Mynetmask) == (Myip[Myself]&Mynetmask)){ 
1991/0401    
		memmove(gate, dst, 4); 
		return; 
	} 
                 
1991/0330    
	/* 
	 *  first check routes 
	 */ 
	for(r = iprtab.first; r; r = r->next){ 
1991/0401    
		if((r->mask&udst) == r->dst){ 
			hnputl(gate, r->gate); 
1991/0330    
			return; 
		} 
	} 
                 
	/* 
1991/0401    
	 *  else just return the same address 
1991/0330    
	 */	 
	memmove(gate, dst, 4); 
} 
                 
/* 
 *  Add a route, create a mask if the first mask is 0. 
 * 
 *  All routes are stored sorted by the length of leading 
 *  ones in the mask. 
 * 
 *  NOTE: A default route has an all zeroes mask and dst. 
 */ 
void 
1991/0401    
ipaddroute(ulong dst, ulong mask, ulong gate) 
1991/0330    
{ 
	Iproute *r, *e, *free; 
                 
	/* 
	 *  filter out impossible requests 
	 */ 
1991/0401    
	if((dst&mask) != dst) 
1992/0114    
		error(Enetaddr); 
1991/0330    
                 
	/* 
	 *  see if we already have a route for 
	 *  the destination 
	 */ 
	lock(&iprtab); 
	free = 0; 
	for(r = iprtab.r; r < &iprtab.r[Nroutes]; r++){ 
		if(r->inuse == 0){ 
			free = r; 
			continue; 
		} 
1991/0401    
		if(dst==r->dst && mask==r->mask){ 
			r->gate = gate; 
1991/0330    
			unlock(&iprtab); 
			return; 
		} 
	} 
1991/0401    
	if(free == 0){ 
		unlock(&iprtab); 
1992/0114    
		exhausted("routes"); 
1991/0401    
	} 
1991/0330    
                 
	/* 
	 *  add the new route in sorted order 
	 */ 
1991/0401    
	free->dst = dst; 
	free->mask = mask; 
	free->gate = gate; 
1991/0330    
	free->inuse = 1; 
1991/0401    
	for(r = e = iprtab.first; r; r = r->next){ 
		if(mask > r->mask) 
1991/0330    
			break; 
		e = r; 
	} 
	free->next = r; 
	if(r == iprtab.first) 
		iprtab.first = free; 
	else 
		e->next = free; 
1991/0331    
	iprtab.n++; 
1991/0330    
	unlock(&iprtab); 
} 
                 
/* 
 *  remove a route 
 */ 
void 
1991/0401    
ipremroute(ulong dst, ulong mask) 
1991/0330    
{ 
	Iproute *r, *e; 
                 
	lock(&iprtab); 
1991/0401    
	for(r = e = iprtab.first; r; r = r->next){ 
		if(dst==r->dst && mask==r->mask){ 
1991/0330    
			if(r == iprtab.first) 
				iprtab.first = r->next; 
			else 
				e->next = r->next; 
			r->inuse = 0; 
1991/0331    
			iprtab.n--; 
1991/0330    
			break; 
		} 
		e = r; 
	} 
	unlock(&iprtab); 
} 
                 
/* 
 *  remove all routes 
 */ 
void 
ipflushroute(void) 
{ 
	Iproute *r; 
                 
	lock(&iprtab); 
	for(r = iprtab.first; r; r = r->next) 
		r->inuse = 0; 
	iprtab.first = 0; 
1991/0331    
	iprtab.n = 0; 
1991/0330    
	unlock(&iprtab); 
1991/0331    
} 
                 
/* 
 *  device interface 
 */ 
enum{ 
	Qdir, 
	Qdata, 
}; 
Dirtab iproutetab[]={ 
1991/1112    
	"iproute",		{Qdata},		0,	0666, 
1991/0331    
}; 
#define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) 
                 
void 
iproutereset(void) 
{ 
} 
                 
void 
iprouteinit(void) 
{ 
} 
                 
Chan * 
iprouteattach(char *spec) 
{ 
1991/0418    
	return devattach('P', spec); 
1991/0331    
} 
                 
Chan * 
iprouteclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
                 
int 
iproutewalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); 
1991/0419    
} 
                 
1991/0331    
void 
iproutestat(Chan *c, char *db) 
{ 
	devstat(c, db, iproutetab, (long)Niproutetab, devgen); 
} 
                 
Chan * 
iprouteopen(Chan *c, int omode) 
{ 
	if(c->qid.path == CHDIR){ 
		if(omode != OREAD) 
			error(Eperm); 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
                 
void 
iproutecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	USED(c, name, omode, perm); 
1991/0331    
	error(Eperm); 
} 
                 
void 
iprouteremove(Chan *c) 
{ 
1991/1115    
	USED(c); 
1991/0331    
	error(Eperm); 
} 
                 
void 
iproutewstat(Chan *c, char *dp) 
{ 
1991/1115    
	USED(c, dp); 
1991/0331    
	error(Eperm); 
} 
                 
void 
iprouteclose(Chan *c) 
{ 
1991/1115    
	USED(c); 
1991/0331    
} 
                 
#define IPR_ENTRYLEN 54 
#define PAD "                                                                  " 
                 
long 
1991/0411    
iprouteread(Chan *c, void *a, long n, ulong offset) 
1991/0331    
{ 
1991/0401    
	char	buf[IPR_ENTRYLEN*3]; 
1991/0331    
	Iproute	*r; 
	int	part, bytes, size; 
1991/0401    
	uchar	dst[4], mask[4], gate[4]; 
1991/0331    
                 
	switch((int)(c->qid.path&~CHDIR)){ 
	case Qdir: 
		return devdirread(c, a, n, iproutetab, Niproutetab, devgen); 
	case Qdata: 
		lock(&iprtab); 
1991/0411    
		part = offset/IPR_ENTRYLEN; 
1991/0331    
		for(r = iprtab.first; part && r; r = r->next) 
1991/0401    
			part--; 
1991/0411    
		bytes = offset; 
1991/0401    
		while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){ 
1991/0331    
			part = bytes%IPR_ENTRYLEN; 
                 
1991/0401    
			hnputl(dst, r->dst); 
			hnputl(mask, r->mask); 
			hnputl(gate, r->gate); 
1991/0331    
			sprint(buf,"%d.%d.%d.%d & %d.%d.%d.%d -> %d.%d.%d.%d%s", 
1991/0401    
				dst[0], dst[1], dst[2], dst[3], 
				mask[0], mask[1], mask[2], mask[3], 
				gate[0], gate[1], gate[2], gate[3], 
1991/0331    
				PAD);  
			                 
			buf[IPR_ENTRYLEN-1] = '\n'; 
                 
			size = IPR_ENTRYLEN - part; 
1991/0401    
			if(size > n) 
				size = n; 
1991/0331    
			memmove(a, buf+part, size); 
                 
			a = (void *)((int)a + size); 
			n -= size; 
			bytes += size; 
1991/0401    
			r = r->next; 
1991/0331    
		} 
		unlock(&iprtab); 
1991/0411    
		return bytes - offset; 
1991/0331    
		break; 
	default: 
		n=0; 
		break; 
	} 
	return n; 
} 
                 
long 
1991/0411    
iproutewrite(Chan *c, char *a, long n, ulong offset) 
1991/0331    
{ 
	char buf[IPR_ENTRYLEN]; 
	char *field[4]; 
1991/0401    
	Ipaddr mask, dst, gate; 
1991/0331    
	int m; 
1992/0711    
                 
	USED(offset); 
1991/0331    
                 
	switch((int)(c->qid.path&~CHDIR)){ 
	case Qdata: 
		strncpy(buf, a, sizeof buf); 
		m = getfields(buf, field, 4, ' '); 
                 
		if(strncmp(field[0], "flush", 5) == 0) 
			ipflushroute(); 
		else if(strcmp(field[0], "add") == 0){ 
			switch(m){ 
			case 4: 
1991/0401    
				dst = ipparse(field[1]); 
				mask = ipparse(field[2]); 
				gate = ipparse(field[3]); 
1991/0331    
				ipaddroute(dst, mask, gate); 
				break; 
			case 3: 
1991/0401    
				dst = ipparse(field[1]); 
				gate = ipparse(field[2]); 
				ipaddroute(dst, classmask[dst>>30], gate); 
1991/0331    
				break; 
			default: 
				error(Ebadarg); 
			} 
		} else if(strcmp(field[0], "delete") == 0){ 
			switch(m){ 
			case 3: 
1991/0401    
				dst = ipparse(field[1]); 
				mask = ipparse(field[2]); 
1991/0331    
				ipremroute(dst, mask); 
				break; 
			case 2: 
1991/0401    
				dst = ipparse(field[1]); 
				ipremroute(dst, classmask[dst>>30]); 
1991/0331    
				break; 
			default: 
				error(Ebadarg); 
			} 
		} 
		break; 
	default: 
		error(Ebadusefd); 
	} 
	return n; 
1991/0330    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)