diff mbox

[RFC,nf_conntrack_extend] new extensions without changes kernel source

Message ID 525EEAB7.4090901@guap.ru
State RFC
Headers show

Commit Message

Vitaly E. Lavrov Oct. 16, 2013, 7:36 p.m. UTC
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?

Comments

Pablo Neira Ayuso Oct. 29, 2013, 12:22 p.m. UTC | #1
Hi Vitaly,

On Wed, Oct 16, 2013 at 11:36:23PM +0400, Vitaly E. Lavrov wrote:
> 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?

I'm reticent to get this extremely generic infrastructure into
mainstream, we need to know more on the ndpi needs and discuss some
generic infrastructure that most layer 7 implementation can benefit
from.

BTW, please try to avoid /proc interfaces, we try to run away from them
if possible, using ctnetlink would be better.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dirk Oct. 31, 2013, 9:22 a.m. UTC | #2
> I'm reticent to get this extremely generic infrastructure into
> mainstream, we need to know more on the ndpi needs and discuss some
> generic infrastructure that most layer 7 implementation can benefit
> from.

I was always under the impression a more generic conntrack extend
mechanism that could also be used by kernel modules would never be
allowed into mainstream?

My use case is a QoS module that does per flow packet queueing. A more
generic mechanism that doesn't require a kernel patch/recompile would
be very welcome :-)


Kind regards,
Dirk
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vitaly E. Lavrov Nov. 2, 2013, 2:30 p.m. UTC | #3
On 29.10.2013 16:22, Pablo Neira Ayuso wrote:
> Hi Vitaly,
>
> On Wed, Oct 16, 2013 at 11:36:23PM +0400, Vitaly E. Lavrov wrote:
>> 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?
> I'm reticent to get this extremely generic infrastructure into
> mainstream, we need to know more on the ndpi needs and discuss some
> generic infrastructure that most layer 7 implementation can benefit
> from.
There are two implementations of DPI: l7 filter and opendpi. Both extensions
use conntrack. To work they need: a pointer to its internal structure of the
conntrack and the release of internal structures at the close of CT.
All of these features are implemented in conntrack_extend, but the addition
of new data there requires a change in the kernel code (changing one line).
In conntrack_extend already has 7 add-ons. What cardinally change from 2 - 3
generic extensions?
> BTW, please try to avoid /proc interfaces, we try to run away from them
> if possible, using ctnetlink would be better.
/proc interface for backward compatibility only. This part of the patch can be discarded.

I ask again: what in the patch is made poorly or improperly but to use /proc/net/conntrack ?

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

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))