Commit eeb4cb952386aac764a5cf4cf2490e50a24a8880

Authored by Pablo Neira Ayuso
1 parent 1ac0bf9926

netfilter: xt_CT: fix assignation of the generic protocol tracker

`iptables -p all' uses 0 to match all protocols, while the conntrack
subsystem uses 255. We still need `-p all' to attach the custom
timeout policies for the generic protocol tracker.

Moreover, we may use `iptables -p sctp' while the SCTP tracker is
not loaded. In that case, we have to default on the generic protocol
tracker.

Another possibility is `iptables -p ip' that should be supported
as well. This patch makes sure we validate all possible scenarios.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 1 changed file with 8 additions and 1 deletions Inline Diff

net/netfilter/xt_CT.c
1 /* 1 /*
2 * Copyright (c) 2010 Patrick McHardy <kaber@trash.net> 2 * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 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 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/module.h> 9 #include <linux/module.h>
10 #include <linux/gfp.h> 10 #include <linux/gfp.h>
11 #include <linux/skbuff.h> 11 #include <linux/skbuff.h>
12 #include <linux/netfilter_ipv4/ip_tables.h> 12 #include <linux/netfilter_ipv4/ip_tables.h>
13 #include <linux/netfilter_ipv6/ip6_tables.h> 13 #include <linux/netfilter_ipv6/ip6_tables.h>
14 #include <linux/netfilter/x_tables.h> 14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter/xt_CT.h> 15 #include <linux/netfilter/xt_CT.h>
16 #include <net/netfilter/nf_conntrack.h> 16 #include <net/netfilter/nf_conntrack.h>
17 #include <net/netfilter/nf_conntrack_l4proto.h>
17 #include <net/netfilter/nf_conntrack_helper.h> 18 #include <net/netfilter/nf_conntrack_helper.h>
18 #include <net/netfilter/nf_conntrack_ecache.h> 19 #include <net/netfilter/nf_conntrack_ecache.h>
19 #include <net/netfilter/nf_conntrack_l4proto.h> 20 #include <net/netfilter/nf_conntrack_l4proto.h>
20 #include <net/netfilter/nf_conntrack_timeout.h> 21 #include <net/netfilter/nf_conntrack_timeout.h>
21 #include <net/netfilter/nf_conntrack_zones.h> 22 #include <net/netfilter/nf_conntrack_zones.h>
22 23
23 static unsigned int xt_ct_target_v0(struct sk_buff *skb, 24 static unsigned int xt_ct_target_v0(struct sk_buff *skb,
24 const struct xt_action_param *par) 25 const struct xt_action_param *par)
25 { 26 {
26 const struct xt_ct_target_info *info = par->targinfo; 27 const struct xt_ct_target_info *info = par->targinfo;
27 struct nf_conn *ct = info->ct; 28 struct nf_conn *ct = info->ct;
28 29
29 /* Previously seen (loopback)? Ignore. */ 30 /* Previously seen (loopback)? Ignore. */
30 if (skb->nfct != NULL) 31 if (skb->nfct != NULL)
31 return XT_CONTINUE; 32 return XT_CONTINUE;
32 33
33 atomic_inc(&ct->ct_general.use); 34 atomic_inc(&ct->ct_general.use);
34 skb->nfct = &ct->ct_general; 35 skb->nfct = &ct->ct_general;
35 skb->nfctinfo = IP_CT_NEW; 36 skb->nfctinfo = IP_CT_NEW;
36 37
37 return XT_CONTINUE; 38 return XT_CONTINUE;
38 } 39 }
39 40
40 static unsigned int xt_ct_target_v1(struct sk_buff *skb, 41 static unsigned int xt_ct_target_v1(struct sk_buff *skb,
41 const struct xt_action_param *par) 42 const struct xt_action_param *par)
42 { 43 {
43 const struct xt_ct_target_info_v1 *info = par->targinfo; 44 const struct xt_ct_target_info_v1 *info = par->targinfo;
44 struct nf_conn *ct = info->ct; 45 struct nf_conn *ct = info->ct;
45 46
46 /* Previously seen (loopback)? Ignore. */ 47 /* Previously seen (loopback)? Ignore. */
47 if (skb->nfct != NULL) 48 if (skb->nfct != NULL)
48 return XT_CONTINUE; 49 return XT_CONTINUE;
49 50
50 atomic_inc(&ct->ct_general.use); 51 atomic_inc(&ct->ct_general.use);
51 skb->nfct = &ct->ct_general; 52 skb->nfct = &ct->ct_general;
52 skb->nfctinfo = IP_CT_NEW; 53 skb->nfctinfo = IP_CT_NEW;
53 54
54 return XT_CONTINUE; 55 return XT_CONTINUE;
55 } 56 }
56 57
57 static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) 58 static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
58 { 59 {
59 if (par->family == NFPROTO_IPV4) { 60 if (par->family == NFPROTO_IPV4) {
60 const struct ipt_entry *e = par->entryinfo; 61 const struct ipt_entry *e = par->entryinfo;
61 62
62 if (e->ip.invflags & IPT_INV_PROTO) 63 if (e->ip.invflags & IPT_INV_PROTO)
63 return 0; 64 return 0;
64 return e->ip.proto; 65 return e->ip.proto;
65 } else if (par->family == NFPROTO_IPV6) { 66 } else if (par->family == NFPROTO_IPV6) {
66 const struct ip6t_entry *e = par->entryinfo; 67 const struct ip6t_entry *e = par->entryinfo;
67 68
68 if (e->ipv6.invflags & IP6T_INV_PROTO) 69 if (e->ipv6.invflags & IP6T_INV_PROTO)
69 return 0; 70 return 0;
70 return e->ipv6.proto; 71 return e->ipv6.proto;
71 } else 72 } else
72 return 0; 73 return 0;
73 } 74 }
74 75
75 static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) 76 static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
76 { 77 {
77 struct xt_ct_target_info *info = par->targinfo; 78 struct xt_ct_target_info *info = par->targinfo;
78 struct nf_conntrack_tuple t; 79 struct nf_conntrack_tuple t;
79 struct nf_conn_help *help; 80 struct nf_conn_help *help;
80 struct nf_conn *ct; 81 struct nf_conn *ct;
81 int ret = 0; 82 int ret = 0;
82 u8 proto; 83 u8 proto;
83 84
84 if (info->flags & ~XT_CT_NOTRACK) 85 if (info->flags & ~XT_CT_NOTRACK)
85 return -EINVAL; 86 return -EINVAL;
86 87
87 if (info->flags & XT_CT_NOTRACK) { 88 if (info->flags & XT_CT_NOTRACK) {
88 ct = nf_ct_untracked_get(); 89 ct = nf_ct_untracked_get();
89 atomic_inc(&ct->ct_general.use); 90 atomic_inc(&ct->ct_general.use);
90 goto out; 91 goto out;
91 } 92 }
92 93
93 #ifndef CONFIG_NF_CONNTRACK_ZONES 94 #ifndef CONFIG_NF_CONNTRACK_ZONES
94 if (info->zone) 95 if (info->zone)
95 goto err1; 96 goto err1;
96 #endif 97 #endif
97 98
98 ret = nf_ct_l3proto_try_module_get(par->family); 99 ret = nf_ct_l3proto_try_module_get(par->family);
99 if (ret < 0) 100 if (ret < 0)
100 goto err1; 101 goto err1;
101 102
102 memset(&t, 0, sizeof(t)); 103 memset(&t, 0, sizeof(t));
103 ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); 104 ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
104 ret = PTR_ERR(ct); 105 ret = PTR_ERR(ct);
105 if (IS_ERR(ct)) 106 if (IS_ERR(ct))
106 goto err2; 107 goto err2;
107 108
108 ret = 0; 109 ret = 0;
109 if ((info->ct_events || info->exp_events) && 110 if ((info->ct_events || info->exp_events) &&
110 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, 111 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
111 GFP_KERNEL)) 112 GFP_KERNEL))
112 goto err3; 113 goto err3;
113 114
114 if (info->helper[0]) { 115 if (info->helper[0]) {
115 ret = -ENOENT; 116 ret = -ENOENT;
116 proto = xt_ct_find_proto(par); 117 proto = xt_ct_find_proto(par);
117 if (!proto) { 118 if (!proto) {
118 pr_info("You must specify a L4 protocol, " 119 pr_info("You must specify a L4 protocol, "
119 "and not use inversions on it.\n"); 120 "and not use inversions on it.\n");
120 goto err3; 121 goto err3;
121 } 122 }
122 123
123 ret = -ENOMEM; 124 ret = -ENOMEM;
124 help = nf_ct_helper_ext_add(ct, GFP_KERNEL); 125 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
125 if (help == NULL) 126 if (help == NULL)
126 goto err3; 127 goto err3;
127 128
128 ret = -ENOENT; 129 ret = -ENOENT;
129 help->helper = nf_conntrack_helper_try_module_get(info->helper, 130 help->helper = nf_conntrack_helper_try_module_get(info->helper,
130 par->family, 131 par->family,
131 proto); 132 proto);
132 if (help->helper == NULL) { 133 if (help->helper == NULL) {
133 pr_info("No such helper \"%s\"\n", info->helper); 134 pr_info("No such helper \"%s\"\n", info->helper);
134 goto err3; 135 goto err3;
135 } 136 }
136 } 137 }
137 138
138 __set_bit(IPS_TEMPLATE_BIT, &ct->status); 139 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
139 __set_bit(IPS_CONFIRMED_BIT, &ct->status); 140 __set_bit(IPS_CONFIRMED_BIT, &ct->status);
140 out: 141 out:
141 info->ct = ct; 142 info->ct = ct;
142 return 0; 143 return 0;
143 144
144 err3: 145 err3:
145 nf_conntrack_free(ct); 146 nf_conntrack_free(ct);
146 err2: 147 err2:
147 nf_ct_l3proto_module_put(par->family); 148 nf_ct_l3proto_module_put(par->family);
148 err1: 149 err1:
149 return ret; 150 return ret;
150 } 151 }
151 152
152 static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 153 static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
153 { 154 {
154 struct xt_ct_target_info_v1 *info = par->targinfo; 155 struct xt_ct_target_info_v1 *info = par->targinfo;
155 struct nf_conntrack_tuple t; 156 struct nf_conntrack_tuple t;
156 struct nf_conn_help *help; 157 struct nf_conn_help *help;
157 struct nf_conn *ct; 158 struct nf_conn *ct;
158 int ret = 0; 159 int ret = 0;
159 u8 proto; 160 u8 proto;
160 161
161 if (info->flags & ~XT_CT_NOTRACK) 162 if (info->flags & ~XT_CT_NOTRACK)
162 return -EINVAL; 163 return -EINVAL;
163 164
164 if (info->flags & XT_CT_NOTRACK) { 165 if (info->flags & XT_CT_NOTRACK) {
165 ct = nf_ct_untracked_get(); 166 ct = nf_ct_untracked_get();
166 atomic_inc(&ct->ct_general.use); 167 atomic_inc(&ct->ct_general.use);
167 goto out; 168 goto out;
168 } 169 }
169 170
170 #ifndef CONFIG_NF_CONNTRACK_ZONES 171 #ifndef CONFIG_NF_CONNTRACK_ZONES
171 if (info->zone) 172 if (info->zone)
172 goto err1; 173 goto err1;
173 #endif 174 #endif
174 175
175 ret = nf_ct_l3proto_try_module_get(par->family); 176 ret = nf_ct_l3proto_try_module_get(par->family);
176 if (ret < 0) 177 if (ret < 0)
177 goto err1; 178 goto err1;
178 179
179 memset(&t, 0, sizeof(t)); 180 memset(&t, 0, sizeof(t));
180 ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); 181 ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
181 ret = PTR_ERR(ct); 182 ret = PTR_ERR(ct);
182 if (IS_ERR(ct)) 183 if (IS_ERR(ct))
183 goto err2; 184 goto err2;
184 185
185 ret = 0; 186 ret = 0;
186 if ((info->ct_events || info->exp_events) && 187 if ((info->ct_events || info->exp_events) &&
187 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, 188 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
188 GFP_KERNEL)) 189 GFP_KERNEL))
189 goto err3; 190 goto err3;
190 191
191 if (info->helper[0]) { 192 if (info->helper[0]) {
192 ret = -ENOENT; 193 ret = -ENOENT;
193 proto = xt_ct_find_proto(par); 194 proto = xt_ct_find_proto(par);
194 if (!proto) { 195 if (!proto) {
195 pr_info("You must specify a L4 protocol, " 196 pr_info("You must specify a L4 protocol, "
196 "and not use inversions on it.\n"); 197 "and not use inversions on it.\n");
197 goto err3; 198 goto err3;
198 } 199 }
199 200
200 ret = -ENOMEM; 201 ret = -ENOMEM;
201 help = nf_ct_helper_ext_add(ct, GFP_KERNEL); 202 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
202 if (help == NULL) 203 if (help == NULL)
203 goto err3; 204 goto err3;
204 205
205 ret = -ENOENT; 206 ret = -ENOENT;
206 help->helper = nf_conntrack_helper_try_module_get(info->helper, 207 help->helper = nf_conntrack_helper_try_module_get(info->helper,
207 par->family, 208 par->family,
208 proto); 209 proto);
209 if (help->helper == NULL) { 210 if (help->helper == NULL) {
210 pr_info("No such helper \"%s\"\n", info->helper); 211 pr_info("No such helper \"%s\"\n", info->helper);
211 goto err3; 212 goto err3;
212 } 213 }
213 } 214 }
214 215
215 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 216 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
216 if (info->timeout) { 217 if (info->timeout) {
217 typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 218 typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
218 struct ctnl_timeout *timeout; 219 struct ctnl_timeout *timeout;
219 struct nf_conn_timeout *timeout_ext; 220 struct nf_conn_timeout *timeout_ext;
220 221
221 rcu_read_lock(); 222 rcu_read_lock();
222 timeout_find_get = 223 timeout_find_get =
223 rcu_dereference(nf_ct_timeout_find_get_hook); 224 rcu_dereference(nf_ct_timeout_find_get_hook);
224 225
225 if (timeout_find_get) { 226 if (timeout_find_get) {
226 const struct ipt_entry *e = par->entryinfo; 227 const struct ipt_entry *e = par->entryinfo;
228 struct nf_conntrack_l4proto *l4proto;
227 229
228 if (e->ip.invflags & IPT_INV_PROTO) { 230 if (e->ip.invflags & IPT_INV_PROTO) {
229 ret = -EINVAL; 231 ret = -EINVAL;
230 pr_info("You cannot use inversion on " 232 pr_info("You cannot use inversion on "
231 "L4 protocol\n"); 233 "L4 protocol\n");
232 goto err4; 234 goto err4;
233 } 235 }
234 timeout = timeout_find_get(info->timeout); 236 timeout = timeout_find_get(info->timeout);
235 if (timeout == NULL) { 237 if (timeout == NULL) {
236 ret = -ENOENT; 238 ret = -ENOENT;
237 pr_info("No such timeout policy \"%s\"\n", 239 pr_info("No such timeout policy \"%s\"\n",
238 info->timeout); 240 info->timeout);
239 goto err4; 241 goto err4;
240 } 242 }
241 if (timeout->l3num != par->family) { 243 if (timeout->l3num != par->family) {
242 ret = -EINVAL; 244 ret = -EINVAL;
243 pr_info("Timeout policy `%s' can only be " 245 pr_info("Timeout policy `%s' can only be "
244 "used by L3 protocol number %d\n", 246 "used by L3 protocol number %d\n",
245 info->timeout, timeout->l3num); 247 info->timeout, timeout->l3num);
246 goto err4; 248 goto err4;
247 } 249 }
248 if (timeout->l4proto->l4proto != e->ip.proto) { 250 /* Make sure the timeout policy matches any existing
251 * protocol tracker, otherwise default to generic.
252 */
253 l4proto = __nf_ct_l4proto_find(par->family,
254 e->ip.proto);
255 if (timeout->l4proto->l4proto != l4proto->l4proto) {
249 ret = -EINVAL; 256 ret = -EINVAL;
250 pr_info("Timeout policy `%s' can only be " 257 pr_info("Timeout policy `%s' can only be "
251 "used by L4 protocol number %d\n", 258 "used by L4 protocol number %d\n",
252 info->timeout, 259 info->timeout,
253 timeout->l4proto->l4proto); 260 timeout->l4proto->l4proto);
254 goto err4; 261 goto err4;
255 } 262 }
256 timeout_ext = nf_ct_timeout_ext_add(ct, timeout, 263 timeout_ext = nf_ct_timeout_ext_add(ct, timeout,
257 GFP_KERNEL); 264 GFP_KERNEL);
258 if (timeout_ext == NULL) { 265 if (timeout_ext == NULL) {
259 ret = -ENOMEM; 266 ret = -ENOMEM;
260 goto err4; 267 goto err4;
261 } 268 }
262 } else { 269 } else {
263 ret = -ENOENT; 270 ret = -ENOENT;
264 pr_info("Timeout policy base is empty\n"); 271 pr_info("Timeout policy base is empty\n");
265 goto err4; 272 goto err4;
266 } 273 }
267 rcu_read_unlock(); 274 rcu_read_unlock();
268 } 275 }
269 #endif 276 #endif
270 277
271 __set_bit(IPS_TEMPLATE_BIT, &ct->status); 278 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
272 __set_bit(IPS_CONFIRMED_BIT, &ct->status); 279 __set_bit(IPS_CONFIRMED_BIT, &ct->status);
273 out: 280 out:
274 info->ct = ct; 281 info->ct = ct;
275 return 0; 282 return 0;
276 283
277 err4: 284 err4:
278 rcu_read_unlock(); 285 rcu_read_unlock();
279 err3: 286 err3:
280 nf_conntrack_free(ct); 287 nf_conntrack_free(ct);
281 err2: 288 err2:
282 nf_ct_l3proto_module_put(par->family); 289 nf_ct_l3proto_module_put(par->family);
283 err1: 290 err1:
284 return ret; 291 return ret;
285 } 292 }
286 293
287 static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) 294 static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
288 { 295 {
289 struct xt_ct_target_info *info = par->targinfo; 296 struct xt_ct_target_info *info = par->targinfo;
290 struct nf_conn *ct = info->ct; 297 struct nf_conn *ct = info->ct;
291 struct nf_conn_help *help; 298 struct nf_conn_help *help;
292 299
293 if (!nf_ct_is_untracked(ct)) { 300 if (!nf_ct_is_untracked(ct)) {
294 help = nfct_help(ct); 301 help = nfct_help(ct);
295 if (help) 302 if (help)
296 module_put(help->helper->me); 303 module_put(help->helper->me);
297 304
298 nf_ct_l3proto_module_put(par->family); 305 nf_ct_l3proto_module_put(par->family);
299 } 306 }
300 nf_ct_put(info->ct); 307 nf_ct_put(info->ct);
301 } 308 }
302 309
303 static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) 310 static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
304 { 311 {
305 struct xt_ct_target_info_v1 *info = par->targinfo; 312 struct xt_ct_target_info_v1 *info = par->targinfo;
306 struct nf_conn *ct = info->ct; 313 struct nf_conn *ct = info->ct;
307 struct nf_conn_help *help; 314 struct nf_conn_help *help;
308 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 315 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
309 struct nf_conn_timeout *timeout_ext; 316 struct nf_conn_timeout *timeout_ext;
310 typeof(nf_ct_timeout_put_hook) timeout_put; 317 typeof(nf_ct_timeout_put_hook) timeout_put;
311 #endif 318 #endif
312 if (!nf_ct_is_untracked(ct)) { 319 if (!nf_ct_is_untracked(ct)) {
313 help = nfct_help(ct); 320 help = nfct_help(ct);
314 if (help) 321 if (help)
315 module_put(help->helper->me); 322 module_put(help->helper->me);
316 323
317 nf_ct_l3proto_module_put(par->family); 324 nf_ct_l3proto_module_put(par->family);
318 325
319 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 326 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
320 rcu_read_lock(); 327 rcu_read_lock();
321 timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 328 timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
322 329
323 if (timeout_put) { 330 if (timeout_put) {
324 timeout_ext = nf_ct_timeout_find(ct); 331 timeout_ext = nf_ct_timeout_find(ct);
325 if (timeout_ext) 332 if (timeout_ext)
326 timeout_put(timeout_ext->timeout); 333 timeout_put(timeout_ext->timeout);
327 } 334 }
328 rcu_read_unlock(); 335 rcu_read_unlock();
329 #endif 336 #endif
330 } 337 }
331 nf_ct_put(info->ct); 338 nf_ct_put(info->ct);
332 } 339 }
333 340
334 static struct xt_target xt_ct_tg_reg[] __read_mostly = { 341 static struct xt_target xt_ct_tg_reg[] __read_mostly = {
335 { 342 {
336 .name = "CT", 343 .name = "CT",
337 .family = NFPROTO_UNSPEC, 344 .family = NFPROTO_UNSPEC,
338 .targetsize = sizeof(struct xt_ct_target_info), 345 .targetsize = sizeof(struct xt_ct_target_info),
339 .checkentry = xt_ct_tg_check_v0, 346 .checkentry = xt_ct_tg_check_v0,
340 .destroy = xt_ct_tg_destroy_v0, 347 .destroy = xt_ct_tg_destroy_v0,
341 .target = xt_ct_target_v0, 348 .target = xt_ct_target_v0,
342 .table = "raw", 349 .table = "raw",
343 .me = THIS_MODULE, 350 .me = THIS_MODULE,
344 }, 351 },
345 { 352 {
346 .name = "CT", 353 .name = "CT",
347 .family = NFPROTO_UNSPEC, 354 .family = NFPROTO_UNSPEC,
348 .revision = 1, 355 .revision = 1,
349 .targetsize = sizeof(struct xt_ct_target_info_v1), 356 .targetsize = sizeof(struct xt_ct_target_info_v1),
350 .checkentry = xt_ct_tg_check_v1, 357 .checkentry = xt_ct_tg_check_v1,
351 .destroy = xt_ct_tg_destroy_v1, 358 .destroy = xt_ct_tg_destroy_v1,
352 .target = xt_ct_target_v1, 359 .target = xt_ct_target_v1,
353 .table = "raw", 360 .table = "raw",
354 .me = THIS_MODULE, 361 .me = THIS_MODULE,
355 }, 362 },
356 }; 363 };
357 364
358 static int __init xt_ct_tg_init(void) 365 static int __init xt_ct_tg_init(void)
359 { 366 {
360 return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 367 return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
361 } 368 }
362 369
363 static void __exit xt_ct_tg_exit(void) 370 static void __exit xt_ct_tg_exit(void)
364 { 371 {
365 xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 372 xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
366 } 373 }
367 374
368 module_init(xt_ct_tg_init); 375 module_init(xt_ct_tg_init);
369 module_exit(xt_ct_tg_exit); 376 module_exit(xt_ct_tg_exit);
370 377
371 MODULE_LICENSE("GPL"); 378 MODULE_LICENSE("GPL");
372 MODULE_DESCRIPTION("Xtables: connection tracking target"); 379 MODULE_DESCRIPTION("Xtables: connection tracking target");
373 MODULE_ALIAS("ipt_CT"); 380 MODULE_ALIAS("ipt_CT");
374 MODULE_ALIAS("ip6t_CT"); 381 MODULE_ALIAS("ip6t_CT");
375 382