aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2008-01-10 06:20:28 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:01:23 -0500
commit5fd30ee7c48bf7f9cd16ab44c8a09fa4a57cc21d (patch)
treeeb5fc97bcf41f7f1e9dd9d7c312e13c85c1610d0 /net/core
parent868d13ac811746e28e4c806f2b1bd8575796f9af (diff)
[NETNS]: Namespacing in the generic fib rules code.
Move static rules_ops & rules_mod_lock to the struct net, register the pernet subsys to init them and enjoy the fact that the core rules infrastructure works in the namespace. Real IPv4 fib rules virtualization requires fib tables support in the namespace and will be done seriously later in the patchset. Acked-by: Benjamin Thery <benjamin.thery@bull.net> Acked-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: Denis V. Lunev <den@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/fib_rules.c91
1 files changed, 54 insertions, 37 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index e12e9f583949..c5f78fed6885 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -15,9 +15,6 @@
15#include <net/sock.h> 15#include <net/sock.h>
16#include <net/fib_rules.h> 16#include <net/fib_rules.h>
17 17
18static LIST_HEAD(rules_ops);
19static DEFINE_SPINLOCK(rules_mod_lock);
20
21int fib_default_rule_add(struct fib_rules_ops *ops, 18int fib_default_rule_add(struct fib_rules_ops *ops,
22 u32 pref, u32 table, u32 flags) 19 u32 pref, u32 table, u32 flags)
23{ 20{
@@ -40,16 +37,17 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
40} 37}
41EXPORT_SYMBOL(fib_default_rule_add); 38EXPORT_SYMBOL(fib_default_rule_add);
42 39
43static void notify_rule_change(int event, struct fib_rule *rule, 40static void notify_rule_change(struct net *net, int event,
41 struct fib_rule *rule,
44 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 42 struct fib_rules_ops *ops, struct nlmsghdr *nlh,
45 u32 pid); 43 u32 pid);
46 44
47static struct fib_rules_ops *lookup_rules_ops(int family) 45static struct fib_rules_ops *lookup_rules_ops(struct net *net, int family)
48{ 46{
49 struct fib_rules_ops *ops; 47 struct fib_rules_ops *ops;
50 48
51 rcu_read_lock(); 49 rcu_read_lock();
52 list_for_each_entry_rcu(ops, &rules_ops, list) { 50 list_for_each_entry_rcu(ops, &net->rules_ops, list) {
53 if (ops->family == family) { 51 if (ops->family == family) {
54 if (!try_module_get(ops->owner)) 52 if (!try_module_get(ops->owner))
55 ops = NULL; 53 ops = NULL;
@@ -87,15 +85,16 @@ int fib_rules_register(struct net *net, struct fib_rules_ops *ops)
87 ops->action == NULL) 85 ops->action == NULL)
88 return -EINVAL; 86 return -EINVAL;
89 87
90 spin_lock(&rules_mod_lock); 88 spin_lock(&net->rules_mod_lock);
91 list_for_each_entry(o, &rules_ops, list) 89 list_for_each_entry(o, &net->rules_ops, list)
92 if (ops->family == o->family) 90 if (ops->family == o->family)
93 goto errout; 91 goto errout;
94 92
95 list_add_tail_rcu(&ops->list, &rules_ops); 93 hold_net(net);
94 list_add_tail_rcu(&ops->list, &net->rules_ops);
96 err = 0; 95 err = 0;
97errout: 96errout:
98 spin_unlock(&rules_mod_lock); 97 spin_unlock(&net->rules_mod_lock);
99 98
100 return err; 99 return err;
101} 100}
@@ -118,8 +117,8 @@ int fib_rules_unregister(struct net *net, struct fib_rules_ops *ops)
118 int err = 0; 117 int err = 0;
119 struct fib_rules_ops *o; 118 struct fib_rules_ops *o;
120 119
121 spin_lock(&rules_mod_lock); 120 spin_lock(&net->rules_mod_lock);
122 list_for_each_entry(o, &rules_ops, list) { 121 list_for_each_entry(o, &net->rules_ops, list) {
123 if (o == ops) { 122 if (o == ops) {
124 list_del_rcu(&o->list); 123 list_del_rcu(&o->list);
125 fib_rules_cleanup_ops(ops); 124 fib_rules_cleanup_ops(ops);
@@ -129,9 +128,11 @@ int fib_rules_unregister(struct net *net, struct fib_rules_ops *ops)
129 128
130 err = -ENOENT; 129 err = -ENOENT;
131out: 130out:
132 spin_unlock(&rules_mod_lock); 131 spin_unlock(&net->rules_mod_lock);
133 132
134 synchronize_rcu(); 133 synchronize_rcu();
134 if (!err)
135 release_net(net);
135 136
136 return err; 137 return err;
137} 138}
@@ -229,13 +230,10 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
229 struct nlattr *tb[FRA_MAX+1]; 230 struct nlattr *tb[FRA_MAX+1];
230 int err = -EINVAL, unresolved = 0; 231 int err = -EINVAL, unresolved = 0;
231 232
232 if (net != &init_net)
233 return -EINVAL;
234
235 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) 233 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
236 goto errout; 234 goto errout;
237 235
238 ops = lookup_rules_ops(frh->family); 236 ops = lookup_rules_ops(net, frh->family);
239 if (ops == NULL) { 237 if (ops == NULL) {
240 err = EAFNOSUPPORT; 238 err = EAFNOSUPPORT;
241 goto errout; 239 goto errout;
@@ -348,7 +346,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
348 else 346 else
349 list_add_rcu(&rule->list, &ops->rules_list); 347 list_add_rcu(&rule->list, &ops->rules_list);
350 348
351 notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid); 349 notify_rule_change(net, RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
352 flush_route_cache(ops); 350 flush_route_cache(ops);
353 rules_ops_put(ops); 351 rules_ops_put(ops);
354 return 0; 352 return 0;
@@ -369,13 +367,10 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
369 struct nlattr *tb[FRA_MAX+1]; 367 struct nlattr *tb[FRA_MAX+1];
370 int err = -EINVAL; 368 int err = -EINVAL;
371 369
372 if (net != &init_net)
373 return -EINVAL;
374
375 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) 370 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
376 goto errout; 371 goto errout;
377 372
378 ops = lookup_rules_ops(frh->family); 373 ops = lookup_rules_ops(net, frh->family);
379 if (ops == NULL) { 374 if (ops == NULL) {
380 err = EAFNOSUPPORT; 375 err = EAFNOSUPPORT;
381 goto errout; 376 goto errout;
@@ -441,7 +436,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
441 } 436 }
442 437
443 synchronize_rcu(); 438 synchronize_rcu();
444 notify_rule_change(RTM_DELRULE, rule, ops, nlh, 439 notify_rule_change(net, RTM_DELRULE, rule, ops, nlh,
445 NETLINK_CB(skb).pid); 440 NETLINK_CB(skb).pid);
446 fib_rule_put(rule); 441 fib_rule_put(rule);
447 flush_route_cache(ops); 442 flush_route_cache(ops);
@@ -551,13 +546,10 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
551 struct fib_rules_ops *ops; 546 struct fib_rules_ops *ops;
552 int idx = 0, family; 547 int idx = 0, family;
553 548
554 if (net != &init_net)
555 return -EINVAL;
556
557 family = rtnl_msg_family(cb->nlh); 549 family = rtnl_msg_family(cb->nlh);
558 if (family != AF_UNSPEC) { 550 if (family != AF_UNSPEC) {
559 /* Protocol specific dump request */ 551 /* Protocol specific dump request */
560 ops = lookup_rules_ops(family); 552 ops = lookup_rules_ops(net, family);
561 if (ops == NULL) 553 if (ops == NULL)
562 return -EAFNOSUPPORT; 554 return -EAFNOSUPPORT;
563 555
@@ -565,7 +557,7 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
565 } 557 }
566 558
567 rcu_read_lock(); 559 rcu_read_lock();
568 list_for_each_entry_rcu(ops, &rules_ops, list) { 560 list_for_each_entry_rcu(ops, &net->rules_ops, list) {
569 if (idx < cb->args[0] || !try_module_get(ops->owner)) 561 if (idx < cb->args[0] || !try_module_get(ops->owner))
570 goto skip; 562 goto skip;
571 563
@@ -582,7 +574,7 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
582 return skb->len; 574 return skb->len;
583} 575}
584 576
585static void notify_rule_change(int event, struct fib_rule *rule, 577static void notify_rule_change(struct net *net, int event, struct fib_rule *rule,
586 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 578 struct fib_rules_ops *ops, struct nlmsghdr *nlh,
587 u32 pid) 579 u32 pid)
588{ 580{
@@ -600,10 +592,10 @@ static void notify_rule_change(int event, struct fib_rule *rule,
600 kfree_skb(skb); 592 kfree_skb(skb);
601 goto errout; 593 goto errout;
602 } 594 }
603 err = rtnl_notify(skb, &init_net, pid, ops->nlgroup, nlh, GFP_KERNEL); 595 err = rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL);
604errout: 596errout:
605 if (err < 0) 597 if (err < 0)
606 rtnl_set_sk_err(&init_net, ops->nlgroup, err); 598 rtnl_set_sk_err(net, ops->nlgroup, err);
607} 599}
608 600
609static void attach_rules(struct list_head *rules, struct net_device *dev) 601static void attach_rules(struct list_head *rules, struct net_device *dev)
@@ -631,22 +623,20 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
631 void *ptr) 623 void *ptr)
632{ 624{
633 struct net_device *dev = ptr; 625 struct net_device *dev = ptr;
626 struct net *net = dev->nd_net;
634 struct fib_rules_ops *ops; 627 struct fib_rules_ops *ops;
635 628
636 if (dev->nd_net != &init_net)
637 return NOTIFY_DONE;
638
639 ASSERT_RTNL(); 629 ASSERT_RTNL();
640 rcu_read_lock(); 630 rcu_read_lock();
641 631
642 switch (event) { 632 switch (event) {
643 case NETDEV_REGISTER: 633 case NETDEV_REGISTER:
644 list_for_each_entry(ops, &rules_ops, list) 634 list_for_each_entry(ops, &net->rules_ops, list)
645 attach_rules(&ops->rules_list, dev); 635 attach_rules(&ops->rules_list, dev);
646 break; 636 break;
647 637
648 case NETDEV_UNREGISTER: 638 case NETDEV_UNREGISTER:
649 list_for_each_entry(ops, &rules_ops, list) 639 list_for_each_entry(ops, &net->rules_ops, list)
650 detach_rules(&ops->rules_list, dev); 640 detach_rules(&ops->rules_list, dev);
651 break; 641 break;
652 } 642 }
@@ -660,13 +650,40 @@ static struct notifier_block fib_rules_notifier = {
660 .notifier_call = fib_rules_event, 650 .notifier_call = fib_rules_event,
661}; 651};
662 652
653static int fib_rules_net_init(struct net *net)
654{
655 INIT_LIST_HEAD(&net->rules_ops);
656 spin_lock_init(&net->rules_mod_lock);
657 return 0;
658}
659
660static struct pernet_operations fib_rules_net_ops = {
661 .init = fib_rules_net_init,
662};
663
663static int __init fib_rules_init(void) 664static int __init fib_rules_init(void)
664{ 665{
666 int err;
665 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL); 667 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
666 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL); 668 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
667 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule); 669 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
668 670
669 return register_netdevice_notifier(&fib_rules_notifier); 671 err = register_netdevice_notifier(&fib_rules_notifier);
672 if (err < 0)
673 goto fail;
674
675 err = register_pernet_subsys(&fib_rules_net_ops);
676 if (err < 0)
677 goto fail_unregister;
678 return 0;
679
680fail_unregister:
681 unregister_netdevice_notifier(&fib_rules_notifier);
682fail:
683 rtnl_unregister(PF_UNSPEC, RTM_NEWRULE);
684 rtnl_unregister(PF_UNSPEC, RTM_DELRULE);
685 rtnl_unregister(PF_UNSPEC, RTM_GETRULE);
686 return err;
670} 687}
671 688
672subsys_initcall(fib_rules_init); 689subsys_initcall(fib_rules_init);