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

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


## diffname ip/gre.c 1997/0327
## diff -e /dev/null /n/emeliedump/1997/0327/sys/src/brazil/ip/gre.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"

#define DPRINT if(0)print

enum
{
	GRE_IPHDRSIZE	= 20,		/* size of ip header */
	GRE_HDRSIZE	= 4,		/* minimum size of GRE header */
	IP_GREPROTO	= 47,

	GRErxms		= 200,
	GREtickms	= 100,
	GREmaxxmit	= 10,
};

typedef struct GREhdr
{
	/* ip header */
	byte	vihl;		/* Version and header length */
	byte	tos;		/* Type of service */
	byte	len[2];		/* packet length (including headers) */
	byte	id[2];		/* Identification */
	byte	frag[2];	/* Fragment information */
	byte	Unused;	
	byte	proto;		/* Protocol */
	byte	cksum[2];	/* checksum */
	byte	src[4];		/* Ip source */
	byte	dst[4];		/* Ip destination */

	/* gre header */
	byte	flags[2];
	byte	eproto[2];	/* encapsulation protocol */
} GREhdr;

	Proto	gre;
extern	Fs	fs;
	int	gredebug;

static char*
greconnect(Conv *c, char **argv, int argc)
{
	Proto *p;
	char *err;
	Conv *tc, **cp, **ecp;

	err = Fsstdconnect(c, argv, argc);
	if(err != nil)
		return err;

	/* make sure noone's already connected to this other sys */
	p = c->p;
	lock(p);
	ecp = &p->conv[p->nc];
	for(cp = p->conv; cp < ecp; cp++){
		tc = *cp;
		if(tc == nil)
			break;
		if(tc == c)
			continue;
		if(tc->rport == c->rport && tc->raddr == c->raddr){
			err = "already connected to that addr/proto";
			c->rport = 0;
			c->raddr = 0;
			break;
		}
	}
	unlock(p);

	Fsconnected(&fs, c, err);

	return err;
}

static int
grestate(char **msg, Conv *c)
{
	USED(c);
	*msg = "Datagram";
	return 1;
}

static void
grecreate(Conv *c)
{
	c->rq = qopen(64*1024, 0, 0, c);
	c->wq = qopen(64*1024, 0, 0, 0);
}

static void
greannounce(Conv *c)
{
	Fsconnected(&fs, c, "pktifc does not support announce");
}

static void
greclose(Conv *c)
{
	qclose(c->rq);
	qclose(c->wq);
	qclose(c->eq);
	c->laddr = 0;
	c->raddr = 0;
	c->lport = 0;
	c->rport = 0;

	unlock(c);
}

int drop;

static void
grekick(Conv *c, int l)
{
	GREhdr *ghp;
	Block *bp, *f;
	int dlen;

	USED(l);

	bp = qget(c->wq);
	if(bp == nil)
		return;

	/* Round packet up to even number of bytes */
	dlen = blocklen(bp);
	if(dlen & 1) {
		for(f = bp; f->next; f = f->next)
			;
		if(f->wp >= f->lim) {
			f->next = allocb(1);
			f = f->next;
		}
		*f->wp++ = 0;
	}

	/* Make space to fit ip header (gre header already there) */
	bp = padblock(bp, GRE_IPHDRSIZE);
	if(bp == nil)
		return;

	/* make sure the message has a GRE header */
	bp = pullupblock(bp, GRE_IPHDRSIZE+GRE_HDRSIZE);
	if(bp == nil)
		return;

	ghp = (GREhdr *)(bp->rp);

	ghp->proto = IP_GREPROTO;
	hnputl(ghp->dst, c->raddr);
	hnputl(ghp->src, c->laddr);
	hnputs(ghp->eproto, c->rport);

	ipoput(bp, 0, c->ttl);
}

