summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano <dlezcano@fr.ibm.com>2008-01-10 22:43:18 -0800
committerDavid S. Miller <davem@davemloft.net>2008-01-28 15:01:44 -0800
commitbfeade087005278fc8cafe230b7658a4f40c5acb (patch)
treed9bbacab07552cc6c33f9f022a34af2391d9ecc1
parent3c40090a0f5b69deecc5ca615f994957f949333d (diff)
downloadlinux-3.10-bfeade087005278fc8cafe230b7658a4f40c5acb.tar.gz
linux-3.10-bfeade087005278fc8cafe230b7658a4f40c5acb.tar.bz2
linux-3.10-bfeade087005278fc8cafe230b7658a4f40c5acb.zip
[NETNS][IPV6]: inet6_addr - check ipv6 address per namespace
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>
-rw-r--r--include/net/addrconf.h4
-rw-r--r--net/ipv6/addrconf.c6
-rw-r--r--net/ipv6/af_inet6.c3
-rw-r--r--net/ipv6/anycast.c2
-rw-r--r--net/ipv6/datagram.c3
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ip6_tunnel.c8
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/sctp/ipv6.c5
10 files changed, 23 insertions, 15 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 1c3a5602990..d1697b587a1 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -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
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d7b440343e9..f35c3df410d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -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
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ac8772dd968..3150c4be3c0 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -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;
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 5c4190060e7..9c7f83fbc3a 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -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);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index f49a06aa97d..94fa6ae77cf 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -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;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 5395afe55ca..cbb5b9cf84a 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -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;
/*
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 29b5321e39c..425c9ae8b31 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -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",
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index b66a1f81bd8..e217d3ff00f 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -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) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 45a580e843d..cb0b110a2ac 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -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;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index bd04aed673c..74f106a7a7e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -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;
}