extern int addrconf_set_dstaddr(void *arg);
extern int ipv6_chk_addr(struct in6_addr *addr,
- struct net_device *dev);
+ struct net_device *dev,
+ int strict);
extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
- struct net_device *dev);
+ struct net_device *dev,
+ int strict);
extern int ipv6_get_saddr(struct dst_entry *dst,
struct in6_addr *daddr,
struct in6_addr *saddr);
return cnt;
}
-int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev)
+int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
{
struct inet6_ifaddr * ifp;
u8 hash = ipv6_addr_hash(addr);
if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
!(ifp->flags&IFA_F_TENTATIVE)) {
if (dev == NULL || ifp->idev->dev == dev ||
- !(ifp->scope&(IFA_LINK|IFA_HOST)))
+ !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))
break;
}
}
return ifp != NULL;
}
-struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev)
+struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict)
{
struct inet6_ifaddr * ifp;
u8 hash = ipv6_addr_hash(addr);
for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
if (ipv6_addr_cmp(&ifp->addr, addr) == 0) {
if (dev == NULL || ifp->idev->dev == dev ||
- !(ifp->scope&(IFA_LINK|IFA_HOST))) {
+ !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
in6_ifa_hold(ifp);
break;
}
ok:
- ifp = ipv6_get_ifaddr(&addr, dev);
+ ifp = ipv6_get_ifaddr(&addr, dev, 1);
if (ifp == NULL && valid_lft) {
int max_addresses = in6_dev->cnf.max_addresses;
if (!ipv6_addr_any(&addr))
ipv6_dev_ac_dec(ifp->idev->dev, &addr);
}
- if (!ipv6_chk_addr(&ifp->addr, NULL))
+ if (!ipv6_chk_addr(&ifp->addr, ifp->idev->dev, 1))
ip6_rt_addr_del(&ifp->addr, ifp->idev->dev);
break;
}
*/
v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
- if (!ipv6_chk_addr(&addr->sin6_addr, dev)) {
+ if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) {
if (dev)
dev_put(dev);
err = -EADDRNOTAVAIL;
return -EPERM;
if (ipv6_addr_type(addr) & IPV6_ADDR_MULTICAST)
return -EINVAL;
- if (ipv6_chk_addr(addr, NULL))
+ if (ipv6_chk_addr(addr, NULL, 0))
return -EINVAL;
pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
return -ENODEV;
}
}
- if (!ipv6_chk_addr(&src_info->ipi6_addr, dev)) {
+ if (!ipv6_chk_addr(&src_info->ipi6_addr, dev, 0)) {
if (dev)
dev_put(dev);
err = -EINVAL;
*/
addr_type = ipv6_addr_type(&hdr->daddr);
- if (ipv6_chk_addr(&hdr->daddr, skb->dev))
+ if (ipv6_chk_addr(&hdr->daddr, skb->dev, 0))
saddr = &hdr->daddr;
/*
if (p->link)
ldev = dev_get_by_index(p->link);
- if ((ltype&IPV6_ADDR_UNICAST) && !ipv6_chk_addr(laddr, ldev))
+ if (ltype&IPV6_ADDR_UNICAST && !ipv6_chk_addr(laddr, ldev, 0))
l_ok = 0;
- if ((rtype&IPV6_ADDR_UNICAST) && ipv6_chk_addr(raddr, NULL))
+ if (rtype&IPV6_ADDR_UNICAST && ipv6_chk_addr(raddr, NULL, 0))
r_ok = 0;
if (l_ok && r_ok) {
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
/* for anycast or proxy, solicited_addr != src_addr */
- ifp = ipv6_get_ifaddr(solicited_addr, dev);
+ ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
if (ifp) {
src_addr = solicited_addr;
in6_ifa_put(ifp);
struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
int probes = atomic_read(&neigh->probes);
- if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev))
+ if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1))
saddr = &skb->nh.ipv6h->saddr;
if ((probes -= neigh->parms->ucast_probes) < 0) {
}
}
- if ((ifp = ipv6_get_ifaddr(&msg->target, dev)) != NULL) {
+ if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
if (ifp->flags & IFA_F_TENTATIVE) {
/* Address is tentative. If the source
is unspecified address, it is someone
return;
}
}
- if ((ifp = ipv6_get_ifaddr(&msg->target, dev))) {
+ if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1))) {
if (ifp->flags & IFA_F_TENTATIVE) {
addrconf_dad_failure(ifp);
return;
v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
err = -EADDRNOTAVAIL;
- if (!ipv6_chk_addr(&addr->sin6_addr, dev)) {
+ if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) {
if (dev)
dev_put(dev);
goto out;
if (!(type & IPV6_ADDR_UNICAST))
return 0;
- return ipv6_chk_addr(in6, NULL);
+ return ipv6_chk_addr(in6, NULL, 0);
}
/* This function checks if the address is a valid address to be used for