ibcore: ip6_dev_find() needs to know the scope ID.
Else the wrong network device can be returned for link-local addresses. Submitted by: hselasky@ Approved by: hselasky (mentor) MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
ed5f1f49e7
commit
5413daa1a0
@ -59,37 +59,32 @@ ip_dev_find(struct vnet *vnet, uint32_t addr)
|
||||
}
|
||||
|
||||
static inline struct net_device *
|
||||
ip6_dev_find(struct vnet *vnet, struct in6_addr addr)
|
||||
ip6_dev_find(struct vnet *vnet, struct in6_addr addr, uint16_t scope_id)
|
||||
{
|
||||
struct sockaddr_in6 sin6;
|
||||
struct ifaddr *ifa = NULL;
|
||||
struct ifnet *ifp = NULL;
|
||||
int x;
|
||||
struct ifaddr *ifa;
|
||||
struct ifnet *ifp;
|
||||
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_addr = addr;
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
NET_EPOCH_ENTER();
|
||||
CURVNET_SET_QUIET(vnet);
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(&addr) ||
|
||||
IN6_IS_ADDR_MC_INTFACELOCAL(&addr)) {
|
||||
/* XXX need to search all scope ID's */
|
||||
for (x = 0; x <= V_if_index && x < 65536; x++) {
|
||||
sin6.sin6_addr.s6_addr16[1] = htons(x);
|
||||
ifa = ifa_ifwithaddr((struct sockaddr *)&sin6);
|
||||
if (ifa != NULL)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ifa = ifa_ifwithaddr((struct sockaddr *)&sin6);
|
||||
/* embed the IPv6 scope ID */
|
||||
sin6.sin6_addr.s6_addr16[1] = htons(scope_id);
|
||||
}
|
||||
NET_EPOCH_ENTER();
|
||||
CURVNET_SET_QUIET(vnet);
|
||||
ifa = ifa_ifwithaddr((struct sockaddr *)&sin6);
|
||||
CURVNET_RESTORE();
|
||||
if (ifa != NULL) {
|
||||
ifp = ifa->ifa_ifp;
|
||||
if_ref(ifp);
|
||||
} else {
|
||||
ifp = NULL;
|
||||
}
|
||||
NET_EPOCH_EXIT();
|
||||
CURVNET_RESTORE();
|
||||
return (ifp);
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ int rdma_translate_ip(const struct sockaddr *addr,
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
dev = ip6_dev_find(dev_addr->net,
|
||||
((const struct sockaddr_in6 *)addr)->sin6_addr);
|
||||
((const struct sockaddr_in6 *)addr)->sin6_addr, 0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@ -525,7 +525,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
|
||||
if (addr->bound_dev_if != 0) {
|
||||
ifp = dev_get_by_index(addr->net, addr->bound_dev_if);
|
||||
} else {
|
||||
ifp = ip6_dev_find(addr->net, src_in->sin6_addr);
|
||||
ifp = ip6_dev_find(addr->net, src_in->sin6_addr, 0);
|
||||
}
|
||||
|
||||
/* check source interface */
|
||||
|
@ -1329,7 +1329,8 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
|
||||
struct rtentry *rte;
|
||||
bool ret;
|
||||
|
||||
dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr);
|
||||
dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr,
|
||||
net_dev->if_index);
|
||||
if (dst_dev != net_dev) {
|
||||
if (dst_dev != NULL)
|
||||
dev_put(dst_dev);
|
||||
|
Loading…
Reference in New Issue
Block a user