aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c113
-rw-r--r--fs/nfs/internal.h4
-rw-r--r--fs/nfs/nfs4client.c5
3 files changed, 3 insertions, 119 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 4a90c9bb3135..57c5a02f6213 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -20,6 +20,7 @@
20#include <linux/stat.h> 20#include <linux/stat.h>
21#include <linux/errno.h> 21#include <linux/errno.h>
22#include <linux/unistd.h> 22#include <linux/unistd.h>
23#include <linux/sunrpc/addr.h>
23#include <linux/sunrpc/clnt.h> 24#include <linux/sunrpc/clnt.h>
24#include <linux/sunrpc/stats.h> 25#include <linux/sunrpc/stats.h>
25#include <linux/sunrpc/metrics.h> 26#include <linux/sunrpc/metrics.h>
@@ -285,116 +286,6 @@ void nfs_put_client(struct nfs_client *clp)
285} 286}
286EXPORT_SYMBOL_GPL(nfs_put_client); 287EXPORT_SYMBOL_GPL(nfs_put_client);
287 288
288#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
289/*
290 * Test if two ip6 socket addresses refer to the same socket by
291 * comparing relevant fields. The padding bytes specifically, are not
292 * compared. sin6_flowinfo is not compared because it only affects QoS
293 * and sin6_scope_id is only compared if the address is "link local"
294 * because "link local" addresses need only be unique to a specific
295 * link. Conversely, ordinary unicast addresses might have different
296 * sin6_scope_id.
297 *
298 * The caller should ensure both socket addresses are AF_INET6.
299 */
300static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
301 const struct sockaddr *sa2)
302{
303 const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
304 const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
305
306 if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
307 return 0;
308 else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL)
309 return sin1->sin6_scope_id == sin2->sin6_scope_id;
310
311 return 1;
312}
313#else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */
314static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
315 const struct sockaddr *sa2)
316{
317 return 0;
318}
319#endif
320
321/*
322 * Test if two ip4 socket addresses refer to the same socket, by
323 * comparing relevant fields. The padding bytes specifically, are
324 * not compared.
325 *
326 * The caller should ensure both socket addresses are AF_INET.
327 */
328static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1,
329 const struct sockaddr *sa2)
330{
331 const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
332 const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
333
334 return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
335}
336
337static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
338 const struct sockaddr *sa2)
339{
340 const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
341 const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
342
343 return nfs_sockaddr_match_ipaddr6(sa1, sa2) &&
344 (sin1->sin6_port == sin2->sin6_port);
345}
346
347static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
348 const struct sockaddr *sa2)
349{
350 const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
351 const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
352
353 return nfs_sockaddr_match_ipaddr4(sa1, sa2) &&
354 (sin1->sin_port == sin2->sin_port);
355}
356
357#if defined(CONFIG_NFS_V4_1)
358/*
359 * Test if two socket addresses represent the same actual socket,
360 * by comparing (only) relevant fields, excluding the port number.
361 */
362int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
363 const struct sockaddr *sa2)
364{
365 if (sa1->sa_family != sa2->sa_family)
366 return 0;
367
368 switch (sa1->sa_family) {
369 case AF_INET:
370 return nfs_sockaddr_match_ipaddr4(sa1, sa2);
371 case AF_INET6:
372 return nfs_sockaddr_match_ipaddr6(sa1, sa2);
373 }
374 return 0;
375}
376EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr);
377#endif /* CONFIG_NFS_V4_1 */
378
379/*
380 * Test if two socket addresses represent the same actual socket,
381 * by comparing (only) relevant fields, including the port number.
382 */
383static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
384 const struct sockaddr *sa2)
385{
386 if (sa1->sa_family != sa2->sa_family)
387 return 0;
388
389 switch (sa1->sa_family) {
390 case AF_INET:
391 return nfs_sockaddr_cmp_ip4(sa1, sa2);
392 case AF_INET6:
393 return nfs_sockaddr_cmp_ip6(sa1, sa2);
394 }
395 return 0;
396}
397
398/* 289/*
399 * Find an nfs_client on the list that matches the initialisation data 290 * Find an nfs_client on the list that matches the initialisation data
400 * that is supplied. 291 * that is supplied.
@@ -421,7 +312,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
421 if (clp->cl_minorversion != data->minorversion) 312 if (clp->cl_minorversion != data->minorversion)
422 continue; 313 continue;
423 /* Match the full socket address */ 314 /* Match the full socket address */
424 if (!nfs_sockaddr_cmp(sap, clap)) 315 if (!rpc_cmp_addr_port(sap, clap))
425 continue; 316 continue;
426 317
427 atomic_inc(&clp->cl_count); 318 atomic_inc(&clp->cl_count);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 1dad18105ed0..9ab3b1c21bb4 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -219,10 +219,6 @@ static inline void nfs_fs_proc_exit(void)
219} 219}
220#endif 220#endif
221 221
222#ifdef CONFIG_NFS_V4_1
223int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *);
224#endif
225
226/* callback_xdr.c */ 222/* callback_xdr.c */
227extern struct svc_version nfs4_callback_version1; 223extern struct svc_version nfs4_callback_version1;
228extern struct svc_version nfs4_callback_version4; 224extern struct svc_version nfs4_callback_version4;
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 3aa6a9ba5113..223bedda64ae 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -729,10 +729,7 @@ static bool nfs4_cb_match_client(const struct sockaddr *addr,
729 return false; 729 return false;
730 730
731 /* Match only the IP address, not the port number */ 731 /* Match only the IP address, not the port number */
732 if (!nfs_sockaddr_match_ipaddr(addr, clap)) 732 return rpc_cmp_addr(addr, clap);
733 return false;
734
735 return true;
736} 733}
737 734
738/* 735/*