Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/ip/iproute.c

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


## diffname ip/iproute.c 1998/0306
## diff -e /dev/null /n/emeliedump/1998/0306/sys/src/brazil/ip/iproute.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

#include	"ip.h"

enum
{
	Lroot	= 10,
};

Route *v4root[1<<Lroot], *v6root[1<<Lroot], *queue;

static void	walkadd(Route**, Route*);
static void	addnode(Route**, Route*);
static void	calcd(Route*);

Route*	v4freelist;
Route*	v6freelist;
RWlock	routelock;

static void
freeroute(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;

	return r;
}

static void
addqueue(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 int
lcmp(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 int
rangecompare(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 void
copygate(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 void
walkadd(Route **root, Route *p)
{
	Route *l, *r;

	l = p->left;
	r = p->right;
	p->left = 0;
	p->right = 0;
	addnode(root, p);
	if(l)
		walkadd(root, l);
	if(r)
		walkadd(root, r);
}

/*
 *  calculate depth
 */
static void
calcd(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 void
balancetree(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 void
addnode(Route **cur, Route *new)
{
	Route *p;

	p = *cur;
	if(p == 0) {
		*cur = new;
		new->depth = 1;
		return;
	}

	switch(rangecompare(new, p)){
	case Rpreceeds:
		addnode(&p->left, new);
		break;
	case Rfollows:
		addnode(&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(&queue, p);
		break;
	case Requals:
		copygate(p, new);
		freeroute(new);
		break;
	case Rcontained:
		addnode(&p->mid, new);
		break;
	}
	
	balancetree(cur);
}

#define	V4H(a)	((a&0x07ffffff)>>(32-Lroot-5))

void
v4addroute(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(&v4root[h], p);
		while(p = queue) {
			queue = p->mid;
			walkadd(&v4root[h], p->left);
			freeroute(p);
		}
		wunlock(&routelock);
	}

	ipifcaddroute(Rv4, a, mask, gate, type);
}

#define	V6H(a)	(((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))

void
v6addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type)
{
	Route *p;
	ulong sa[IPllen], ea[IPllen];
	ulong x, y;
	int h, eh;

	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(&v6root[h], p);
		while(p = queue) {
			queue = p->mid;
			walkadd(&v6root[h], p->left);
			freeroute(p);
		}
		wunlock(&routelock);
	}

	ipifcaddroute(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;
		}
	}
}

void
v4delroute(uchar *a, uchar *mask)
{
	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++) {
		wlock(&routelock);
		r = looknode(&v4root[h], &rt);
		if(r) {
			p = *r;
			*r = 0;
			addqueue(&queue, p->left);
			addqueue(&queue, p->mid);
			addqueue(&queue, p->right);
			freeroute(p);
			while(p = queue) {
				queue = p->mid;
				walkadd(&v4root[h], p->left);
				freeroute(p);
			}
		}
		wunlock(&routelock);
	}

	ipifcremroute(Rv4, a, mask);
}

void
v6delroute(uchar *a, uchar *mask)
{
	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++) {
		wlock(&routelock);
		r = looknode(&v6root[h], &rt);
		if(r) {
			p = *r;
			*r = 0;
			addqueue(&queue, p->left);
			addqueue(&queue, p->mid);
			addqueue(&queue, p->right);
			freeroute(p);
			while(p = queue) {
				queue = p->mid;
				walkadd(&v6root[h], p->left);
				freeroute(p);
			}
		}
		wunlock(&routelock);
	}

	ipifcremroute(0, a, mask);
}

Route*
v4lookup(uchar *a)
{
	Route *p, *q;
	ulong la;
	uchar gate[IPaddrlen];

	la = nhgetl(a);
	q = nil;
	for(p=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)){
		v4tov6(gate, q->v4.gate);
		q->ifc = findipifc(gate, q->type);
		if(q->ifc == nil)
			return nil;
		q->ifcid = q->ifc->ifcid;
	}

	return q;
}

Route*
v6lookup(uchar *a)
{
	Route *p, *q;
	ulong la[IPllen];
	int h;
	ulong x, y;

	if(memcmp(a, v4prefix, 12) == 0){
		q = v4lookup(a+12);
		if(q != nil)
			return q;
	}

	for(h = 0; h < IPllen; h++)
		la[h] = nhgetl(a+4*h);

	q = 0;
	for(p=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->ifc = findipifc(q->v6.gate, q->type);
		if(q->ifc == nil)
			return nil;
		if(q->ifcid != q->ifc->ifcid)
			return nil;
	}
	
	return q;
}

