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

📄 ip_tables.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct ipt_match *m;	int have_rev = 0;	list_for_each_entry(m, &ipt_match, list) {		if (strcmp(m->name, name) == 0) {			if (m->revision > *bestp)				*bestp = m->revision;			if (m->revision == revision)				have_rev = 1;		}	}	return have_rev;}static int target_revfn(const char *name, u8 revision, int *bestp){	struct ipt_target *t;	int have_rev = 0;	list_for_each_entry(t, &ipt_target, list) {		if (strcmp(t->name, name) == 0) {			if (t->revision > *bestp)				*bestp = t->revision;			if (t->revision == revision)				have_rev = 1;		}	}	return have_rev;}/* Returns true or false (if no such extension at all) */static inline int find_revision(const char *name, u8 revision,				int (*revfn)(const char *, u8, int *),				int *err){	int have_rev, best = -1;	if (down_interruptible(&ipt_mutex) != 0) {		*err = -EINTR;		return 1;	}	have_rev = revfn(name, revision, &best);	up(&ipt_mutex);	/* Nothing at all?  Return 0 to try loading module. */	if (best == -1) {		*err = -ENOENT;		return 0;	}	*err = best;	if (!have_rev)		*err = -EPROTONOSUPPORT;	return 1;}/* All zeroes == unconditional rule. */static inline intunconditional(const struct ipt_ip *ip){	unsigned int i;	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)		if (((__u32 *)ip)[i])			return 0;	return 1;}/* Figures out from what hook each rule can be called: returns 0 if   there are loops.  Puts hook bitmask in comefrom. */static intmark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks){	unsigned int hook;	/* No recursion; use packet counter to save back ptrs (reset	   to 0 as we leave), and comefrom to save source hook bitmask */	for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {		unsigned int pos = newinfo->hook_entry[hook];		struct ipt_entry *e			= (struct ipt_entry *)(newinfo->entries + pos);		if (!(valid_hooks & (1 << hook)))			continue;		/* Set initial back pointer. */		e->counters.pcnt = pos;		for (;;) {			struct ipt_standard_target *t				= (void *)ipt_get_target(e);			if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {				printk("iptables: loop hook %u pos %u %08X.\n",				       hook, pos, e->comefrom);				return 0;			}			e->comefrom				|= ((1 << hook) | (1 << NF_IP_NUMHOOKS));			/* Unconditional return/END. */			if (e->target_offset == sizeof(struct ipt_entry)			    && (strcmp(t->target.u.user.name,				       IPT_STANDARD_TARGET) == 0)			    && t->verdict < 0			    && unconditional(&e->ip)) {				unsigned int oldpos, size;				/* Return: backtrack through the last				   big jump. */				do {					e->comefrom ^= (1<<NF_IP_NUMHOOKS);#ifdef DEBUG_IP_FIREWALL_USER					if (e->comefrom					    & (1 << NF_IP_NUMHOOKS)) {						duprintf("Back unset "							 "on hook %u "							 "rule %u\n",							 hook, pos);					}#endif					oldpos = pos;					pos = e->counters.pcnt;					e->counters.pcnt = 0;					/* We're at the start. */					if (pos == oldpos)						goto next;					e = (struct ipt_entry *)						(newinfo->entries + pos);				} while (oldpos == pos + e->next_offset);				/* Move along one */				size = e->next_offset;				e = (struct ipt_entry *)					(newinfo->entries + pos + size);				e->counters.pcnt = pos;				pos += size;			} else {				int newpos = t->verdict;				if (strcmp(t->target.u.user.name,					   IPT_STANDARD_TARGET) == 0				    && newpos >= 0) {					/* This a jump; chase it. */					duprintf("Jump rule %u -> %u\n",						 pos, newpos);				} else {					/* ... this is a fallthru */					newpos = pos + e->next_offset;				}				e = (struct ipt_entry *)					(newinfo->entries + newpos);				e->counters.pcnt = pos;				pos = newpos;			}		}		next:		duprintf("Finished chain %u\n", hook);	}	return 1;}static inline intcleanup_match(struct ipt_entry_match *m, unsigned int *i){	if (i && (*i)-- == 0)		return 1;	if (m->u.kernel.match->destroy)		m->u.kernel.match->destroy(m->data,					   m->u.match_size - sizeof(*m));	module_put(m->u.kernel.match->me);	return 0;}static inline intstandard_check(const struct ipt_entry_target *t,	       unsigned int max_offset){	struct ipt_standard_target *targ = (void *)t;	/* Check standard info. */	if (t->u.target_size	    != IPT_ALIGN(sizeof(struct ipt_standard_target))) {		duprintf("standard_check: target size %u != %u\n",			 t->u.target_size,			 IPT_ALIGN(sizeof(struct ipt_standard_target)));		return 0;	}	if (targ->verdict >= 0	    && targ->verdict > max_offset - sizeof(struct ipt_entry)) {		duprintf("ipt_standard_check: bad verdict (%i)\n",			 targ->verdict);		return 0;	}	if (targ->verdict < -NF_MAX_VERDICT - 1) {		duprintf("ipt_standard_check: bad negative verdict (%i)\n",			 targ->verdict);		return 0;	}	return 1;}static inline intcheck_match(struct ipt_entry_match *m,	    const char *name,	    const struct ipt_ip *ip,	    unsigned int hookmask,	    unsigned int *i){	struct ipt_match *match;	match = try_then_request_module(find_match(m->u.user.name,						   m->u.user.revision),					"ipt_%s", m->u.user.name);	if (IS_ERR(match) || !match) {		duprintf("check_match: `%s' not found\n", m->u.user.name);		return match ? PTR_ERR(match) : -ENOENT;	}	m->u.kernel.match = match;	if (m->u.kernel.match->checkentry	    && !m->u.kernel.match->checkentry(name, ip, m->data,					      m->u.match_size - sizeof(*m),					      hookmask)) {		module_put(m->u.kernel.match->me);		duprintf("ip_tables: check failed for `%s'.\n",			 m->u.kernel.match->name);		return -EINVAL;	}	(*i)++;	return 0;}static struct ipt_target ipt_standard_target;static inline intcheck_entry(struct ipt_entry *e, const char *name, unsigned int size,	    unsigned int *i){	struct ipt_entry_target *t;	struct ipt_target *target;	int ret;	unsigned int j;	if (!ip_checkentry(&e->ip)) {		duprintf("ip_tables: ip check failed %p %s.\n", e, name);		return -EINVAL;	}	j = 0;	ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);	if (ret != 0)		goto cleanup_matches;	t = ipt_get_target(e);	target = try_then_request_module(find_target(t->u.user.name,						     t->u.user.revision),					 "ipt_%s", t->u.user.name);	if (IS_ERR(target) || !target) {		duprintf("check_entry: `%s' not found\n", t->u.user.name);		ret = target ? PTR_ERR(target) : -ENOENT;		goto cleanup_matches;	}	t->u.kernel.target = target;	if (t->u.kernel.target == &ipt_standard_target) {		if (!standard_check(t, size)) {			ret = -EINVAL;			goto cleanup_matches;		}	} else if (t->u.kernel.target->checkentry		   && !t->u.kernel.target->checkentry(name, e, t->data,						      t->u.target_size						      - sizeof(*t),						      e->comefrom)) {		module_put(t->u.kernel.target->me);		duprintf("ip_tables: check failed for `%s'.\n",			 t->u.kernel.target->name);		ret = -EINVAL;		goto cleanup_matches;	}	(*i)++;	return 0; cleanup_matches:	IPT_MATCH_ITERATE(e, cleanup_match, &j);	return ret;}static inline intcheck_entry_size_and_hooks(struct ipt_entry *e,			   struct ipt_table_info *newinfo,			   unsigned char *base,			   unsigned char *limit,			   const unsigned int *hook_entries,			   const unsigned int *underflows,			   unsigned int *i){	unsigned int h;	if ((unsigned long)e % __alignof__(struct ipt_entry) != 0	    || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {		duprintf("Bad offset %p\n", e);		return -EINVAL;	}	if (e->next_offset	    < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {		duprintf("checking: element %p size %u\n",			 e, e->next_offset);		return -EINVAL;	}	/* Check hooks & underflows */	for (h = 0; h < NF_IP_NUMHOOKS; h++) {		if ((unsigned char *)e - base == hook_entries[h])			newinfo->hook_entry[h] = hook_entries[h];		if ((unsigned char *)e - base == underflows[h])			newinfo->underflow[h] = underflows[h];	}	/* FIXME: underflows must be unconditional, standard verdicts           < 0 (not IPT_RETURN). --RR */	/* Clear counters and comefrom */	e->counters = ((struct ipt_counters) { 0, 0 });	e->comefrom = 0;	(*i)++;	return 0;}static inline intcleanup_entry(struct ipt_entry *e, unsigned int *i){	struct ipt_entry_target *t;	if (i && (*i)-- == 0)		return 1;	/* Cleanup all matches */	IPT_MATCH_ITERATE(e, cleanup_match, NULL);	t = ipt_get_target(e);	if (t->u.kernel.target->destroy)		t->u.kernel.target->destroy(t->data,					    t->u.target_size - sizeof(*t));	module_put(t->u.kernel.target->me);	return 0;}/* Checks and translates the user-supplied table segment (held in   newinfo) */static inttranslate_table(const char *name,		unsigned int valid_hooks,		struct ipt_table_info *newinfo,		unsigned int size,		unsigned int number,		const unsigned int *hook_entries,		const unsigned int *underflows){	unsigned int i;	int ret;	newinfo->size = size;	newinfo->number = number;	/* Init all hooks to impossible value. */	for (i = 0; i < NF_IP_NUMHOOKS; i++) {		newinfo->hook_entry[i] = 0xFFFFFFFF;		newinfo->underflow[i] = 0xFFFFFFFF;	}	duprintf("translate_table: size %u\n", newinfo->size);	i = 0;	/* Walk through entries, checking offsets. */	ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,				check_entry_size_and_hooks,				newinfo,				newinfo->entries,				newinfo->entries + size,				hook_entries, underflows, &i);	if (ret != 0)		return ret;	if (i != number) {		duprintf("translate_table: %u not %u entries\n",			 i, number);		return -EINVAL;	}	/* Check hooks all assigned */	for (i = 0; i < NF_IP_NUMHOOKS; i++) {		/* Only hooks which are valid */		if (!(valid_hooks & (1 << i)))			continue;		if (newinfo->hook_entry[i] == 0xFFFFFFFF) {			duprintf("Invalid hook entry %u %u\n",				 i, hook_entries[i]);			return -EINVAL;		}		if (newinfo->underflow[i] == 0xFFFFFFFF) {			duprintf("Invalid underflow %u %u\n",				 i, underflows[i]);			return -EINVAL;		}	}	if (!mark_source_chains(newinfo, valid_hooks))		return -ELOOP;	/* Finally, each sanity check must pass */	i = 0;	ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,				check_entry, name, size, &i);	if (ret != 0) {		IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,				  cleanup_entry, &i);		return ret;	}	/* And one copy for every other CPU */	for_each_cpu(i) {		if (i == 0)			continue;		memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,		       newinfo->entries,		       SMP_ALIGN(newinfo->size));	}	return ret;}static struct ipt_table_info *replace_table(struct ipt_table *table,	      unsigned int num_counters,	      struct ipt_table_info *newinfo,	      int *error){	struct ipt_table_info *oldinfo;#ifdef CONFIG_NETFILTER_DEBUG	{		struct ipt_entry *table_base;		unsigned int i;		for_each_cpu(i) {			table_base =				(void *)newinfo->entries				+ TABLE_OFFSET(newinfo, i);			table_base->comefrom = 0xdead57ac;		}	}#endif	/* Do the substitution. */	write_lock_bh(&table->lock);	/* Check inside lock: is the old number correct? */	if (num_counters != table->private->number) {		duprintf("num_counters != table->private->number (%u/%u)\n",			 num_counters, table->private->number);		write_unlock_bh(&table->lock);		*error = -EAGAIN;		return NULL;	}	oldinfo = table->private;	table->private = newinfo;	newinfo->initial_entries = oldinfo->initial_entries;	write_unlock_bh(&table->lock);	return oldinfo;}/* Gets counters. */static inline intadd_entry_to_counter(const struct ipt_entry *e,		     struct ipt_counters total[],		     unsigned int *i){	ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);

⌨️ 快捷键说明

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