]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/addrconf.c
osk: use gpiolib with tps65010
[linux-2.6-omap-h63xx.git] / net / ipv6 / addrconf.c
index cd90f9a6da3356eefd30ce996e4346722c91b9ff..e40213db9e4c6355e665c8684e4549feca77614d 100644 (file)
@@ -149,7 +149,8 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
 
 static void inet6_prefix_notify(int event, struct inet6_dev *idev,
                                struct prefix_info *pinfo);
-static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
+static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
+                             struct net_device *dev);
 
 static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
 
@@ -560,7 +561,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
        write_lock(&addrconf_hash_lock);
 
        /* Ignore adding duplicate addresses on an interface */
-       if (ipv6_chk_same_addr(addr, idev->dev)) {
+       if (ipv6_chk_same_addr(&init_net, addr, idev->dev)) {
                ADBG(("ipv6_add_addr: already assigned\n"));
                err = -EEXIST;
                goto out;
@@ -1206,13 +1207,16 @@ static int ipv6_count_addresses(struct inet6_dev *idev)
        return cnt;
 }
 
-int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
+int ipv6_chk_addr(struct net *net, struct in6_addr *addr,
+                 struct net_device *dev, int strict)
 {
        struct inet6_ifaddr * ifp;
        u8 hash = ipv6_addr_hash(addr);
 
        read_lock_bh(&addrconf_hash_lock);
        for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+               if (ifp->idev->dev->nd_net != net)
+                       continue;
                if (ipv6_addr_equal(&ifp->addr, addr) &&
                    !(ifp->flags&IFA_F_TENTATIVE)) {
                        if (dev == NULL || ifp->idev->dev == dev ||
@@ -1223,16 +1227,18 @@ int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
        read_unlock_bh(&addrconf_hash_lock);
        return ifp != NULL;
 }
-
 EXPORT_SYMBOL(ipv6_chk_addr);
 
 static
-int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev)
+int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
+                      struct net_device *dev)
 {
        struct inet6_ifaddr * ifp;
        u8 hash = ipv6_addr_hash(addr);
 
        for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+               if (ifp->idev->dev->nd_net != net)
+                       continue;
                if (ipv6_addr_equal(&ifp->addr, addr)) {
                        if (dev == NULL || ifp->idev->dev == dev)
                                break;
@@ -1241,13 +1247,16 @@ int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev)
        return ifp != NULL;
 }
 
-struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict)
+struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr,
+                                    struct net_device *dev, int strict)
 {
        struct inet6_ifaddr * ifp;
        u8 hash = ipv6_addr_hash(addr);
 
        read_lock_bh(&addrconf_hash_lock);
        for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+               if (ifp->idev->dev->nd_net != net)
+                       continue;
                if (ipv6_addr_equal(&ifp->addr, addr)) {
                        if (dev == NULL || ifp->idev->dev == dev ||
                            !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
@@ -1733,7 +1742,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
 
 ok:
 
-               ifp = ipv6_get_ifaddr(&addr, dev, 1);
+               ifp = ipv6_get_ifaddr(&init_net, &addr, dev, 1);
 
                if (ifp == NULL && valid_lft) {
                        int max_addresses = in6_dev->cnf.max_addresses;
@@ -1891,7 +1900,7 @@ int addrconf_set_dstaddr(void __user *arg)
                p.iph.ihl = 5;
                p.iph.protocol = IPPROTO_IPV6;
                p.iph.ttl = 64;
-               ifr.ifr_ifru.ifru_data = (void __user *)&p;
+               ifr.ifr_ifru.ifru_data = (__force void __user *)&p;
 
                oldfs = get_fs(); set_fs(KERNEL_DS);
                err = dev->do_ioctl(dev, &ifr, SIOCADDTUNNEL);
@@ -2736,6 +2745,7 @@ static void addrconf_dad_run(struct inet6_dev *idev) {
 
 #ifdef CONFIG_PROC_FS
 struct if6_iter_state {
+       struct seq_net_private p;
        int bucket;
 };
 
@@ -2743,9 +2753,13 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
 {
        struct inet6_ifaddr *ifa = NULL;
        struct if6_iter_state *state = seq->private;
+       struct net *net = state->p.net;
 
        for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
                ifa = inet6_addr_lst[state->bucket];
+
+               while (ifa && ifa->idev->dev->nd_net != net)
+                       ifa = ifa->lst_next;
                if (ifa)
                        break;
        }
@@ -2755,13 +2769,22 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
 static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
 {
        struct if6_iter_state *state = seq->private;
+       struct net *net = state->p.net;
 
        ifa = ifa->lst_next;
 try_again:
+       if (ifa) {
+               if (ifa->idev->dev->nd_net != net) {
+                       ifa = ifa->lst_next;
+                       goto try_again;
+               }
+       }
+
        if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) {
                ifa = inet6_addr_lst[state->bucket];
                goto try_again;
        }
+
        return ifa;
 }
 
@@ -2776,6 +2799,7 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos)
 }
 
 static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(addrconf_hash_lock)
 {
        read_lock_bh(&addrconf_hash_lock);
        return if6_get_idx(seq, *pos);
@@ -2791,6 +2815,7 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void if6_seq_stop(struct seq_file *seq, void *v)
+       __releases(addrconf_hash_lock)
 {
        read_unlock_bh(&addrconf_hash_lock);
 }
@@ -2818,8 +2843,8 @@ static const struct seq_operations if6_seq_ops = {
 
 static int if6_seq_open(struct inode *inode, struct file *file)
 {
-       return seq_open_private(file, &if6_seq_ops,
-                       sizeof(struct if6_iter_state));
+       return seq_open_net(inode, file, &if6_seq_ops,
+                           sizeof(struct if6_iter_state));
 }
 
 static const struct file_operations if6_fops = {
@@ -2827,31 +2852,48 @@ static const struct file_operations if6_fops = {
        .open           = if6_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release_private,
+       .release        = seq_release_net,
 };
 
-int __init if6_proc_init(void)
+static int if6_proc_net_init(struct net *net)
 {
-       if (!proc_net_fops_create(&init_net, "if_inet6", S_IRUGO, &if6_fops))
+       if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops))
                return -ENOMEM;
        return 0;
 }
 
+static void if6_proc_net_exit(struct net *net)
+{
+       proc_net_remove(net, "if_inet6");
+}
+
+static struct pernet_operations if6_proc_net_ops = {
+       .init = if6_proc_net_init,
+       .exit = if6_proc_net_exit,
+};
+
+int __init if6_proc_init(void)
+{
+       return register_pernet_subsys(&if6_proc_net_ops);
+}
+
 void if6_proc_exit(void)
 {
-       proc_net_remove(&init_net, "if_inet6");
+       unregister_pernet_subsys(&if6_proc_net_ops);
 }
 #endif /* CONFIG_PROC_FS */
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 /* Check if address is a home address configured on any interface. */
-int ipv6_chk_home_addr(struct in6_addr *addr)
+int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr)
 {
        int ret = 0;
        struct inet6_ifaddr * ifp;
        u8 hash = ipv6_addr_hash(addr);
        read_lock_bh(&addrconf_hash_lock);
        for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
+               if (ifp->idev->dev->nd_net != net)
+                       continue;
                if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
                    (ifp->flags & IFA_F_HOMEADDRESS)) {
                        ret = 1;
@@ -3100,7 +3142,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        /* We ignore other flags so far. */
        ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
 
-       ifa = ipv6_get_ifaddr(pfx, dev, 1);
+       ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
        if (ifa == NULL) {
                /*
                 * It would be best to check for !NLM_F_CREATE here but
@@ -3293,11 +3335,11 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                             ifa = ifa->if_next, ip_idx++) {
                                if (ip_idx < s_ip_idx)
                                        continue;
-                               if ((err = inet6_fill_ifaddr(skb, ifa,
-                                   NETLINK_CB(cb->skb).pid,
-                                   cb->nlh->nlmsg_seq, RTM_NEWADDR,
-                                   NLM_F_MULTI)) <= 0)
-                                       goto done;
+                               err = inet6_fill_ifaddr(skb, ifa,
+                                                       NETLINK_CB(cb->skb).pid,
+                                                       cb->nlh->nlmsg_seq,
+                                                       RTM_NEWADDR,
+                                                       NLM_F_MULTI);
                        }
                        break;
                case MULTICAST_ADDR:
@@ -3306,11 +3348,11 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                             ifmca = ifmca->next, ip_idx++) {
                                if (ip_idx < s_ip_idx)
                                        continue;
-                               if ((err = inet6_fill_ifmcaddr(skb, ifmca,
-                                   NETLINK_CB(cb->skb).pid,
-                                   cb->nlh->nlmsg_seq, RTM_GETMULTICAST,
-                                   NLM_F_MULTI)) <= 0)
-                                       goto done;
+                               err = inet6_fill_ifmcaddr(skb, ifmca,
+                                                         NETLINK_CB(cb->skb).pid,
+                                                         cb->nlh->nlmsg_seq,
+                                                         RTM_GETMULTICAST,
+                                                         NLM_F_MULTI);
                        }
                        break;
                case ANYCAST_ADDR:
@@ -3319,11 +3361,11 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                             ifaca = ifaca->aca_next, ip_idx++) {
                                if (ip_idx < s_ip_idx)
                                        continue;
-                               if ((err = inet6_fill_ifacaddr(skb, ifaca,
-                                   NETLINK_CB(cb->skb).pid,
-                                   cb->nlh->nlmsg_seq, RTM_GETANYCAST,
-                                   NLM_F_MULTI)) <= 0)
-                                       goto done;
+                               err = inet6_fill_ifacaddr(skb, ifaca,
+                                                         NETLINK_CB(cb->skb).pid,
+                                                         cb->nlh->nlmsg_seq,
+                                                         RTM_GETANYCAST,
+                                                         NLM_F_MULTI);
                        }
                        break;
                default:
@@ -3331,14 +3373,12 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                }
                read_unlock_bh(&idev->lock);
                in6_dev_put(idev);
+
+               if (err <= 0)
+                       break;
 cont:
                idx++;
        }
-done:
-       if (err <= 0) {
-               read_unlock_bh(&idev->lock);
-               in6_dev_put(idev);
-       }
        cb->args[0] = idx;
        cb->args[1] = ip_idx;
        return skb->len;
@@ -3407,7 +3447,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
        if (ifm->ifa_index)
                dev = __dev_get_by_index(&init_net, ifm->ifa_index);
 
-       if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
+       if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) {
                err = -EADDRNOTAVAIL;
                goto errout;
        }