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

📄 ebtables.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {		if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {			/* we make userspace set this right,			   so there is no misunderstanding */			BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "			         "in distinguisher\n");			return -EINVAL;		}		/* this checks if the previous chain has as many entries		   as it said it has */		if (*n != *cnt) {			BUGPRINT("nentries does not equal the nr of entries "		                 "in the chain\n");			return -EINVAL;		}		/* before we look at the struct, be sure it is not too big */		if ((char *)hook_entries[i] + sizeof(struct ebt_entries)		   > limit) {			BUGPRINT("entries_size too small\n");			return -EINVAL;		}		if (((struct ebt_entries *)e)->policy != EBT_DROP &&		   ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {			/* only RETURN from udc */			if (i != NF_BR_NUMHOOKS ||			   ((struct ebt_entries *)e)->policy != EBT_RETURN) {				BUGPRINT("bad policy\n");				return -EINVAL;			}		}		if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */			(*udc_cnt)++;		else			newinfo->hook_entry[i] = (struct ebt_entries *)e;		if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {			BUGPRINT("counter_offset != totalcnt");			return -EINVAL;		}		*n = ((struct ebt_entries *)e)->nentries;		*cnt = 0;		return 0;	}	/* a plain old entry, heh */	if (sizeof(struct ebt_entry) > e->watchers_offset ||	   e->watchers_offset > e->target_offset ||	   e->target_offset >= e->next_offset) {		BUGPRINT("entry offsets not in right order\n");		return -EINVAL;	}	/* this is not checked anywhere else */	if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {		BUGPRINT("target size too small\n");		return -EINVAL;	}	(*cnt)++;	(*totalcnt)++;	return 0;}struct ebt_cl_stack{	struct ebt_chainstack cs;	int from;	unsigned int hookmask;};/* * we need these positions to check that the jumps to a different part of the * entries is a jump to the beginning of a new chain. */static inline intebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,   struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,   struct ebt_cl_stack *udc){	int i;	/* we're only interested in chain starts */	if (e->bitmask & EBT_ENTRY_OR_ENTRIES)		return 0;	for (i = 0; i < NF_BR_NUMHOOKS; i++) {		if ((valid_hooks & (1 << i)) == 0)			continue;		if (newinfo->hook_entry[i] == (struct ebt_entries *)e)			break;	}	/* only care about udc */	if (i != NF_BR_NUMHOOKS)		return 0;	udc[*n].cs.chaininfo = (struct ebt_entries *)e;	/* these initialisations are depended on later in check_chainloops() */	udc[*n].cs.n = 0;	udc[*n].hookmask = 0;	(*n)++;	return 0;}static inline intebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i){	if (i && (*i)-- == 0)		return 1;	if (m->u.match->destroy)		m->u.match->destroy(m->data, m->match_size);	module_put(m->u.match->me);	return 0;}static inline intebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i){	if (i && (*i)-- == 0)		return 1;	if (w->u.watcher->destroy)		w->u.watcher->destroy(w->data, w->watcher_size);	module_put(w->u.watcher->me);	return 0;}static inline intebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt){	struct ebt_entry_target *t;	if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)		return 0;	/* we're done */	if (cnt && (*cnt)-- == 0)		return 1;	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);	EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);	t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);	if (t->u.target->destroy)		t->u.target->destroy(t->data, t->target_size);	module_put(t->u.target->me);	return 0;}static inline intebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,   const char *name, unsigned int *cnt, unsigned int valid_hooks,   struct ebt_cl_stack *cl_s, unsigned int udc_cnt){	struct ebt_entry_target *t;	struct ebt_target *target;	unsigned int i, j, hook = 0, hookmask = 0;	int ret;	/* don't mess with the struct ebt_entries */	if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)		return 0;	if (e->bitmask & ~EBT_F_MASK) {		BUGPRINT("Unknown flag for bitmask\n");		return -EINVAL;	}	if (e->invflags & ~EBT_INV_MASK) {		BUGPRINT("Unknown flag for inv bitmask\n");		return -EINVAL;	}	if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {		BUGPRINT("NOPROTO & 802_3 not allowed\n");		return -EINVAL;	}	/* what hook do we belong to? */	for (i = 0; i < NF_BR_NUMHOOKS; i++) {		if ((valid_hooks & (1 << i)) == 0)			continue;		if ((char *)newinfo->hook_entry[i] < (char *)e)			hook = i;		else			break;	}	/* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on	   a base chain */	if (i < NF_BR_NUMHOOKS)		hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);	else {		for (i = 0; i < udc_cnt; i++)			if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)				break;		if (i == 0)			hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);		else			hookmask = cl_s[i - 1].hookmask;	}	i = 0;	ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);	if (ret != 0)		goto cleanup_matches;	j = 0;	ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);	if (ret != 0)		goto cleanup_watchers;	t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);	target = find_target_lock(t->u.name, &ret, &ebt_mutex);	if (!target)		goto cleanup_watchers;	if (!try_module_get(target->me)) {		up(&ebt_mutex);		ret = -ENOENT;		goto cleanup_watchers;	}	up(&ebt_mutex);	t->u.target = target;	if (t->u.target == &ebt_standard_target) {		if (e->target_offset + sizeof(struct ebt_standard_target) >		   e->next_offset) {			BUGPRINT("Standard target size too big\n");			ret = -EFAULT;			goto cleanup_watchers;		}		if (((struct ebt_standard_target *)t)->verdict <		   -NUM_STANDARD_TARGETS) {			BUGPRINT("Invalid standard target\n");			ret = -EFAULT;			goto cleanup_watchers;		}	} else if ((e->target_offset + t->target_size +	   sizeof(struct ebt_entry_target) > e->next_offset) ||	   (t->u.target->check &&	   t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){		module_put(t->u.target->me);		ret = -EFAULT;		goto cleanup_watchers;	}	(*cnt)++;	return 0;cleanup_watchers:	EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);cleanup_matches:	EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);	return ret;}/* * checks for loops and sets the hook mask for udc * the hook mask for udc tells us from which base chains the udc can be * accessed. This mask is a parameter to the check() functions of the extensions */static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,   unsigned int udc_cnt, unsigned int hooknr, char *base){	int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;	struct ebt_entry *e = (struct ebt_entry *)chain->data;	struct ebt_entry_target *t;	while (pos < nentries || chain_nr != -1) {		/* end of udc, go back one 'recursion' step */		if (pos == nentries) {			/* put back values of the time when this chain was called */			e = cl_s[chain_nr].cs.e;			if (cl_s[chain_nr].from != -1)				nentries =				cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;			else				nentries = chain->nentries;			pos = cl_s[chain_nr].cs.n;			/* make sure we won't see a loop that isn't one */			cl_s[chain_nr].cs.n = 0;			chain_nr = cl_s[chain_nr].from;			if (pos == nentries)				continue;		}		t = (struct ebt_entry_target *)		   (((char *)e) + e->target_offset);		if (strcmp(t->u.name, EBT_STANDARD_TARGET))			goto letscontinue;		if (e->target_offset + sizeof(struct ebt_standard_target) >		   e->next_offset) {			BUGPRINT("Standard target size too big\n");			return -1;		}		verdict = ((struct ebt_standard_target *)t)->verdict;		if (verdict >= 0) { /* jump to another chain */			struct ebt_entries *hlp2 =			   (struct ebt_entries *)(base + verdict);			for (i = 0; i < udc_cnt; i++)				if (hlp2 == cl_s[i].cs.chaininfo)					break;			/* bad destination or loop */			if (i == udc_cnt) {				BUGPRINT("bad destination\n");				return -1;			}			if (cl_s[i].cs.n) {				BUGPRINT("loop\n");				return -1;			}			/* this can't be 0, so the above test is correct */			cl_s[i].cs.n = pos + 1;			pos = 0;			cl_s[i].cs.e = ((void *)e + e->next_offset);			e = (struct ebt_entry *)(hlp2->data);			nentries = hlp2->nentries;			cl_s[i].from = chain_nr;			chain_nr = i;			/* this udc is accessible from the base chain for hooknr */			cl_s[i].hookmask |= (1 << hooknr);			continue;		}letscontinue:		e = (void *)e + e->next_offset;		pos++;	}	return 0;}/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */static int translate_table(struct ebt_replace *repl,   struct ebt_table_info *newinfo){	unsigned int i, j, k, udc_cnt;	int ret;	struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */	i = 0;	while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))		i++;	if (i == NF_BR_NUMHOOKS) {		BUGPRINT("No valid hooks specified\n");		return -EINVAL;	}	if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {		BUGPRINT("Chains don't start at beginning\n");		return -EINVAL;	}	/* make sure chains are ordered after each other in same order	   as their corresponding hooks */	for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {		if (!(repl->valid_hooks & (1 << j)))			continue;		if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {			BUGPRINT("Hook order must be followed\n");			return -EINVAL;		}		i = j;	}	for (i = 0; i < NF_BR_NUMHOOKS; i++)		newinfo->hook_entry[i] = NULL;	newinfo->entries_size = repl->entries_size;	newinfo->nentries = repl->nentries;	/* do some early checkings and initialize some things */	i = 0; /* holds the expected nr. of entries for the chain */	j = 0; /* holds the up to now counted entries for the chain */	k = 0; /* holds the total nr. of entries, should equal	          newinfo->nentries afterwards */	udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */	ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,	   ebt_check_entry_size_and_hooks, newinfo, repl->entries,	   repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,	   &udc_cnt, repl->valid_hooks);	if (ret != 0)		return ret;	if (i != j) {		BUGPRINT("nentries does not equal the nr of entries in the "		         "(last) chain\n");		return -EINVAL;	}	if (k != newinfo->nentries) {		BUGPRINT("Total nentries is wrong\n");		return -EINVAL;	}	/* check if all valid hooks have a chain */	for (i = 0; i < NF_BR_NUMHOOKS; i++) {		if (newinfo->hook_entry[i] == NULL &&		   (repl->valid_hooks & (1 << i))) {			BUGPRINT("Valid hook without chain\n");			return -EINVAL;		}	}	/* get the location of the udc, put them in an array	   while we're at it, allocate the chainstack */	if (udc_cnt) {		/* this will get free'd in do_replace()/ebt_register_table()		   if an error occurs */		newinfo->chainstack = (struct ebt_chainstack **)		   vmalloc(NR_CPUS * sizeof(struct ebt_chainstack));		if (!newinfo->chainstack)			return -ENOMEM;		for (i = 0; i < NR_CPUS; i++) {			newinfo->chainstack[i] =			   vmalloc(udc_cnt * sizeof(struct ebt_chainstack));			if (!newinfo->chainstack[i]) {				while (i)					vfree(newinfo->chainstack[--i]);				vfree(newinfo->chainstack);				newinfo->chainstack = NULL;				return -ENOMEM;			}		}		cl_s = (struct ebt_cl_stack *)		   vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));		if (!cl_s)			return -ENOMEM;		i = 0; /* the i'th udc */		EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,		   ebt_get_udc_positions, newinfo, repl->hook_entry, &i,		   repl->valid_hooks, cl_s);		/* sanity check */		if (i != udc_cnt) {			BUGPRINT("i != udc_cnt\n");			vfree(cl_s);			return -EFAULT;		}	}	/* Check for loops */	for (i = 0; i < NF_BR_NUMHOOKS; i++)		if (repl->valid_hooks & (1 << i))			if (check_chainloops(newinfo->hook_entry[i],			   cl_s, udc_cnt, i, newinfo->entries)) {				if (cl_s)					vfree(cl_s);				return -EINVAL;			}	/* we now know the following (along with E=mc

⌨️ 快捷键说明

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