aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/xt_CT.c145
1 files changed, 56 insertions, 89 deletions
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index bde009ed8d3b..d69f1c7532f7 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -20,12 +20,8 @@
20#include <net/netfilter/nf_conntrack_timeout.h> 20#include <net/netfilter/nf_conntrack_timeout.h>
21#include <net/netfilter/nf_conntrack_zones.h> 21#include <net/netfilter/nf_conntrack_zones.h>
22 22
23static unsigned int xt_ct_target_v0(struct sk_buff *skb, 23static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
24 const struct xt_action_param *par)
25{ 24{
26 const struct xt_ct_target_info *info = par->targinfo;
27 struct nf_conn *ct = info->ct;
28
29 /* Previously seen (loopback)? Ignore. */ 25 /* Previously seen (loopback)? Ignore. */
30 if (skb->nfct != NULL) 26 if (skb->nfct != NULL)
31 return XT_CONTINUE; 27 return XT_CONTINUE;
@@ -37,21 +33,22 @@ static unsigned int xt_ct_target_v0(struct sk_buff *skb,
37 return XT_CONTINUE; 33 return XT_CONTINUE;
38} 34}
39 35
40static unsigned int xt_ct_target_v1(struct sk_buff *skb, 36static unsigned int xt_ct_target_v0(struct sk_buff *skb,
41 const struct xt_action_param *par) 37 const struct xt_action_param *par)
42{ 38{
43 const struct xt_ct_target_info_v1 *info = par->targinfo; 39 const struct xt_ct_target_info *info = par->targinfo;
44 struct nf_conn *ct = info->ct; 40 struct nf_conn *ct = info->ct;
45 41
46 /* Previously seen (loopback)? Ignore. */ 42 return xt_ct_target(skb, ct);
47 if (skb->nfct != NULL) 43}
48 return XT_CONTINUE;
49 44
50 atomic_inc(&ct->ct_general.use); 45static unsigned int xt_ct_target_v1(struct sk_buff *skb,
51 skb->nfct = &ct->ct_general; 46 const struct xt_action_param *par)
52 skb->nfctinfo = IP_CT_NEW; 47{
48 const struct xt_ct_target_info_v1 *info = par->targinfo;
49 struct nf_conn *ct = info->ct;
53 50
54 return XT_CONTINUE; 51 return xt_ct_target(skb, ct);
55} 52}
56 53
57static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) 54static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
@@ -104,67 +101,6 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
104 return 0; 101 return 0;
105} 102}
106 103
107static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
108{
109 struct xt_ct_target_info *info = par->targinfo;
110 struct nf_conntrack_tuple t;
111 struct nf_conn *ct;
112 int ret = -EOPNOTSUPP;
113
114 if (info->flags & ~XT_CT_NOTRACK)
115 return -EINVAL;
116
117 if (info->flags & XT_CT_NOTRACK) {
118 ct = nf_ct_untracked_get();
119 atomic_inc(&ct->ct_general.use);
120 goto out;
121 }
122
123#ifndef CONFIG_NF_CONNTRACK_ZONES
124 if (info->zone)
125 goto err1;
126#endif
127
128 ret = nf_ct_l3proto_try_module_get(par->family);
129 if (ret < 0)
130 goto err1;
131
132 memset(&t, 0, sizeof(t));
133 ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
134 ret = PTR_ERR(ct);
135 if (IS_ERR(ct))
136 goto err2;
137
138 ret = 0;
139 if ((info->ct_events || info->exp_events) &&
140 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
141 GFP_KERNEL))
142 goto err3;
143
144 if (info->helper[0]) {
145 ret = xt_ct_set_helper(ct, info->helper, par);
146 if (ret < 0)
147 goto err3;
148 }
149
150 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
151 __set_bit(IPS_CONFIRMED_BIT, &ct->status);
152
153 /* Overload tuple linked list to put us in template list. */
154 hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
155 &par->net->ct.tmpl);
156out:
157 info->ct = ct;
158 return 0;
159
160err3:
161 nf_conntrack_free(ct);
162err2:
163 nf_ct_l3proto_module_put(par->family);
164err1:
165 return ret;
166}
167
168#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 104#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
169static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) 105static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
170{ 106{
@@ -242,9 +178,9 @@ out:
242#endif 178#endif
243} 179}
244 180
245static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 181static int xt_ct_tg_check(const struct xt_tgchk_param *par,
182 struct xt_ct_target_info_v1 *info)
246{ 183{
247 struct xt_ct_target_info_v1 *info = par->targinfo;
248 struct nf_conntrack_tuple t; 184 struct nf_conntrack_tuple t;
249 struct nf_conn *ct; 185 struct nf_conn *ct;
250 int ret = -EOPNOTSUPP; 186 int ret = -EOPNOTSUPP;
@@ -309,20 +245,31 @@ err1:
309 return ret; 245 return ret;
310} 246}
311 247
312static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) 248static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
313{ 249{
314 struct xt_ct_target_info *info = par->targinfo; 250 struct xt_ct_target_info *info = par->targinfo;
315 struct nf_conn *ct = info->ct; 251 struct xt_ct_target_info_v1 info_v1 = {
316 struct nf_conn_help *help; 252 .flags = info->flags,
253 .zone = info->zone,
254 .ct_events = info->ct_events,
255 .exp_events = info->exp_events,
256 };
257 int ret;
317 258
318 if (!nf_ct_is_untracked(ct)) { 259 memcpy(info_v1.helper, info->helper, sizeof(info->helper));
319 help = nfct_help(ct);
320 if (help)
321 module_put(help->helper->me);
322 260
323 nf_ct_l3proto_module_put(par->family); 261 ret = xt_ct_tg_check(par, &info_v1);
324 } 262 if (ret < 0)
325 nf_ct_put(info->ct); 263 return ret;
264
265 info->ct = info_v1.ct;
266
267 return ret;
268}
269
270static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
271{
272 return xt_ct_tg_check(par, par->targinfo);
326} 273}
327 274
328static void xt_ct_destroy_timeout(struct nf_conn *ct) 275static void xt_ct_destroy_timeout(struct nf_conn *ct)
@@ -343,9 +290,9 @@ static void xt_ct_destroy_timeout(struct nf_conn *ct)
343#endif 290#endif
344} 291}
345 292
346static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) 293static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
294 struct xt_ct_target_info_v1 *info)
347{ 295{
348 struct xt_ct_target_info_v1 *info = par->targinfo;
349 struct nf_conn *ct = info->ct; 296 struct nf_conn *ct = info->ct;
350 struct nf_conn_help *help; 297 struct nf_conn_help *help;
351 298
@@ -361,6 +308,26 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
361 nf_ct_put(info->ct); 308 nf_ct_put(info->ct);
362} 309}
363 310
311static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
312{
313 struct xt_ct_target_info *info = par->targinfo;
314 struct xt_ct_target_info_v1 info_v1 = {
315 .flags = info->flags,
316 .zone = info->zone,
317 .ct_events = info->ct_events,
318 .exp_events = info->exp_events,
319 .ct = info->ct,
320 };
321 memcpy(info_v1.helper, info->helper, sizeof(info->helper));
322
323 xt_ct_tg_destroy(par, &info_v1);
324}
325
326static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
327{
328 xt_ct_tg_destroy(par, par->targinfo);
329}
330
364static struct xt_target xt_ct_tg_reg[] __read_mostly = { 331static struct xt_target xt_ct_tg_reg[] __read_mostly = {
365 { 332 {
366 .name = "CT", 333 .name = "CT",