[RFC PATCH nf_conntrack_extend] new extensions without changes kernel source

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



How to add additional data to the conntrack? This is needed to
the implementation of ndpi-netfilter.

Now it is possible to add data to a struct "nf_conn-> ext" through
nf_conntrack_extend, but it requires a change in the kernel code.

I have developed a patch to register custom extensions in nf_conn->ext.
In the kernel configuration, you can specify the maximum number of additional
extensions (0..8). When registering a custom extension to specify an
additional unique identifier extension (u32). In the extension properties
seq_print added optional method to display data in "/proc/net/nf_conntrack".

What lacks is in this patch?

diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index 977bc8a..720f699 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -26,7 +26,8 @@ enum nf_ct_ext_id {
 #ifdef CONFIG_NF_CONNTRACK_LABELS
 	NF_CT_EXT_LABELS,
 #endif
-	NF_CT_EXT_NUM,
+	NF_CT_EXT_CUSTOM,
+	NF_CT_EXT_NUM=NF_CT_EXT_CUSTOM+CONFIG_NF_CONNTRACK_CUSTOM,
 };
 
 #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
@@ -94,12 +95,16 @@ void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id,
 
 #define NF_CT_EXT_F_PREALLOC	0x0001
 
+struct seq_file;
+
 struct nf_ct_ext_type {
 	/* Destroys relationships (can be NULL). */
 	void (*destroy)(struct nf_conn *ct);
 	/* Called when realloacted (can be NULL).
 	   Contents has already been moved. */
 	void (*move)(void *new, void *old);
+	/* Print custom info (can be NULL) */
+	unsigned int (*seq_print)(struct seq_file *s, const struct nf_conn *ct, int dir);
 
 	enum nf_ct_ext_id id;
 
@@ -112,6 +117,8 @@ struct nf_ct_ext_type {
 	u8 alloc_size;
 };
 
+unsigned int nf_ct_ext_seq_print(struct seq_file *s, const struct nf_conn *ct, int dir);
 int nf_ct_extend_register(struct nf_ct_ext_type *type);
+int nf_ct_extend_custom_register(struct nf_ct_ext_type *type,unsigned long int cid);
 void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
 #endif /* _NF_CONNTRACK_EXTEND_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 9e7732d..75c8a5d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -70,6 +70,16 @@ config NF_CONNTRACK_SECMARK
 
 	  If unsure, say 'N'.
 
+config NF_CONNTRACK_CUSTOM
+	int "Number of custom extend"
+	range 0 8
+	depends on NETFILTER_ADVANCED
+	default "4"
+	help
+	  This parameter specifies how many custom extensions can be registered.
+
+	  The default value is 4.
+
 config NF_CONNTRACK_ZONES
 	bool  'Connection tracking zones'
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 2d3030a..7f97126 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -52,6 +52,7 @@ seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
 EXPORT_SYMBOL_GPL(seq_print_acct);
 
 static struct nf_ct_ext_type acct_extend __read_mostly = {
+	.seq_print = seq_print_acct,
 	.len	= sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),
 	.align	= __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),
 	.id	= NF_CT_EXT_ACCT,
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index 1a95459..28499ae 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -43,6 +43,30 @@ void __nf_ct_ext_destroy(struct nf_conn *ct)
 }
 EXPORT_SYMBOL(__nf_ct_ext_destroy);
 
+struct seq_file;
+
+unsigned int nf_ct_ext_seq_print(struct seq_file *s, const struct nf_conn *ct, int dir)
+{
+	unsigned int i,ret=0;
+	struct nf_ct_ext_type *t;
+	struct nf_ct_ext *ext = ct->ext;
+
+	for (i = 0; i < NF_CT_EXT_NUM; i++) {
+		if (!__nf_ct_ext_exist(ext, i))
+			continue;
+
+		rcu_read_lock(); // FIXME
+		t = rcu_dereference(nf_ct_ext_types[i]);
+		if (t && t->seq_print)
+			ret = t->seq_print(s,ct,dir);
+		rcu_read_unlock();
+		if(ret)
+			return ret;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(nf_ct_ext_seq_print);
+
 static void *
 nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id,
 		 size_t var_alloc_len, gfp_t gfp)
@@ -156,6 +180,24 @@ static void update_alloc_size(struct nf_ct_ext_type *type)
 	}
 }
 
+static unsigned long int nf_ct_ext_cust_id[CONFIG_NF_CONNTRACK_CUSTOM];
+static enum nf_ct_ext_id 
+nf_ct_extend_get_custom_id(unsigned long int ext_id)
+{
+	enum nf_ct_ext_id ret = 0;
+	int i;
+	mutex_lock(&nf_ct_ext_type_mutex);
+	for(i = 0; i < CONFIG_NF_CONNTRACK_CUSTOM; i++) {
+		if(!nf_ct_ext_cust_id[i]) {
+			nf_ct_ext_cust_id[i] = ext_id;
+			ret = i+NF_CT_EXT_CUSTOM;
+			break;
+		}
+	}
+	mutex_unlock(&nf_ct_ext_type_mutex);
+	return ret;
+}
+
 /* This MUST be called in process context. */
 int nf_ct_extend_register(struct nf_ct_ext_type *type)
 {
@@ -179,12 +221,32 @@ out:
 }
 EXPORT_SYMBOL_GPL(nf_ct_extend_register);
 
+int nf_ct_extend_custom_register(struct nf_ct_ext_type *type,
+				 unsigned long int cid)
+{
+	int ret;
+	enum nf_ct_ext_id new_id = nf_ct_extend_get_custom_id(cid);
+	if(!new_id)
+		return -EBUSY;
+	type->id = new_id;
+	ret = nf_ct_extend_register(type);
+	if(ret < 0) {
+		mutex_lock(&nf_ct_ext_type_mutex);
+		nf_ct_ext_cust_id[new_id - NF_CT_EXT_CUSTOM] = 0;
+		mutex_unlock(&nf_ct_ext_type_mutex);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_custom_register);
+
 /* This MUST be called in process context. */
 void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
 {
 	mutex_lock(&nf_ct_ext_type_mutex);
 	RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL);
 	update_alloc_size(type);
+	if(type->id >= NF_CT_EXT_CUSTOM && type->id < NF_CT_EXT_NUM)
+		nf_ct_ext_cust_id[type->id-NF_CT_EXT_CUSTOM] = 0;
 	mutex_unlock(&nf_ct_ext_type_mutex);
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 63bad61..1d5b311 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -206,7 +206,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
 			l3proto, l4proto))
 		goto release;
 
-	if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
+	if (nf_ct_ext_seq_print(s,ct,IP_CT_DIR_ORIGINAL))
 		goto release;
 
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -217,7 +217,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
 			l3proto, l4proto))
 		goto release;
 
-	if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
+	if (nf_ct_ext_seq_print(s,ct,IP_CT_DIR_REPLY))
 		goto release;
 
 	if (test_bit(IPS_ASSURED_BIT, &ct->status))

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux