]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/addrconf.c
[NET]: Make the loopback device per network namespace.
[net-next-2.6.git] / net / ipv6 / addrconf.c
index 91ef3be5abadeab0b778dfaba86cce6b440c3362..6d5c3c299148dc940bf002e4381b7d8338dcd07f 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/notifier.h>
 #include <linux/string.h>
 
+#include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/snmp.h>
 
@@ -260,9 +261,15 @@ static int snmp6_alloc_dev(struct inet6_dev *idev)
                          sizeof(struct icmpv6_mib),
                          __alignof__(struct icmpv6_mib)) < 0)
                goto err_icmp;
+       if (snmp_mib_init((void **)idev->stats.icmpv6msg,
+                         sizeof(struct icmpv6msg_mib),
+                         __alignof__(struct icmpv6msg_mib)) < 0)
+               goto err_icmpmsg;
 
        return 0;
 
+err_icmpmsg:
+       snmp_mib_free((void **)idev->stats.icmpv6);
 err_icmp:
        snmp_mib_free((void **)idev->stats.ipv6);
 err_ip:
@@ -271,6 +278,7 @@ err_ip:
 
 static int snmp6_free_dev(struct inet6_dev *idev)
 {
+       snmp_mib_free((void **)idev->stats.icmpv6msg);
        snmp_mib_free((void **)idev->stats.icmpv6);
        snmp_mib_free((void **)idev->stats.ipv6);
        return 0;
@@ -449,7 +457,7 @@ static void addrconf_forward_change(void)
        struct inet6_dev *idev;
 
        read_lock(&dev_base_lock);
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                rcu_read_lock();
                idev = __in6_dev_get(dev);
                if (idev) {
@@ -911,7 +919,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
        read_lock(&dev_base_lock);
        rcu_read_lock();
 
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                struct inet6_dev *idev;
                struct inet6_ifaddr *ifa;
 
@@ -1021,7 +1029,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
                                hiscore.rule++;
                        }
                        if (ipv6_saddr_preferred(score.addr_type) ||
-                          (((ifa_result->flags &
+                          (((ifa->flags &
                            (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
                                score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
                                if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
@@ -1857,7 +1865,7 @@ int addrconf_set_dstaddr(void __user *arg)
        if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
                goto err_exit;
 
-       dev = __dev_get_by_index(ireq.ifr6_ifindex);
+       dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex);
 
        err = -ENODEV;
        if (dev == NULL)
@@ -1888,7 +1896,7 @@ int addrconf_set_dstaddr(void __user *arg)
 
                if (err == 0) {
                        err = -ENOBUFS;
-                       if ((dev = __dev_get_by_name(p.name)) == NULL)
+                       if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL)
                                goto err_exit;
                        err = dev_open(dev);
                }
@@ -1918,7 +1926,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
        if (!valid_lft || prefered_lft > valid_lft)
                return -EINVAL;
 
-       if ((dev = __dev_get_by_index(ifindex)) == NULL)
+       if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
                return -ENODEV;
 
        if ((idev = addrconf_add_dev(dev)) == NULL)
@@ -1969,7 +1977,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
        struct inet6_dev *idev;
        struct net_device *dev;
 
-       if ((dev = __dev_get_by_index(ifindex)) == NULL)
+       if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
                return -ENODEV;
 
        if ((idev = __in6_dev_get(dev)) == NULL)
@@ -2064,7 +2072,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
                return;
        }
 
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                struct in_device * in_dev = __in_dev_get_rtnl(dev);
                if (in_dev && (dev->flags & IFF_UP)) {
                        struct in_ifaddr * ifa;
@@ -2220,12 +2228,12 @@ static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
 
        /* first try to inherit the link-local address from the link device */
        if (idev->dev->iflink &&
-           (link_dev = __dev_get_by_index(idev->dev->iflink))) {
+           (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) {
                if (!ipv6_inherit_linklocal(idev, link_dev))
                        return;
        }
        /* then try to inherit it from any device */
-       for_each_netdev(link_dev) {
+       for_each_netdev(&init_net, link_dev) {
                if (!ipv6_inherit_linklocal(idev, link_dev))
                        return;
        }
@@ -2258,6 +2266,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
        int run_pending = 0;
        int err;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        switch(event) {
        case NETDEV_REGISTER:
                if (!idev && dev->mtu >= IPV6_MIN_MTU) {
@@ -2399,7 +2410,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 
        ASSERT_RTNL();
 
-       if (dev == &loopback_dev && how == 1)
+       if (dev == init_net.loopback_dev && how == 1)
                how = 0;
 
        rt6_ifdown(dev);
@@ -2491,9 +2502,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
        else
                ipv6_mc_down(idev);
 
-       /* Step 5: netlink notification of this interface */
        idev->tstamp = jiffies;
-       inet6_ifinfo_notify(RTM_DELLINK, idev);
 
        /* Shot the device (if unregistered) */
 
@@ -2827,14 +2836,14 @@ static const struct file_operations if6_fops = {
 
 int __init if6_proc_init(void)
 {
-       if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops))
+       if (!proc_net_fops_create(&init_net, "if_inet6", S_IRUGO, &if6_fops))
                return -ENOMEM;
        return 0;
 }
 
 void if6_proc_exit(void)
 {
-       proc_net_remove("if_inet6");
+       proc_net_remove(&init_net, "if_inet6");
 }
 #endif /* CONFIG_PROC_FS */
 
@@ -3080,7 +3089,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                valid_lft = INFINITY_LIFE_TIME;
        }
 
-       dev =  __dev_get_by_index(ifm->ifa_index);
+       dev =  __dev_get_by_index(&init_net, ifm->ifa_index);
        if (dev == NULL)
                return -ENODEV;
 
@@ -3264,7 +3273,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
        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)
@@ -3373,7 +3382,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
 
        ifm = nlmsg_data(nlh);
        if (ifm->ifa_index)
-               dev = __dev_get_by_index(ifm->ifa_index);
+               dev = __dev_get_by_index(&init_net, ifm->ifa_index);
 
        if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
                err = -EADDRNOTAVAIL;
@@ -3585,7 +3594,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 
        read_lock(&dev_base_lock);
        idx = 0;
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                if (idx < s_idx)
                        goto cont;
                if ((idev = in6_dev_get(dev)) == NULL)
@@ -4203,16 +4212,19 @@ int __init addrconf_init(void)
         * device and it being up should be removed.
         */
        rtnl_lock();
-       if (!ipv6_add_dev(&loopback_dev))
+       if (!ipv6_add_dev(init_net.loopback_dev))
                err = -ENOMEM;
        rtnl_unlock();
        if (err)
                return err;
 
-       ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+       ip6_null_entry.u.dst.dev = init_net.loopback_dev;
+       ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-       ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
-       ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+       ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev;
+       ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+       ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev;
+       ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
 #endif
 
        register_netdevice_notifier(&ipv6_dev_notf);
@@ -4262,12 +4274,12 @@ void __exit addrconf_cleanup(void)
         *      clean dev list.
         */
 
-       for_each_netdev(dev) {
+       for_each_netdev(&init_net, dev) {
                if (__in6_dev_get(dev) == NULL)
                        continue;
                addrconf_ifdown(dev, 1);
        }
-       addrconf_ifdown(&loopback_dev, 2);
+       addrconf_ifdown(init_net.loopback_dev, 2);
 
        /*
         *      Check hash table.
@@ -4293,6 +4305,6 @@ void __exit addrconf_cleanup(void)
        rtnl_unlock();
 
 #ifdef CONFIG_PROC_FS
-       proc_net_remove("if_inet6");
+       proc_net_remove(&init_net, "if_inet6");
 #endif
 }