aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c116
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)
227static 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
242static 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 */
270static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, 238static 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
285static 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
291static 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) */
300static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1, 251static 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 */
265static 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
274static 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
314static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, 284static 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 */
298static 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 */
329static int nfs_sockaddr_cmp(const struct sockaddr *sa1, 317static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
330 const struct sockaddr *sa2) 318 const struct sockaddr *sa2)