Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/deviproute.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/deviproute.c 1991/0330
## diff -e /dev/null /n/bootesdump/1991/0330/sys/src/9/port/deviproute.c
0a
#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);
}
.
## diffname port/deviproute.c 1991/0331
## diff -e /n/bootesdump/1991/0330/sys/src/9/port/deviproute.c /n/bootesdump/1991/0331/sys/src/9/port/deviproute.c
206a
}

/*
 *  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;
.
205a
	iprtab.n = 0;
.
186a
			iprtab.n--;
.
167a
	iprtab.n++;
.
149a
	if(free == 0)
		errors("no free ip routes");
.
131c
			errors("bad ip route");
.
48,54c
	/* 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];
		}
.
46c
	int i, off, first;
	char *rptr = s;
.
44c
strtoip(char *s, uchar *addr)
.
40,42c
/*
 *  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.
 */
.
34,36c
	Lock;
	int	n;		/* number of valid routes */
	Iproute *first;		/* list of valid routes */
	Iproute	r[Nroutes];	/* all routes */
.
22a
uchar netbytes[4] = { 1, 1, 2, 3 };
#define NETBYTES(x)	netbytes[(*x>>6) & 3]

.
3a
#include	"devtab.h"

.
1,2c
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"
.
## diffname port/deviproute.c 1991/0401
## diff -e /n/bootesdump/1991/0331/sys/src/9/port/deviproute.c /n/bootesdump/1991/0401/sys/src/9/port/deviproute.c
401,402c
				dst = ipparse(field[1]);
				ipremroute(dst, classmask[dst>>30]);
.
396,397c
				dst = ipparse(field[1]);
				mask = ipparse(field[2]);
.
386,388c
				dst = ipparse(field[1]);
				gate = ipparse(field[2]);
				ipaddroute(dst, classmask[dst>>30], gate);
.
380,382c
				dst = ipparse(field[1]);
				mask = ipparse(field[2]);
				gate = ipparse(field[3]);
.
367c
	Ipaddr mask, dst, gate;
.
350a
			r = r->next;
.
345c
			if(size > n)
				size = n;
.
337,339c
				dst[0], dst[1], dst[2], dst[3],
				mask[0], mask[1], mask[2], mask[3],
				gate[0], gate[1], gate[2], gate[3],
.
335a
			hnputl(dst, r->dst);
			hnputl(mask, r->mask);
			hnputl(gate, r->gate);
.
333c
		while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){
.
331c
			part--;
.
322a
	uchar	dst[4], mask[4], gate[4];
.
320c
	char	buf[IPR_ENTRYLEN*3];
.
201,202c
	for(r = e = iprtab.first; r; r = r->next){
		if(dst==r->dst && mask==r->mask){
.
196c
ipremroute(ulong dst, ulong mask)
.
178,179c
	for(r = e = iprtab.first; r; r = r->next){
		if(mask > r->mask)
.
174,176c
	free->dst = dst;
	free->mask = mask;
	free->gate = gate;
.
169a
	}
.
168c
	if(free == 0){
		unlock(&iprtab);
.
162,163c
		if(dst==r->dst && mask==r->mask){
			r->gate = gate;
.
147,149c
	if((dst&mask) != dst)
		errors("bad ip route");
.
141,143d
136c
ipaddroute(ulong dst, ulong mask, ulong gate)
.
112,127d
106c
	 *  else just return the same address
.
103d
94,99c
		if((r->mask&udst) == r->dst){
			hnputl(gate, r->gate);
.
92d
88a
	udst = nhgetl(dst);
	if((udst&Mymask) == (Myip&Mymask)){
		memmove(gate, dst, 4);
		return;
	}

.
87a
	ulong udst;
.
80,82c
 *  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.
.
77c
 *		r->mask & dst == r->dst
.
51,75d
36,38c
	ulong	dst;
	ulong	gate;
	ulong	mask;
.
19,32d
9a
/*
 *  All ip numbers and masks are stored as ulongs.
 *  All interfaces to this code uses the standard byte
 *  string representation.
 */

.
6a
#include	"arp.h"
#include	"ipdat.h"
.
## diffname port/deviproute.c 1991/0411
## diff -e /n/bootesdump/1991/0401/sys/src/9/port/deviproute.c /n/bootesdump/1991/0411/sys/src/9/port/deviproute.c
322c
iproutewrite(Chan *c, char *a, long n, ulong offset)
.
312c
		return bytes - offset;
.
286c
		bytes = offset;
.
283c
		part = offset/IPR_ENTRYLEN;
.
271c
iprouteread(Chan *c, void *a, long n, ulong offset)
.
## diffname port/deviproute.c 1991/0418
## diff -e /n/bootesdump/1991/0411/sys/src/9/port/deviproute.c /n/bootesdump/1991/0418/sys/src/9/port/deviproute.c
210c
	return devattach('P', spec);
.
## diffname port/deviproute.c 1991/0419
## diff -e /n/bootesdump/1991/0418/sys/src/9/port/deviproute.c /n/bootesdump/1991/0419/sys/src/9/port/deviproute.c
222a
}

Chan*
iprouteclwalk(Chan *c, char *name)
{
	return devclwalk(c, name);
.
193c
	"iproute",		{Qdata},		0,	0600,
.
## diffname port/deviproute.c 1991/0427
## diff -e /n/bootesdump/1991/0419/sys/src/9/port/deviproute.c /n/bootesdump/1991/0427/sys/src/9/port/deviproute.c
225,230d
## diffname port/deviproute.c 1991/0629
## diff -e /n/bootesdump/1991/0427/sys/src/9/port/deviproute.c /n/bootesdump/1991/0629/sys/src/9/port/deviproute.c
193c
	"iproute",		{Qdata},		0,	0666,
.
## diffname port/deviproute.c 1991/0705
## diff -e /n/bootesdump/1991/0629/sys/src/9/port/deviproute.c /n/bootesdump/1991/0705/sys/src/9/port/deviproute.c
193c
	"iproute",		{Qdata},		0,	0600,
.
## diffname port/deviproute.c 1991/1112
## diff -e /n/bootesdump/1991/0705/sys/src/9/port/deviproute.c /n/bootesdump/1991/1112/sys/src/9/port/deviproute.c
193c
	"iproute",		{Qdata},		0,	0666,
.
## diffname port/deviproute.c 1991/1115
## diff -e /n/bootesdump/1991/1112/sys/src/9/port/deviproute.c /n/bootesdump/1991/1115/sys/src/9/port/deviproute.c
264a
	USED(c);
.
258a
	USED(c, dp);
.
252a
	USED(c);
.
246a
	USED(c, name, omode, perm);
.
## diffname port/deviproute.c 1992/0111
## diff -e /n/bootesdump/1991/1115/sys/src/9/port/deviproute.c /n/bootesdump/1992/0111/sys/src/9/port/deviproute.c
6c
#include	"../port/error.h"
.
## diffname port/deviproute.c 1992/0112
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/deviproute.c /n/bootesdump/1992/0112/sys/src/9/port/deviproute.c
121c
		error(Enoroute);
.
100c
		error(Ebadaddr);
.
## diffname port/deviproute.c 1992/0114
## diff -e /n/bootesdump/1992/0112/sys/src/9/port/deviproute.c /n/bootesdump/1992/0114/sys/src/9/port/deviproute.c
121c
		exhausted("routes");
.
100c
		error(Enetaddr);
.
## diffname port/deviproute.c 1992/0213
## diff -e /n/bootesdump/1992/0114/sys/src/9/port/deviproute.c /n/bootesdump/1992/0213/sys/src/9/port/deviproute.c
61c
	if((udst&Mymask) == (Myip[Myself]&Mymask)){
.
## diffname port/deviproute.c 1992/0304
## diff -e /n/bootesdump/1992/0213/sys/src/9/port/deviproute.c /n/bootesdump/1992/0304/sys/src/9/port/deviproute.c
61c
	if((udst&Mynetmask) == (Myip[Myself]&Mynetmask)){
.
## diffname port/deviproute.c 1992/0321
## diff -e /n/bootesdump/1992/0304/sys/src/9/port/deviproute.c /n/bootesdump/1992/0321/sys/src/9/port/deviproute.c
2c
#include	"../port/lib.h"
.
## diffname port/deviproute.c 1992/0711
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/deviproute.c /n/bootesdump/1992/0711/sys/src/9/port/deviproute.c
331a

	USED(offset);
.
94d
## diffname port/deviproute.c 1993/0804 # deleted
## diff -e /n/bootesdump/1992/0711/sys/src/9/port/deviproute.c /n/fornaxdump/1993/0804/sys/src/brazil/port/deviproute.c
1,377d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].