aboutsummaryrefslogtreecommitdiff
path: root/sys/ofed/drivers/infiniband/core/ib_cma.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ofed/drivers/infiniband/core/ib_cma.c')
-rw-r--r--sys/ofed/drivers/infiniband/core/ib_cma.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/sys/ofed/drivers/infiniband/core/ib_cma.c b/sys/ofed/drivers/infiniband/core/ib_cma.c
index 4a45efc5852e..51e74a451967 100644
--- a/sys/ofed/drivers/infiniband/core/ib_cma.c
+++ b/sys/ofed/drivers/infiniband/core/ib_cma.c
@@ -1292,6 +1292,12 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,
dev_put(dst_dev);
/*
+ * Check for loopback.
+ */
+ if (saddr == daddr)
+ return true;
+
+ /*
* Make sure the socket address length field
* is set, else rtalloc1() will fail.
*/
@@ -1318,12 +1324,12 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
{
#ifdef INET6
struct sockaddr_in6 src_tmp = *src_addr;
- struct in6_addr in6_addr = dst_addr->sin6_addr;
+ struct sockaddr_in6 dst_tmp = *dst_addr;
struct net_device *dst_dev;
struct rtentry *rte;
bool ret;
- dst_dev = ip6_dev_find(net_dev->if_vnet, in6_addr);
+ dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr);
if (dst_dev != net_dev) {
if (dst_dev != NULL)
dev_put(dst_dev);
@@ -1345,12 +1351,25 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
src_tmp.sin6_scope_id = net_dev->if_index;
sa6_embedscope(&src_tmp, 0);
- rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0);
- if (rte != NULL) {
- ret = (rte->rt_ifp == net_dev);
- RTFREE_LOCKED(rte);
+ dst_tmp.sin6_scope_id = net_dev->if_index;
+ sa6_embedscope(&dst_tmp, 0);
+
+ /*
+ * Check for loopback after scope ID
+ * has been embedded:
+ */
+ if (memcmp(&src_tmp.sin6_addr, &dst_tmp.sin6_addr,
+ sizeof(dst_tmp.sin6_addr)) == 0) {
+ ret = true;
} else {
- ret = false;
+ /* non-loopback case */
+ rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0);
+ if (rte != NULL) {
+ ret = (rte->rt_ifp == net_dev);
+ RTFREE_LOCKED(rte);
+ } else {
+ ret = false;
+ }
}
CURVNET_RESTORE();
return ret;