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

📄 ip_conntrack_standalone.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This file contains all the functions required for the standalone   ip_conntrack module.   These are not required by the compatibility layer.*//* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-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/config.h>#include <linux/types.h>#include <linux/ip.h>#include <linux/netfilter.h>#include <linux/netfilter_ipv4.h>#include <linux/module.h>#include <linux/skbuff.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/percpu.h>#ifdef CONFIG_SYSCTL#include <linux/sysctl.h>#endif#include <net/checksum.h>#include <net/ip.h>#define ASSERT_READ_LOCK(x)#define ASSERT_WRITE_LOCK(x)#include <linux/netfilter_ipv4/ip_conntrack.h>#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>#include <linux/netfilter_ipv4/ip_conntrack_core.h>#include <linux/netfilter_ipv4/ip_conntrack_helper.h>#include <linux/netfilter_ipv4/listhelp.h>#if 0#define DEBUGP printk#else#define DEBUGP(format, args...)#endifMODULE_LICENSE("GPL");extern atomic_t ip_conntrack_count;DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);static int kill_proto(struct ip_conntrack *i, void *data){	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 			*((u_int8_t *) data));}#ifdef CONFIG_PROC_FSstatic intprint_tuple(struct seq_file *s, const struct ip_conntrack_tuple *tuple,	    struct ip_conntrack_protocol *proto){	seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",		   NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));	return proto->print_tuple(s, tuple);}#ifdef CONFIG_IP_NF_CT_ACCTstatic unsigned intseq_print_counters(struct seq_file *s,		   const struct ip_conntrack_counter *counter){	return seq_printf(s, "packets=%llu bytes=%llu ",			  (unsigned long long)counter->packets,			  (unsigned long long)counter->bytes);}#else#define seq_print_counters(x, y)	0#endifstruct ct_iter_state {	unsigned int bucket;};static struct list_head *ct_get_first(struct seq_file *seq){	struct ct_iter_state *st = seq->private;	for (st->bucket = 0;	     st->bucket < ip_conntrack_htable_size;	     st->bucket++) {		if (!list_empty(&ip_conntrack_hash[st->bucket]))			return ip_conntrack_hash[st->bucket].next;	}	return NULL;}static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head){	struct ct_iter_state *st = seq->private;	head = head->next;	while (head == &ip_conntrack_hash[st->bucket]) {		if (++st->bucket >= ip_conntrack_htable_size)			return NULL;		head = ip_conntrack_hash[st->bucket].next;	}	return head;}static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos){	struct list_head *head = ct_get_first(seq);	if (head)		while (pos && (head = ct_get_next(seq, head)))			pos--;	return pos ? NULL : head;}static void *ct_seq_start(struct seq_file *seq, loff_t *pos){	read_lock_bh(&ip_conntrack_lock);	return ct_get_idx(seq, *pos);}static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos){	(*pos)++;	return ct_get_next(s, v);}  static void ct_seq_stop(struct seq_file *s, void *v){	read_unlock_bh(&ip_conntrack_lock);} static int ct_seq_show(struct seq_file *s, void *v){	const struct ip_conntrack_tuple_hash *hash = v;	const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);	struct ip_conntrack_protocol *proto;	ASSERT_READ_LOCK(&ip_conntrack_lock);	IP_NF_ASSERT(conntrack);	/* we only want to print DIR_ORIGINAL */	if (DIRECTION(hash))		return 0;	proto = __ip_conntrack_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);	IP_NF_ASSERT(proto);	if (seq_printf(s, "%-8s %u %ld ",		      proto->name,		      conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,		      timer_pending(&conntrack->timeout)		      ? (long)(conntrack->timeout.expires - jiffies)/HZ		      : 0) != 0)		return -ENOSPC;	if (proto->print_conntrack(s, conntrack))		return -ENOSPC;  	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,			proto))		return -ENOSPC; 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))		return -ENOSPC;	if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))		if (seq_printf(s, "[UNREPLIED] "))			return -ENOSPC;	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,			proto))		return -ENOSPC; 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))		return -ENOSPC;	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))		if (seq_printf(s, "[ASSURED] "))			return -ENOSPC;#if defined(CONFIG_IP_NF_CONNTRACK_MARK)	if (seq_printf(s, "mark=%u ", conntrack->mark))		return -ENOSPC;#endif	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))		return -ENOSPC;	return 0;}static struct seq_operations ct_seq_ops = {	.start = ct_seq_start,	.next  = ct_seq_next,	.stop  = ct_seq_stop,	.show  = ct_seq_show};  static int ct_open(struct inode *inode, struct file *file){	struct seq_file *seq;	struct ct_iter_state *st;	int ret;	st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);	if (st == NULL)		return -ENOMEM;	ret = seq_open(file, &ct_seq_ops);	if (ret)		goto out_free;	seq          = file->private_data;	seq->private = st;	memset(st, 0, sizeof(struct ct_iter_state));	return ret;out_free:	kfree(st);	return ret;}static struct file_operations ct_file_ops = {	.owner   = THIS_MODULE,	.open    = ct_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release_private,};  /* expects */static void *exp_seq_start(struct seq_file *s, loff_t *pos){	struct list_head *e = &ip_conntrack_expect_list;	loff_t i;	/* strange seq_file api calls stop even if we fail,	 * thus we need to grab lock since stop unlocks */	read_lock_bh(&ip_conntrack_lock);	if (list_empty(e))		return NULL;	for (i = 0; i <= *pos; i++) {		e = e->next;		if (e == &ip_conntrack_expect_list)			return NULL;	}	return e;}static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos){ 	struct list_head *e = v;	++*pos;	e = e->next;	if (e == &ip_conntrack_expect_list)		return NULL;	return e;}static void exp_seq_stop(struct seq_file *s, void *v){	read_unlock_bh(&ip_conntrack_lock);}static int exp_seq_show(struct seq_file *s, void *v){	struct ip_conntrack_expect *expect = v;	if (expect->timeout.function)		seq_printf(s, "%ld ", timer_pending(&expect->timeout)			   ? (long)(expect->timeout.expires - jiffies)/HZ : 0);	else		seq_printf(s, "- ");	seq_printf(s, "proto=%u ", expect->tuple.dst.protonum);	print_tuple(s, &expect->tuple,		    __ip_conntrack_proto_find(expect->tuple.dst.protonum));	return seq_putc(s, '\n');}static struct seq_operations exp_seq_ops = {	.start = exp_seq_start,	.next = exp_seq_next,	.stop = exp_seq_stop,	.show = exp_seq_show};static int exp_open(struct inode *inode, struct file *file){	return seq_open(file, &exp_seq_ops);}  static struct file_operations exp_file_ops = {	.owner   = THIS_MODULE,	.open    = exp_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release};static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos){	int cpu;	if (*pos == 0)		return SEQ_START_TOKEN;	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {		if (!cpu_possible(cpu))			continue;		*pos = cpu+1;		return &per_cpu(ip_conntrack_stat, cpu);	}	return NULL;}static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos){	int cpu;	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {		if (!cpu_possible(cpu))			continue;		*pos = cpu+1;		return &per_cpu(ip_conntrack_stat, cpu);	}	return NULL;}static void ct_cpu_seq_stop(struct seq_file *seq, void *v){}static int ct_cpu_seq_show(struct seq_file *seq, void *v){	unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);	struct ip_conntrack_stat *st = v;	if (v == SEQ_START_TOKEN) {		seq_printf(seq, "entries  searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error  expect_new expect_create expect_delete\n");		return 0;	}	seq_printf(seq, "%08x  %08x %08x %08x %08x %08x %08x %08x "			"%08x %08x %08x %08x %08x  %08x %08x %08x \n",		   nr_conntracks,		   st->searched,		   st->found,		   st->new,		   st->invalid,		   st->ignore,		   st->delete,		   st->delete_list,		   st->insert,		   st->insert_failed,		   st->drop,		   st->early_drop,		   st->error,		   st->expect_new,		   st->expect_create,		   st->expect_delete		);	return 0;}static struct seq_operations ct_cpu_seq_ops = {	.start  = ct_cpu_seq_start,	.next   = ct_cpu_seq_next,	.stop   = ct_cpu_seq_stop,	.show   = ct_cpu_seq_show,};static int ct_cpu_seq_open(struct inode *inode, struct file *file){	return seq_open(file, &ct_cpu_seq_ops);}static struct file_operations ct_cpu_seq_fops = {	.owner   = THIS_MODULE,	.open    = ct_cpu_seq_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release_private,};#endifstatic unsigned int ip_confirm(unsigned int hooknum,			       struct sk_buff **pskb,			       const struct net_device *in,			       const struct net_device *out,			       int (*okfn)(struct sk_buff *)){	/* We've seen it coming out the other side: confirm it */	return ip_conntrack_confirm(pskb);}static unsigned int ip_conntrack_help(unsigned int hooknum,				      struct sk_buff **pskb,				      const struct net_device *in,				      const struct net_device *out,				      int (*okfn)(struct sk_buff *)){	struct ip_conntrack *ct;	enum ip_conntrack_info ctinfo;	/* This is where we call the helper: as the packet goes out. */	ct = ip_conntrack_get(*pskb, &ctinfo);	if (ct && ct->helper) {		unsigned int ret;		ret = ct->helper->help(pskb, ct, ctinfo);		if (ret != NF_ACCEPT)			return ret;	}	return NF_ACCEPT;}static unsigned int ip_conntrack_defrag(unsigned int hooknum,				        struct sk_buff **pskb,				        const struct net_device *in,				        const struct net_device *out,				        int (*okfn)(struct sk_buff *)){#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)	/* Previously seen (loopback)?  Ignore.  Do this before           fragment check. */	if ((*pskb)->nfct)		return NF_ACCEPT;#endif	/* Gather fragments. */	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {		*pskb = ip_ct_gather_frags(*pskb,		                           hooknum == NF_IP_PRE_ROUTING ? 					   IP_DEFRAG_CONNTRACK_IN :					   IP_DEFRAG_CONNTRACK_OUT);		if (!*pskb)			return NF_STOLEN;	}	return NF_ACCEPT;}static unsigned int ip_refrag(unsigned int hooknum,			      struct sk_buff **pskb,			      const struct net_device *in,			      const struct net_device *out,			      int (*okfn)(struct sk_buff *)){	struct rtable *rt = (struct rtable *)(*pskb)->dst;	/* We've seen it coming out the other side: confirm */	if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)		return NF_DROP;	/* Local packets are never produced too large for their	   interface.  We degfragment them at LOCAL_OUT, however,	   so we have to refragment them here. */	if ((*pskb)->len > dst_mtu(&rt->u.dst) &&	    !skb_shinfo(*pskb)->tso_size) {		/* No hook can be after us, so this should be OK. */		ip_fragment(*pskb, okfn);		return NF_STOLEN;	}	return NF_ACCEPT;}static unsigned int ip_conntrack_local(unsigned int hooknum,				       struct sk_buff **pskb,				       const struct net_device *in,				       const struct net_device *out,				       int (*okfn)(struct sk_buff *)){	/* root is playing with raw sockets. */	if ((*pskb)->len < sizeof(struct iphdr)	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {		if (net_ratelimit())			printk("ipt_hook: happy cracking.\n");		return NF_ACCEPT;	}	return ip_conntrack_in(hooknum, pskb, in, out, okfn);}/* Connection tracking may drop packets, but never alters them, so   make it the first hook. */static struct nf_hook_ops ip_conntrack_defrag_ops = {	.hook		= ip_conntrack_defrag,	.owner		= THIS_MODULE,	.pf		= PF_INET,	.hooknum	= NF_IP_PRE_ROUTING,	.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,};static struct nf_hook_ops ip_conntrack_in_ops = {	.hook		= ip_conntrack_in,	.owner		= THIS_MODULE,	.pf		= PF_INET,	.hooknum	= NF_IP_PRE_ROUTING,	.priority	= NF_IP_PRI_CONNTRACK,};static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {	.hook		= ip_conntrack_defrag,	.owner		= THIS_MODULE,	.pf		= PF_INET,	.hooknum	= NF_IP_LOCAL_OUT,	.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,};

⌨️ 快捷键说明

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