Commit 0ce490ad4387a67ee8ca5253476272d508fc0b6f
Committed by
Pablo Neira Ayuso
1 parent
d2ba1fde42
netfilter: nf_ct_udp: add namespace support
This patch adds namespace support for UDP protocol tracker. Acked-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Showing 3 changed files with 103 additions and 11 deletions Side-by-side Diff
include/net/netns/conntrack.h
... | ... | @@ -34,9 +34,21 @@ |
34 | 34 | unsigned int tcp_max_retrans; |
35 | 35 | }; |
36 | 36 | |
37 | +enum udp_conntrack { | |
38 | + UDP_CT_UNREPLIED, | |
39 | + UDP_CT_REPLIED, | |
40 | + UDP_CT_MAX | |
41 | +}; | |
42 | + | |
43 | +struct nf_udp_net { | |
44 | + struct nf_proto_net pn; | |
45 | + unsigned int timeouts[UDP_CT_MAX]; | |
46 | +}; | |
47 | + | |
37 | 48 | struct nf_ip_net { |
38 | 49 | struct nf_generic_net generic; |
39 | 50 | struct nf_tcp_net tcp; |
51 | + struct nf_udp_net udp; | |
40 | 52 | #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) |
41 | 53 | struct ctl_table_header *ctl_table_header; |
42 | 54 | struct ctl_table *ctl_table; |
net/netfilter/nf_conntrack_proto.c
... | ... | @@ -305,6 +305,8 @@ |
305 | 305 | switch (l4proto->l4proto) { |
306 | 306 | case IPPROTO_TCP: |
307 | 307 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.tcp; |
308 | + case IPPROTO_UDP: | |
309 | + return (struct nf_proto_net *)&net->ct.nf_ct_proto.udp; | |
308 | 310 | case 255: /* l4proto_generic */ |
309 | 311 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.generic; |
310 | 312 | default: |
net/netfilter/nf_conntrack_proto_udp.c
... | ... | @@ -25,17 +25,16 @@ |
25 | 25 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
26 | 26 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
27 | 27 | |
28 | -enum udp_conntrack { | |
29 | - UDP_CT_UNREPLIED, | |
30 | - UDP_CT_REPLIED, | |
31 | - UDP_CT_MAX | |
32 | -}; | |
33 | - | |
34 | 28 | static unsigned int udp_timeouts[UDP_CT_MAX] = { |
35 | 29 | [UDP_CT_UNREPLIED] = 30*HZ, |
36 | 30 | [UDP_CT_REPLIED] = 180*HZ, |
37 | 31 | }; |
38 | 32 | |
33 | +static inline struct nf_udp_net *udp_pernet(struct net *net) | |
34 | +{ | |
35 | + return &net->ct.nf_ct_proto.udp; | |
36 | +} | |
37 | + | |
39 | 38 | static bool udp_pkt_to_tuple(const struct sk_buff *skb, |
40 | 39 | unsigned int dataoff, |
41 | 40 | struct nf_conntrack_tuple *tuple) |
... | ... | @@ -73,7 +72,7 @@ |
73 | 72 | |
74 | 73 | static unsigned int *udp_get_timeouts(struct net *net) |
75 | 74 | { |
76 | - return udp_timeouts; | |
75 | + return udp_pernet(net)->timeouts; | |
77 | 76 | } |
78 | 77 | |
79 | 78 | /* Returns verdict for packet, and may modify conntracktype */ |
80 | 79 | |
... | ... | @@ -205,14 +204,12 @@ |
205 | 204 | static struct ctl_table udp_sysctl_table[] = { |
206 | 205 | { |
207 | 206 | .procname = "nf_conntrack_udp_timeout", |
208 | - .data = &udp_timeouts[UDP_CT_UNREPLIED], | |
209 | 207 | .maxlen = sizeof(unsigned int), |
210 | 208 | .mode = 0644, |
211 | 209 | .proc_handler = proc_dointvec_jiffies, |
212 | 210 | }, |
213 | 211 | { |
214 | 212 | .procname = "nf_conntrack_udp_timeout_stream", |
215 | - .data = &udp_timeouts[UDP_CT_REPLIED], | |
216 | 213 | .maxlen = sizeof(unsigned int), |
217 | 214 | .mode = 0644, |
218 | 215 | .proc_handler = proc_dointvec_jiffies, |
219 | 216 | |
... | ... | @@ -223,14 +220,12 @@ |
223 | 220 | static struct ctl_table udp_compat_sysctl_table[] = { |
224 | 221 | { |
225 | 222 | .procname = "ip_conntrack_udp_timeout", |
226 | - .data = &udp_timeouts[UDP_CT_UNREPLIED], | |
227 | 223 | .maxlen = sizeof(unsigned int), |
228 | 224 | .mode = 0644, |
229 | 225 | .proc_handler = proc_dointvec_jiffies, |
230 | 226 | }, |
231 | 227 | { |
232 | 228 | .procname = "ip_conntrack_udp_timeout_stream", |
233 | - .data = &udp_timeouts[UDP_CT_REPLIED], | |
234 | 229 | .maxlen = sizeof(unsigned int), |
235 | 230 | .mode = 0644, |
236 | 231 | .proc_handler = proc_dointvec_jiffies, |
... | ... | @@ -240,6 +235,87 @@ |
240 | 235 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
241 | 236 | #endif /* CONFIG_SYSCTL */ |
242 | 237 | |
238 | +static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn) | |
239 | +{ | |
240 | +#ifdef CONFIG_SYSCTL | |
241 | + struct nf_udp_net *un = (struct nf_udp_net *)pn; | |
242 | + if (pn->ctl_table) | |
243 | + return 0; | |
244 | + pn->ctl_table = kmemdup(udp_sysctl_table, | |
245 | + sizeof(udp_sysctl_table), | |
246 | + GFP_KERNEL); | |
247 | + if (!pn->ctl_table) | |
248 | + return -ENOMEM; | |
249 | + pn->ctl_table[0].data = &un->timeouts[UDP_CT_UNREPLIED]; | |
250 | + pn->ctl_table[1].data = &un->timeouts[UDP_CT_REPLIED]; | |
251 | +#endif | |
252 | + return 0; | |
253 | +} | |
254 | + | |
255 | +static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | |
256 | +{ | |
257 | +#ifdef CONFIG_SYSCTL | |
258 | +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | |
259 | + struct nf_udp_net *un = (struct nf_udp_net *)pn; | |
260 | + pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table, | |
261 | + sizeof(udp_compat_sysctl_table), | |
262 | + GFP_KERNEL); | |
263 | + if (!pn->ctl_compat_table) | |
264 | + return -ENOMEM; | |
265 | + | |
266 | + pn->ctl_compat_table[0].data = &un->timeouts[UDP_CT_UNREPLIED]; | |
267 | + pn->ctl_compat_table[1].data = &un->timeouts[UDP_CT_REPLIED]; | |
268 | +#endif | |
269 | +#endif | |
270 | + return 0; | |
271 | +} | |
272 | + | |
273 | +static void udp_init_net_data(struct nf_udp_net *un) | |
274 | +{ | |
275 | + int i; | |
276 | +#ifdef CONFIG_SYSCTL | |
277 | + if (!un->pn.ctl_table) { | |
278 | +#else | |
279 | + if (!un->pn.user++) { | |
280 | +#endif | |
281 | + for (i = 0; i < UDP_CT_MAX; i++) | |
282 | + un->timeouts[i] = udp_timeouts[i]; | |
283 | + } | |
284 | +} | |
285 | + | |
286 | +static int udpv4_init_net(struct net *net) | |
287 | +{ | |
288 | + int ret; | |
289 | + struct nf_udp_net *un = udp_pernet(net); | |
290 | + struct nf_proto_net *pn = (struct nf_proto_net *)un; | |
291 | + | |
292 | + udp_init_net_data(un); | |
293 | + | |
294 | + ret = udp_kmemdup_compat_sysctl_table(pn); | |
295 | + if (ret < 0) | |
296 | + return ret; | |
297 | + | |
298 | + ret = udp_kmemdup_sysctl_table(pn); | |
299 | +#ifdef CONFIG_SYSCTL | |
300 | +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | |
301 | + if (ret < 0) { | |
302 | + kfree(pn->ctl_compat_table); | |
303 | + pn->ctl_compat_table = NULL; | |
304 | + } | |
305 | +#endif | |
306 | +#endif | |
307 | + return ret; | |
308 | +} | |
309 | + | |
310 | +static int udpv6_init_net(struct net *net) | |
311 | +{ | |
312 | + struct nf_udp_net *un = udp_pernet(net); | |
313 | + struct nf_proto_net *pn = (struct nf_proto_net *)un; | |
314 | + | |
315 | + udp_init_net_data(un); | |
316 | + return udp_kmemdup_sysctl_table(pn); | |
317 | +} | |
318 | + | |
243 | 319 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = |
244 | 320 | { |
245 | 321 | .l3proto = PF_INET, |
... | ... | @@ -275,6 +351,7 @@ |
275 | 351 | .ctl_compat_table = udp_compat_sysctl_table, |
276 | 352 | #endif |
277 | 353 | #endif |
354 | + .init_net = udpv4_init_net, | |
278 | 355 | }; |
279 | 356 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); |
280 | 357 | |
... | ... | @@ -310,6 +387,7 @@ |
310 | 387 | .ctl_table_header = &udp_sysctl_header, |
311 | 388 | .ctl_table = udp_sysctl_table, |
312 | 389 | #endif |
390 | + .init_net = udpv6_init_net, | |
313 | 391 | }; |
314 | 392 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6); |