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

📄 core.c

📁 linux 内核源代码
💻 C
字号:
/* netfilter.c: look after the filters for various protocols. * Heavily influenced by the old firewall.c by David Bonn and Alan Cox. * * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any * way. * * Rusty Russell (C)2000 -- This code is GPL. */#include <linux/kernel.h>#include <linux/netfilter.h>#include <net/protocol.h>#include <linux/init.h>#include <linux/skbuff.h>#include <linux/wait.h>#include <linux/module.h>#include <linux/interrupt.h>#include <linux/if.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/proc_fs.h>#include <linux/mutex.h>#include <net/net_namespace.h>#include <net/sock.h>#include "nf_internals.h"static DEFINE_MUTEX(afinfo_mutex);struct nf_afinfo *nf_afinfo[NPROTO] __read_mostly;EXPORT_SYMBOL(nf_afinfo);int nf_register_afinfo(struct nf_afinfo *afinfo){	int err;	err = mutex_lock_interruptible(&afinfo_mutex);	if (err < 0)		return err;	rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);	mutex_unlock(&afinfo_mutex);	return 0;}EXPORT_SYMBOL_GPL(nf_register_afinfo);void nf_unregister_afinfo(struct nf_afinfo *afinfo){	mutex_lock(&afinfo_mutex);	rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);	mutex_unlock(&afinfo_mutex);	synchronize_rcu();}EXPORT_SYMBOL_GPL(nf_unregister_afinfo);/* In this code, we can be waiting indefinitely for userspace to * service a packet if a hook returns NF_QUEUE.  We could keep a count * of skbuffs queued for userspace, and not deregister a hook unless * this is zero, but that sucks.  Now, we simply check when the * packets come back: if the hook is gone, the packet is discarded. */struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;EXPORT_SYMBOL(nf_hooks);static DEFINE_MUTEX(nf_hook_mutex);int nf_register_hook(struct nf_hook_ops *reg){	struct list_head *i;	int err;	err = mutex_lock_interruptible(&nf_hook_mutex);	if (err < 0)		return err;	list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {		if (reg->priority < ((struct nf_hook_ops *)i)->priority)			break;	}	list_add_rcu(&reg->list, i->prev);	mutex_unlock(&nf_hook_mutex);	return 0;}EXPORT_SYMBOL(nf_register_hook);void nf_unregister_hook(struct nf_hook_ops *reg){	mutex_lock(&nf_hook_mutex);	list_del_rcu(&reg->list);	mutex_unlock(&nf_hook_mutex);	synchronize_net();}EXPORT_SYMBOL(nf_unregister_hook);int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n){	unsigned int i;	int err = 0;	for (i = 0; i < n; i++) {		err = nf_register_hook(&reg[i]);		if (err)			goto err;	}	return err;err:	if (i > 0)		nf_unregister_hooks(reg, i);	return err;}EXPORT_SYMBOL(nf_register_hooks);void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n){	unsigned int i;	for (i = 0; i < n; i++)		nf_unregister_hook(&reg[i]);}EXPORT_SYMBOL(nf_unregister_hooks);unsigned int nf_iterate(struct list_head *head,			struct sk_buff *skb,			int hook,			const struct net_device *indev,			const struct net_device *outdev,			struct list_head **i,			int (*okfn)(struct sk_buff *),			int hook_thresh){	unsigned int verdict;	/*	 * The caller must not block between calls to this	 * function because of risk of continuing from deleted element.	 */	list_for_each_continue_rcu(*i, head) {		struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;		if (hook_thresh > elem->priority)			continue;		/* Optimization: we don't need to hold module		   reference here, since function can't sleep. --RR */		verdict = elem->hook(hook, skb, indev, outdev, okfn);		if (verdict != NF_ACCEPT) {#ifdef CONFIG_NETFILTER_DEBUG			if (unlikely((verdict & NF_VERDICT_MASK)							> NF_MAX_VERDICT)) {				NFDEBUG("Evil return from %p(%u).\n",					elem->hook, hook);				continue;			}#endif			if (verdict != NF_REPEAT)				return verdict;			*i = (*i)->prev;		}	}	return NF_ACCEPT;}/* Returns 1 if okfn() needs to be executed by the caller, * -EPERM for NF_DROP, 0 otherwise. */int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,		 struct net_device *indev,		 struct net_device *outdev,		 int (*okfn)(struct sk_buff *),		 int hook_thresh){	struct list_head *elem;	unsigned int verdict;	int ret = 0;	/* We may already have this, but read-locks nest anyway */	rcu_read_lock();	elem = &nf_hooks[pf][hook];next_hook:	verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,			     outdev, &elem, okfn, hook_thresh);	if (verdict == NF_ACCEPT || verdict == NF_STOP) {		ret = 1;		goto unlock;	} else if (verdict == NF_DROP) {		kfree_skb(skb);		ret = -EPERM;	} else if ((verdict & NF_VERDICT_MASK)  == NF_QUEUE) {		NFDEBUG("nf_hook: Verdict = QUEUE.\n");		if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,			      verdict >> NF_VERDICT_BITS))			goto next_hook;	}unlock:	rcu_read_unlock();	return ret;}EXPORT_SYMBOL(nf_hook_slow);int skb_make_writable(struct sk_buff *skb, unsigned int writable_len){	if (writable_len > skb->len)		return 0;	/* Not exclusive use of packet?  Must copy. */	if (!skb_cloned(skb)) {		if (writable_len <= skb_headlen(skb))			return 1;	} else if (skb_clone_writable(skb, writable_len))		return 1;	if (writable_len <= skb_headlen(skb))		writable_len = 0;	else		writable_len -= skb_headlen(skb);	return !!__pskb_pull_tail(skb, writable_len);}EXPORT_SYMBOL(skb_make_writable);void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,			    __be32 from, __be32 to, int pseudohdr){	__be32 diff[] = { ~from, to };	if (skb->ip_summed != CHECKSUM_PARTIAL) {		*sum = csum_fold(csum_partial(diff, sizeof(diff),				~csum_unfold(*sum)));		if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)			skb->csum = ~csum_partial(diff, sizeof(diff),						~skb->csum);	} else if (pseudohdr)		*sum = ~csum_fold(csum_partial(diff, sizeof(diff),				csum_unfold(*sum)));}EXPORT_SYMBOL(nf_proto_csum_replace4);#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)/* This does not belong here, but locally generated errors need it if connection   tracking in use: without this, connection may not be in hash table, and hence   manufactured ICMP or RST packets will not be associated with it. */void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);EXPORT_SYMBOL(ip_ct_attach);void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb){	void (*attach)(struct sk_buff *, struct sk_buff *);	if (skb->nfct) {		rcu_read_lock();		attach = rcu_dereference(ip_ct_attach);		if (attach)			attach(new, skb);		rcu_read_unlock();	}}EXPORT_SYMBOL(nf_ct_attach);void (*nf_ct_destroy)(struct nf_conntrack *);EXPORT_SYMBOL(nf_ct_destroy);void nf_conntrack_destroy(struct nf_conntrack *nfct){	void (*destroy)(struct nf_conntrack *);	rcu_read_lock();	destroy = rcu_dereference(nf_ct_destroy);	BUG_ON(destroy == NULL);	destroy(nfct);	rcu_read_unlock();}EXPORT_SYMBOL(nf_conntrack_destroy);#endif /* CONFIG_NF_CONNTRACK */#ifdef CONFIG_PROC_FSstruct proc_dir_entry *proc_net_netfilter;EXPORT_SYMBOL(proc_net_netfilter);#endifvoid __init netfilter_init(void){	int i, h;	for (i = 0; i < NPROTO; i++) {		for (h = 0; h < NF_MAX_HOOKS; h++)			INIT_LIST_HEAD(&nf_hooks[i][h]);	}#ifdef CONFIG_PROC_FS	proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);	if (!proc_net_netfilter)		panic("cannot create netfilter proc entry");#endif	if (netfilter_queue_init() < 0)		panic("cannot initialize nf_queue");	if (netfilter_log_init() < 0)		panic("cannot initialize nf_log");}

⌨️ 快捷键说明

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