diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 1c3a5602990e..d1697b587a1a 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 d7b440343e97..f35c3df410df 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 ac8772dd968f..3150c4be3c0c 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 5c4190060e75..9c7f83fbc3a1 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 f49a06aa97de..94fa6ae77cfe 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 5395afe55ca5..cbb5b9cf84ad 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 29b5321e39c3..425c9ae8b315 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 b66a1f81bd83..e217d3ff00f3 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 45a580e843dc..cb0b110a2ac8 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 bd04aed673cb..74f106a7a7e9 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; }