enum
{
	Rlinelen=	89,
};

char *rformat = "%-24.24I %-24.24M %-24.24I %4.4s %4.4s %3s\n";

void
convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc)
{
	int i;
	char *p = t;

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

	memset(t, ' ', 4);
	t[4] = 0;
	if(r->type & Rv4)
		*p++ = '4';
	else
		*p++ = '6';
	if(r->type & Rifc)
		*p++ = 'i';
	if(r->type & Runi)
		*p++ = 'u';
	else if(r->type & Rbcast)
		*p++ = 'b';
	else if(r->type & Rmulti)
		*p++ = 'm';
	if(r->type & Rptpt)
		*p = 'p';

	if(r->ifc)
		*nifc = r->ifc->conv->x;
	else
		*nifc = -1;
}

/*
 *  this code is not in rr to reduce stack size
 */
static void
sprintroute(Route *r, Routewalk *rw)
{
	int nifc;
	char t[5], *iname, ifbuf[5];
	uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];

	if(rw->o >= 0) {
		convroute(r, addr, mask, gate, t, &nifc);
		iname = "-";
		if(nifc != -1) {
			iname = ifbuf;
			sprint(ifbuf, "%d", nifc);
		}
		sprint(rw->p, rformat, addr, mask, gate, t, r->tag, iname);
		rw->p += Rlinelen;
	}
	rw->o++;
}

/*
 *  recurse descending tree, applying the function in Routewalk
 */
static int
rr(Route *r, Routewalk *rw)
{
	int h;

	if(rw->n <= rw->o)
		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);
}

void
ipwalkroutes(Routewalk *rw)
{
	rlock(&routelock);
	if(rw->n > rw->o) {
		for(rw->h = 0; rw->h < nelem(v4root); rw->h++)
			if(rr(v4root[rw->h], rw) == 0)
				break;
	}
	if(rw->n > rw->o) {
		for(rw->h = 0; rw->h < nelem(v6root); rw->h++)
			if(rr(v6root[rw->h], rw) == 0)
				break;
	}
	runlock(&routelock);
}

long
routeread(char *p, ulong offset, int n)
{
	Routewalk rw;

	if(offset % Rlinelen)
		return 0;

	rw.p = p;
	rw.n = n/Rlinelen;
	rw.o = -(offset/Rlinelen);
	rw.walk = sprintroute;

	ipwalkroutes(&rw);

	if(rw.o < 0)
		rw.o = 0;

	return rw.o*Rlinelen;
}

/*
 *  this code is not in routeflush to reduce stack size
 */
void
delroute(Route *r)
{
	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(addr+IPv4off, mask+IPv4off);
	else
		v6delroute(addr, mask);
}

/*
 *  recurse until one route is deleted
 *    returns 0 if nothing is deleted, 1 otherwise
 */
int
routeflush(Route *r)
{
	if(r == nil)
		return 0;
	if(routeflush(r->mid))
		return 1;
	if(routeflush(r->left))
		return 1;
	if(routeflush(r->right))
		return 1;
	if((r->type & Rifc) == 0){
		delroute(r);
		return 1;
	}
	return 0;
}

long
routewrite(Chan *c, char *p, int n)
{
	int h;
	char *tag;
	Cmdbuf *cb;
	uchar addr[IPaddrlen];
	uchar mask[IPaddrlen];
	uchar gate[IPaddrlen];

	cb = parsecmd(p, n);
	if(waserror()){
		free(cb);
		nexterror();
	}

	if(strcmp(cb->f[0], "flush") == 0){
		wlock(&routelock);
		for(h = 0; h < nelem(v4root); h++)
			while(routeflush(v4root[h]) == 1)
				;
		for(h = 0; h < nelem(v6root); h++)
			while(routeflush(v6root[h]) == 1)
				;
		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(addr+IPv4off, mask+IPv4off);
		else
			v6delroute(addr, mask);
	} 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)
			tag = c->tag;
		if(memcmp(addr, v4prefix, IPv4off) == 0)
			v4addroute(tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);
		else
			v6addroute(tag, addr, mask, gate, 0);
	} else if(strcmp(cb->f[0], "tag") == 0) {
		if(cb->nf < 2)
			error(Ebadarg);

		h = strlen(cb->f[1]);
		if(h > sizeof(c->tag))
			h = sizeof(c->tag);
		strncpy(c->tag, cb->f[1], h);
		if(h < 4)
			memset(c->tag+h, ' ', sizeof(c->tag)-h);
	}

	poperror();
	free(cb);
	return n;
}
.
## diffname ip/iproute.c 1998/0310
## diff -e /n/emeliedump/1998/0306/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0310/sys/src/brazil/ip/iproute.c
575,590c
	routetype(r->type, t);
