[NET]: Make the device list and device lookups per namespace.
[deliverable/linux.git] / net / core / fib_rules.c
index 7ac602cc8c85a6f1d7a43fe4fbde1d6afea0fe25..1ba71baf87ef1a96754cd26e02f978d8e3378cb1 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
 #include <net/fib_rules.h>
 
 static LIST_HEAD(rules_ops);
@@ -44,6 +46,12 @@ static void rules_ops_put(struct fib_rules_ops *ops)
                module_put(ops->owner);
 }
 
+static void flush_route_cache(struct fib_rules_ops *ops)
+{
+       if (ops->flush_cache)
+               ops->flush_cache();
+}
+
 int fib_rules_register(struct fib_rules_ops *ops)
 {
        int err = -EEXIST;
@@ -146,7 +154,9 @@ jumped:
                                rule = target;
                                goto jumped;
                        }
-               } else
+               } else if (rule->action == FR_ACT_NOP)
+                       continue;
+               else
                        err = ops->action(rule, fl, flags, arg);
 
                if (err != -EAGAIN) {
@@ -189,6 +199,7 @@ errout:
 
 static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
+       struct net *net = skb->sk->sk_net;
        struct fib_rule_hdr *frh = nlmsg_data(nlh);
        struct fib_rules_ops *ops = NULL;
        struct fib_rule *rule, *r, *last = NULL;
@@ -226,7 +237,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
                rule->ifindex = -1;
                nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ);
-               dev = __dev_get_by_name(rule->ifname);
+               dev = __dev_get_by_name(net, rule->ifname);
                if (dev)
                        rule->ifindex = dev->ifindex;
        }
@@ -312,6 +323,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                list_add_rcu(&rule->list, ops->rules_list);
 
        notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
+       flush_route_cache(ops);
        rules_ops_put(ops);
        return 0;
 
@@ -402,6 +414,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                notify_rule_change(RTM_DELRULE, rule, ops, nlh,
                                   NETLINK_CB(skb).pid);
                fib_rule_put(rule);
+               flush_route_cache(ops);
                rules_ops_put(ops);
                return 0;
        }
@@ -485,8 +498,7 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
        int idx = 0;
        struct fib_rule *rule;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(rule, ops->rules_list, list) {
+       list_for_each_entry(rule, ops->rules_list, list) {
                if (idx < cb->args[1])
                        goto skip;
 
@@ -497,7 +509,6 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
 skip:
                idx++;
        }
-       rcu_read_unlock();
        cb->args[1] = idx;
        rules_ops_put(ops);
 
@@ -588,6 +599,9 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
        struct net_device *dev = ptr;
        struct fib_rules_ops *ops;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        ASSERT_RTNL();
        rcu_read_lock();
 
This page took 0.048187 seconds and 5 git commands to generate.