Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 406b6a25 authored by Sean Hefty's avatar Sean Hefty Committed by Roland Dreier
Browse files

RDMA/cma: Listen on specific address family



The rdma_cm maps IPv4 and IPv6 addresses to the same service ID.  This
prevents apps from listening only for IPv4 or IPv6 addresses.  It also
results in an app binding to an IPv4 address receiving connection
requests for an IPv6 address.

Change this to match socket behavior: restrict listens on IPv4
addresses to only IPv4 addresses, and if a listen is on an IPv6
address, allow it to receive either IPv4 or IPv6 addresses, based on
its address family binding.

Signed-off-by: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 5b0ec991
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -1298,9 +1298,11 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
		} else {
			cma_set_ip_ver(cma_data, 4);
			cma_set_ip_ver(cma_mask, 0xF);
			if (!cma_any_addr(addr)) {
				cma_data->dst_addr.ip4.addr = ip4_addr;
				cma_mask->dst_addr.ip4.addr = htonl(~0);
			}
		}
		break;
	case AF_INET6:
		ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
@@ -1313,10 +1315,12 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
		} else {
			cma_set_ip_ver(cma_data, 6);
			cma_set_ip_ver(cma_mask, 0xF);
			if (!cma_any_addr(addr)) {
				cma_data->dst_addr.ip6 = ip6_addr;
				memset(&cma_mask->dst_addr.ip6, 0xFF,
				       sizeof cma_mask->dst_addr.ip6);
			}
		}
		break;
	default:
		break;
@@ -1500,7 +1504,7 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)

	addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
	svc_id = cma_get_service_id(id_priv->id.ps, addr);
	if (cma_any_addr(addr))
	if (cma_any_addr(addr) && !id_priv->afonly)
		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
	else {
		cma_set_compare_data(id_priv->id.ps, addr, &compare_data);