From patchwork Wed Oct 16 19:36:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Vitaly E. Lavrov" X-Patchwork-Id: 284021 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 440E02C0199 for ; Thu, 17 Oct 2013 06:36:28 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753968Ab3JPTg0 (ORCPT ); Wed, 16 Oct 2013 15:36:26 -0400 Received: from ns1.guap.ru ([91.151.188.3]:12331 "EHLO ns1.guap.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753183Ab3JPTg0 (ORCPT ); Wed, 16 Oct 2013 15:36:26 -0400 Received: from [10.150.100.7] (95-161-251-39.broadband.spb.TiERA.org [95.161.251.39]) (user=lve@guap.ru mech=CRAM-MD5 bits=0) by mail.guap.ru (8.14.7/8.14.4) with ESMTP id r9GJaNXr029838 for ; Wed, 16 Oct 2013 23:36:23 +0400 X-DKIM: OpenDKIM Filter v2.4.1 mail.guap.ru r9GJaNXr029838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=guap.ru; s=default; t=1381952184; bh=5uHM4hsNU9oNmMbjSYvq81KtYP4Ffii5AGpf8XKnguo=; h=Message-ID:Date:From:MIME-Version:To:Subject:Content-Type; z=Message-ID:=20<525EEAB7.4090901@guap.ru>|Date:=20Wed,=2016=20Oct= 202013=2023:36:23=20+0400|From:=20"Vitaly=20E.=20Lavrov"=20|MIME-Version:=201.0|To:=20netfilter-devel@vger.kernel.org|S ubject:=20[RFC=20PATCH=20nf_conntrack_extend]=20new=20extensions=2 0without=20changes=20kernel=0D=0A=20source|Content-Type:=20multipa rt/mixed=3B=0D=0A=20boundary=3D"------------0306080903010705090903 08"; b=VlsrEfLqmkqbHxmEGodegC0Epbdu/APlbg/KoHHfyjk6TD09ogkBvEj0sY968s72t BoP4S0noBz3gjok1Ui56TRzIaJgymDbKjTQ0qMPMkmH7lLPxj+6sKrneMemKffRC0t gbSWbFTNDdw2rdiARFFZ6rSKKQ8VTVTqLtXzWVbA= DomainKey-Signature: a=rsa-sha1; s=default; d=guap.ru; c=nofws; q=dns; b=JmYelL0xu4QruTHK/g7eT/AKru5LR2uHQ0eKOePGI1EOywh7FdmuyOs09NlySsP9Z 3tU9e9mqvSXiZnoGDATjY45/xvRBN9TbYb3ynBuadmgd0x01BkegPPKd69zge9cT2Er 73A2sboJpksik4JRMk9eNKyykF2znPdqJhQepoM= Message-ID: <525EEAB7.4090901@guap.ru> Date: Wed, 16 Oct 2013 23:36:23 +0400 From: "Vitaly E. Lavrov" User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130801 Thunderbird/17.0.8 MIME-Version: 1.0 To: netfilter-devel@vger.kernel.org Subject: [RFC PATCH nf_conntrack_extend] new extensions without changes kernel source Received-SPF: pass X-Relay-level: 30 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org 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))