diff options
-rw-r--r-- | include/net/netfilter/nf_conntrack_core.h | 4 | ||||
-rw-r--r-- | include/net/netns/conntrack.h | 6 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 17 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 46 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_generic.c | 38 |
5 files changed, 78 insertions, 33 deletions
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index aced085132e7..d8f5b9f52169 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h | |||
@@ -28,8 +28,8 @@ extern unsigned int nf_conntrack_in(struct net *net, | |||
28 | extern int nf_conntrack_init(struct net *net); | 28 | extern int nf_conntrack_init(struct net *net); |
29 | extern void nf_conntrack_cleanup(struct net *net); | 29 | extern void nf_conntrack_cleanup(struct net *net); |
30 | 30 | ||
31 | extern int nf_conntrack_proto_init(void); | 31 | extern int nf_conntrack_proto_init(struct net *net); |
32 | extern void nf_conntrack_proto_fini(void); | 32 | extern void nf_conntrack_proto_fini(struct net *net); |
33 | 33 | ||
34 | extern bool | 34 | extern bool |
35 | nf_ct_get_tuple(const struct sk_buff *skb, | 35 | nf_ct_get_tuple(const struct sk_buff *skb, |
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index b2dbcc5cd813..0ef8592d48bf 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h | |||
@@ -20,7 +20,13 @@ struct nf_proto_net { | |||
20 | unsigned int users; | 20 | unsigned int users; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | struct nf_generic_net { | ||
24 | struct nf_proto_net pn; | ||
25 | unsigned int timeout; | ||
26 | }; | ||
27 | |||
23 | struct nf_ip_net { | 28 | struct nf_ip_net { |
29 | struct nf_generic_net generic; | ||
24 | #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) | 30 | #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) |
25 | struct ctl_table_header *ctl_table_header; | 31 | struct ctl_table_header *ctl_table_header; |
26 | struct ctl_table *ctl_table; | 32 | struct ctl_table *ctl_table; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ac3af97cc468..068f2e0ec58e 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -1333,7 +1333,6 @@ static void nf_conntrack_cleanup_init_net(void) | |||
1333 | while (untrack_refs() > 0) | 1333 | while (untrack_refs() > 0) |
1334 | schedule(); | 1334 | schedule(); |
1335 | 1335 | ||
1336 | nf_conntrack_proto_fini(); | ||
1337 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 1336 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
1338 | nf_ct_extend_unregister(&nf_ct_zone_extend); | 1337 | nf_ct_extend_unregister(&nf_ct_zone_extend); |
1339 | #endif | 1338 | #endif |
@@ -1372,7 +1371,7 @@ void nf_conntrack_cleanup(struct net *net) | |||
1372 | netfilter framework. Roll on, two-stage module | 1371 | netfilter framework. Roll on, two-stage module |
1373 | delete... */ | 1372 | delete... */ |
1374 | synchronize_net(); | 1373 | synchronize_net(); |
1375 | 1374 | nf_conntrack_proto_fini(net); | |
1376 | nf_conntrack_cleanup_net(net); | 1375 | nf_conntrack_cleanup_net(net); |
1377 | 1376 | ||
1378 | if (net_eq(net, &init_net)) { | 1377 | if (net_eq(net, &init_net)) { |
@@ -1496,11 +1495,6 @@ static int nf_conntrack_init_init_net(void) | |||
1496 | printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n", | 1495 | printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n", |
1497 | NF_CONNTRACK_VERSION, nf_conntrack_htable_size, | 1496 | NF_CONNTRACK_VERSION, nf_conntrack_htable_size, |
1498 | nf_conntrack_max); | 1497 | nf_conntrack_max); |
1499 | |||
1500 | ret = nf_conntrack_proto_init(); | ||
1501 | if (ret < 0) | ||
1502 | goto err_proto; | ||
1503 | |||
1504 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 1498 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
1505 | ret = nf_ct_extend_register(&nf_ct_zone_extend); | 1499 | ret = nf_ct_extend_register(&nf_ct_zone_extend); |
1506 | if (ret < 0) | 1500 | if (ret < 0) |
@@ -1518,9 +1512,7 @@ static int nf_conntrack_init_init_net(void) | |||
1518 | 1512 | ||
1519 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 1513 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
1520 | err_extend: | 1514 | err_extend: |
1521 | nf_conntrack_proto_fini(); | ||
1522 | #endif | 1515 | #endif |
1523 | err_proto: | ||
1524 | return ret; | 1516 | return ret; |
1525 | } | 1517 | } |
1526 | 1518 | ||
@@ -1583,9 +1575,7 @@ static int nf_conntrack_init_net(struct net *net) | |||
1583 | ret = nf_conntrack_helper_init(net); | 1575 | ret = nf_conntrack_helper_init(net); |
1584 | if (ret < 0) | 1576 | if (ret < 0) |
1585 | goto err_helper; | 1577 | goto err_helper; |
1586 | |||
1587 | return 0; | 1578 | return 0; |
1588 | |||
1589 | err_helper: | 1579 | err_helper: |
1590 | nf_conntrack_timeout_fini(net); | 1580 | nf_conntrack_timeout_fini(net); |
1591 | err_timeout: | 1581 | err_timeout: |
@@ -1622,6 +1612,9 @@ int nf_conntrack_init(struct net *net) | |||
1622 | if (ret < 0) | 1612 | if (ret < 0) |
1623 | goto out_init_net; | 1613 | goto out_init_net; |
1624 | } | 1614 | } |
1615 | ret = nf_conntrack_proto_init(net); | ||
1616 | if (ret < 0) | ||
1617 | goto out_proto; | ||
1625 | ret = nf_conntrack_init_net(net); | 1618 | ret = nf_conntrack_init_net(net); |
1626 | if (ret < 0) | 1619 | if (ret < 0) |
1627 | goto out_net; | 1620 | goto out_net; |
@@ -1637,6 +1630,8 @@ int nf_conntrack_init(struct net *net) | |||
1637 | return 0; | 1630 | return 0; |
1638 | 1631 | ||
1639 | out_net: | 1632 | out_net: |
1633 | nf_conntrack_proto_fini(net); | ||
1634 | out_proto: | ||
1640 | if (net_eq(net, &init_net)) | 1635 | if (net_eq(net, &init_net)) |
1641 | nf_conntrack_cleanup_init_net(); | 1636 | nf_conntrack_cleanup_init_net(); |
1642 | out_init_net: | 1637 | out_init_net: |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index a8daf0faadb7..b095b4aefd7c 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -302,10 +302,16 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); | |||
302 | static struct nf_proto_net *nf_ct_l4proto_net(struct net *net, | 302 | static struct nf_proto_net *nf_ct_l4proto_net(struct net *net, |
303 | struct nf_conntrack_l4proto *l4proto) | 303 | struct nf_conntrack_l4proto *l4proto) |
304 | { | 304 | { |
305 | if (l4proto->net_id) | 305 | switch (l4proto->l4proto) { |
306 | return net_generic(net, *l4proto->net_id); | 306 | case 255: /* l4proto_generic */ |
307 | else | 307 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.generic; |
308 | return NULL; | 308 | default: |
309 | if (l4proto->net_id) | ||
310 | return net_generic(net, *l4proto->net_id); | ||
311 | else | ||
312 | return NULL; | ||
313 | } | ||
314 | return NULL; | ||
309 | } | 315 | } |
310 | 316 | ||
311 | static | 317 | static |
@@ -487,28 +493,34 @@ void nf_conntrack_l4proto_unregister(struct net *net, | |||
487 | } | 493 | } |
488 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); | 494 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); |
489 | 495 | ||
490 | int nf_conntrack_proto_init(void) | 496 | int nf_conntrack_proto_init(struct net *net) |
491 | { | 497 | { |
492 | unsigned int i; | 498 | unsigned int i; |
493 | int err; | 499 | int err; |
494 | 500 | err = nf_conntrack_l4proto_generic.init_net(net); | |
495 | err = nf_ct_l4proto_register_sysctl(&init_net, &nf_conntrack_l4proto_generic); | 501 | if (err < 0) |
502 | return err; | ||
503 | err = nf_ct_l4proto_register_sysctl(net, | ||
504 | &nf_conntrack_l4proto_generic); | ||
496 | if (err < 0) | 505 | if (err < 0) |
497 | return err; | 506 | return err; |
498 | 507 | ||
499 | for (i = 0; i < AF_MAX; i++) | 508 | if (net == &init_net) { |
500 | rcu_assign_pointer(nf_ct_l3protos[i], | 509 | for (i = 0; i < AF_MAX; i++) |
501 | &nf_conntrack_l3proto_generic); | 510 | rcu_assign_pointer(nf_ct_l3protos[i], |
511 | &nf_conntrack_l3proto_generic); | ||
512 | } | ||
502 | return 0; | 513 | return 0; |
503 | } | 514 | } |
504 | 515 | ||
505 | void nf_conntrack_proto_fini(void) | 516 | void nf_conntrack_proto_fini(struct net *net) |
506 | { | 517 | { |
507 | unsigned int i; | 518 | unsigned int i; |
508 | 519 | nf_ct_l4proto_unregister_sysctl(net, | |
509 | nf_ct_l4proto_unregister_sysctl(&init_net, &nf_conntrack_l4proto_generic); | 520 | &nf_conntrack_l4proto_generic); |
510 | 521 | if (net == &init_net) { | |
511 | /* free l3proto protocol tables */ | 522 | /* free l3proto protocol tables */ |
512 | for (i = 0; i < PF_MAX; i++) | 523 | for (i = 0; i < PF_MAX; i++) |
513 | kfree(nf_ct_protos[i]); | 524 | kfree(nf_ct_protos[i]); |
525 | } | ||
514 | } | 526 | } |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index d8923d54b358..19bc880eb4e2 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
@@ -14,6 +14,11 @@ | |||
14 | 14 | ||
15 | static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; | 15 | static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; |
16 | 16 | ||
17 | static inline struct nf_generic_net *generic_pernet(struct net *net) | ||
18 | { | ||
19 | return &net->ct.nf_ct_proto.generic; | ||
20 | } | ||
21 | |||
17 | static bool generic_pkt_to_tuple(const struct sk_buff *skb, | 22 | static bool generic_pkt_to_tuple(const struct sk_buff *skb, |
18 | unsigned int dataoff, | 23 | unsigned int dataoff, |
19 | struct nf_conntrack_tuple *tuple) | 24 | struct nf_conntrack_tuple *tuple) |
@@ -42,7 +47,7 @@ static int generic_print_tuple(struct seq_file *s, | |||
42 | 47 | ||
43 | static unsigned int *generic_get_timeouts(struct net *net) | 48 | static unsigned int *generic_get_timeouts(struct net *net) |
44 | { | 49 | { |
45 | return &nf_ct_generic_timeout; | 50 | return &(generic_pernet(net)->timeout); |
46 | } | 51 | } |
47 | 52 | ||
48 | /* Returns verdict for packet, or -1 for invalid. */ | 53 | /* Returns verdict for packet, or -1 for invalid. */ |
@@ -110,7 +115,6 @@ static struct ctl_table_header *generic_sysctl_header; | |||
110 | static struct ctl_table generic_sysctl_table[] = { | 115 | static struct ctl_table generic_sysctl_table[] = { |
111 | { | 116 | { |
112 | .procname = "nf_conntrack_generic_timeout", | 117 | .procname = "nf_conntrack_generic_timeout", |
113 | .data = &nf_ct_generic_timeout, | ||
114 | .maxlen = sizeof(unsigned int), | 118 | .maxlen = sizeof(unsigned int), |
115 | .mode = 0644, | 119 | .mode = 0644, |
116 | .proc_handler = proc_dointvec_jiffies, | 120 | .proc_handler = proc_dointvec_jiffies, |
@@ -121,7 +125,6 @@ static struct ctl_table generic_sysctl_table[] = { | |||
121 | static struct ctl_table generic_compat_sysctl_table[] = { | 125 | static struct ctl_table generic_compat_sysctl_table[] = { |
122 | { | 126 | { |
123 | .procname = "ip_conntrack_generic_timeout", | 127 | .procname = "ip_conntrack_generic_timeout", |
124 | .data = &nf_ct_generic_timeout, | ||
125 | .maxlen = sizeof(unsigned int), | 128 | .maxlen = sizeof(unsigned int), |
126 | .mode = 0644, | 129 | .mode = 0644, |
127 | .proc_handler = proc_dointvec_jiffies, | 130 | .proc_handler = proc_dointvec_jiffies, |
@@ -131,6 +134,34 @@ static struct ctl_table generic_compat_sysctl_table[] = { | |||
131 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 134 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
132 | #endif /* CONFIG_SYSCTL */ | 135 | #endif /* CONFIG_SYSCTL */ |
133 | 136 | ||
137 | static int generic_init_net(struct net *net) | ||
138 | { | ||
139 | struct nf_generic_net *gn = generic_pernet(net); | ||
140 | struct nf_proto_net *pn = (struct nf_proto_net *)gn; | ||
141 | gn->timeout = nf_ct_generic_timeout; | ||
142 | #ifdef CONFIG_SYSCTL | ||
143 | pn->ctl_table = kmemdup(generic_sysctl_table, | ||
144 | sizeof(generic_sysctl_table), | ||
145 | GFP_KERNEL); | ||
146 | if (!pn->ctl_table) | ||
147 | return -ENOMEM; | ||
148 | pn->ctl_table[0].data = &gn->timeout; | ||
149 | |||
150 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | ||
151 | pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table, | ||
152 | sizeof(generic_compat_sysctl_table), | ||
153 | GFP_KERNEL); | ||
154 | if (!pn->ctl_compat_table) { | ||
155 | kfree(pn->ctl_table); | ||
156 | pn->ctl_table = NULL; | ||
157 | return -ENOMEM; | ||
158 | } | ||
159 | pn->ctl_compat_table[0].data = &gn->timeout; | ||
160 | #endif | ||
161 | #endif | ||
162 | return 0; | ||
163 | } | ||
164 | |||
134 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = | 165 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = |
135 | { | 166 | { |
136 | .l3proto = PF_UNSPEC, | 167 | .l3proto = PF_UNSPEC, |
@@ -158,4 +189,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = | |||
158 | .ctl_compat_table = generic_compat_sysctl_table, | 189 | .ctl_compat_table = generic_compat_sysctl_table, |
159 | #endif | 190 | #endif |
160 | #endif | 191 | #endif |
192 | .init_net = generic_init_net, | ||
161 | }; | 193 | }; |