diff options
Diffstat (limited to 'fs/nfs/client.c')
| -rw-r--r-- | fs/nfs/client.c | 116 |
1 files changed, 52 insertions, 64 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 574158ae2398..855daac0f246 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -224,38 +224,6 @@ void nfs_put_client(struct nfs_client *clp) | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 226 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 227 | static const struct in6_addr *nfs_map_ipv4_addr(const struct sockaddr *sa, struct in6_addr *addr_mapped) | ||
| 228 | { | ||
| 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 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | ||
| 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 | |||
| 259 | /* | 227 | /* |
| 260 | * Test if two ip6 socket addresses refer to the same socket by | 228 | * Test if two ip6 socket addresses refer to the same socket by |
| 261 | * comparing relevant fields. The padding bytes specifically, are not | 229 | * comparing relevant fields. The padding bytes specifically, are not |
| @@ -267,38 +235,21 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | |||
| 267 | * | 235 | * |
| 268 | * The caller should ensure both socket addresses are AF_INET6. | 236 | * The caller should ensure both socket addresses are AF_INET6. |
| 269 | */ | 237 | */ |
| 270 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, | 238 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
| 271 | const struct sockaddr *sa2) | 239 | const struct sockaddr *sa2) |
| 272 | { | 240 | { |
| 273 | const struct sockaddr_in6 *saddr1 = (const struct sockaddr_in6 *)sa1; | 241 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; |
| 274 | const struct sockaddr_in6 *saddr2 = (const struct sockaddr_in6 *)sa2; | 242 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; |
| 275 | 243 | ||
| 276 | if (!ipv6_addr_equal(&saddr1->sin6_addr, | 244 | if (ipv6_addr_scope(&sin1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && |
| 277 | &saddr1->sin6_addr)) | 245 | sin1->sin6_scope_id != sin2->sin6_scope_id) |
| 278 | return 0; | 246 | return 0; |
| 279 | if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && | ||
| 280 | saddr1->sin6_scope_id != saddr2->sin6_scope_id) | ||
| 281 | return 0; | ||
| 282 | return saddr1->sin6_port == saddr2->sin6_port; | ||
| 283 | } | ||
| 284 | #else | ||
| 285 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, | ||
| 286 | const struct sockaddr_in *sa2) | ||
| 287 | { | ||
| 288 | return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr; | ||
| 289 | } | ||
| 290 | 247 | ||
| 291 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | 248 | return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); |
| 292 | const struct sockaddr *sa2) | ||
| 293 | { | ||
| 294 | if (unlikely(sa1->sa_family != AF_INET || sa2->sa_family != AF_INET)) | ||
| 295 | return 0; | ||
| 296 | return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, | ||
| 297 | (const struct sockaddr_in *)sa2); | ||
| 298 | } | 249 | } |
| 299 | 250 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | |
| 300 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1, | 251 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
| 301 | const struct sockaddr * sa2) | 252 | const struct sockaddr *sa2) |
| 302 | { | 253 | { |
| 303 | return 0; | 254 | return 0; |
| 304 | } | 255 | } |
| @@ -311,20 +262,57 @@ static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1, | |||
| 311 | * | 262 | * |
| 312 | * The caller should ensure both socket addresses are AF_INET. | 263 | * The caller should ensure both socket addresses are AF_INET. |
| 313 | */ | 264 | */ |
| 265 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1, | ||
| 266 | const struct sockaddr *sa2) | ||
| 267 | { | ||
| 268 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; | ||
| 269 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; | ||
| 270 | |||
| 271 | return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, | ||
| 275 | const struct sockaddr *sa2) | ||
| 276 | { | ||
| 277 | const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1; | ||
| 278 | const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2; | ||
| 279 | |||
| 280 | return nfs_sockaddr_match_ipaddr6(sa1, sa2) && | ||
| 281 | (sin1->sin6_port == sin2->sin6_port); | ||
| 282 | } | ||
| 283 | |||
| 314 | static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, | 284 | static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, |
| 315 | const struct sockaddr *sa2) | 285 | const struct sockaddr *sa2) |
| 316 | { | 286 | { |
| 317 | const struct sockaddr_in *saddr1 = (const struct sockaddr_in *)sa1; | 287 | const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; |
| 318 | const struct sockaddr_in *saddr2 = (const struct sockaddr_in *)sa2; | 288 | const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; |
| 319 | 289 | ||
| 320 | if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr) | 290 | return nfs_sockaddr_match_ipaddr4(sa1, sa2) && |
| 291 | (sin1->sin_port == sin2->sin_port); | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * Test if two socket addresses represent the same actual socket, | ||
| 296 | * by comparing (only) relevant fields, excluding the port number. | ||
| 297 | */ | ||
| 298 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | ||
| 299 | const struct sockaddr *sa2) | ||
| 300 | { | ||
| 301 | if (sa1->sa_family != sa2->sa_family) | ||
| 321 | return 0; | 302 | return 0; |
| 322 | return saddr1->sin_port == saddr2->sin_port; | 303 | |
| 304 | switch (sa1->sa_family) { | ||
| 305 | case AF_INET: | ||
| 306 | return nfs_sockaddr_match_ipaddr4(sa1, sa2); | ||
| 307 | case AF_INET6: | ||
| 308 | return nfs_sockaddr_match_ipaddr6(sa1, sa2); | ||
| 309 | } | ||
| 310 | return 0; | ||
| 323 | } | 311 | } |
| 324 | 312 | ||
| 325 | /* | 313 | /* |
| 326 | * Test if two socket addresses represent the same actual socket, | 314 | * Test if two socket addresses represent the same actual socket, |
| 327 | * by comparing (only) relevant fields. | 315 | * by comparing (only) relevant fields, including the port number. |
| 328 | */ | 316 | */ |
| 329 | static int nfs_sockaddr_cmp(const struct sockaddr *sa1, | 317 | static int nfs_sockaddr_cmp(const struct sockaddr *sa1, |
| 330 | const struct sockaddr *sa2) | 318 | const struct sockaddr *sa2) |
