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

📄 ipmux.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	*nf = *f;	nf->no = ipmuxcopy(f->no);	nf->yes = ipmuxcopy(f->yes);	nf->val = smalloc(f->n*f->len);	nf->e = nf->val + f->len*f->n;	memmove(nf->val, f->val, f->n*f->len);	return nf;}static voidipmuxfree(Ipmux *f){	if(f->val != nil)		free(f->val);	free(f);}static voidipmuxtreefree(Ipmux *f){	if(f == nil)		return;	if(f->no != nil)		ipmuxfree(f->no);	if(f->yes != nil)		ipmuxfree(f->yes);	ipmuxfree(f);}/* *  merge two trees */static Ipmux*ipmuxmerge(Ipmux *a, Ipmux *b){	int n;	Ipmux *f;	if(a == nil)		return b;	if(b == nil)		return a;	n = ipmuxcmp(a, b);	if(n < 0){		f = ipmuxcopy(b);		a->yes = ipmuxmerge(a->yes, b);		a->no = ipmuxmerge(a->no, f);		return a;	}	if(n > 0){		f = ipmuxcopy(a);		b->yes = ipmuxmerge(b->yes, a);		b->no = ipmuxmerge(b->no, f);		return b;	}	if(ipmuxvalcmp(a, b) == 0){		a->yes = ipmuxmerge(a->yes, b->yes);		a->no = ipmuxmerge(a->no, b->no);		a->ref++;		ipmuxfree(b);		return a;	}	a->no = ipmuxmerge(a->no, b);	return a;}/* *  remove a chain from a demux tree.  This is like merging accept that *  we remove instead of insert. */static intipmuxremove(Ipmux **l, Ipmux *f){	int n, rv;	Ipmux *ft;	if(f == nil)		return 0;		/* we've removed it all */	if(*l == nil)		return -1;	ft = *l;	n = ipmuxcmp(ft, f);	if(n < 0){		/* *l is maching an earlier field, descend both paths */		rv = ipmuxremove(&ft->yes, f);		rv += ipmuxremove(&ft->no, f);		return rv;	}	if(n > 0){		/* f represents an earlier field than *l, this should be impossible */		return -1;	}	/* if we get here f and *l are comparing the same fields */	if(ipmuxvalcmp(ft, f) != 0){		/* different values mean mutually exclusive */		return ipmuxremove(&ft->no, f);	}	/* we found a match */	if(--(ft->ref) == 0){		/*		 *  a dead node implies the whole yes side is also dead.		 *  since our chain is constrained to be on that side,		 *  we're done.		 */		ipmuxtreefree(ft->yes);		*l = ft->no;		ipmuxfree(ft);		return 0;	}	/*	 *  free the rest of the chain.  it is constrained to match the	 *  yes side.	 */	return ipmuxremove(&ft->yes, f->yes);}/* *  connection request is a semi separated list of filters *  e.g. proto=17;dat[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0 * *  there's no protection against overlapping specs. */static char*ipmuxconnect(Conv *c, char **argv, int argc){	int i, n;	char *field[10];	Ipmux *mux, *chain;	Ipmuxrock *r;	Fs *f;	f = c->p->f;	if(argc != 2)		return Ebadarg;	n = getfields(argv[1], field, nelem(field), 1, ";");	if(n <= 0)		return Ebadarg;	chain = nil;	mux = nil;	for(i = 0; i < n; i++){		mux = parsemux(field[i]);		if(mux == nil){			ipmuxtreefree(chain);			return Ebadarg;		}		ipmuxchain(&chain, mux);	}	if(chain == nil)		return Ebadarg;	mux->conv = c;	/* save a copy of the chain so we can later remove it */	mux = ipmuxcopy(chain);	r = (Ipmuxrock*)(c->ptcl);	r->chain = chain;	/* add the chain to the protocol demultiplexor tree */	wlock(f);	f->ipmux->priv = ipmuxmerge(f->ipmux->priv, mux);	wunlock(f);	Fsconnected(c, nil);	return nil;}static intipmuxstate(Conv *c, char *state, int n){	Ipmuxrock *r;		r = (Ipmuxrock*)(c->ptcl);	return ipmuxsprint(r->chain, 0, state, n);}static voidipmuxcreate(Conv *c){	Ipmuxrock *r;	c->rq = qopen(64*1024, Qmsg, 0, c);	c->wq = qopen(64*1024, Qkick, ipmuxkick, c);	r = (Ipmuxrock*)(c->ptcl);	r->chain = nil;}static char*ipmuxannounce(Conv*, char**, int){	return "ipmux does not support announce";}static voidipmuxclose(Conv *c){	Ipmuxrock *r;	Fs *f = c->p->f;	r = (Ipmuxrock*)(c->ptcl);	qclose(c->rq);	qclose(c->wq);	qclose(c->eq);	ipmove(c->laddr, IPnoaddr);	ipmove(c->raddr, IPnoaddr);	c->lport = 0;	c->rport = 0;	wlock(f);	ipmuxremove(&(c->p->priv), r->chain);	wunlock(f);	ipmuxtreefree(r->chain);	r->chain = nil;}/* *  takes a fully formed ip packet and just passes it down *  the stack */static voidipmuxkick(void *x){	Conv *c = x;	Block *bp;	struct Ip6hdr *ih6;	bp = qget(c->wq);	if(bp == nil)		return;	else {		Ip4hdr *ih4 = (Ip4hdr*)(bp->rp);		if((ih4->vihl)&0xF0 != 0x60)			ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);		else {			ih6 = (struct Ip6hdr*)ih4;			ipoput6(c->p->f, bp, 0, ih6->ttl, 0, nil);		}	}}static voidipmuxiput(Proto *p, Ipifc *ifc, Block *bp){	int len, hl;	Fs *f = p->f;	uchar *m, *h, *v, *e, *ve, *hp;	Conv *c;	Ipmux *mux;	Ip4hdr *ip;	Ip6hdr *ip6;	ip = (Ip4hdr*)bp->rp;	hl = (ip->vihl&0x0F)<<2;	if(p->priv == nil)		goto nomatch;	h = bp->rp;	len = BLEN(bp);	/* run the v4 filter */	rlock(f);	c = nil;	mux = f->ipmux->priv;	while(mux != nil){		if(mux->eoff > len){			mux = mux->no;			continue;		}		hp = h + mux->off + ((int)mux->skiphdr)*hl;		switch(mux->ctype){		case Cbyte:			if(*mux->val == *hp)				goto yes;			break;		case Cmbyte:			if((*hp & *mux->mask) == *mux->val)				goto yes;			break;		case Cshort:			if(*((ushort*)mux->val) == *(ushort*)hp)				goto yes;			break;		case Cmshort:			if((*(ushort*)hp & (*((ushort*)mux->mask))) == *((ushort*)mux->val))				goto yes;			break;		case Clong:			if(*((ulong*)mux->val) == *(ulong*)hp)				goto yes;			break;		case Cmlong:			if((*(ulong*)hp & (*((ulong*)mux->mask))) == *((ulong*)mux->val))				goto yes;			break;		case Cifc:			if(*((ulong*)mux->val) == *(ulong*)(ifc->lifc->local + IPv4off))				goto yes;			break;		case Cmifc:			if((*(ulong*)(ifc->lifc->local + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val))				goto yes;			break;		default:			v = mux->val;			for(e = mux->e; v < e; v = ve){				m = mux->mask;				hp = h + mux->off;				for(ve = v + mux->len; v < ve; v++){					if((*hp++ & *m++) != *v)						break;				}				if(v == ve)					goto yes;			}		}		mux = mux->no;		continue;yes:		if(mux->conv != nil)			c = mux->conv;		mux = mux->yes;	}	runlock(f);	if(c != nil){		/* tack on interface address */		bp = padblock(bp, IPaddrlen);		ipmove(bp->rp, ifc->lifc->local);		bp = concatblock(bp);		if(bp != nil)			if(qpass(c->rq, bp) < 0)				print("Q");		return;	}nomatch:	/* doesn't match any filter, hand it to the specific protocol handler */	ip = (Ip4hdr*)bp->rp;	if((ip->vihl&0xF0)==0x40) {		p = f->t2p[ip->proto];	} else {		ip6 = (Ip6hdr*)bp->rp;		p = f->t2p[ip6->proto];	}	if(p && p->rcv)		(*p->rcv)(p, ifc, bp);	else		freeblist(bp);	return;}static intipmuxsprint(Ipmux *mux, int level, char *buf, int len){	int i, j, n;	uchar *v;	n = 0;	for(i = 0; i < level; i++)		n += snprint(buf+n, len-n, " ");	if(mux == nil){		n += snprint(buf+n, len-n, "\n");		return n;	}	n += snprint(buf+n, len-n, "h[%d:%d]&",                mux->off+((int)mux->skiphdr)*((int)ipoff->data),                mux->off+(((int)mux->skiphdr)*((int)ipoff->data))+mux->len-1);	for(i = 0; i < mux->len; i++)		n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);	n += snprint(buf+n, len-n, "=");	v = mux->val;	for(j = 0; j < mux->n; j++){		for(i = 0; i < mux->len; i++)			n += snprint(buf+n, len - n, "%2.2ux", *v++);		n += snprint(buf+n, len-n, "|");	}	n += snprint(buf+n, len-n, "\n");	level++;	n += ipmuxsprint(mux->no, level, buf+n, len-n);	n += ipmuxsprint(mux->yes, level, buf+n, len-n);	return n;}static intipmuxstats(Proto *p, char *buf, int len){	int n;	Fs *f = p->f;	rlock(f);	n = ipmuxsprint(p->priv, 0, buf, len);	runlock(f);	return n;}voidipmuxinit(Fs *f){	Proto *ipmux;	ipmux = smalloc(sizeof(Proto));	ipmux->priv = nil;	ipmux->name = "ipmux";	ipmux->connect = ipmuxconnect;	ipmux->announce = ipmuxannounce;	ipmux->state = ipmuxstate;	ipmux->create = ipmuxcreate;	ipmux->close = ipmuxclose;	ipmux->rcv = ipmuxiput;	ipmux->ctl = nil;	ipmux->advise = nil;	ipmux->stats = ipmuxstats;	ipmux->ipproto = -1;	ipmux->nc = 64;	ipmux->ptclsize = sizeof(Ipmuxrock);	f->ipmux = ipmux;			/* hack for Fsrcvpcol */	Fsproto(f, ipmux);}

⌨️ 快捷键说明

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