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

📄 optimize.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		}#endif	} while (!done);}/* * Optimize the filter code in its dag representation. */voidbpf_optimize(rootp)	struct block **rootp;{	struct block *root;	root = *rootp;	opt_init(root);	opt_loop(root, 0);	opt_loop(root, 1);	intern_blocks(root);#ifdef BDEBUG	if (dflag > 1) {		printf("after intern_blocks()\n");		opt_dump(root);	}#endif	opt_root(rootp);#ifdef BDEBUG	if (dflag > 1) {		printf("after opt_root()\n");		opt_dump(root);	}#endif	opt_cleanup();}static voidmake_marks(p)	struct block *p;{	if (!isMarked(p)) {		Mark(p);		if (BPF_CLASS(p->s.code) != BPF_RET) {			make_marks(JT(p));			make_marks(JF(p));		}	}}/* * Mark code array such that isMarked(i) is true * only for nodes that are alive. */static voidmark_code(p)	struct block *p;{	cur_mark += 1;	make_marks(p);}/* * True iff the two stmt lists load the same value from the packet into * the accumulator. */static inteq_slist(x, y)	struct slist *x, *y;{	while (1) {		while (x && x->s.code == NOP)			x = x->next;		while (y && y->s.code == NOP)			y = y->next;		if (x == 0)			return y == 0;		if (y == 0)			return x == 0;		if (x->s.code != y->s.code || x->s.k != y->s.k)			return 0;		x = x->next;		y = y->next;	}}static inline inteq_blk(b0, b1)	struct block *b0, *b1;{	if (b0->s.code == b1->s.code &&	    b0->s.k == b1->s.k &&	    b0->et.succ == b1->et.succ &&	    b0->ef.succ == b1->ef.succ)		return eq_slist(b0->stmts, b1->stmts);	return 0;}static voidintern_blocks(root)	struct block *root;{	struct block *p;	int i, j;	int done; top:	done = 1;	for (i = 0; i < n_blocks; ++i)		blocks[i]->link = 0;	mark_code(root);	for (i = n_blocks - 1; --i >= 0; ) {		if (!isMarked(blocks[i]))			continue;		for (j = i + 1; j < n_blocks; ++j) {			if (!isMarked(blocks[j]))				continue;			if (eq_blk(blocks[i], blocks[j])) {				blocks[i]->link = blocks[j]->link ?					blocks[j]->link : blocks[j];				break;			}		}	}	for (i = 0; i < n_blocks; ++i) {		p = blocks[i];		if (JT(p) == 0)			continue;		if (JT(p)->link) {			done = 0;			JT(p) = JT(p)->link;		}		if (JF(p)->link) {			done = 0;			JF(p) = JF(p)->link;		}	}	if (!done)		goto top;}static voidopt_cleanup(){	free((void *)vnode_base);	free((void *)vmap);	free((void *)edges);	free((void *)space);	free((void *)levels);	free((void *)blocks);}/* * Return the number of stmts in 's'. */static intslength(s)	struct slist *s;{	int n = 0;	for (; s; s = s->next)		if (s->s.code != NOP)			++n;	return n;}/* * Return the number of nodes reachable by 'p'. * All nodes should be initially unmarked. */static intcount_blocks(p)	struct block *p;{	if (p == 0 || isMarked(p))		return 0;	Mark(p);	return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;}/* * Do a depth first search on the flow graph, numbering the * the basic blocks, and entering them into the 'blocks' array.` */static voidnumber_blks_r(p)	struct block *p;{	int n;	if (p == 0 || isMarked(p))		return;	Mark(p);	n = n_blocks++;	p->id = n;	blocks[n] = p;	number_blks_r(JT(p));	number_blks_r(JF(p));}/* * Return the number of stmts in the flowgraph reachable by 'p'. * The nodes should be unmarked before calling. * * Note that "stmts" means "instructions", and that this includes * *	side-effect statements in 'p' (slength(p->stmts)); * *	statements in the true branch from 'p' (count_stmts(JT(p))); * *	statements in the false branch from 'p' (count_stmts(JF(p))); * *	the conditional jump itself (1); * *	an extra long jump if the true branch requires it (p->longjt); * *	an extra long jump if the false branch requires it (p->longjf). */static intcount_stmts(p)	struct block *p;{	int n;	if (p == 0 || isMarked(p))		return 0;	Mark(p);	n = count_stmts(JT(p)) + count_stmts(JF(p));	return slength(p->stmts) + n + 1 + p->longjt + p->longjf;}/* * Allocate memory.  All allocation is done before optimization * is begun.  A linear bound on the size of all data structures is computed * from the total number of blocks and/or statements. */static voidopt_init(root)	struct block *root;{	bpf_u_int32 *p;	int i, n, max_stmts;	/*	 * First, count the blocks, so we can malloc an array to map	 * block number to block.  Then, put the blocks into the array.	 */	unMarkAll();	n = count_blocks(root);	blocks = (struct block **)malloc(n * sizeof(*blocks));	if (blocks == NULL)		bpf_error("malloc");	unMarkAll();	n_blocks = 0;	number_blks_r(root);	n_edges = 2 * n_blocks;	edges = (struct edge **)malloc(n_edges * sizeof(*edges));	if (edges == NULL)		bpf_error("malloc");	/*	 * The number of levels is bounded by the number of nodes.	 */	levels = (struct block **)malloc(n_blocks * sizeof(*levels));	if (levels == NULL)		bpf_error("malloc");	edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1;	nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1;	/* XXX */	space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space)				 + n_edges * edgewords * sizeof(*space));	if (space == NULL)		bpf_error("malloc");	p = space;	all_dom_sets = p;	for (i = 0; i < n; ++i) {		blocks[i]->dom = p;		p += nodewords;	}	all_closure_sets = p;	for (i = 0; i < n; ++i) {		blocks[i]->closure = p;		p += nodewords;	}	all_edge_sets = p;	for (i = 0; i < n; ++i) {		register struct block *b = blocks[i];		b->et.edom = p;		p += edgewords;		b->ef.edom = p;		p += edgewords;		b->et.id = i;		edges[i] = &b->et;		b->ef.id = n_blocks + i;		edges[n_blocks + i] = &b->ef;		b->et.pred = b;		b->ef.pred = b;	}	max_stmts = 0;	for (i = 0; i < n; ++i)		max_stmts += slength(blocks[i]->stmts) + 1;	/*	 * We allocate at most 3 value numbers per statement,	 * so this is an upper bound on the number of valnodes	 * we'll need.	 */	maxval = 3 * max_stmts;	vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap));	vnode_base = (struct valnode *)malloc(maxval * sizeof(*vnode_base));	if (vmap == NULL || vnode_base == NULL)		bpf_error("malloc");}/* * Some pointers used to convert the basic block form of the code, * into the array form that BPF requires.  'fstart' will point to * the malloc'd array while 'ftail' is used during the recursive traversal. */static struct bpf_insn *fstart;static struct bpf_insn *ftail;#ifdef BDEBUGint bids[1000];#endif/* * Returns true if successful.  Returns false if a branch has * an offset that is too large.  If so, we have marked that * branch so that on a subsequent iteration, it will be treated * properly. */static intconvert_code_r(p)	struct block *p;{	struct bpf_insn *dst;	struct slist *src;	int slen;	u_int off;	int extrajmps;		/* number of extra jumps inserted */	struct slist **offset = NULL;	if (p == 0 || isMarked(p))		return (1);	Mark(p);	if (convert_code_r(JF(p)) == 0)		return (0);	if (convert_code_r(JT(p)) == 0)		return (0);	slen = slength(p->stmts);	dst = ftail -= (slen + 1 + p->longjt + p->longjf);		/* inflate length by any extra jumps */	p->offset = dst - fstart;	/* generate offset[] for convenience  */	if (slen) {		offset = (struct slist **)calloc(slen, sizeof(struct slist *));		if (!offset) {			bpf_error("not enough core");			/*NOTREACHED*/		}	}	src = p->stmts;	for (off = 0; off < slen && src; off++) {#if 0		printf("off=%d src=%x\n", off, src);#endif		offset[off] = src;		src = src->next;	}	off = 0;	for (src = p->stmts; src; src = src->next) {		if (src->s.code == NOP)			continue;		dst->code = (u_short)src->s.code;		dst->k = src->s.k;		/* fill block-local relative jump */		if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) {#if 0			if (src->s.jt || src->s.jf) {				bpf_error("illegal jmp destination");				/*NOTREACHED*/			}#endif			goto filled;		}		if (off == slen - 2)	/*???*/			goto filled;	    {		int i;		int jt, jf;		char *ljerr = "%s for block-local relative jump: off=%d";#if 0		printf("code=%x off=%d %x %x\n", src->s.code,			off, src->s.jt, src->s.jf);#endif		if (!src->s.jt || !src->s.jf) {			bpf_error(ljerr, "no jmp destination", off);			/*NOTREACHED*/		}		jt = jf = 0;		for (i = 0; i < slen; i++) {			if (offset[i] == src->s.jt) {				if (jt) {					bpf_error(ljerr, "multiple matches", off);					/*NOTREACHED*/				}				dst->jt = i - off - 1;				jt++;			}			if (offset[i] == src->s.jf) {				if (jf) {					bpf_error(ljerr, "multiple matches", off);					/*NOTREACHED*/				}				dst->jf = i - off - 1;				jf++;			}		}		if (!jt || !jf) {			bpf_error(ljerr, "no destination found", off);			/*NOTREACHED*/		}	    }filled:		++dst;		++off;	}	if (offset)		free(offset);#ifdef BDEBUG	bids[dst - fstart] = p->id + 1;#endif	dst->code = (u_short)p->s.code;	dst->k = p->s.k;	if (JT(p)) {		extrajmps = 0;		off = JT(p)->offset - (p->offset + slen) - 1;		if (off >= 256) {		    /* offset too large for branch, must add a jump */		    if (p->longjt == 0) {		    	/* mark this instruction and retry */			p->longjt++;			return(0);		    }		    /* branch if T to following jump */		    dst->jt = extrajmps;		    extrajmps++;		    dst[extrajmps].code = BPF_JMP|BPF_JA;		    dst[extrajmps].k = off - extrajmps;		}		else		    dst->jt = off;		off = JF(p)->offset - (p->offset + slen) - 1;		if (off >= 256) {		    /* offset too large for branch, must add a jump */		    if (p->longjf == 0) {		    	/* mark this instruction and retry */			p->longjf++;			return(0);		    }		    /* branch if F to following jump */		    /* if two jumps are inserted, F goes to second one */		    dst->jf = extrajmps;		    extrajmps++;		    dst[extrajmps].code = BPF_JMP|BPF_JA;		    dst[extrajmps].k = off - extrajmps;		}		else		    dst->jf = off;	}	return (1);}/* * Convert flowgraph intermediate representation to the * BPF array representation.  Set *lenp to the number of instructions. */struct bpf_insn *icode_to_fcode(root, lenp)	struct block *root;	int *lenp;{	int n;	struct bpf_insn *fp;	/*	 * Loop doing convert_code_r() until no branches remain	 * with too-large offsets.	 */	while (1) {	    unMarkAll();	    n = *lenp = count_stmts(root);	    fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);	    if (fp == NULL)		    bpf_error("malloc");	    memset((char *)fp, 0, sizeof(*fp) * n);	    fstart = fp;	    ftail = fp + n;	    unMarkAll();	    if (convert_code_r(root))		break;	    free(fp);	}	return fp;}/* * Make a copy of a BPF program and put it in the "fcode" member of * a "pcap_t". * * If we fail to allocate memory for the copy, fill in the "errbuf" * member of the "pcap_t" with an error message, and return -1; * otherwise, return 0. */intinstall_bpf_program(pcap_t *p, struct bpf_program *fp){	size_t prog_size;	/*	 * Free up any already installed program.	 */	pcap_freecode(&p->fcode);	prog_size = sizeof(*fp->bf_insns) * fp->bf_len;	p->fcode.bf_len = fp->bf_len;	p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);	if (p->fcode.bf_insns == NULL) {		snprintf(p->errbuf, sizeof(p->errbuf),			 "malloc: %s", pcap_strerror(errno));		return (-1);	}	memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);	return (0);}#ifdef BDEBUGstatic voidopt_dump(root)	struct block *root;{	struct bpf_program f;	memset(bids, 0, sizeof bids);	f.bf_insns = icode_to_fcode(root, &f.bf_len);	bpf_dump(&f, 1);	putchar('\n');	free((char *)f.bf_insns);}#endif

⌨️ 快捷键说明

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