Commit 43b752da authored by Hefty, Sean's avatar Hefty, Sean Committed by Roland Dreier

RDMA/cma: Fix handling of IPv6 addressing in cma_use_port

cma_use_port() assumes that the sockaddr is an IPv4 address.  Since
IPv6 addressing is supported (and also to support other address
families) make the code more generic in its address handling.
Signed-off-by: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 693d92a1
...@@ -712,6 +712,21 @@ static inline int cma_any_addr(struct sockaddr *addr) ...@@ -712,6 +712,21 @@ static inline int cma_any_addr(struct sockaddr *addr)
return cma_zero_addr(addr) || cma_loopback_addr(addr); return cma_zero_addr(addr) || cma_loopback_addr(addr);
} }
static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst)
{
if (src->sa_family != dst->sa_family)
return -1;
switch (src->sa_family) {
case AF_INET:
return ((struct sockaddr_in *) src)->sin_addr.s_addr !=
((struct sockaddr_in *) dst)->sin_addr.s_addr;
default:
return ipv6_addr_cmp(&((struct sockaddr_in6 *) src)->sin6_addr,
&((struct sockaddr_in6 *) dst)->sin6_addr);
}
}
static inline __be16 cma_port(struct sockaddr *addr) static inline __be16 cma_port(struct sockaddr *addr)
{ {
if (addr->sa_family == AF_INET) if (addr->sa_family == AF_INET)
...@@ -2168,13 +2183,13 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) ...@@ -2168,13 +2183,13 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
{ {
struct rdma_id_private *cur_id; struct rdma_id_private *cur_id;
struct sockaddr_in *sin, *cur_sin; struct sockaddr *addr, *cur_addr;
struct rdma_bind_list *bind_list; struct rdma_bind_list *bind_list;
struct hlist_node *node; struct hlist_node *node;
unsigned short snum; unsigned short snum;
sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
snum = ntohs(sin->sin_port); snum = ntohs(cma_port(addr));
if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
return -EACCES; return -EACCES;
...@@ -2186,15 +2201,15 @@ static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) ...@@ -2186,15 +2201,15 @@ static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
* We don't support binding to any address if anyone is bound to * We don't support binding to any address if anyone is bound to
* a specific address on the same port. * a specific address on the same port.
*/ */
if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) if (cma_any_addr(addr))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
if (cma_any_addr((struct sockaddr *) &cur_id->id.route.addr.src_addr)) cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr;
if (cma_any_addr(cur_addr))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr; if (!cma_addr_cmp(addr, cur_addr))
if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
return -EADDRINUSE; return -EADDRINUSE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment