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

📄 ipmux.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#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)printtypedef struct Ipmuxrock  Ipmuxrock;typedef struct Ipmux      Ipmux;typedef struct Ip4hdr     Ip4hdr;typedef struct Ip6hdr     Ip6hdr;enum{	IPHDR		= 20,		/* sizeof(Ip4hdr) */};struct Ip4hdr{	uchar	vihl;		/* Version and header length */	uchar	tos;		/* Type of service */	uchar	length[2];	/* packet length */	uchar	id[2];		/* ip->identification */	uchar	frag[2];	/* Fragment information */	uchar	ttl;		/* Time to live */	uchar	proto;		/* Protocol */	uchar	cksum[2];	/* Header checksum */	uchar	src[4];		/* IP source */	uchar	dst[4];		/* IP destination */	uchar	data[1];	/* start of data */};Ip4hdr *ipoff = 0;struct Ip6hdr{	uchar vcf[4];		/* version, class label, and flow label */ 	uchar ploadlen[2];	/* payload length */	uchar proto;		/* next header, i.e. proto */	uchar ttl;		/* hop limit, i.e. ttl */	uchar src[16];		/* IP source */	uchar dst[16];		/* IP destination */};enum{	Tproto,	Tdata,	Tiph,	Tdst,	Tsrc,	Tifc,	Cother = 0,	Cbyte,		/* single byte */	Cmbyte,		/* single byte with mask */	Cshort,		/* single short */	Cmshort,	/* single short with mask */	Clong,		/* single long */	Cmlong,		/* single long with mask */	Cifc,	Cmifc,};char *ftname[] = {[Tproto]	"proto",[Tdata]		"data",[Tiph]	 	"iph",[Tdst]		"dst",[Tsrc]		"src",[Tifc]		"ifc",};/* *  a node in the decision tree */struct Ipmux{	Ipmux	*yes;	Ipmux	*no;	uchar	type;		/* type of field(Txxxx) */	uchar	ctype;		/* tupe of comparison(Cxxxx) */	uchar	len;		/* length in bytes of item to compare */	uchar	n;		/* number of items val points to */	short	off;		/* offset of comparison */	short	eoff;		/* end offset of comparison */	uchar	skiphdr;	/* should offset start after ipheader */	uchar	*val;	uchar	*mask;	uchar	*e;		/* val+n*len*/	int	ref;		/* so we can garbage collect */	Conv	*conv;};/* *  someplace to hold per conversation data */struct Ipmuxrock{	Ipmux	*chain;};static int	ipmuxsprint(Ipmux*, int, char*, int);static void	ipmuxkick(void *x);static char*skipwhite(char *p){	while(*p == ' ' || *p == '\t')		p++;	return p;}static char*follows(char *p, char c){	char *f;	f = strchr(p, c);	if(f == nil)		return nil;	*f++ = 0;	f = skipwhite(f);	if(*f == 0)		return nil;	return f;}static Ipmux*parseop(char **pp){	char *p = *pp;	int type, off, end, len;	Ipmux *f;	p = skipwhite(p);	if(strncmp(p, "dst", 3) == 0){		type = Tdst;		off = (ulong)(ipoff->dst);		len = IPv4addrlen;		p += 3;	}	else if(strncmp(p, "src", 3) == 0){		type = Tsrc;		off = (ulong)(ipoff->src);		len = IPv4addrlen;		p += 3;	}	else if(strncmp(p, "ifc", 3) == 0){		type = Tifc;		off = -IPv4addrlen;		len = IPv4addrlen;		p += 3;	}	else if(strncmp(p, "proto", 5) == 0){		type = Tproto;		off = (ulong)&(ipoff->proto);		len = 1;		p += 5;	}	else if(strncmp(p, "data", 4) == 0 || strncmp(p, "iph", 3) == 0){		if(strncmp(p, "data", 4) == 0) {			type = Tdata;			p += 4;		}		else {			type = Tiph;			p += 3;		}		p = skipwhite(p);		if(*p != '[')			return nil;		p++;		off = strtoul(p, &p, 0);		if(off < 0 || off > (64-IPHDR))			return nil;		p = skipwhite(p);		if(*p != ':')			end = off;		else {			p++;			p = skipwhite(p);			end = strtoul(p, &p, 0);			if(end < off)				return nil;			p = skipwhite(p);		}		if(*p != ']')			return nil;		p++;		len = end - off + 1;	}	else		return nil;	f = smalloc(sizeof(*f));	f->type = type;	f->len = len;	f->off = off;	f->val = nil;	f->mask = nil;	f->n = 1;	f->ref = 1;	if(type == Tdata)		f->skiphdr = 1;	else		f->skiphdr = 0;	return f;	}static inthtoi(char x){	if(x >= '0' && x <= '9')		x -= '0';	else if(x >= 'a' && x <= 'f')		x -= 'a' - 10;	else if(x >= 'A' && x <= 'F')		x -= 'A' - 10;	else		x = 0;	return x;}static inthextoi(char *p){	return (htoi(p[0])<<4) | htoi(p[1]);}static voidparseval(uchar *v, char *p, int len){	while(*p && len-- > 0){		*v++ = hextoi(p);		p += 2;	}}static Ipmux*parsemux(char *p){	int n, nomask;	Ipmux *f;	char *val;	char *mask;	char *vals[20];	uchar *v;	/* parse operand */	f = parseop(&p);	if(f == nil)		return nil;	/* find value */	val = follows(p, '=');	if(val == nil)		goto parseerror;	/* parse mask */	mask = follows(p, '&');	if(mask != nil){		switch(f->type){		case Tsrc:		case Tdst:		case Tifc:			f->mask = smalloc(f->len);			v4parseip(f->mask, mask);			break;		case Tdata:		case Tiph:			f->mask = smalloc(f->len);			parseval(f->mask, mask, f->len);			break;		default:			goto parseerror;		}		nomask = 0;	} else {		nomask = 1;		f->mask = smalloc(f->len);		memset(f->mask, 0xff, f->len);	}	/* parse vals */	f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|");	if(f->n == 0)		goto parseerror;	f->val = smalloc(f->n*f->len);	v = f->val;	for(n = 0; n < f->n; n++){		switch(f->type){		case Tsrc:		case Tdst:		case Tifc:			v4parseip(v, vals[n]);			break;		case Tproto:		case Tdata:		case Tiph:			parseval(v, vals[n], f->len);			break;		}		v += f->len;	}	f->eoff = f->off + f->len;	f->e = f->val + f->n*f->len;	f->ctype = Cother;	if(f->n == 1){		switch(f->len){		case 1:			f->ctype = nomask ? Cbyte : Cmbyte;			break;		case 2:			f->ctype = nomask ? Cshort : Cmshort;			break;		case 4:			if(f->type == Tifc)				f->ctype = nomask ? Cifc : Cmifc;			else				f->ctype = nomask ? Clong : Cmlong;			break;		}	}	return f;parseerror:	if(f->mask)		free(f->mask);	if(f->val)		free(f->val);	free(f);	return nil;}/* *  Compare relative ordering of two ipmuxs.  This doesn't compare the *  values, just the fields being looked at.   * *  returns:	<0 if a is a more specific match *		 0 if a and b are matching on the same fields *		>0 if b is a more specific match */static intipmuxcmp(Ipmux *a, Ipmux *b){	int n;	/* compare types, lesser ones are more important */	n = a->type - b->type;	if(n != 0)		return n;	/* compare offsets, call earlier ones more specific */	n = (a->off+((int)a->skiphdr)*(ulong)ipoff->data) - 		(b->off+((int)b->skiphdr)*(ulong)ipoff->data);	if(n != 0)		return n;	/* compare match lengths, longer ones are more specific */	n = b->len - a->len;	if(n != 0)		return n;	/*	 *  if we get here we have two entries matching	 *  the same bytes of the record.  Now check	 *  the mask for equality.  Longer masks are	 *  more specific.	 */	if(a->mask != nil && b->mask == nil)		return -1;	if(a->mask == nil && b->mask != nil)		return 1;	if(a->mask != nil && b->mask != nil){		n = memcmp(b->mask, a->mask, a->len);		if(n != 0)			return n;	}	return 0;}/* *  Compare the values of two ipmuxs.  We're assuming that ipmuxcmp *  returned 0 comparing them. */static intipmuxvalcmp(Ipmux *a, Ipmux *b){	int n;	n = b->len*b->n - a->len*a->n;	if(n != 0)		return n;	return memcmp(a->val, b->val, a->len*a->n);} /* *  add onto an existing ipmux chain in the canonical comparison *  order */static voidipmuxchain(Ipmux **l, Ipmux *f){	for(; *l; l = &(*l)->yes)		if(ipmuxcmp(f, *l) < 0)			break;	f->yes = *l;	*l = f;}/* *  copy a tree */static Ipmux*ipmuxcopy(Ipmux *f){	Ipmux *nf;	if(f == nil)		return nil;	nf = smalloc(sizeof *nf);

⌨️ 快捷键说明

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