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

📄 netfilter.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * Any packet that leaves via this function must come back  * through nf_reinject(). */static int nf_queue(struct sk_buff *skb, 		    struct list_head *elem, 		    int pf, unsigned int hook,		    struct net_device *indev,		    struct net_device *outdev,		    int (*okfn)(struct sk_buff *)){	int status;	struct nf_info *info;#ifdef CONFIG_BRIDGE_NETFILTER	struct net_device *physindev = NULL;	struct net_device *physoutdev = NULL;#endif	/* QUEUE == DROP if noone is waiting, to be safe. */	read_lock(&queue_handler_lock);	if (!queue_handler[pf].outfn) {		read_unlock(&queue_handler_lock);		kfree_skb(skb);		return 1;	}	info = kmalloc(sizeof(*info), GFP_ATOMIC);	if (!info) {		if (net_ratelimit())			printk(KERN_ERR "OOM queueing packet %p\n",			       skb);		read_unlock(&queue_handler_lock);		kfree_skb(skb);		return 1;	}	*info = (struct nf_info) { 		(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };	/* If it's going away, ignore hook. */	if (!try_module_get(info->elem->owner)) {		read_unlock(&queue_handler_lock);		kfree(info);		return 0;	}	/* Bump dev refs so they don't vanish while packet is out */	if (indev) dev_hold(indev);	if (outdev) dev_hold(outdev);#ifdef CONFIG_BRIDGE_NETFILTER	if (skb->nf_bridge) {		physindev = skb->nf_bridge->physindev;		if (physindev) dev_hold(physindev);		physoutdev = skb->nf_bridge->physoutdev;		if (physoutdev) dev_hold(physoutdev);	}#endif	status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);	read_unlock(&queue_handler_lock);	if (status < 0) {		/* James M doesn't say fuck enough. */		if (indev) dev_put(indev);		if (outdev) dev_put(outdev);#ifdef CONFIG_BRIDGE_NETFILTER		if (physindev) dev_put(physindev);		if (physoutdev) dev_put(physoutdev);#endif		module_put(info->elem->owner);		kfree(info);		kfree_skb(skb);		return 1;	}	return 1;}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();#ifdef CONFIG_NETFILTER_DEBUG	if (skb->nf_debug & (1 << hook)) {		printk("nf_hook: hook %i already set.\n", hook);		nf_dump_skb(pf, skb);	}	skb->nf_debug |= (1 << hook);#endif	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_QUEUE) {		NFDEBUG("nf_hook: Verdict = QUEUE.\n");		if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn))			goto next_hook;	}	switch (verdict) {	case NF_ACCEPT:		ret = okfn(skb);		break;	case NF_DROP:		kfree_skb(skb);		ret = -EPERM;		break;	}	rcu_read_unlock();	return ret;}void nf_reinject(struct sk_buff *skb, struct nf_info *info,		 unsigned int verdict){	struct list_head *elem = &info->elem->list;	struct list_head *i;	rcu_read_lock();	/* Release those devices we held, or Alexey will kill me. */	if (info->indev) dev_put(info->indev);	if (info->outdev) dev_put(info->outdev);#ifdef CONFIG_BRIDGE_NETFILTER	if (skb->nf_bridge) {		if (skb->nf_bridge->physindev)			dev_put(skb->nf_bridge->physindev);		if (skb->nf_bridge->physoutdev)			dev_put(skb->nf_bridge->physoutdev);	}#endif	/* Drop reference to owner of hook which queued us. */	module_put(info->elem->owner);	list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {		if (i == elem)   			break;  	}  	if (elem == &nf_hooks[info->pf][info->hook]) {		/* The module which sent it to userspace is gone. */		NFDEBUG("%s: module disappeared, dropping packet.\n",			__FUNCTION__);		verdict = NF_DROP;	}	/* Continue traversal iff userspace said ok... */	if (verdict == NF_REPEAT) {		elem = elem->prev;		verdict = NF_ACCEPT;	}	if (verdict == NF_ACCEPT) {	next_hook:		verdict = nf_iterate(&nf_hooks[info->pf][info->hook],				     &skb, info->hook, 				     info->indev, info->outdev, &elem,				     info->okfn, INT_MIN);	}	switch (verdict) {	case NF_ACCEPT:		info->okfn(skb);		break;	case NF_QUEUE:		if (!nf_queue(skb, elem, info->pf, info->hook, 			      info->indev, info->outdev, info->okfn))			goto next_hook;		break;	}	rcu_read_unlock();	if (verdict == NF_DROP)		kfree_skb(skb);	kfree(info);	return;}#ifdef CONFIG_INET/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */int ip_route_me_harder(struct sk_buff **pskb){	struct iphdr *iph = (*pskb)->nh.iph;	struct rtable *rt;	struct flowi fl = {};	struct dst_entry *odst;	unsigned int hh_len;	/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause	 * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.	 */	if (inet_addr_type(iph->saddr) == RTN_LOCAL) {		fl.nl_u.ip4_u.daddr = iph->daddr;		fl.nl_u.ip4_u.saddr = iph->saddr;		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);		fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;#ifdef CONFIG_IP_ROUTE_FWMARK		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;#endif		fl.proto = iph->protocol;		if (ip_route_output_key(&rt, &fl) != 0)			return -1;		/* Drop old route. */		dst_release((*pskb)->dst);		(*pskb)->dst = &rt->u.dst;	} else {		/* non-local src, find valid iif to satisfy		 * rp-filter when calling ip_route_input. */		fl.nl_u.ip4_u.daddr = iph->saddr;		if (ip_route_output_key(&rt, &fl) != 0)			return -1;		odst = (*pskb)->dst;		if (ip_route_input(*pskb, iph->daddr, iph->saddr,				   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {			dst_release(&rt->u.dst);			return -1;		}		dst_release(&rt->u.dst);		dst_release(odst);	}		if ((*pskb)->dst->error)		return -1;	/* Change in oif may mean change in hh_len. */	hh_len = (*pskb)->dst->dev->hard_header_len;	if (skb_headroom(*pskb) < hh_len) {		struct sk_buff *nskb;		nskb = skb_realloc_headroom(*pskb, hh_len);		if (!nskb) 			return -1;		if ((*pskb)->sk)			skb_set_owner_w(nskb, (*pskb)->sk);		kfree_skb(*pskb);		*pskb = nskb;	}	return 0;}int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len){	struct sk_buff *nskb;	unsigned int iplen;	if (writable_len > (*pskb)->len)		return 0;	/* Not exclusive use of packet?  Must copy. */	if (skb_shared(*pskb) || skb_cloned(*pskb))		goto copy_skb;	/* Alexey says IP hdr is always modifiable and linear, so ok. */	if (writable_len <= (*pskb)->nh.iph->ihl*4)		return 1;	iplen = writable_len - (*pskb)->nh.iph->ihl*4;	/* DaveM says protocol headers are also modifiable. */	switch ((*pskb)->nh.iph->protocol) {	case IPPROTO_TCP: {		struct tcphdr _hdr, *hp;		hp = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,					sizeof(_hdr), &_hdr);		if (hp == NULL)			goto copy_skb;		if (writable_len <= (*pskb)->nh.iph->ihl*4 + hp->doff*4)			goto pull_skb;		goto copy_skb;	}	case IPPROTO_UDP:		if (writable_len<=(*pskb)->nh.iph->ihl*4+sizeof(struct udphdr))			goto pull_skb;		goto copy_skb;	case IPPROTO_ICMP:		if (writable_len		    <= (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr))			goto pull_skb;		goto copy_skb;	/* Insert other cases here as desired */	}copy_skb:	nskb = skb_copy(*pskb, GFP_ATOMIC);	if (!nskb)		return 0;	BUG_ON(skb_is_nonlinear(nskb));	/* Rest of kernel will get very unhappy if we pass it a	   suddenly-orphaned skbuff */	if ((*pskb)->sk)		skb_set_owner_w(nskb, (*pskb)->sk);	kfree_skb(*pskb);	*pskb = nskb;	return 1;pull_skb:	return pskb_may_pull(*pskb, writable_len);}EXPORT_SYMBOL(skb_ip_make_writable);#endif /*CONFIG_INET*//* Internal logging interface, which relies on the real    LOG target modules */#define NF_LOG_PREFIXLEN		128static nf_logfn *nf_logging[NPROTO]; /* = NULL */static int reported = 0;static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;int nf_log_register(int pf, nf_logfn *logfn){	int ret = -EBUSY;	/* Any setup of logging members must be done before	 * substituting pointer. */	smp_wmb();	spin_lock(&nf_log_lock);	if (!nf_logging[pf]) {		nf_logging[pf] = logfn;		ret = 0;	}	spin_unlock(&nf_log_lock);	return ret;}		void nf_log_unregister(int pf, nf_logfn *logfn){	spin_lock(&nf_log_lock);	if (nf_logging[pf] == logfn)		nf_logging[pf] = NULL;	spin_unlock(&nf_log_lock);	/* Give time to concurrent readers. */	synchronize_net();}		void nf_log_packet(int pf,		   unsigned int hooknum,		   const struct sk_buff *skb,		   const struct net_device *in,		   const struct net_device *out,		   const char *fmt, ...){	va_list args;	char prefix[NF_LOG_PREFIXLEN];	nf_logfn *logfn;		rcu_read_lock();	logfn = rcu_dereference(nf_logging[pf]);	if (logfn) {		va_start(args, fmt);		vsnprintf(prefix, sizeof(prefix), fmt, args);		va_end(args);		/* We must read logging before nf_logfn[pf] */		logfn(hooknum, skb, in, out, prefix);	} else if (!reported) {		printk(KERN_WARNING "nf_log_packet: can\'t log yet, "		       "no backend logging module loaded in!\n");		reported++;	}	rcu_read_unlock();}EXPORT_SYMBOL(nf_log_register);EXPORT_SYMBOL(nf_log_unregister);EXPORT_SYMBOL(nf_log_packet);/* This does not belong here, but ipt_REJECT needs 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 *);void __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]);	}}EXPORT_SYMBOL(ip_ct_attach);EXPORT_SYMBOL(ip_route_me_harder);EXPORT_SYMBOL(nf_getsockopt);EXPORT_SYMBOL(nf_hook_slow);EXPORT_SYMBOL(nf_hooks);EXPORT_SYMBOL(nf_register_hook);EXPORT_SYMBOL(nf_register_queue_handler);EXPORT_SYMBOL(nf_register_sockopt);EXPORT_SYMBOL(nf_reinject);EXPORT_SYMBOL(nf_setsockopt);EXPORT_SYMBOL(nf_unregister_hook);EXPORT_SYMBOL(nf_unregister_queue_handler);EXPORT_SYMBOL(nf_unregister_sockopt);

⌨️ 快捷键说明

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