static void
greiput(Block *bp)
{
	int len;
	GREhdr *ghp;
	Ipaddr addr;
	Conv *c, **p;
	ushort eproto;

	ghp = (GREhdr*)(bp->rp);

	eproto = nhgets(ghp->eproto);
	addr = nhgetl(ghp->src);

	/* Look for a conversation structure for this port and address */
	c = nil;
	for(p = gre.conv; *p; p++) {
		c = *p;
		if(c->inuse == 0)
			continue;
		if(c->raddr == addr && c->rport == eproto)
			break;
	}

	if(*p == nil) {
		freeblist(bp);
		return;
	}

	/*
	 * Trim the packet down to data size
	 */
	len = nhgets(ghp->len) - GRE_IPHDRSIZE;
	if(len < GRE_HDRSIZE){
		freeblist(bp);
		return;
	}
	bp = trimblock(bp, GRE_IPHDRSIZE, len);
	if(bp == nil){
		gre.lenerr++;
		return;
	}

	/*
	 *  Can't delimit packet so pull it all into one block.
	 */
	if(qlen(c->rq) > 64*1024)
		freeblist(bp);
	else{
		bp = concatblock(bp);
		if(bp == 0)
			panic("greiput");
		qpass(c->rq, bp);
	}
}

void
greinit(Fs *fs)
{
	gre.name = "gre";
	gre.kick = grekick;
	gre.connect = greconnect;
	gre.announce = greannounce;
	gre.state = grestate;
	gre.create = grecreate;
	gre.close = greclose;
	gre.rcv = greiput;
	gre.ctl = nil;
	gre.advise = nil;
	gre.ipproto = IP_GREPROTO;
	gre.nc = 64;
	gre.ptclsize = 0;

	Fsproto(fs, &gre);
}
.
## diffname ip/gre.c 1997/0403
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/ip/gre.c /n/emeliedump/1997/0403/sys/src/brazil/ip/gre.c
99c
	return "pktifc does not support announce";
.
96,97c
static char*
greannounce(Conv*, char**, int)
.
78c
	return nil;
.
76c
	if(err != nil)
		return err;
	Fsconnected(&fs, c, nil);
.
## diffname ip/gre.c 1997/0423
## diff -e /n/emeliedump/1997/0403/sys/src/brazil/ip/gre.c /n/emeliedump/1997/0423/sys/src/brazil/ip/gre.c
173a
	USED(m);
.
166c
greiput(Media *m, Block *bp)
.
## diffname ip/gre.c 1997/0522
## diff -e /n/emeliedump/1997/0423/sys/src/brazil/ip/gre.c /n/emeliedump/1997/0522/sys/src/brazil/ip/gre.c
160a
	ghp->frag[0] = 0;
	ghp->frag[1] = 0;
.
## diffname ip/gre.c 1997/0524
## diff -e /n/emeliedump/1997/0522/sys/src/brazil/ip/gre.c /n/emeliedump/1997/0524/sys/src/brazil/ip/gre.c
132,143d
124,125c
	Block *bp;
.
## diffname ip/gre.c 1997/0530
## diff -e /n/emeliedump/1997/0524/sys/src/brazil/ip/gre.c /n/emeliedump/1997/0530/sys/src/brazil/ip/gre.c
192c
	bp = trimblock(bp, GRE_IPONLY, len);
.
187,188c
	len = nhgets(ghp->len) - GRE_IPONLY;
	if(len < GRE_IPPLUSGRE){
.
145,146c
	hnputl(ghp->dst, raddr);
	hnputl(ghp->src, laddr);
.
143a
	raddr = nhgetl(ghp->src);
	laddr = nhgetl(ghp->dst);
	if(raddr == 0)
		raddr = c->raddr;
	if(laddr == 0 || Mediaforme(ghp->dst) <= 0)
		laddr = c->laddr;

.
138c
	bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE);
.
133c
	bp = padblock(bp, GRE_IPONLY);
.
124a
	ulong raddr, laddr;
.
14,15c
	GRE_IPONLY	= 12,		/* size of ip header */
	GRE_IPPLUSGRE	= 12,		/* minimum size of GRE header */
.
## diffname ip/gre.c 1997/0531
## diff -e /n/emeliedump/1997/0530/sys/src/brazil/ip/gre.c /n/emeliedump/1997/0531/sys/src/brazil/ip/gre.c
149c
	if(laddr == 0 || Mediaforme(ghp->src) <= 0)
.
145,146c
	raddr = nhgetl(ghp->dst);
	laddr = nhgetl(ghp->src);
