diff options
-rw-r--r-- | fs/nfs/client.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index b643f0ec5c21..9b728f3565a1 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -223,31 +223,54 @@ void nfs_put_client(struct nfs_client *clp) | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, | 226 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
227 | const struct sockaddr_in *sa2) | 227 | static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped) |
228 | { | 228 | { |
229 | return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr; | 229 | switch (sa->sa_family) { |
230 | default: | ||
231 | return NULL; | ||
232 | case AF_INET6: | ||
233 | return &((const struct sockaddr_in6 *)sa)->sin6_addr; | ||
234 | break; | ||
235 | case AF_INET: | ||
236 | ipv6_addr_set_v4mapped(((const struct sockaddr_in *)sa)->sin_addr.s_addr, | ||
237 | addr_mapped); | ||
238 | return addr_mapped; | ||
239 | } | ||
230 | } | 240 | } |
231 | 241 | ||
232 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1, | 242 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, |
233 | const struct sockaddr_in6 *sa2) | 243 | const struct sockaddr *sa2) |
244 | { | ||
245 | const struct in6_addr *addr1; | ||
246 | const struct in6_addr *addr2; | ||
247 | struct in6_addr addr1_mapped; | ||
248 | struct in6_addr addr2_mapped; | ||
249 | |||
250 | addr1 = nfs_map_ipv4_addr(sa1, &addr1_mapped); | ||
251 | if (likely(addr1 != NULL)) { | ||
252 | addr2 = nfs_map_ipv4_addr(sa2, &addr2_mapped); | ||
253 | if (likely(addr2 != NULL)) | ||
254 | return ipv6_addr_equal(addr1, addr2); | ||
255 | } | ||
256 | return 0; | ||
257 | } | ||
258 | #else | ||
259 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, | ||
260 | const struct sockaddr_in *sa2) | ||
234 | { | 261 | { |
235 | return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr); | 262 | return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr; |
236 | } | 263 | } |
237 | 264 | ||
238 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | 265 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, |
239 | const struct sockaddr *sa2) | 266 | const struct sockaddr *sa2) |
240 | { | 267 | { |
241 | switch (sa1->sa_family) { | 268 | if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET)) |
242 | case AF_INET: | 269 | return 0; |
243 | return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, | 270 | return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, |
244 | (const struct sockaddr_in *)sa2); | 271 | (const struct sockaddr_in *)sa2); |
245 | case AF_INET6: | ||
246 | return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1, | ||
247 | (const struct sockaddr_in6 *)sa2); | ||
248 | } | ||
249 | BUG(); | ||
250 | } | 272 | } |
273 | #endif | ||
251 | 274 | ||
252 | /* | 275 | /* |
253 | * Find a client by IP address and protocol version | 276 | * Find a client by IP address and protocol version |
@@ -269,8 +292,6 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion) | |||
269 | if (clp->rpc_ops->version != nfsversion) | 292 | if (clp->rpc_ops->version != nfsversion) |
270 | continue; | 293 | continue; |
271 | 294 | ||
272 | if (addr->sa_family != clap->sa_family) | ||
273 | continue; | ||
274 | /* Match only the IP address, not the port number */ | 295 | /* Match only the IP address, not the port number */ |
275 | if (!nfs_sockaddr_match_ipaddr(addr, clap)) | 296 | if (!nfs_sockaddr_match_ipaddr(addr, clap)) |
276 | continue; | 297 | continue; |
@@ -304,8 +325,6 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp) | |||
304 | if (clp->rpc_ops->version != nfsvers) | 325 | if (clp->rpc_ops->version != nfsvers) |
305 | continue; | 326 | continue; |
306 | 327 | ||
307 | if (sap->sa_family != clap->sa_family) | ||
308 | continue; | ||
309 | /* Match only the IP address, not the port number */ | 328 | /* Match only the IP address, not the port number */ |
310 | if (!nfs_sockaddr_match_ipaddr(sap, clap)) | 329 | if (!nfs_sockaddr_match_ipaddr(sap, clap)) |
311 | continue; | 330 | continue; |