.
558d
546a
void
routetype(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';
}

.
## diffname ip/iproute.c 1998/0313
## diff -e /n/emeliedump/1998/0310/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0313/sys/src/brazil/ip/iproute.c
781c
			v6addroute(f, tag, addr, mask, gate, 0);
.
779c
			v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);
.
768c
			v6delroute(f, addr, mask);
.
766c
			v4delroute(f, addr+IPv4off, mask+IPv4off);
.
756,757c
		for(h = 0; h < nelem(f->v6root); h++)
			while(routeflush(f, f->v6root[h]) == 1)
.
753,754c
		for(h = 0; h < nelem(f->v4root); h++)
			while(routeflush(f, f->v4root[h]) == 1)
.
736c
routewrite(Fs *f, Chan *c, char *p, int n)
.
729c
		delroute(f, r);
.
726c
	if(routeflush(f, r->right))
.
724c
	if(routeflush(f, r->left))
.
722c
	if(routeflush(f, r->mid))
.
718c
routeflush(Fs *f, Route *r)
.
710c
		v6delroute(f, addr, mask);
.
708c
		v4delroute(f, addr+IPv4off, mask+IPv4off);
.
698c
delroute(Fs *f, Route *r)
.
686c
	ipwalkroutes(f, &rw);
.
674c
routeread(Fs *f, char *p, ulong offset, int n)
.
666,667c
		for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++)
			if(rr(f->v6root[rw->h], rw) == 0)
.
661,662c
		for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++)
			if(rr(f->v4root[rw->h], rw) == 0)
.
657c
ipwalkroutes(Fs *f, Routewalk *rw)
.
537c
		q->ifc = findipifc(f, q->v6.gate, q->type);
