aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-03 11:17:06 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-03 11:17:06 -0500
commit84f3bb9ae9db90f7fb15d98b55279a58ab1b2363 (patch)
tree7fe7b882f027ee138edbc0f189e21532dad6531a
parentb2a15a604d379af323645e330638e2cfcc696aff (diff)
netfilter: xtables: add CT target
Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper. The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing a new conntrack. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter/Kbuild1
-rw-r--r--include/linux/netfilter/xt_CT.h17
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h3
-rw-r--r--net/netfilter/Kconfig12
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nf_conntrack_helper.c19
-rw-r--r--net/netfilter/xt_CT.c158
7 files changed, 211 insertions, 0 deletions
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 2aea50399c0b..a5a63e41b8af 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -6,6 +6,7 @@ header-y += nfnetlink_queue.h
6header-y += xt_CLASSIFY.h 6header-y += xt_CLASSIFY.h
7header-y += xt_CONNMARK.h 7header-y += xt_CONNMARK.h
8header-y += xt_CONNSECMARK.h 8header-y += xt_CONNSECMARK.h
9header-y += xt_CT.h
9header-y += xt_DSCP.h 10header-y += xt_DSCP.h
10header-y += xt_LED.h 11header-y += xt_LED.h
11header-y += xt_MARK.h 12header-y += xt_MARK.h
diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h
new file mode 100644
index 000000000000..7fd0effe1316
--- /dev/null
+++ b/include/linux/netfilter/xt_CT.h
@@ -0,0 +1,17 @@
1#ifndef _XT_CT_H
2#define _XT_CT_H
3
4#define XT_CT_NOTRACK 0x1
5
6struct xt_ct_target_info {
7 u_int16_t flags;
8 u_int16_t __unused;
9 u_int32_t ct_events;
10 u_int32_t exp_events;
11 char helper[16];
12
13 /* Used internally by the kernel */
14 struct nf_conn *ct __attribute__((aligned(8)));
15};
16
17#endif /* _XT_CT_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index e17aaa3e19fd..32c305dbdab6 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -42,6 +42,9 @@ struct nf_conntrack_helper {
42extern struct nf_conntrack_helper * 42extern struct nf_conntrack_helper *
43__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum); 43__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
44 44
45extern struct nf_conntrack_helper *
46nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
47
45extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); 48extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
46extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); 49extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
47 50
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 634d14affc8d..4469d45261f4 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -341,6 +341,18 @@ config NETFILTER_XT_TARGET_CONNSECMARK
341 341
342 To compile it as a module, choose M here. If unsure, say N. 342 To compile it as a module, choose M here. If unsure, say N.
343 343
344config NETFILTER_XT_TARGET_CT
345 tristate '"CT" target support'
346 depends on NF_CONNTRACK
347 depends on IP_NF_RAW || IP6_NF_RAW
348 depends on NETFILTER_ADVANCED
349 help
350 This options adds a `CT' target, which allows to specify initial
351 connection tracking parameters like events to be delivered and
352 the helper to be used.
353
354 To compile it as a module, choose M here. If unsure, say N.
355
344config NETFILTER_XT_TARGET_DSCP 356config NETFILTER_XT_TARGET_DSCP
345 tristate '"DSCP" and "TOS" target support' 357 tristate '"DSCP" and "TOS" target support'
346 depends on IP_NF_MANGLE || IP6_NF_MANGLE 358 depends on IP_NF_MANGLE || IP6_NF_MANGLE
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 49f62ee4e9ff..f873644f02f6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
44obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o 44obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
45obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o 45obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
46obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o 46obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
47obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
47obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 48obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
48obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o 49obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
49obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o 50obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 8144b0da5515..a74a5769877b 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -83,6 +83,25 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
83} 83}
84EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find); 84EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find);
85 85
86struct nf_conntrack_helper *
87nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
88{
89 struct nf_conntrack_helper *h;
90
91 h = __nf_conntrack_helper_find(name, l3num, protonum);
92#ifdef CONFIG_MODULES
93 if (h == NULL) {
94 if (request_module("nfct-helper-%s", name) == 0)
95 h = __nf_conntrack_helper_find(name, l3num, protonum);
96 }
97#endif
98 if (h != NULL && !try_module_get(h->me))
99 h = NULL;
100
101 return h;
102}
103EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
104
86struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) 105struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
87{ 106{
88 struct nf_conn_help *help; 107 struct nf_conn_help *help;
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
new file mode 100644
index 000000000000..8183a054256f
--- /dev/null
+++ b/net/netfilter/xt_CT.c
@@ -0,0 +1,158 @@
1/*
2 * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
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 <linux/selinux.h>
12#include <linux/netfilter_ipv4/ip_tables.h>
13#include <linux/netfilter_ipv6/ip6_tables.h>
14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter/xt_CT.h>
16#include <net/netfilter/nf_conntrack.h>
17#include <net/netfilter/nf_conntrack_helper.h>
18#include <net/netfilter/nf_conntrack_ecache.h>
19
20static unsigned int xt_ct_target(struct sk_buff *skb,
21 const struct xt_target_param *par)
22{
23 const struct xt_ct_target_info *info = par->targinfo;
24 struct nf_conn *ct = info->ct;
25
26 /* Previously seen (loopback)? Ignore. */
27 if (skb->nfct != NULL)
28 return XT_CONTINUE;
29
30 atomic_inc(&ct->ct_general.use);
31 skb->nfct = &ct->ct_general;
32 skb->nfctinfo = IP_CT_NEW;
33
34 return XT_CONTINUE;
35}
36
37static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
38{
39 if (par->family == AF_INET) {
40 const struct ipt_entry *e = par->entryinfo;
41
42 if (e->ip.invflags & IPT_INV_PROTO)
43 return 0;
44 return e->ip.proto;
45 } else if (par->family == AF_INET6) {
46 const struct ip6t_entry *e = par->entryinfo;
47
48 if (e->ipv6.invflags & IP6T_INV_PROTO)
49 return 0;
50 return e->ipv6.proto;
51 } else
52 return 0;
53}
54
55static bool xt_ct_tg_check(const struct xt_tgchk_param *par)
56{
57 struct xt_ct_target_info *info = par->targinfo;
58 struct nf_conntrack_tuple t;
59 struct nf_conn_help *help;
60 struct nf_conn *ct;
61 u8 proto;
62
63 if (info->flags & ~XT_CT_NOTRACK)
64 return false;
65
66 if (info->flags & XT_CT_NOTRACK) {
67 ct = &nf_conntrack_untracked;
68 atomic_inc(&ct->ct_general.use);
69 goto out;
70 }
71
72 if (nf_ct_l3proto_try_module_get(par->family) < 0)
73 goto err1;
74
75 memset(&t, 0, sizeof(t));
76 ct = nf_conntrack_alloc(par->net, &t, &t, GFP_KERNEL);
77 if (IS_ERR(ct))
78 goto err2;
79
80 if ((info->ct_events || info->exp_events) &&
81 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
82 GFP_KERNEL))
83 goto err3;
84
85 if (info->helper[0]) {
86 proto = xt_ct_find_proto(par);
87 if (!proto)
88 goto err3;
89
90 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
91 if (help == NULL)
92 goto err3;
93
94 help->helper = nf_conntrack_helper_try_module_get(info->helper,
95 par->family,
96 proto);
97 if (help->helper == NULL)
98 goto err3;
99 }
100
101 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
102 __set_bit(IPS_CONFIRMED_BIT, &ct->status);
103out:
104 info->ct = ct;
105 return true;
106
107err3:
108 nf_conntrack_free(ct);
109err2:
110 nf_ct_l3proto_module_put(par->family);
111err1:
112 return false;
113}
114
115static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par)
116{
117 struct xt_ct_target_info *info = par->targinfo;
118 struct nf_conn *ct = info->ct;
119 struct nf_conn_help *help;
120
121 if (ct != &nf_conntrack_untracked) {
122 help = nfct_help(ct);
123 if (help)
124 module_put(help->helper->me);
125
126 nf_ct_l3proto_module_put(par->family);
127 }
128 nf_ct_put(info->ct);
129}
130
131static struct xt_target xt_ct_tg __read_mostly = {
132 .name = "CT",
133 .family = NFPROTO_UNSPEC,
134 .targetsize = XT_ALIGN(sizeof(struct xt_ct_target_info)),
135 .checkentry = xt_ct_tg_check,
136 .destroy = xt_ct_tg_destroy,
137 .target = xt_ct_target,
138 .table = "raw",
139 .me = THIS_MODULE,
140};
141
142static int __init xt_ct_tg_init(void)
143{
144 return xt_register_target(&xt_ct_tg);
145}
146
147static void __exit xt_ct_tg_exit(void)
148{
149 xt_unregister_target(&xt_ct_tg);
150}
151
152module_init(xt_ct_tg_init);
153module_exit(xt_ct_tg_exit);
154
155MODULE_LICENSE("GPL");
156MODULE_DESCRIPTION("Xtables: connection tracking target");
157MODULE_ALIAS("ipt_CT");
158MODULE_ALIAS("ip6t_CT");