aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2012-06-14 16:31:39 -0400
committerRoland Dreier <roland@purestorage.com>2012-07-08 21:02:23 -0400
commit5b0ec991c0576c54db75803fbcb0ef5bebfa0828 (patch)
tree7d1abd89f59d77b596056df3c2c2bb97a113c301 /drivers/infiniband/core
parent6887a4131da3adaab011613776d865f4bcfb5678 (diff)
RDMA/cma: Bind to a specific address family
The RDMA CM uses a single port space for all associated (tcp, udp, etc.) port bindings, regardless of the address family that the user binds to. The result is that if a user binds to AF_INET, but does not specify an IP address, the bind will occur for AF_INET6. This causes an attempt to bind to the same port using AF_INET6 to fail, and connection requests to AF_INET6 will match with the AF_INET listener. Align the behavior with sockets and restrict the bind to AF_INET only. If a user binds to AF_INET6, we bind the port to AF_INET6 and AF_INET depending on the value of bindv6only. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r--drivers/infiniband/core/cma.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2e826f9702c6..c10c45a07162 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -140,6 +140,7 @@ struct rdma_id_private {
140 u8 srq; 140 u8 srq;
141 u8 tos; 141 u8 tos;
142 u8 reuseaddr; 142 u8 reuseaddr;
143 u8 afonly;
143}; 144};
144 145
145struct cma_multicast { 146struct cma_multicast {
@@ -1573,6 +1574,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
1573 list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); 1574 list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
1574 atomic_inc(&id_priv->refcount); 1575 atomic_inc(&id_priv->refcount);
1575 dev_id_priv->internal_id = 1; 1576 dev_id_priv->internal_id = 1;
1577 dev_id_priv->afonly = id_priv->afonly;
1576 1578
1577 ret = rdma_listen(id, id_priv->backlog); 1579 ret = rdma_listen(id, id_priv->backlog);
1578 if (ret) 1580 if (ret)
@@ -2187,22 +2189,24 @@ static int cma_check_port(struct rdma_bind_list *bind_list,
2187 struct hlist_node *node; 2189 struct hlist_node *node;
2188 2190
2189 addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; 2191 addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
2190 if (cma_any_addr(addr) && !reuseaddr)
2191 return -EADDRNOTAVAIL;
2192
2193 hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { 2192 hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
2194 if (id_priv == cur_id) 2193 if (id_priv == cur_id)
2195 continue; 2194 continue;
2196 2195
2197 if ((cur_id->state == RDMA_CM_LISTEN) || 2196 if ((cur_id->state != RDMA_CM_LISTEN) && reuseaddr &&
2198 !reuseaddr || !cur_id->reuseaddr) { 2197 cur_id->reuseaddr)
2199 cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr; 2198 continue;
2200 if (cma_any_addr(cur_addr))
2201 return -EADDRNOTAVAIL;
2202 2199
2203 if (!cma_addr_cmp(addr, cur_addr)) 2200 cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr;
2204 return -EADDRINUSE; 2201 if (id_priv->afonly && cur_id->afonly &&
2205 } 2202 (addr->sa_family != cur_addr->sa_family))
2203 continue;
2204
2205 if (cma_any_addr(addr) || cma_any_addr(cur_addr))
2206 return -EADDRNOTAVAIL;
2207
2208 if (!cma_addr_cmp(addr, cur_addr))
2209 return -EADDRINUSE;
2206 } 2210 }
2207 return 0; 2211 return 0;
2208} 2212}
@@ -2371,6 +2375,12 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2371 } 2375 }
2372 2376
2373 memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); 2377 memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
2378 if (addr->sa_family == AF_INET)
2379 id_priv->afonly = 1;
2380#if IS_ENABLED(CONFIG_IPV6)
2381 else if (addr->sa_family == AF_INET6)
2382 id_priv->afonly = init_net.ipv6.sysctl.bindv6only;
2383#endif
2374 ret = cma_get_port(id_priv); 2384 ret = cma_get_port(id_priv);
2375 if (ret) 2385 if (ret)
2376 goto err2; 2386 goto err2;