.
508c
	for(p=f->v6root[V6H(la)]; p;){
.
499c
		q = v4lookup(f, a+12);
.
491c
v6lookup(Fs *f, uchar *a)
.
481c
		q->ifc = findipifc(f, gate, q->type);
.
469c
	for(p=f->v4root[V4H(la)]; p;)
.
461c
v4lookup(Fs *f, uchar *a)
.
457c
	ipifcremroute(f, 0, a, mask);
.
448,450c
			while(p = f->queue) {
				f->queue = p->mid;
				walkadd(f, &f->v6root[h], p->left);
.
444,446c
			addqueue(&f->queue, p->left);
			addqueue(&f->queue, p->mid);
			addqueue(&f->queue, p->right);
.
440c
		r = looknode(&f->v6root[h], &rt);
.
422c
v6delroute(Fs *f, uchar *a, uchar *mask)
.
418c
	ipifcremroute(f, Rv4, a, mask);
.
409,411c
			while(p = f->queue) {
				f->queue = p->mid;
				walkadd(f, &f->v4root[h], p->left);
.
405,407c
			addqueue(&f->queue, p->left);
			addqueue(&f->queue, p->mid);
			addqueue(&f->queue, p->right);
.
401c
		r = looknode(&f->v4root[h], &rt);
.
386c
v4delroute(Fs *f, uchar *a, uchar *mask)
.
354c
	ipifcaddroute(f, 0, a, mask, gate, type);
.
345,348c
		addnode(f, &f->v6root[h], p);
		while(p = f->queue) {
			f->queue = p->mid;
			walkadd(f, &f->v6root[h], p->left);
.
322c
v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
.
316c
	ipifcaddroute(f, Rv4, a, mask, gate, type);
.
307,310c
		addnode(f, &f->v4root[h], p);
		while(p = f->queue) {
			f->queue = p->mid;
			walkadd(f, &f->v4root[h], p->left);
.
286c
v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
.
276c
		addnode(f, &p->mid, new);
.
269c
		addqueue(&f->queue, p);
.
257c
		addnode(f, &p->right, new);
.
254c
		addnode(f, &p->left, new);
.
241c
addnode(Fs *f, Route **cur, Route *new)
.
175c
		walkadd(f, root, r);
.
173c
		walkadd(f, root, l);
.
171c
	addnode(f, root, p);
.
163c
walkadd(Fs *f, Route **root, Route *p)
.
20a
/* these are used for all instances of IP */
.
10,18c
static void	walkadd(Fs*, Route**, Route*);
static void	addnode(Fs*, Route**, Route*);
.
## diffname ip/iproute.c 1998/0316
## diff -e /n/emeliedump/1998/0313/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0316/sys/src/brazil/ip/iproute.c
534,535c
		q->ifcid = q->ifc->ifcid;
.
530,531c
	if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
		if(q->type & Rifc) {
			hnputl(gate, q->v6.gate[0]);
			hnputl(gate+4, q->v6.gate[1]);
			hnputl(gate+8, q->v6.gate[2]);
			hnputl(gate+12, q->v6.gate[3]);
			q->ifc = findipifc(f, gate, q->type);
		} else
			q->ifc = findipifc(f, q->v6.gate, q->type);
.
490a
	uchar gate[IPaddrlen];
.
474c
		if(q->type & Rifc) {
			hnputl(gate+IPv4off, q->v4.address);
			memmove(gate, v4prefix, IPv4off);
		} else
			v4tov6(gate, q->v4.gate);
.
266c
		/*
		 *  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);
		}
.
## diffname ip/iproute.c 1998/0630
## diff -e /n/emeliedump/1998/0316/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0630/sys/src/brazil/ip/iproute.c
781c
			v6delroute(f, addr, mask, 1);
.
779c
			v4delroute(f, addr+IPv4off, mask+IPv4off, 1);
.
770,772c
			for(changed = 1; changed;){
				wlock(&routelock);
				changed = routeflush(f, f->v6root[h], tag);
				wunlock(&routelock);
			}
.
767,768c
			for(changed = 1; changed;){
				wlock(&routelock);
				changed = routeflush(f, f->v4root[h], tag);
				wunlock(&routelock);
			}
.
765c
		tag = cb->f[1];
.
751c
	int h, changed;
.
742c
		if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0)
			delroute(f, r, 0);
.
739c
	if(routeflush(f, r->right, tag))
.
737c
	if(routeflush(f, r->left, tag))
.
735c
	if(routeflush(f, r->mid, tag))
.
731c
routeflush(Fs *f, Route *r, char *tag)
.
723c
		v6delroute(f, addr, mask, dolock);
.
721c
		v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);
.
711c
delroute(Fs *f, Route *r, int dolock)
.
456c
		if(dolock)
			wunlock(&routelock);
.
441c
		if(dolock)
			wlock(&routelock);
.
424c
v6delroute(Fs *f, uchar *a, uchar *mask, int dolock)
.
417c
		if(dolock)
			wunlock(&routelock);
.
402c
		if(dolock)
			wlock(&routelock);
.
388c
v4delroute(Fs *f, uchar *a, uchar *mask, int dolock)
.
## diffname ip/iproute.c 1998/0701
## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0701/sys/src/brazil/ip/iproute.c
748c
			return 1;
		}
.
746c
		if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0){
.
## diffname ip/iproute.c 2001/0405
## diff -e /n/emeliedump/1998/0701/sys/src/brazil/ip/iproute.c /n/emeliedump/2001/0405/sys/src/9/ip/iproute.c
810,815c
		a = c->aux;
		na = newipaux(a->owner, cb->f[1]);
		c->aux = na;
		free(a);
.
800,801c
		if(c != nil){
			a = c->aux;
			tag = a->tag;
		}
.
762a
	IPaux *a, *na;
.
## diffname ip/iproute.c 2001/0710
## diff -e /n/emeliedump/2001/0405/sys/src/9/ip/iproute.c /n/emeliedump/2001/0710/sys/src/9/ip/iproute.c
456a
				while(p = f->queue) {
					f->queue = p->mid;
					walkadd(f, &f->v6root[h], p->left);
					freeroute(p);
				}
.
448,455c
			if(--(p->ref) == 0){
				*r = 0;
				addqueue(&f->queue, p->left);
				addqueue(&f->queue, p->mid);
				addqueue(&f->queue, p->right);
.
415a
				while(p = f->queue) {
					f->queue = p->mid;
					walkadd(f, &f->v4root[h], p->left);
					freeroute(p);
				}
.
407,414c
			if(--(p->ref) == 0){
				*r = 0;
				addqueue(&f->queue, p->left);
				addqueue(&f->queue, p->mid);
				addqueue(&f->queue, p->right);
.
274c
		} else if(new->type & Rifc)
			p->ref++;
.
59a
	r->ref = 1;
.
## diffname ip/iproute.c 2001/1120
## diff -e /n/emeliedump/2001/0710/sys/src/9/ip/iproute.c /n/emeliedump/2001/1120/sys/src/9/ip/iproute.c
818a
	case RWtag:
.
800,817c
		break;
.
791,793c
		break;

	case RWremove:
.
777c
	ct = lookupcmd(cb, routecmd, nelem(routecmd));

	switch(ct->index){
	case RWadd:
		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);
		break;

	case RWflush:
.
765a
	Cmdtab *ct;
.
18a
enum
{
	RWadd,
	RWflush,
	RWremove,
	RWtag,
};

static
Cmdtab routecmd[] = {
	RWadd,		"add",		4,
	RWflush,	"flush",	2,
	RWremove,	"remove",	3,
	RWtag,		"tag",		2,
};

.
## diffname ip/iproute.c 2002/0507
## diff -e /n/emeliedump/2001/1120/sys/src/9/ip/iproute.c /n/emeliedump/2002/0507/sys/src/9/ip/iproute.c
837d
835c
	} 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);
.
826,828c
	} else if(strcmp(cb->f[0], "remove") == 0){
		if(cb->nf < 3)
			error(Ebadarg);
.
794,812c
	if(strcmp(cb->f[0], "flush") == 0){
.
782d
612c
char *rformat = "%-40.40I %-40.40M %-40.40I %4.4s %4.4s %3s\n";
.
609c
	Rlinelen=	137,
.
571,574c
			for(h = 0; h < IPllen; h++)
				hnputl(gate+4*h, q->v6.address[h]);
.
531,532c
	if(memcmp(a, v4prefix, IPv4off) == 0){
		q = v4lookup(f, a+IPv4off);
.
348a
	/*
	if(ISDFLT(a, mask, tag))
		f->v6p->cdrouter = -1;
	*/


.
339a
#define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
.
19,34d
## diffname ip/iproute.c 2003/0308
## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/iproute.c /n/emeliedump/2003/0308/sys/src/9/ip/iproute.c
569a
	}
	if(c != nil){
		c->r = q;
		c->rgen = v6routegeneration;
.
527a
	if(c != nil && c->r != nil && c->rgen == v6routegeneration)
		return c->r;

.
523c
		q = v4lookup(f, a+IPv4off, c);
.
514c
v6lookup(Fs *f, uchar *a, Conv *c)
.
508a
	if(c != nil){
		c->r = q;
		c->rgen = v4routegeneration;
	}
.
485a
	if(c != nil && c->r != nil && c->rgen == v4routegeneration)
		return c->r;

.
480c
v4lookup(Fs *f, uchar *a, Conv *c)
.
474a
	v6routegeneration++;
.
431a
	v4routegeneration++;
.
363a
	v6routegeneration++;
.
318a
	v4routegeneration++;
.
17a
ulong	v4routegeneration, v6routegeneration;
.
## diffname ip/iproute.c 2003/0314
## diff -e /n/emeliedump/2003/0308/sys/src/9/ip/iproute.c /n/emeliedump/2003/0314/sys/src/9/ip/iproute.c
584c
		q->ifc = ifc;
		q->ifcid = ifc->ifcid;
.
581,582c
			ifc = findipifc(f, q->v6.gate, q->type);
		if(ifc == nil)
.
579c
			ifc = findipifc(f, gate, q->type);
.
540c
	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration)
.
532a
	Ipifc *ifc;
.
516a

.
515c
		q->ifc = ifc;
		q->ifcid = ifc->ifcid;
.
512,513c
		ifc = findipifc(f, gate, q->type);
		if(ifc == nil)
.
491c
	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration)
.
489a
	Ipifc *ifc;
.
## diffname ip/iproute.c 2003/0404
## diff -e /n/emeliedump/2003/0314/sys/src/9/ip/iproute.c /n/emeliedump/2003/0404/sys/src/9/ip/iproute.c
740,743c
	return rw.p - p;
.
734,735c
	rw.e = p+n;
	rw.o = -offset;
.
730,732d
717c
	if(rw->e > rw->p) {
.
712c
	if(rw->e > rw->p) {
.
686c
	if(rw->e <= rw->p)
.
675c
	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;
.
665,673c
	convroute(r, addr, mask, gate, t, &nifc);
	iname = "-";
	if(nifc != -1) {
		iname = ifbuf;
		sprint(ifbuf, "%d", nifc);
.
663a
	char *p;
.
661c
	int nifc, n;
.
625,626d
620,623c
char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.