]> err.no Git - linux-2.6/commitdiff
[NETNS][IPV6]: inet6_addr - check ipv6 address per namespace
authorDaniel Lezcano <dlezcano@fr.ibm.com>
Fri, 11 Jan 2008 06:43:18 +0000 (22:43 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 23:01:44 +0000 (15:01 -0800)
When a new address is added, we must check if the new address does not
already exists.  This patch makes this check to be aware of a network
namespace, so the check will look if the address already exists for
the specified network namespace. While the addresses are browsed, the
addresses which do not belong to the namespace are discarded.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/addrconf.h
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/anycast.c
net/ipv6/datagram.c
net/ipv6/icmp.c
net/ipv6/ip6_tunnel.c
net/ipv6/ndisc.c
net/ipv6/raw.c
net/sctp/ipv6.c

index 1c3a5602990efb47595bac47de3916f8caa054dc..d1697b587a1add2901a64b2abeed5cf66d6a5894 100644 (file)
@@ -59,9 +59,11 @@ extern int                   addrconf_add_ifaddr(void __user *arg);
 extern int                     addrconf_del_ifaddr(void __user *arg);
 extern int                     addrconf_set_dstaddr(void __user *arg);
 
-extern int                     ipv6_chk_addr(struct in6_addr *addr,
+extern int                     ipv6_chk_addr(struct net *net,
+                                             struct in6_addr *addr,
                                              struct net_device *dev,
                                              int strict);
+
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 extern int                     ipv6_chk_home_addr(struct in6_addr *addr);
 #endif
index d7b440343e97555534f53480b5ad4c815dfff6cb..f35c3df410df364fb6e6aa1f23046edf78663b2e 100644 (file)
@@ -1206,13 +1206,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,7 +1226,6 @@ 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
index ac8772dd968f6999dca4439d02e2764633898d15..3150c4be3c0cee7017504d8e58757749ad14c205 100644 (file)
@@ -314,7 +314,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                         */
                        v4addr = LOOPBACK4_IPV6;
                        if (!(addr_type & IPV6_ADDR_MULTICAST)) {
-                               if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) {
+                               if (!ipv6_chk_addr(&init_net, &addr->sin6_addr,
+                                                  dev, 0)) {
                                        if (dev)
                                                dev_put(dev);
                                        err = -EADDRNOTAVAIL;
index 5c4190060e754d5b3ae7702ee01df8a9dbe1bbc3..9c7f83fbc3a1d28b89bf7f26115c4d8d39f92085 100644 (file)
@@ -89,7 +89,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
                return -EPERM;
        if (ipv6_addr_is_multicast(addr))
                return -EINVAL;
-       if (ipv6_chk_addr(addr, NULL, 0))
+       if (ipv6_chk_addr(&init_net, addr, NULL, 0))
                return -EINVAL;
 
        pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
index f49a06aa97de197710841dc013e50e7d8ba2b575..94fa6ae77cfe28c6f92c04e336cc56aedfbf4507 100644 (file)
@@ -549,7 +549,8 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
                                                return -ENODEV;
                                }
                        }
-                       if (!ipv6_chk_addr(&src_info->ipi6_addr, dev, 0)) {
+                       if (!ipv6_chk_addr(&init_net, &src_info->ipi6_addr,
+                                          dev, 0)) {
                                if (dev)
                                        dev_put(dev);
                                err = -EINVAL;
index 5395afe55ca5a0e61b03f07eb10400625d9a0b0a..cbb5b9cf84ad36eba8741bec98cb2409040d3c93 100644 (file)
@@ -332,7 +332,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
         */
        addr_type = ipv6_addr_type(&hdr->daddr);
 
-       if (ipv6_chk_addr(&hdr->daddr, skb->dev, 0))
+       if (ipv6_chk_addr(&init_net, &hdr->daddr, skb->dev, 0))
                saddr = &hdr->daddr;
 
        /*
index 29b5321e39c398b2f030fd7bbac76057b6e2c700..425c9ae8b3150e976c3ed7853af16bbd38ead341 100644 (file)
@@ -653,8 +653,8 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t)
                        ldev = dev_get_by_index(&init_net, p->link);
 
                if ((ipv6_addr_is_multicast(&p->laddr) ||
-                    likely(ipv6_chk_addr(&p->laddr, ldev, 0))) &&
-                   likely(!ipv6_chk_addr(&p->raddr, NULL, 0)))
+                    likely(ipv6_chk_addr(&init_net, &p->laddr, ldev, 0))) &&
+                   likely(!ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
                        ret = 1;
 
                if (ldev)
@@ -788,12 +788,12 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
                if (p->link)
                        ldev = dev_get_by_index(&init_net, p->link);
 
-               if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0)))
+               if (unlikely(!ipv6_chk_addr(&init_net, &p->laddr, ldev, 0)))
                        printk(KERN_WARNING
                               "%s xmit: Local address not yet configured!\n",
                               p->name);
                else if (!ipv6_addr_is_multicast(&p->raddr) &&
-                        unlikely(ipv6_chk_addr(&p->raddr, NULL, 0)))
+                        unlikely(ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
                        printk(KERN_WARNING
                               "%s xmit: Routing loop! "
                               "Remote address found on this node!\n",
index b66a1f81bd837103c640d8efe1bd5cd1b0f6bbec..e217d3ff00f3d9ed03bc748bcc9f82e56d4e4abb 100644 (file)
@@ -653,7 +653,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
        struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
        int probes = atomic_read(&neigh->probes);
 
-       if (skb && ipv6_chk_addr(&ipv6_hdr(skb)->saddr, dev, 1))
+       if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1))
                saddr = &ipv6_hdr(skb)->saddr;
 
        if ((probes -= neigh->parms->ucast_probes) < 0) {
index 45a580e843dcca7f295d206a86aa37a83eadb0b1..cb0b110a2ac8c2a85b153fbe7a5b254620f4310d 100644 (file)
@@ -298,7 +298,8 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                v4addr = LOOPBACK4_IPV6;
                if (!(addr_type & IPV6_ADDR_MULTICAST)) {
                        err = -EADDRNOTAVAIL;
-                       if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) {
+                       if (!ipv6_chk_addr(&init_net, &addr->sin6_addr,
+                                          dev, 0)) {
                                if (dev)
                                        dev_put(dev);
                                goto out;
index bd04aed673cb838cfdceb3d8483f7db3eafe2665..74f106a7a7e9d2fc0be78c2c6c46cd50400e4808 100644 (file)
@@ -556,7 +556,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
        if (!(type & IPV6_ADDR_UNICAST))
                return 0;
 
-       return ipv6_chk_addr(in6, NULL, 0);
+       return ipv6_chk_addr(&init_net, in6, NULL, 0);
 }
 
 /* This function checks if the address is a valid address to be used for
@@ -858,7 +858,8 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
                        dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
                        if (!dev)
                                return 0;
-                       if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
+                       if (!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
+                                          dev, 0)) {
                                dev_put(dev);
                                return 0;
                        }