[NET]: Make rtnetlink infrastructure network namespace aware (v3)
[cascardo/linux.git] / net / ipv4 / devinet.c
index 5dbe580..6e75c88 100644 (file)
@@ -203,8 +203,6 @@ static void inetdev_destroy(struct in_device *in_dev)
        ASSERT_RTNL();
 
        dev = in_dev->dev;
-       if (dev == &loopback_dev)
-               return;
 
        in_dev->dead = 1;
 
@@ -420,7 +418,7 @@ struct in_device *inetdev_by_index(int ifindex)
        struct net_device *dev;
        struct in_device *in_dev = NULL;
        read_lock(&dev_base_lock);
-       dev = __dev_get_by_index(ifindex);
+       dev = __dev_get_by_index(&init_net, ifindex);
        if (dev)
                in_dev = in_dev_get(dev);
        read_unlock(&dev_base_lock);
@@ -443,6 +441,7 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
 
 static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
+       struct net *net = skb->sk->sk_net;
        struct nlattr *tb[IFA_MAX+1];
        struct in_device *in_dev;
        struct ifaddrmsg *ifm;
@@ -451,6 +450,9 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
 
        ASSERT_RTNL();
 
+       if (net != &init_net)
+               return -EINVAL;
+
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
        if (err < 0)
                goto errout;
@@ -506,7 +508,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
                goto errout;
        }
 
-       dev = __dev_get_by_index(ifm->ifa_index);
+       dev = __dev_get_by_index(&init_net, ifm->ifa_index);
        if (dev == NULL) {
                err = -ENODEV;
                goto errout;
@@ -518,8 +520,6 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
                goto errout;
        }
 
-       ipv4_devconf_setall(in_dev);
-
        ifa = inet_alloc_ifa();
        if (ifa == NULL) {
                /*
@@ -530,6 +530,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
                goto errout;
        }
 
+       ipv4_devconf_setall(in_dev);
        in_dev_hold(in_dev);
 
        if (tb[IFA_ADDRESS] == NULL)
@@ -563,10 +564,14 @@ errout:
 
 static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
+       struct net *net = skb->sk->sk_net;
        struct in_ifaddr *ifa;
 
        ASSERT_RTNL();
 
+       if (net != &init_net)
+               return -EINVAL;
+
        ifa = rtm_to_ifaddr(nlh);
        if (IS_ERR(ifa))
                return PTR_ERR(ifa);
@@ -628,7 +633,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
                *colon = 0;
 
 #ifdef CONFIG_KMOD
-       dev_load(ifr.ifr_name);
+       dev_load(&init_net, ifr.ifr_name);
 #endif
 
        switch (cmd) {
@@ -669,7 +674,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
        rtnl_lock();
 
        ret = -ENODEV;
-       if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL)
+       if ((dev = __dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
                goto done;
 
        if (colon)
@@ -909,7 +914,7 @@ no_in_dev:
         */
        read_lock(&dev_base_lock);
        rcu_read_lock();
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
                        continue;
 
@@ -988,7 +993,7 @@ __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local,
 
        read_lock(&dev_base_lock);
        rcu_read_lock();
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                if ((in_dev = __in_dev_get_rcu(dev))) {
                        addr = confirm_addr_indev(in_dev, dst, local, scope);
                        if (addr)
@@ -1030,7 +1035,7 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
                if (named++ == 0)
                        continue;
-               dot = strchr(ifa->ifa_label, ':');
+               dot = strchr(old, ':');
                if (dot == NULL) {
                        sprintf(old, ":%d", named);
                        dot = old;
@@ -1051,6 +1056,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        struct net_device *dev = ptr;
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        ASSERT_RTNL();
 
        if (!in_dev) {
@@ -1058,7 +1066,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                        in_dev = inetdev_init(dev);
                        if (!in_dev)
                                return notifier_from_errno(-ENOMEM);
-                       if (dev == &loopback_dev) {
+                       if (dev->flags & IFF_LOOPBACK) {
                                IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
                                IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
                        }
@@ -1074,7 +1082,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        case NETDEV_UP:
                if (dev->mtu < 68)
                        break;
-               if (dev == &loopback_dev) {
+               if (dev->flags & IFF_LOOPBACK) {
                        struct in_ifaddr *ifa;
                        if ((ifa = inet_alloc_ifa()) != NULL) {
                                ifa->ifa_local =
@@ -1174,15 +1182,19 @@ nla_put_failure:
 
 static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       struct net *net = skb->sk->sk_net;
        int idx, ip_idx;
        struct net_device *dev;
        struct in_device *in_dev;
        struct in_ifaddr *ifa;
        int s_ip_idx, s_idx = cb->args[0];
 
+       if (net != &init_net)
+               return 0;
+
        s_ip_idx = ip_idx = cb->args[1];
        idx = 0;
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                if (idx < s_idx)
                        goto cont;
                if (idx > s_idx)
@@ -1228,10 +1240,10 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
+       err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV4_IFADDR, err);
 }
 
 #ifdef CONFIG_SYSCTL
@@ -1241,7 +1253,7 @@ static void devinet_copy_dflt_conf(int i)
        struct net_device *dev;
 
        read_lock(&dev_base_lock);
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                struct in_device *in_dev;
                rcu_read_lock();
                in_dev = __in_dev_get_rcu(dev);
@@ -1330,7 +1342,7 @@ void inet_forward_change(void)
        IPV4_DEVCONF_DFLT(FORWARDING) = on;
 
        read_lock(&dev_base_lock);
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                struct in_device *in_dev;
                rcu_read_lock();
                in_dev = __in_dev_get_rcu(dev);