⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gre.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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)printenum{	GRE_IPONLY	= 12,		/* size of ip header */	GRE_IPPLUSGRE	= 12,		/* minimum size of GRE header */	IP_GREPROTO	= 47,	GRErxms		= 200,	GREtickms	= 100,	GREmaxxmit	= 10,};typedef struct GREhdr{	/* ip header */	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 */	/* gre header */	uchar	flags[2];	uchar	eproto[2];	/* encapsulation protocol */} GREhdr;typedef struct GREpriv GREpriv;struct GREpriv{	int		raw;			/* Raw GRE mode */	/* non-MIB stats */	ulong		csumerr;		/* checksum errors */	ulong		lenerr;			/* short packet */};static void grekick(void *x, Block *bp);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;	qlock(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 && ipcmp(tc->raddr, c->raddr) == 0){			err = "already connected to that addr/proto";			ipmove(c->laddr, IPnoaddr);			ipmove(c->raddr, IPnoaddr);			break;		}	}	qunlock(p);	if(err != nil)		return err;	Fsconnected(c, nil);	return nil;}static voidgrecreate(Conv *c){	c->rq = qopen(64*1024, Qmsg, 0, c);	c->wq = qbypass(grekick, c);}static intgrestate(Conv *c, char *state, int n){	USED(c);	return snprint(state, n, "%s", "Datagram");}static char*greannounce(Conv*, char**, int){	return "pktifc does not support announce";}static voidgreclose(Conv *c){	qclose(c->rq);	qclose(c->wq);	qclose(c->eq);	ipmove(c->laddr, IPnoaddr);	ipmove(c->raddr, IPnoaddr);	c->lport = 0;	c->rport = 0;}int drop;static voidgrekick(void *x, Block *bp){	Conv *c = x;	GREhdr *ghp;	uchar laddr[IPaddrlen], raddr[IPaddrlen];	if(bp == nil)		return;	/* Make space to fit ip header (gre header already there) */	bp = padblock(bp, GRE_IPONLY);	if(bp == nil)		return;	/* make sure the message has a GRE header */	bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE);	if(bp == nil)		return;	ghp = (GREhdr *)(bp->rp);	ghp->vihl = IP_VER4;	if(!((GREpriv*)c->p->priv)->raw){		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->p->f, c->laddr, raddr); /* pick interface closest to dest */			memmove(ghp->src, c->laddr + IPv4off, IPv4addrlen);		}		hnputs(ghp->eproto, c->rport);	}	ghp->proto = IP_GREPROTO;	ghp->frag[0] = 0;	ghp->frag[1] = 0;	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);}static voidgreiput(Proto *gre, Ipifc*, Block *bp){	int len;	GREhdr *ghp;	Conv *c, **p;	ushort eproto;	uchar raddr[IPaddrlen];	GREpriv *gpriv;	gpriv = gre->priv;	ghp = (GREhdr*)(bp->rp);	v4tov6(raddr, ghp->src);	eproto = nhgets(ghp->eproto);	qlock(gre);	/* 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->rport == eproto && 			(gpriv->raw || ipcmp(c->raddr, raddr) == 0))			break;	}	if(*p == nil) {		qunlock(gre);		freeblist(bp);		return;	}	qunlock(gre);	/*	 * Trim the packet down to data size	 */	len = nhgets(ghp->len) - GRE_IPONLY;	if(len < GRE_IPPLUSGRE){		freeblist(bp);		return;	}	bp = trimblock(bp, GRE_IPONLY, len);	if(bp == nil){		gpriv->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);	}}intgrestats(Proto *gre, char *buf, int len){	GREpriv *gpriv;	gpriv = gre->priv;	return snprint(buf, len, "gre: len %lud\n", gpriv->lenerr);}char*grectl(Conv *c, char **f, int n){	GREpriv *gpriv;	gpriv = c->p->priv;	if(n == 1){		if(strcmp(f[0], "raw") == 0){			gpriv->raw = 1;			return nil;		}		else if(strcmp(f[0], "cooked") == 0){			gpriv->raw = 0;			return nil;		}	}	return "unknown control request";}voidgreinit(Fs *fs){	Proto *gre;	gre = smalloc(sizeof(Proto));	gre->priv = smalloc(sizeof(GREpriv));	gre->name = "gre";	gre->connect = greconnect;	gre->announce = greannounce;	gre->state = grestate;	gre->create = grecreate;	gre->close = greclose;	gre->rcv = greiput;	gre->ctl = grectl;	gre->advise = nil;	gre->stats = grestats;	gre->ipproto = IP_GREPROTO;	gre->nc = 64;	gre->ptclsize = 0;	Fsproto(fs, gre);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -