Commit bfeade08 authored by Daniel Lezcano's avatar Daniel Lezcano Committed by David S. Miller

[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: default avatarDaniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: default avatarBenjamin Thery <benjamin.thery@bull.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3c40090a
...@@ -59,9 +59,11 @@ extern int addrconf_add_ifaddr(void __user *arg); ...@@ -59,9 +59,11 @@ extern int addrconf_add_ifaddr(void __user *arg);
extern int addrconf_del_ifaddr(void __user *arg); extern int addrconf_del_ifaddr(void __user *arg);
extern int addrconf_set_dstaddr(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, struct net_device *dev,
int strict); int strict);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
extern int ipv6_chk_home_addr(struct in6_addr *addr); extern int ipv6_chk_home_addr(struct in6_addr *addr);
#endif #endif
......
...@@ -1206,13 +1206,16 @@ static int ipv6_count_addresses(struct inet6_dev *idev) ...@@ -1206,13 +1206,16 @@ static int ipv6_count_addresses(struct inet6_dev *idev)
return cnt; 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; struct inet6_ifaddr * ifp;
u8 hash = ipv6_addr_hash(addr); u8 hash = ipv6_addr_hash(addr);
read_lock_bh(&addrconf_hash_lock); read_lock_bh(&addrconf_hash_lock);
for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { 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 (ipv6_addr_equal(&ifp->addr, addr) &&
!(ifp->flags&IFA_F_TENTATIVE)) { !(ifp->flags&IFA_F_TENTATIVE)) {
if (dev == NULL || ifp->idev->dev == dev || 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) ...@@ -1223,7 +1226,6 @@ int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
read_unlock_bh(&addrconf_hash_lock); read_unlock_bh(&addrconf_hash_lock);
return ifp != NULL; return ifp != NULL;
} }
EXPORT_SYMBOL(ipv6_chk_addr); EXPORT_SYMBOL(ipv6_chk_addr);
static static
......
...@@ -314,7 +314,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -314,7 +314,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
*/ */
v4addr = LOOPBACK4_IPV6; v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) { 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) if (dev)
dev_put(dev); dev_put(dev);
err = -EADDRNOTAVAIL; err = -EADDRNOTAVAIL;
......
...@@ -89,7 +89,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) ...@@ -89,7 +89,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
return -EPERM; return -EPERM;
if (ipv6_addr_is_multicast(addr)) if (ipv6_addr_is_multicast(addr))
return -EINVAL; return -EINVAL;
if (ipv6_chk_addr(addr, NULL, 0)) if (ipv6_chk_addr(&init_net, addr, NULL, 0))
return -EINVAL; return -EINVAL;
pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
......
...@@ -549,7 +549,8 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, ...@@ -549,7 +549,8 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
return -ENODEV; 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) if (dev)
dev_put(dev); dev_put(dev);
err = -EINVAL; err = -EINVAL;
......
...@@ -332,7 +332,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -332,7 +332,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
*/ */
addr_type = ipv6_addr_type(&hdr->daddr); 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; saddr = &hdr->daddr;
/* /*
......
...@@ -653,8 +653,8 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) ...@@ -653,8 +653,8 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t)
ldev = dev_get_by_index(&init_net, p->link); ldev = dev_get_by_index(&init_net, p->link);
if ((ipv6_addr_is_multicast(&p->laddr) || if ((ipv6_addr_is_multicast(&p->laddr) ||
likely(ipv6_chk_addr(&p->laddr, ldev, 0))) && likely(ipv6_chk_addr(&init_net, &p->laddr, ldev, 0))) &&
likely(!ipv6_chk_addr(&p->raddr, NULL, 0))) likely(!ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
ret = 1; ret = 1;
if (ldev) if (ldev)
...@@ -788,12 +788,12 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) ...@@ -788,12 +788,12 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
if (p->link) if (p->link)
ldev = dev_get_by_index(&init_net, 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 printk(KERN_WARNING
"%s xmit: Local address not yet configured!\n", "%s xmit: Local address not yet configured!\n",
p->name); p->name);
else if (!ipv6_addr_is_multicast(&p->raddr) && 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 printk(KERN_WARNING
"%s xmit: Routing loop! " "%s xmit: Routing loop! "
"Remote address found on this node!\n", "Remote address found on this node!\n",
......
...@@ -653,7 +653,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) ...@@ -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; struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
int probes = atomic_read(&neigh->probes); 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; saddr = &ipv6_hdr(skb)->saddr;
if ((probes -= neigh->parms->ucast_probes) < 0) { if ((probes -= neigh->parms->ucast_probes) < 0) {
......
...@@ -298,7 +298,8 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -298,7 +298,8 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
v4addr = LOOPBACK4_IPV6; v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) { if (!(addr_type & IPV6_ADDR_MULTICAST)) {
err = -EADDRNOTAVAIL; err = -EADDRNOTAVAIL;
if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) { if (!ipv6_chk_addr(&init_net, &addr->sin6_addr,
dev, 0)) {
if (dev) if (dev)
dev_put(dev); dev_put(dev);
goto out; goto out;
......
...@@ -556,7 +556,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) ...@@ -556,7 +556,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
if (!(type & IPV6_ADDR_UNICAST)) if (!(type & IPV6_ADDR_UNICAST))
return 0; 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 /* 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) ...@@ -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); dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
if (!dev) if (!dev)
return 0; 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); dev_put(dev);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment