diff options
author | Hefty, Sean <sean.hefty@intel.com> | 2011-05-10 01:06:10 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-05-10 01:06:10 -0400 |
commit | 43b752daae9445a3b2b075a236840d801fce1593 (patch) | |
tree | 0fb5fabb3bebcbc707a9b1ab6f4d53f5e7fe2cf3 /drivers/infiniband | |
parent | 693d92a1bbc9e42681c42ed190bd42b636ca876f (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.c | 29 |
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 | ||
715 | static 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 | |||
715 | static inline __be16 cma_port(struct sockaddr *addr) | 730 | static 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: | |||
2168 | static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) | 2183 | static 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 | ||