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

📄 ebtables.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	else		ret = 0;	/* decrease module count and free resources */	EBT_ENTRY_ITERATE(table->entries, table->entries_size,	   ebt_cleanup_entry, NULL);	vfree(table->entries);	if (table->chainstack) {		for_each_possible_cpu(i)			vfree(table->chainstack[i]);		vfree(table->chainstack);	}	vfree(table);	vfree(counterstmp);	return ret;free_unlock:	mutex_unlock(&ebt_mutex);free_iterate:	EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,	   ebt_cleanup_entry, NULL);free_counterstmp:	vfree(counterstmp);	/* can be initialized in translate_table() */	if (newinfo->chainstack) {		for_each_possible_cpu(i)			vfree(newinfo->chainstack[i]);		vfree(newinfo->chainstack);	}free_entries:	vfree(newinfo->entries);free_newinfo:	vfree(newinfo);	return ret;}int ebt_register_target(struct ebt_target *target){	struct ebt_target *t;	int ret;	ret = mutex_lock_interruptible(&ebt_mutex);	if (ret != 0)		return ret;	list_for_each_entry(t, &ebt_targets, list) {		if (strcmp(t->name, target->name) == 0) {			mutex_unlock(&ebt_mutex);			return -EEXIST;		}	}	list_add(&target->list, &ebt_targets);	mutex_unlock(&ebt_mutex);	return 0;}void ebt_unregister_target(struct ebt_target *target){	mutex_lock(&ebt_mutex);	list_del(&target->list);	mutex_unlock(&ebt_mutex);}int ebt_register_match(struct ebt_match *match){	struct ebt_match *m;	int ret;	ret = mutex_lock_interruptible(&ebt_mutex);	if (ret != 0)		return ret;	list_for_each_entry(m, &ebt_matches, list) {		if (strcmp(m->name, match->name) == 0) {			mutex_unlock(&ebt_mutex);			return -EEXIST;		}	}	list_add(&match->list, &ebt_matches);	mutex_unlock(&ebt_mutex);	return 0;}void ebt_unregister_match(struct ebt_match *match){	mutex_lock(&ebt_mutex);	list_del(&match->list);	mutex_unlock(&ebt_mutex);}int ebt_register_watcher(struct ebt_watcher *watcher){	struct ebt_watcher *w;	int ret;	ret = mutex_lock_interruptible(&ebt_mutex);	if (ret != 0)		return ret;	list_for_each_entry(w, &ebt_watchers, list) {		if (strcmp(w->name, watcher->name) == 0) {			mutex_unlock(&ebt_mutex);			return -EEXIST;		}	}	list_add(&watcher->list, &ebt_watchers);	mutex_unlock(&ebt_mutex);	return 0;}void ebt_unregister_watcher(struct ebt_watcher *watcher){	mutex_lock(&ebt_mutex);	list_del(&watcher->list);	mutex_unlock(&ebt_mutex);}int ebt_register_table(struct ebt_table *table){	struct ebt_table_info *newinfo;	struct ebt_table *t;	struct ebt_replace_kernel *repl;	int ret, i, countersize;	void *p;	if (!table || !(repl = table->table) || !repl->entries ||	    repl->entries_size == 0 ||	    repl->counters || table->private) {		BUGPRINT("Bad table data for ebt_register_table!!!\n");		return -EINVAL;	}	countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;	newinfo = vmalloc(sizeof(*newinfo) + countersize);	ret = -ENOMEM;	if (!newinfo)		return -ENOMEM;	p = vmalloc(repl->entries_size);	if (!p)		goto free_newinfo;	memcpy(p, repl->entries, repl->entries_size);	newinfo->entries = p;	newinfo->entries_size = repl->entries_size;	newinfo->nentries = repl->nentries;	if (countersize)		memset(newinfo->counters, 0, countersize);	/* fill in newinfo and parse the entries */	newinfo->chainstack = NULL;	for (i = 0; i < NF_BR_NUMHOOKS; i++) {		if ((repl->valid_hooks & (1 << i)) == 0)			newinfo->hook_entry[i] = NULL;		else			newinfo->hook_entry[i] = p +				((char *)repl->hook_entry[i] - repl->entries);	}	ret = translate_table(repl->name, newinfo);	if (ret != 0) {		BUGPRINT("Translate_table failed\n");		goto free_chainstack;	}	if (table->check && table->check(newinfo, table->valid_hooks)) {		BUGPRINT("The table doesn't like its own initial data, lol\n");		return -EINVAL;	}	table->private = newinfo;	rwlock_init(&table->lock);	ret = mutex_lock_interruptible(&ebt_mutex);	if (ret != 0)		goto free_chainstack;	list_for_each_entry(t, &ebt_tables, list) {		if (strcmp(t->name, table->name) == 0) {			ret = -EEXIST;			BUGPRINT("Table name already exists\n");			goto free_unlock;		}	}	/* Hold a reference count if the chains aren't empty */	if (newinfo->nentries && !try_module_get(table->me)) {		ret = -ENOENT;		goto free_unlock;	}	list_add(&table->list, &ebt_tables);	mutex_unlock(&ebt_mutex);	return 0;free_unlock:	mutex_unlock(&ebt_mutex);free_chainstack:	if (newinfo->chainstack) {		for_each_possible_cpu(i)			vfree(newinfo->chainstack[i]);		vfree(newinfo->chainstack);	}	vfree(newinfo->entries);free_newinfo:	vfree(newinfo);	return ret;}void ebt_unregister_table(struct ebt_table *table){	int i;	if (!table) {		BUGPRINT("Request to unregister NULL table!!!\n");		return;	}	mutex_lock(&ebt_mutex);	list_del(&table->list);	mutex_unlock(&ebt_mutex);	vfree(table->private->entries);	if (table->private->chainstack) {		for_each_possible_cpu(i)			vfree(table->private->chainstack[i]);		vfree(table->private->chainstack);	}	vfree(table->private);}/* userspace just supplied us with counters */static int update_counters(void __user *user, unsigned int len){	int i, ret;	struct ebt_counter *tmp;	struct ebt_replace hlp;	struct ebt_table *t;	if (copy_from_user(&hlp, user, sizeof(hlp)))		return -EFAULT;	if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))		return -EINVAL;	if (hlp.num_counters == 0)		return -EINVAL;	if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {		MEMPRINT("Update_counters && nomemory\n");		return -ENOMEM;	}	t = find_table_lock(hlp.name, &ret, &ebt_mutex);	if (!t)		goto free_tmp;	if (hlp.num_counters != t->private->nentries) {		BUGPRINT("Wrong nr of counters\n");		ret = -EINVAL;		goto unlock_mutex;	}	if ( copy_from_user(tmp, hlp.counters,	   hlp.num_counters * sizeof(struct ebt_counter)) ) {		BUGPRINT("Updata_counters && !cfu\n");		ret = -EFAULT;		goto unlock_mutex;	}	/* we want an atomic add of the counters */	write_lock_bh(&t->lock);	/* we add to the counters of the first cpu */	for (i = 0; i < hlp.num_counters; i++) {		t->private->counters[i].pcnt += tmp[i].pcnt;		t->private->counters[i].bcnt += tmp[i].bcnt;	}	write_unlock_bh(&t->lock);	ret = 0;unlock_mutex:	mutex_unlock(&ebt_mutex);free_tmp:	vfree(tmp);	return ret;}static inline int ebt_make_matchname(struct ebt_entry_match *m,   char *base, char __user *ubase){	char __user *hlp = ubase + ((char *)m - base);	if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))		return -EFAULT;	return 0;}static inline int ebt_make_watchername(struct ebt_entry_watcher *w,   char *base, char __user *ubase){	char __user *hlp = ubase + ((char *)w - base);	if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))		return -EFAULT;	return 0;}static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase){	int ret;	char __user *hlp;	struct ebt_entry_target *t;	if (e->bitmask == 0)		return 0;	hlp = ubase + (((char *)e + e->target_offset) - base);	t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);	ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);	if (ret != 0)		return ret;	ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);	if (ret != 0)		return ret;	if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))		return -EFAULT;	return 0;}/* called with ebt_mutex locked */static int copy_everything_to_user(struct ebt_table *t, void __user *user,   int *len, int cmd){	struct ebt_replace tmp;	struct ebt_counter *counterstmp, *oldcounters;	unsigned int entries_size, nentries;	char *entries;	if (cmd == EBT_SO_GET_ENTRIES) {		entries_size = t->private->entries_size;		nentries = t->private->nentries;		entries = t->private->entries;		oldcounters = t->private->counters;	} else {		entries_size = t->table->entries_size;		nentries = t->table->nentries;		entries = t->table->entries;		oldcounters = t->table->counters;	}	if (copy_from_user(&tmp, user, sizeof(tmp))) {		BUGPRINT("Cfu didn't work\n");		return -EFAULT;	}	if (*len != sizeof(struct ebt_replace) + entries_size +	   (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {		BUGPRINT("Wrong size\n");		return -EINVAL;	}	if (tmp.nentries != nentries) {		BUGPRINT("Nentries wrong\n");		return -EINVAL;	}	if (tmp.entries_size != entries_size) {		BUGPRINT("Wrong size\n");		return -EINVAL;	}	/* userspace might not need the counters */	if (tmp.num_counters) {		if (tmp.num_counters != nentries) {			BUGPRINT("Num_counters wrong\n");			return -EINVAL;		}		counterstmp = vmalloc(nentries * sizeof(*counterstmp));		if (!counterstmp) {			MEMPRINT("Couldn't copy counters, out of memory\n");			return -ENOMEM;		}		write_lock_bh(&t->lock);		get_counters(oldcounters, counterstmp, nentries);		write_unlock_bh(&t->lock);		if (copy_to_user(tmp.counters, counterstmp,		   nentries * sizeof(struct ebt_counter))) {			BUGPRINT("Couldn't copy counters to userspace\n");			vfree(counterstmp);			return -EFAULT;		}		vfree(counterstmp);	}	if (copy_to_user(tmp.entries, entries, entries_size)) {		BUGPRINT("Couldn't copy entries to userspace\n");		return -EFAULT;	}	/* set the match/watcher/target names right */	return EBT_ENTRY_ITERATE(entries, entries_size,	   ebt_make_names, entries, tmp.entries);}static int do_ebt_set_ctl(struct sock *sk,	int cmd, void __user *user, unsigned int len){	int ret;	switch(cmd) {	case EBT_SO_SET_ENTRIES:		ret = do_replace(user, len);		break;	case EBT_SO_SET_COUNTERS:		ret = update_counters(user, len);		break;	default:		ret = -EINVAL;  }	return ret;}static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len){	int ret;	struct ebt_replace tmp;	struct ebt_table *t;	if (copy_from_user(&tmp, user, sizeof(tmp)))		return -EFAULT;	t = find_table_lock(tmp.name, &ret, &ebt_mutex);	if (!t)		return ret;	switch(cmd) {	case EBT_SO_GET_INFO:	case EBT_SO_GET_INIT_INFO:		if (*len != sizeof(struct ebt_replace)){			ret = -EINVAL;			mutex_unlock(&ebt_mutex);			break;		}		if (cmd == EBT_SO_GET_INFO) {			tmp.nentries = t->private->nentries;			tmp.entries_size = t->private->entries_size;			tmp.valid_hooks = t->valid_hooks;		} else {			tmp.nentries = t->table->nentries;			tmp.entries_size = t->table->entries_size;			tmp.valid_hooks = t->table->valid_hooks;		}		mutex_unlock(&ebt_mutex);		if (copy_to_user(user, &tmp, *len) != 0){			BUGPRINT("c2u Didn't work\n");			ret = -EFAULT;			break;		}		ret = 0;		break;	case EBT_SO_GET_ENTRIES:	case EBT_SO_GET_INIT_ENTRIES:		ret = copy_everything_to_user(t, user, len, cmd);		mutex_unlock(&ebt_mutex);		break;	default:		mutex_unlock(&ebt_mutex);		ret = -EINVAL;	}	return ret;}static struct nf_sockopt_ops ebt_sockopts ={	.pf		= PF_INET,	.set_optmin	= EBT_BASE_CTL,	.set_optmax	= EBT_SO_SET_MAX + 1,	.set		= do_ebt_set_ctl,	.get_optmin	= EBT_BASE_CTL,	.get_optmax	= EBT_SO_GET_MAX + 1,	.get		= do_ebt_get_ctl,	.owner		= THIS_MODULE,};static int __init ebtables_init(void){	int ret;	mutex_lock(&ebt_mutex);	list_add(&ebt_standard_target.list, &ebt_targets);	mutex_unlock(&ebt_mutex);	if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)		return ret;	printk(KERN_INFO "Ebtables v2.0 registered\n");	return 0;}static void __exit ebtables_fini(void){	nf_unregister_sockopt(&ebt_sockopts);	printk(KERN_INFO "Ebtables v2.0 unregistered\n");}EXPORT_SYMBOL(ebt_register_table);EXPORT_SYMBOL(ebt_unregister_table);EXPORT_SYMBOL(ebt_register_match);EXPORT_SYMBOL(ebt_unregister_match);EXPORT_SYMBOL(ebt_register_watcher);EXPORT_SYMBOL(ebt_unregister_watcher);EXPORT_SYMBOL(ebt_register_target);EXPORT_SYMBOL(ebt_unregister_target);EXPORT_SYMBOL(ebt_do_table);module_init(ebtables_init);module_exit(ebtables_fini);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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