.
## diffname ip/gre.c 1998/0306
## diff -e /n/emeliedump/1997/0531/sys/src/brazil/ip/gre.c /n/emeliedump/1998/0306/sys/src/brazil/ip/gre.c
231a
	gre.stats = grestats;
.
218a
int
grestats(char *buf, int len)
{
	return snprint(buf, len,
		"gre: csum %d hlen %d len %d order %d rexmit %d\n",
		gre.csumerr, gre.hlenerr, gre.lenerr, gre.order, gre.rexmit);
}

.
183c
		if(c->rport == eproto && ipcmp(c->raddr, raddr) == 0)
.
175d
173a
	v4tov6(raddr, ghp->src);
.
171d
169a
	uchar raddr[IPaddrlen];
.
167d
163c
greiput(uchar*, Block *bp)
.
153,154d
145,150c
	v4tov6(raddr, ghp->dst);
	if(ipcmp(raddr, v4prefix) == 0)
		memmove(ghp->dst, c->raddr + IPv4off, IPv4addrlen);
	v4tov6(laddr, ghp->src);
	if(ipcmp(laddr, v4prefix) == 0){
		if(ipcmp(c->laddr, IPnoaddr) == 0)
			findlocalip(c->laddr, raddr); /* pick interface closest to dest */
		memmove(ghp->src, c->laddr + IPv4off, IPv4addrlen);
	}
.
125c
	uchar laddr[IPaddrlen], raddr[IPaddrlen];
.
110,111c
	ipmove(c->laddr, IPnoaddr);
	ipmove(c->raddr, IPnoaddr);
.
87,88c
	return snprint(state, n, "%s", "Datagram");
.
84c
grestate(Conv *c, char *state, int n)
.
74c
	qunlock(p);
.
69,70c
			ipmove(c->laddr, IPnoaddr);
			ipmove(c->raddr, IPnoaddr);
.
59c
	qlock(p);
.
38,39c
	uchar	flags[2];
	uchar	eproto[2];	/* encapsulation protocol */
.
26,35c
	uchar	vihl;		/* Version and header length */
	uchar	tos;		/* Type of service */
	uchar	len[2];		/* packet length (including headers) */
	uchar	id[2];		/* Identification */
	uchar	frag[2];	/* Fragment information */
	uchar	Unused;	
	uchar	proto;		/* Protocol */
	uchar	cksum[2];	/* checksum */
	uchar	src[4];		/* Ip source */
	uchar	dst[4];		/* Ip destination */
.
## diffname ip/gre.c 1998/0313
## diff -e /n/emeliedump/1998/0306/sys/src/brazil/ip/gre.c /n/emeliedump/1998/0313/sys/src/brazil/ip/gre.c
244c
	gre = smalloc(sizeof(Proto));
	gre->priv = smalloc(sizeof(GREpriv));
	gre->name = "gre";
	gre->kick = grekick;
	gre->connect = greconnect;
	gre->announce = greannounce;
	gre->state = grestate;
	gre->create = grecreate;
	gre->close = greclose;
	gre->rcv = greiput;
	gre->ctl = nil;
	gre->advise = nil;
	gre->stats = grestats;
	gre->ipproto = IP_GREPROTO;
	gre->nc = 64;
	gre->ptclsize = 0;

	Fsproto(fs, gre);
.
229,242c
	Proto *gre;
.
221,223c
	GREpriv *gpriv;

	gpriv = gre->priv;

	return snprint(buf, len, "gre: len %d\n", gpriv->lenerr);
.
219c
grestats(Proto *gre, char *buf, int len)
.
201c
		gpriv->lenerr++;
