~kris/9p

9hist

812b0290f086fad80c7f7b93bb311cb5f9bfb561 — David du Colombier 35 years ago 8896bf1
Plan 9 from Bell Labs 1991-03-30
2 files changed, 222 insertions(+), 0 deletions(-)

A port/deviproute.c
M port/stnoether.c
A port/deviproute.c => port/deviproute.c +207 -0
@@ 0,0 1,207 @@
#include <u.h>
#include <libc.h>

typedef	struct Iproute	Iproute;
typedef	struct Iprtab	Iprtab;

enum
{
	Nroutes=	256,
};

/*
 *  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]

/*
 *  routes
 */
struct Iproute {
	uchar	dst[4];
	uchar	gate[4];
	uchar	mask[4];
	Iproute	*next;
	int	inuse;
};
struct Iprtab {
/*	Lock; */
	Iproute *first;
	Iproute	r[Nroutes];	/* routings */
};
Iprtab	iprtab;

#define lock(x)
#define unlock(x)

void
printroute(void)
{
	Iproute *r;

	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");
}

/*
 *  The chosen route is the one obeys the constraint
 *		r->mask[x] & dst[x] == r->dst[x] for x in 0 1 2 3
 *
 *  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.
 */
void
iproute(uchar *dst, uchar *gate)
{
	Iproute *r;

	/*
	 *  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);
			return;
		}
	}
	unlock(&iprtab);

	/*
	 *  else just return what we got
	 */	
	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
 *  ones in the mask.
 *
 *  NOTE: A default route has an all zeroes mask and dst.
 */
void
ipaddroute(uchar *dst, uchar *mask, uchar *gate)
{
	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])
			return;

	/*
	 *  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;
		}
		if(memcmp(dst, r->dst, 4)==0 && memcmp(mask, r->mask, 4)==0){
			memmove(r->gate, gate, 4);
			unlock(&iprtab);
			return;
		}
	}

	/*
	 *  add the new route in sorted order
	 */
	memmove(free->dst, dst, 4);
	memmove(free->mask, mask, 4);
	memmove(free->gate, gate, 4);
	free->inuse = 1;
	for(r = iprtab.first; r; r = r->next){
		if(ipmaskcmp(free->mask, r->mask) > 0)
			break;
		e = r;
	}
	free->next = r;
	if(r == iprtab.first)
		iprtab.first = free;
	else
		e->next = free;
	unlock(&iprtab);
}

/*
 *  remove a route
 */
void
ipremroute(uchar *dst, uchar *mask)
{
	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){
			if(r == iprtab.first)
				iprtab.first = r->next;
			else
				e->next = r->next;
			r->inuse = 0;
			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;
	unlock(&iprtab);
}

M port/stnoether.c => port/stnoether.c +15 -0
@@ 267,10 267,25 @@ noetheriput(Queue *q, Block *bp)
static void
etherparse(uchar *to, char *from)
{
	ulong ip;
	uchar nip[4];
	int tdig;
	int fdig;
	int i;

#ifdef MAGNUM
	/* Dot means ip address */
	if(strchr(from, '.')) {
		ip = ipparse(from);
		if(ip == 0)
			error(Ebadnet);

		hnputl(nip, ip);			
		if(arp_lookup(nip, to))
			return;
	}
#endif

	if(strlen(from) != 12)
		error(Ebadnet);