diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2008-10-08 05:35:06 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-10-08 05:35:06 -0400 |
commit | 5e6b29972b7e9c9c39882227e36fe0cd3463fe96 (patch) | |
tree | c3eff078c0e18757691ac25682c1cd4a30f3b66d /net/ipv4 | |
parent | dc5129f8df7cc3f2f04b322728d71c42795d34cc (diff) |
netfilter: netns nf_conntrack: per-netns /proc/net/ip_conntrack, /proc/net/stat/ip_conntrack, /proc/net/ip_conntrack_expect
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index f8636a57e8cc..b2940836d107 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -21,18 +21,20 @@ | |||
21 | #include <net/netfilter/nf_conntrack_acct.h> | 21 | #include <net/netfilter/nf_conntrack_acct.h> |
22 | 22 | ||
23 | struct ct_iter_state { | 23 | struct ct_iter_state { |
24 | struct seq_net_private p; | ||
24 | unsigned int bucket; | 25 | unsigned int bucket; |
25 | }; | 26 | }; |
26 | 27 | ||
27 | static struct hlist_node *ct_get_first(struct seq_file *seq) | 28 | static struct hlist_node *ct_get_first(struct seq_file *seq) |
28 | { | 29 | { |
30 | struct net *net = seq_file_net(seq); | ||
29 | struct ct_iter_state *st = seq->private; | 31 | struct ct_iter_state *st = seq->private; |
30 | struct hlist_node *n; | 32 | struct hlist_node *n; |
31 | 33 | ||
32 | for (st->bucket = 0; | 34 | for (st->bucket = 0; |
33 | st->bucket < nf_conntrack_htable_size; | 35 | st->bucket < nf_conntrack_htable_size; |
34 | st->bucket++) { | 36 | st->bucket++) { |
35 | n = rcu_dereference(init_net.ct.hash[st->bucket].first); | 37 | n = rcu_dereference(net->ct.hash[st->bucket].first); |
36 | if (n) | 38 | if (n) |
37 | return n; | 39 | return n; |
38 | } | 40 | } |
@@ -42,13 +44,14 @@ static struct hlist_node *ct_get_first(struct seq_file *seq) | |||
42 | static struct hlist_node *ct_get_next(struct seq_file *seq, | 44 | static struct hlist_node *ct_get_next(struct seq_file *seq, |
43 | struct hlist_node *head) | 45 | struct hlist_node *head) |
44 | { | 46 | { |
47 | struct net *net = seq_file_net(seq); | ||
45 | struct ct_iter_state *st = seq->private; | 48 | struct ct_iter_state *st = seq->private; |
46 | 49 | ||
47 | head = rcu_dereference(head->next); | 50 | head = rcu_dereference(head->next); |
48 | while (head == NULL) { | 51 | while (head == NULL) { |
49 | if (++st->bucket >= nf_conntrack_htable_size) | 52 | if (++st->bucket >= nf_conntrack_htable_size) |
50 | return NULL; | 53 | return NULL; |
51 | head = rcu_dereference(init_net.ct.hash[st->bucket].first); | 54 | head = rcu_dereference(net->ct.hash[st->bucket].first); |
52 | } | 55 | } |
53 | return head; | 56 | return head; |
54 | } | 57 | } |
@@ -158,8 +161,8 @@ static const struct seq_operations ct_seq_ops = { | |||
158 | 161 | ||
159 | static int ct_open(struct inode *inode, struct file *file) | 162 | static int ct_open(struct inode *inode, struct file *file) |
160 | { | 163 | { |
161 | return seq_open_private(file, &ct_seq_ops, | 164 | return seq_open_net(inode, file, &ct_seq_ops, |
162 | sizeof(struct ct_iter_state)); | 165 | sizeof(struct ct_iter_state)); |
163 | } | 166 | } |
164 | 167 | ||
165 | static const struct file_operations ct_file_ops = { | 168 | static const struct file_operations ct_file_ops = { |
@@ -167,17 +170,18 @@ static const struct file_operations ct_file_ops = { | |||
167 | .open = ct_open, | 170 | .open = ct_open, |
168 | .read = seq_read, | 171 | .read = seq_read, |
169 | .llseek = seq_lseek, | 172 | .llseek = seq_lseek, |
170 | .release = seq_release_private, | 173 | .release = seq_release_net, |
171 | }; | 174 | }; |
172 | 175 | ||
173 | /* expects */ | 176 | /* expects */ |
174 | struct ct_expect_iter_state { | 177 | struct ct_expect_iter_state { |
178 | struct seq_net_private p; | ||
175 | unsigned int bucket; | 179 | unsigned int bucket; |
176 | }; | 180 | }; |
177 | 181 | ||
178 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) | 182 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) |
179 | { | 183 | { |
180 | struct net *net = &init_net; | 184 | struct net *net = seq_file_net(seq); |
181 | struct ct_expect_iter_state *st = seq->private; | 185 | struct ct_expect_iter_state *st = seq->private; |
182 | struct hlist_node *n; | 186 | struct hlist_node *n; |
183 | 187 | ||
@@ -192,7 +196,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq) | |||
192 | static struct hlist_node *ct_expect_get_next(struct seq_file *seq, | 196 | static struct hlist_node *ct_expect_get_next(struct seq_file *seq, |
193 | struct hlist_node *head) | 197 | struct hlist_node *head) |
194 | { | 198 | { |
195 | struct net *net = &init_net; | 199 | struct net *net = seq_file_net(seq); |
196 | struct ct_expect_iter_state *st = seq->private; | 200 | struct ct_expect_iter_state *st = seq->private; |
197 | 201 | ||
198 | head = rcu_dereference(head->next); | 202 | head = rcu_dereference(head->next); |
@@ -267,8 +271,8 @@ static const struct seq_operations exp_seq_ops = { | |||
267 | 271 | ||
268 | static int exp_open(struct inode *inode, struct file *file) | 272 | static int exp_open(struct inode *inode, struct file *file) |
269 | { | 273 | { |
270 | return seq_open_private(file, &exp_seq_ops, | 274 | return seq_open_net(inode, file, &exp_seq_ops, |
271 | sizeof(struct ct_expect_iter_state)); | 275 | sizeof(struct ct_expect_iter_state)); |
272 | } | 276 | } |
273 | 277 | ||
274 | static const struct file_operations ip_exp_file_ops = { | 278 | static const struct file_operations ip_exp_file_ops = { |
@@ -276,7 +280,7 @@ static const struct file_operations ip_exp_file_ops = { | |||
276 | .open = exp_open, | 280 | .open = exp_open, |
277 | .read = seq_read, | 281 | .read = seq_read, |
278 | .llseek = seq_lseek, | 282 | .llseek = seq_lseek, |
279 | .release = seq_release_private, | 283 | .release = seq_release_net, |
280 | }; | 284 | }; |
281 | 285 | ||
282 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) | 286 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) |
@@ -367,36 +371,51 @@ static const struct file_operations ct_cpu_seq_fops = { | |||
367 | .release = seq_release, | 371 | .release = seq_release, |
368 | }; | 372 | }; |
369 | 373 | ||
370 | int __init nf_conntrack_ipv4_compat_init(void) | 374 | static int __net_init ip_conntrack_net_init(struct net *net) |
371 | { | 375 | { |
372 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; | 376 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; |
373 | 377 | ||
374 | proc = proc_net_fops_create(&init_net, "ip_conntrack", 0440, &ct_file_ops); | 378 | proc = proc_net_fops_create(net, "ip_conntrack", 0440, &ct_file_ops); |
375 | if (!proc) | 379 | if (!proc) |
376 | goto err1; | 380 | goto err1; |
377 | 381 | ||
378 | proc_exp = proc_net_fops_create(&init_net, "ip_conntrack_expect", 0440, | 382 | proc_exp = proc_net_fops_create(net, "ip_conntrack_expect", 0440, |
379 | &ip_exp_file_ops); | 383 | &ip_exp_file_ops); |
380 | if (!proc_exp) | 384 | if (!proc_exp) |
381 | goto err2; | 385 | goto err2; |
382 | 386 | ||
383 | proc_stat = proc_create("ip_conntrack", S_IRUGO, | 387 | proc_stat = proc_create("ip_conntrack", S_IRUGO, |
384 | init_net.proc_net_stat, &ct_cpu_seq_fops); | 388 | net->proc_net_stat, &ct_cpu_seq_fops); |
385 | if (!proc_stat) | 389 | if (!proc_stat) |
386 | goto err3; | 390 | goto err3; |
387 | return 0; | 391 | return 0; |
388 | 392 | ||
389 | err3: | 393 | err3: |
390 | proc_net_remove(&init_net, "ip_conntrack_expect"); | 394 | proc_net_remove(net, "ip_conntrack_expect"); |
391 | err2: | 395 | err2: |
392 | proc_net_remove(&init_net, "ip_conntrack"); | 396 | proc_net_remove(net, "ip_conntrack"); |
393 | err1: | 397 | err1: |
394 | return -ENOMEM; | 398 | return -ENOMEM; |
395 | } | 399 | } |
396 | 400 | ||
401 | static void __net_exit ip_conntrack_net_exit(struct net *net) | ||
402 | { | ||
403 | remove_proc_entry("ip_conntrack", net->proc_net_stat); | ||
404 | proc_net_remove(net, "ip_conntrack_expect"); | ||
405 | proc_net_remove(net, "ip_conntrack"); | ||
406 | } | ||
407 | |||
408 | static struct pernet_operations ip_conntrack_net_ops = { | ||
409 | .init = ip_conntrack_net_init, | ||
410 | .exit = ip_conntrack_net_exit, | ||
411 | }; | ||
412 | |||
413 | int __init nf_conntrack_ipv4_compat_init(void) | ||
414 | { | ||
415 | return register_pernet_subsys(&ip_conntrack_net_ops); | ||
416 | } | ||
417 | |||
397 | void __exit nf_conntrack_ipv4_compat_fini(void) | 418 | void __exit nf_conntrack_ipv4_compat_fini(void) |
398 | { | 419 | { |
399 | remove_proc_entry("ip_conntrack", init_net.proc_net_stat); | 420 | unregister_pernet_subsys(&ip_conntrack_net_ops); |
400 | proc_net_remove(&init_net, "ip_conntrack_expect"); | ||
401 | proc_net_remove(&init_net, "ip_conntrack"); | ||
402 | } | 421 | } |