.
178c
	for(p = gre->conv; *p; p++) {
.
170a
	gpriv = gre->priv;
.
169a
	GREpriv *gpriv;
.
163c
greiput(Proto *gre, uchar*, Block *bp)
.
159c
	ipoput(c->p->f, bp, 0, c->ttl);
.
150c
			findlocalip(c->p->f, c->laddr, raddr); /* pick interface closest to dest */
.
78c
	Fsconnected(c, nil);
.
42,44c
typedef struct GREpriv GREpriv;
struct GREpriv
{
	/* non-MIB stats */
	ulong		csumerr;		/* checksum errors */
	ulong		lenerr;			/* short packet */
};
.
## diffname ip/gre.c 1998/0401
## diff -e /n/emeliedump/1998/0313/sys/src/brazil/ip/gre.c /n/emeliedump/1998/0401/sys/src/brazil/ip/gre.c
71c
		if(tc->rport == c->rport && ipcmp(tc->raddr, c->raddr) == 0){
.
## diffname ip/gre.c 1998/0825
## diff -e /n/emeliedump/1998/0401/sys/src/brazil/ip/gre.c /n/emeliedump/1998/0825/sys/src/brazil/ip/gre.c
231c
	return snprint(buf, len, "gre: len %lud\n", gpriv->lenerr);
.
## diffname ip/gre.c 1999/0302
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/ip/gre.c /n/emeliedump/1999/0302/sys/src/brazil/ip/gre.c
195a

	qunlock(gre);
.
192a
		qunlock(gre);
.
181a
	qlock(gre);

.
118c
	qunlock(c);
.
## diffname ip/gre.c 1999/0817
## diff -e /n/emeliedump/1999/0302/sys/src/brazil/ip/gre.c /n/emeliedump/1999/0817/sys/src/brazil/ip/gre.c
163c
	ipoput(c->p->f, bp, 0, c->ttl, c->tos);
.
## diffname ip/gre.c 2000/1220
## diff -e /n/emeliedump/1999/0817/sys/src/brazil/ip/gre.c /n/emeliedump/2000/1220/sys/src/9/ip/gre.c
117,118d
## diffname ip/gre.c 2001/0127
## diff -e /n/emeliedump/2000/1220/sys/src/9/ip/gre.c /n/emeliedump/2001/0127/sys/src/9/ip/gre.c
97c
	c->rq = qopen(64*1024, 1, 0, c);
.
## diffname ip/gre.c 2001/0306
## diff -e /n/emeliedump/2001/0127/sys/src/9/ip/gre.c /n/emeliedump/2001/0306/sys/src/9/ip/gre.c
127,128d
122c
grekick(Conv *c)
.
## diffname ip/gre.c 2001/0623
## diff -e /n/emeliedump/2001/0306/sys/src/9/ip/gre.c /n/emeliedump/2001/0623/sys/src/9/ip/gre.c
163c
greiput(Proto *gre, Ipifc*, Block *bp)
.
## diffname ip/gre.c 2002/0507
## diff -e /n/emeliedump/2001/0623/sys/src/9/ip/gre.c /n/emeliedump/2002/0507/sys/src/9/ip/gre.c
159c
	ipoput4(c->p->f, bp, 0, c->ttl, c->tos);
.
142a
	ghp->vihl = IP_VER4;
.
## diffname ip/gre.c 2002/0711
## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/gre.c /n/emeliedump/2002/0711/sys/src/9/ip/gre.c
97c
	c->rq = qopen(64*1024, Qmsg, 0, c);
.
## diffname ip/gre.c 2002/0712
## diff -e /n/emeliedump/2002/0711/sys/src/9/ip/gre.c /n/emeliedump/2002/0712/sys/src/9/ip/gre.c
244d
123a
	Conv *c = x;
.
122c
grekick(void *x)
.
94,100d
86a
static void
grecreate(Conv *c)
{
	c->rq = qopen(64*1024, Qmsg, 0, c);
	c->wq = qopen(64*1024, Qkick, grekick, c);
}

.
49a
static void grekick(void *x);

.
## diffname ip/gre.c 2003/0220
## diff -e /n/emeliedump/2002/0712/sys/src/9/ip/gre.c /n/emeliedump/2003/0220/sys/src/9/ip/gre.c
131d
128d
124c
grekick(void *x, Block *bp)
.
93c
	c->wq = qbypass(grekick, c);
.
50c
static void grekick(void *x, Block *bp);
.
## diffname ip/gre.c 2003/0308
## diff -e /n/emeliedump/2003/0220/sys/src/9/ip/gre.c /n/emeliedump/2003/0308/sys/src/9/ip/gre.c
161c
	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
.

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.