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

📄 x_tables.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * x_tables core - Backend for {ip,ip6,arp}_tables * * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org> * * Based on existing ip_tables code which is *   Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling *   Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/kernel.h>#include <linux/socket.h>#include <linux/net.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/string.h>#include <linux/vmalloc.h>#include <linux/mutex.h>#include <linux/mm.h>#include <net/net_namespace.h>#include <linux/netfilter/x_tables.h>#include <linux/netfilter_arp.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))struct xt_af {	struct mutex mutex;	struct list_head match;	struct list_head target;	struct list_head tables;	struct mutex compat_mutex;};static struct xt_af *xt;#ifdef DEBUG_IP_FIREWALL_USER#define duprintf(format, args...) printk(format , ## args)#else#define duprintf(format, args...)#endifenum {	TABLE,	TARGET,	MATCH,};static const char *xt_prefix[NPROTO] = {	[AF_INET]	= "ip",	[AF_INET6]	= "ip6",	[NF_ARP]	= "arp",};/* Registration hooks for targets. */intxt_register_target(struct xt_target *target){	int ret, af = target->family;	ret = mutex_lock_interruptible(&xt[af].mutex);	if (ret != 0)		return ret;	list_add(&target->list, &xt[af].target);	mutex_unlock(&xt[af].mutex);	return ret;}EXPORT_SYMBOL(xt_register_target);voidxt_unregister_target(struct xt_target *target){	int af = target->family;	mutex_lock(&xt[af].mutex);	list_del(&target->list);	mutex_unlock(&xt[af].mutex);}EXPORT_SYMBOL(xt_unregister_target);intxt_register_targets(struct xt_target *target, unsigned int n){	unsigned int i;	int err = 0;	for (i = 0; i < n; i++) {		err = xt_register_target(&target[i]);		if (err)			goto err;	}	return err;err:	if (i > 0)		xt_unregister_targets(target, i);	return err;}EXPORT_SYMBOL(xt_register_targets);voidxt_unregister_targets(struct xt_target *target, unsigned int n){	unsigned int i;	for (i = 0; i < n; i++)		xt_unregister_target(&target[i]);}EXPORT_SYMBOL(xt_unregister_targets);intxt_register_match(struct xt_match *match){	int ret, af = match->family;	ret = mutex_lock_interruptible(&xt[af].mutex);	if (ret != 0)		return ret;	list_add(&match->list, &xt[af].match);	mutex_unlock(&xt[af].mutex);	return ret;}EXPORT_SYMBOL(xt_register_match);voidxt_unregister_match(struct xt_match *match){	int af =  match->family;	mutex_lock(&xt[af].mutex);	list_del(&match->list);	mutex_unlock(&xt[af].mutex);}EXPORT_SYMBOL(xt_unregister_match);intxt_register_matches(struct xt_match *match, unsigned int n){	unsigned int i;	int err = 0;	for (i = 0; i < n; i++) {		err = xt_register_match(&match[i]);		if (err)			goto err;	}	return err;err:	if (i > 0)		xt_unregister_matches(match, i);	return err;}EXPORT_SYMBOL(xt_register_matches);voidxt_unregister_matches(struct xt_match *match, unsigned int n){	unsigned int i;	for (i = 0; i < n; i++)		xt_unregister_match(&match[i]);}EXPORT_SYMBOL(xt_unregister_matches);/* * These are weird, but module loading must not be done with mutex * held (since they will register), and we have to have a single * function to use try_then_request_module(). *//* Find match, grabs ref.  Returns ERR_PTR() on error. */struct xt_match *xt_find_match(int af, const char *name, u8 revision){	struct xt_match *m;	int err = 0;	if (mutex_lock_interruptible(&xt[af].mutex) != 0)		return ERR_PTR(-EINTR);	list_for_each_entry(m, &xt[af].match, list) {		if (strcmp(m->name, name) == 0) {			if (m->revision == revision) {				if (try_module_get(m->me)) {					mutex_unlock(&xt[af].mutex);					return m;				}			} else				err = -EPROTOTYPE; /* Found something. */		}	}	mutex_unlock(&xt[af].mutex);	return ERR_PTR(err);}EXPORT_SYMBOL(xt_find_match);/* Find target, grabs ref.  Returns ERR_PTR() on error. */struct xt_target *xt_find_target(int af, const char *name, u8 revision){	struct xt_target *t;	int err = 0;	if (mutex_lock_interruptible(&xt[af].mutex) != 0)		return ERR_PTR(-EINTR);	list_for_each_entry(t, &xt[af].target, list) {		if (strcmp(t->name, name) == 0) {			if (t->revision == revision) {				if (try_module_get(t->me)) {					mutex_unlock(&xt[af].mutex);					return t;				}			} else				err = -EPROTOTYPE; /* Found something. */		}	}	mutex_unlock(&xt[af].mutex);	return ERR_PTR(err);}EXPORT_SYMBOL(xt_find_target);struct xt_target *xt_request_find_target(int af, const char *name, u8 revision){	struct xt_target *target;	target = try_then_request_module(xt_find_target(af, name, revision),					 "%st_%s", xt_prefix[af], name);	if (IS_ERR(target) || !target)		return NULL;	return target;}EXPORT_SYMBOL_GPL(xt_request_find_target);static int match_revfn(int af, const char *name, u8 revision, int *bestp){	struct xt_match *m;	int have_rev = 0;	list_for_each_entry(m, &xt[af].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(int af, const char *name, u8 revision, int *bestp){	struct xt_target *t;	int have_rev = 0;	list_for_each_entry(t, &xt[af].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) */int xt_find_revision(int af, const char *name, u8 revision, int target,		     int *err){	int have_rev, best = -1;	if (mutex_lock_interruptible(&xt[af].mutex) != 0) {		*err = -EINTR;		return 1;	}	if (target == 1)		have_rev = target_revfn(af, name, revision, &best);	else		have_rev = match_revfn(af, name, revision, &best);	mutex_unlock(&xt[af].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;}EXPORT_SYMBOL_GPL(xt_find_revision);int xt_check_match(const struct xt_match *match, unsigned short family,		   unsigned int size, const char *table, unsigned int hook_mask,		   unsigned short proto, int inv_proto){	if (XT_ALIGN(match->matchsize) != size) {		printk("%s_tables: %s match: invalid size %Zu != %u\n",		       xt_prefix[family], match->name,		       XT_ALIGN(match->matchsize), size);		return -EINVAL;	}	if (match->table && strcmp(match->table, table)) {		printk("%s_tables: %s match: only valid in %s table, not %s\n",		       xt_prefix[family], match->name, match->table, table);		return -EINVAL;	}	if (match->hooks && (hook_mask & ~match->hooks) != 0) {		printk("%s_tables: %s match: bad hook_mask %u/%u\n",		       xt_prefix[family], match->name, hook_mask, match->hooks);		return -EINVAL;	}	if (match->proto && (match->proto != proto || inv_proto)) {		printk("%s_tables: %s match: only valid for protocol %u\n",		       xt_prefix[family], match->name, match->proto);		return -EINVAL;	}	return 0;}EXPORT_SYMBOL_GPL(xt_check_match);#ifdef CONFIG_COMPATint xt_compat_match_offset(struct xt_match *match){	u_int16_t csize = match->compatsize ? : match->matchsize;	return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);}EXPORT_SYMBOL_GPL(xt_compat_match_offset);void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,			       int *size){	struct xt_match *match = m->u.kernel.match;	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;	int pad, off = xt_compat_match_offset(match);	u_int16_t msize = cm->u.user.match_size;	m = *dstptr;	memcpy(m, cm, sizeof(*cm));	if (match->compat_from_user)		match->compat_from_user(m->data, cm->data);	else		memcpy(m->data, cm->data, msize - sizeof(*cm));	pad = XT_ALIGN(match->matchsize) - match->matchsize;	if (pad > 0)		memset(m->data + match->matchsize, 0, pad);	msize += off;	m->u.user.match_size = msize;	*size += off;	*dstptr += msize;}EXPORT_SYMBOL_GPL(xt_compat_match_from_user);int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,			    int *size){	struct xt_match *match = m->u.kernel.match;	struct compat_xt_entry_match __user *cm = *dstptr;	int off = xt_compat_match_offset(match);	u_int16_t msize = m->u.user.match_size - off;	if (copy_to_user(cm, m, sizeof(*cm)) ||	    put_user(msize, &cm->u.user.match_size) ||	    copy_to_user(cm->u.user.name, m->u.kernel.match->name,			 strlen(m->u.kernel.match->name) + 1))		return -EFAULT;	if (match->compat_to_user) {		if (match->compat_to_user((void __user *)cm->data, m->data))			return -EFAULT;	} else {		if (copy_to_user(cm->data, m->data, msize - sizeof(*cm)))			return -EFAULT;	}	*size -= off;	*dstptr += msize;	return 0;}EXPORT_SYMBOL_GPL(xt_compat_match_to_user);#endif /* CONFIG_COMPAT */int xt_check_target(const struct xt_target *target, unsigned short family,		    unsigned int size, const char *table, unsigned int hook_mask,		    unsigned short proto, int inv_proto){	if (XT_ALIGN(target->targetsize) != size) {		printk("%s_tables: %s target: invalid size %Zu != %u\n",		       xt_prefix[family], target->name,		       XT_ALIGN(target->targetsize), size);		return -EINVAL;	}	if (target->table && strcmp(target->table, table)) {		printk("%s_tables: %s target: only valid in %s table, not %s\n",		       xt_prefix[family], target->name, target->table, table);		return -EINVAL;	}	if (target->hooks && (hook_mask & ~target->hooks) != 0) {		printk("%s_tables: %s target: bad hook_mask %u/%u\n",		       xt_prefix[family], target->name, hook_mask,		       target->hooks);		return -EINVAL;	}	if (target->proto && (target->proto != proto || inv_proto)) {		printk("%s_tables: %s target: only valid for protocol %u\n",		       xt_prefix[family], target->name, target->proto);		return -EINVAL;	}	return 0;}EXPORT_SYMBOL_GPL(xt_check_target);#ifdef CONFIG_COMPATint xt_compat_target_offset(struct xt_target *target){	u_int16_t csize = target->compatsize ? : target->targetsize;	return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);}EXPORT_SYMBOL_GPL(xt_compat_target_offset);void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,				int *size){	struct xt_target *target = t->u.kernel.target;	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;	int pad, off = xt_compat_target_offset(target);	u_int16_t tsize = ct->u.user.target_size;	t = *dstptr;

⌨️ 快捷键说明

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