aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorHefty, Sean <sean.hefty@intel.com>2011-05-10 01:06:10 -0400
committerRoland Dreier <roland@purestorage.com>2011-05-10 01:06:10 -0400
commit43b752daae9445a3b2b075a236840d801fce1593 (patch)
tree0fb5fabb3bebcbc707a9b1ab6f4d53f5e7fe2cf3 /drivers/infiniband
parent693d92a1bbc9e42681c42ed190bd42b636ca876f (diff)
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: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/cma.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 5ed9d25d021a..eff5e46f005c 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -712,6 +712,21 @@ static inline int cma_any_addr(struct sockaddr *addr)
712 return cma_zero_addr(addr) || cma_loopback_addr(addr); 712 return cma_zero_addr(addr) || cma_loopback_addr(addr);
713} 713}
714 714
715static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst)
716{
717 if (src->sa_family != dst->sa_family)
718 return -1;
719
720 switch (src->sa_family) {
721 case AF_INET:
722 return ((struct sockaddr_in *) src)->sin_addr.s_addr !=
723 ((struct sockaddr_in *) dst)->sin_addr.s_addr;
724 default:
725 return ipv6_addr_cmp(&((struct sockaddr_in6 *) src)->sin6_addr,
726 &((struct sockaddr_in6 *) dst)->sin6_addr);
727 }
728}
729
715static inline __be16 cma_port(struct sockaddr *addr) 730static inline __be16 cma_port(struct sockaddr *addr)
716{ 731{
717 if (addr->sa_family == AF_INET) 732 if (addr->sa_family == AF_INET)
@@ -2168,13 +2183,13 @@ retry:
2168static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) 2183static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
2169{ 2184{
2170 struct rdma_id_private *cur_id; 2185 struct rdma_id_private *cur_id;
2171 struct sockaddr_in *sin, *cur_sin; 2186 struct sockaddr *addr, *cur_addr;
2172 struct rdma_bind_list *bind_list; 2187 struct rdma_bind_list *bind_list;
2173 struct hlist_node *node; 2188 struct hlist_node *node;
2174 unsigned short snum; 2189 unsigned short snum;
2175 2190
2176 sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; 2191 addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
2177 snum = ntohs(sin->sin_port); 2192 snum = ntohs(cma_port(addr));
2178 if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) 2193 if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
2179 return -EACCES; 2194 return -EACCES;
2180 2195
@@ -2186,15 +2201,15 @@ static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
2186 * We don't support binding to any address if anyone is bound to 2201 * We don't support binding to any address if anyone is bound to
2187 * a specific address on the same port. 2202 * a specific address on the same port.
2188 */ 2203 */
2189 if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) 2204 if (cma_any_addr(addr))
2190 return -EADDRNOTAVAIL; 2205 return -EADDRNOTAVAIL;
2191 2206
2192 hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { 2207 hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
2193 if (cma_any_addr((struct sockaddr *) &cur_id->id.route.addr.src_addr)) 2208 cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr;
2209 if (cma_any_addr(cur_addr))
2194 return -EADDRNOTAVAIL; 2210 return -EADDRNOTAVAIL;
2195 2211
2196 cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr; 2212 if (!cma_addr_cmp(addr, cur_addr))
2197 if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
2198 return -EADDRINUSE; 2213 return -EADDRINUSE;
2199 } 2214 }
2200 2215