aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2013-01-11 01:30:44 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2013-01-17 18:28:15 -0500
commitc539f01717c239cfa0921dd43927afc976f1eedc (patch)
treee0e4881913acb233f6ea83d93eb69da446084101 /net
parent7266507d89991fa1e989283e4e032c6d9357fe26 (diff)
netfilter: add connlabel conntrack extension
similar to connmarks, except labels are bit-based; i.e. all labels may be attached to a flow at the same time. Up to 128 labels are supported. Supporting more labels is possible, but requires increasing the ct offset delta from u8 to u16 type due to increased extension sizes. Mapping of bit-identifier to label name is done in userspace. The extension is enabled at run-time once "-m connlabel" netfilter rules are added. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/Kconfig18
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/nf_conntrack_core.c12
-rw-r--r--net/netfilter/nf_conntrack_labels.c72
-rw-r--r--net/netfilter/nf_conntrack_netlink.c3
-rw-r--r--net/netfilter/xt_connlabel.c99
6 files changed, 206 insertions, 0 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 49e96df5fbc4..bb48607d4ee4 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -124,6 +124,12 @@ config NF_CONNTRACK_TIMESTAMP
124 124
125 If unsure, say `N'. 125 If unsure, say `N'.
126 126
127config NF_CONNTRACK_LABELS
128 bool
129 help
130 This option enables support for assigning user-defined flag bits
131 to connection tracking entries. It selected by the connlabel match.
132
127config NF_CT_PROTO_DCCP 133config NF_CT_PROTO_DCCP
128 tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)' 134 tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)'
129 depends on EXPERIMENTAL 135 depends on EXPERIMENTAL
@@ -842,6 +848,18 @@ config NETFILTER_XT_MATCH_CONNBYTES
842 If you want to compile it as a module, say M here and read 848 If you want to compile it as a module, say M here and read
843 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. 849 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
844 850
851config NETFILTER_XT_MATCH_CONNLABEL
852 tristate '"connlabel" match support'
853 select NF_CONNTRACK_LABELS
854 depends on NETFILTER_ADVANCED
855 ---help---
856 This match allows you to test and assign userspace-defined labels names
857 to a connection. The kernel only stores bit values - mapping
858 names to bits is done by userspace.
859
860 Unlike connmark, more than 32 flag bits may be assigned to a
861 connection simultaneously.
862
845config NETFILTER_XT_MATCH_CONNLIMIT 863config NETFILTER_XT_MATCH_CONNLIMIT
846 tristate '"connlimit" match support"' 864 tristate '"connlimit" match support"'
847 depends on NF_CONNTRACK 865 depends on NF_CONNTRACK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 32596978df1d..b3bbda60945e 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -4,6 +4,7 @@ nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_exp
4nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o 4nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o
5nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o 5nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o
6nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o 6nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
7nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o
7 8
8obj-$(CONFIG_NETFILTER) = netfilter.o 9obj-$(CONFIG_NETFILTER) = netfilter.o
9 10
@@ -101,6 +102,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ADDRTYPE) += xt_addrtype.o
101obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o 102obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o
102obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o 103obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
103obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o 104obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
105obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLABEL) += xt_connlabel.o
104obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o 106obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
105obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o 107obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
106obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o 108obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e4a0c4fb3a7c..85aa4b7149c5 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -45,6 +45,7 @@
45#include <net/netfilter/nf_conntrack_zones.h> 45#include <net/netfilter/nf_conntrack_zones.h>
46#include <net/netfilter/nf_conntrack_timestamp.h> 46#include <net/netfilter/nf_conntrack_timestamp.h>
47#include <net/netfilter/nf_conntrack_timeout.h> 47#include <net/netfilter/nf_conntrack_timeout.h>
48#include <net/netfilter/nf_conntrack_labels.h>
48#include <net/netfilter/nf_nat.h> 49#include <net/netfilter/nf_nat.h>
49#include <net/netfilter/nf_nat_core.h> 50#include <net/netfilter/nf_nat_core.h>
50 51
@@ -763,6 +764,7 @@ void nf_conntrack_free(struct nf_conn *ct)
763} 764}
764EXPORT_SYMBOL_GPL(nf_conntrack_free); 765EXPORT_SYMBOL_GPL(nf_conntrack_free);
765 766
767
766/* Allocate a new conntrack: we return -ENOMEM if classification 768/* Allocate a new conntrack: we return -ENOMEM if classification
767 failed due to stress. Otherwise it really is unclassifiable. */ 769 failed due to stress. Otherwise it really is unclassifiable. */
768static struct nf_conntrack_tuple_hash * 770static struct nf_conntrack_tuple_hash *
@@ -809,6 +811,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
809 811
810 nf_ct_acct_ext_add(ct, GFP_ATOMIC); 812 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
811 nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); 813 nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
814 nf_ct_labels_ext_add(ct);
812 815
813 ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL; 816 ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL;
814 nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0, 817 nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0,
@@ -1352,6 +1355,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
1352 } 1355 }
1353 1356
1354 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size); 1357 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
1358 nf_conntrack_labels_fini(net);
1355 nf_conntrack_helper_fini(net); 1359 nf_conntrack_helper_fini(net);
1356 nf_conntrack_timeout_fini(net); 1360 nf_conntrack_timeout_fini(net);
1357 nf_conntrack_ecache_fini(net); 1361 nf_conntrack_ecache_fini(net);
@@ -1583,7 +1587,15 @@ static int nf_conntrack_init_net(struct net *net)
1583 ret = nf_conntrack_helper_init(net); 1587 ret = nf_conntrack_helper_init(net);
1584 if (ret < 0) 1588 if (ret < 0)
1585 goto err_helper; 1589 goto err_helper;
1590
1591 ret = nf_conntrack_labels_init(net);
1592 if (ret < 0)
1593 goto err_labels;
1594
1586 return 0; 1595 return 0;
1596
1597err_labels:
1598 nf_conntrack_helper_fini(net);
1587err_helper: 1599err_helper:
1588 nf_conntrack_timeout_fini(net); 1600 nf_conntrack_timeout_fini(net);
1589err_timeout: 1601err_timeout:
diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c
new file mode 100644
index 000000000000..0c542f41f338
--- /dev/null
+++ b/net/netfilter/nf_conntrack_labels.c
@@ -0,0 +1,72 @@
1/*
2 * test/set flag bits stored in conntrack extension area.
3 *
4 * (C) 2013 Astaro GmbH & Co KG
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/ctype.h>
12#include <linux/export.h>
13#include <linux/jhash.h>
14#include <linux/spinlock.h>
15#include <linux/types.h>
16#include <linux/slab.h>
17
18#include <net/netfilter/nf_conntrack_ecache.h>
19#include <net/netfilter/nf_conntrack_labels.h>
20
21static unsigned int label_bits(const struct nf_conn_labels *l)
22{
23 unsigned int longs = l->words;
24 return longs * BITS_PER_LONG;
25}
26
27bool nf_connlabel_match(const struct nf_conn *ct, u16 bit)
28{
29 struct nf_conn_labels *labels = nf_ct_labels_find(ct);
30
31 if (!labels)
32 return false;
33
34 return bit < label_bits(labels) && test_bit(bit, labels->bits);
35}
36EXPORT_SYMBOL_GPL(nf_connlabel_match);
37
38int nf_connlabel_set(struct nf_conn *ct, u16 bit)
39{
40 struct nf_conn_labels *labels = nf_ct_labels_find(ct);
41
42 if (!labels || bit >= label_bits(labels))
43 return -ENOSPC;
44
45 if (test_bit(bit, labels->bits))
46 return 0;
47
48 if (test_and_set_bit(bit, labels->bits))
49 return 0;
50
51 return 0;
52}
53EXPORT_SYMBOL_GPL(nf_connlabel_set);
54
55static struct nf_ct_ext_type labels_extend __read_mostly = {
56 .len = sizeof(struct nf_conn_labels),
57 .align = __alignof__(struct nf_conn_labels),
58 .id = NF_CT_EXT_LABELS,
59};
60
61int nf_conntrack_labels_init(struct net *net)
62{
63 if (net_eq(net, &init_net))
64 return nf_ct_extend_register(&labels_extend);
65 return 0;
66}
67
68void nf_conntrack_labels_fini(struct net *net)
69{
70 if (net_eq(net, &init_net))
71 nf_ct_extend_unregister(&labels_extend);
72}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 627b0e50b238..e0b10ee180ef 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -43,6 +43,7 @@
43#include <net/netfilter/nf_conntrack_acct.h> 43#include <net/netfilter/nf_conntrack_acct.h>
44#include <net/netfilter/nf_conntrack_zones.h> 44#include <net/netfilter/nf_conntrack_zones.h>
45#include <net/netfilter/nf_conntrack_timestamp.h> 45#include <net/netfilter/nf_conntrack_timestamp.h>
46#include <net/netfilter/nf_conntrack_labels.h>
46#ifdef CONFIG_NF_NAT_NEEDED 47#ifdef CONFIG_NF_NAT_NEEDED
47#include <net/netfilter/nf_nat_core.h> 48#include <net/netfilter/nf_nat_core.h>
48#include <net/netfilter/nf_nat_l4proto.h> 49#include <net/netfilter/nf_nat_l4proto.h>
@@ -1598,6 +1599,8 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
1598 nf_ct_acct_ext_add(ct, GFP_ATOMIC); 1599 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
1599 nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); 1600 nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
1600 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); 1601 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
1602 nf_ct_labels_ext_add(ct);
1603
1601 /* we must add conntrack extensions before confirmation. */ 1604 /* we must add conntrack extensions before confirmation. */
1602 ct->status |= IPS_CONFIRMED; 1605 ct->status |= IPS_CONFIRMED;
1603 1606
diff --git a/net/netfilter/xt_connlabel.c b/net/netfilter/xt_connlabel.c
new file mode 100644
index 000000000000..9f8719df2001
--- /dev/null
+++ b/net/netfilter/xt_connlabel.c
@@ -0,0 +1,99 @@
1/*
2 * (C) 2013 Astaro GmbH & Co KG
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <net/netfilter/nf_conntrack.h>
12#include <net/netfilter/nf_conntrack_labels.h>
13#include <linux/netfilter/x_tables.h>
14
15MODULE_LICENSE("GPL");
16MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
17MODULE_DESCRIPTION("Xtables: add/match connection trackling labels");
18MODULE_ALIAS("ipt_connlabel");
19MODULE_ALIAS("ip6t_connlabel");
20
21static bool
22connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par)
23{
24 const struct xt_connlabel_mtinfo *info = par->matchinfo;
25 enum ip_conntrack_info ctinfo;
26 struct nf_conn *ct;
27 bool invert = info->options & XT_CONNLABEL_OP_INVERT;
28
29 ct = nf_ct_get(skb, &ctinfo);
30 if (ct == NULL || nf_ct_is_untracked(ct))
31 return invert;
32
33 if (info->options & XT_CONNLABEL_OP_SET)
34 return (nf_connlabel_set(ct, info->bit) == 0) ^ invert;
35
36 return nf_connlabel_match(ct, info->bit) ^ invert;
37}
38
39static int connlabel_mt_check(const struct xt_mtchk_param *par)
40{
41 const int options = XT_CONNLABEL_OP_INVERT |
42 XT_CONNLABEL_OP_SET;
43 struct xt_connlabel_mtinfo *info = par->matchinfo;
44 int ret;
45 size_t words;
46
47 if (info->bit > XT_CONNLABEL_MAXBIT)
48 return -ERANGE;
49
50 if (info->options & ~options) {
51 pr_err("Unknown options in mask %x\n", info->options);
52 return -EINVAL;
53 }
54
55 ret = nf_ct_l3proto_try_module_get(par->family);
56 if (ret < 0) {
57 pr_info("cannot load conntrack support for proto=%u\n",
58 par->family);
59 return ret;
60 }
61
62 par->net->ct.labels_used++;
63 words = BITS_TO_LONGS(info->bit+1);
64 if (words > par->net->ct.label_words)
65 par->net->ct.label_words = words;
66
67 return ret;
68}
69
70static void connlabel_mt_destroy(const struct xt_mtdtor_param *par)
71{
72 par->net->ct.labels_used--;
73 if (par->net->ct.labels_used == 0)
74 par->net->ct.label_words = 0;
75 nf_ct_l3proto_module_put(par->family);
76}
77
78static struct xt_match connlabels_mt_reg __read_mostly = {
79 .name = "connlabel",
80 .family = NFPROTO_UNSPEC,
81 .checkentry = connlabel_mt_check,
82 .match = connlabel_mt,
83 .matchsize = sizeof(struct xt_connlabel_mtinfo),
84 .destroy = connlabel_mt_destroy,
85 .me = THIS_MODULE,
86};
87
88static int __init connlabel_mt_init(void)
89{
90 return xt_register_match(&connlabels_mt_reg);
91}
92
93static void __exit connlabel_mt_exit(void)
94{
95 xt_unregister_match(&connlabels_mt_reg);
96}
97
98module_init(connlabel_mt_init);
99module_exit(connlabel_mt_exit);