aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 701cd193a014..876162cddf1e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -34,6 +34,8 @@
34#include <linux/nfs_idmap.h> 34#include <linux/nfs_idmap.h>
35#include <linux/vfs.h> 35#include <linux/vfs.h>
36#include <linux/inet.h> 36#include <linux/inet.h>
37#include <linux/in6.h>
38#include <net/ipv6.h>
37#include <linux/nfs_xdr.h> 39#include <linux/nfs_xdr.h>
38 40
39#include <asm/system.h> 41#include <asm/system.h>
@@ -208,16 +210,44 @@ void nfs_put_client(struct nfs_client *clp)
208 } 210 }
209} 211}
210 212
213static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
214 const struct sockaddr_in *sa2)
215{
216 return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr;
217}
218
219static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1,
220 const struct sockaddr_in6 *sa2)
221{
222 return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr);
223}
224
225static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
226 const struct sockaddr *sa2)
227{
228 switch (sa1->sa_family) {
229 case AF_INET:
230 return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
231 (const struct sockaddr_in *)sa2);
232 case AF_INET6:
233 return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1,
234 (const struct sockaddr_in6 *)sa2);
235 }
236 BUG();
237}
238
211/* 239/*
212 * Find a client by IP address and protocol version 240 * Find a client by IP address and protocol version
213 * - returns NULL if no such client 241 * - returns NULL if no such client
214 */ 242 */
215struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion) 243struct nfs_client *_nfs_find_client(const struct sockaddr *addr, int nfsversion)
216{ 244{
217 struct nfs_client *clp; 245 struct nfs_client *clp;
218 246
219 spin_lock(&nfs_client_lock); 247 spin_lock(&nfs_client_lock);
220 list_for_each_entry(clp, &nfs_client_list, cl_share_link) { 248 list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
249 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
250
221 /* Don't match clients that failed to initialise properly */ 251 /* Don't match clients that failed to initialise properly */
222 if (clp->cl_cons_state != NFS_CS_READY) 252 if (clp->cl_cons_state != NFS_CS_READY)
223 continue; 253 continue;
@@ -226,8 +256,10 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio
226 if (clp->rpc_ops->version != nfsversion) 256 if (clp->rpc_ops->version != nfsversion)
227 continue; 257 continue;
228 258
259 if (addr->sa_family != clap->sa_family)
260 continue;
229 /* Match only the IP address, not the port number */ 261 /* Match only the IP address, not the port number */
230 if (clp->cl_addr.sin_addr.s_addr != addr->sin_addr.s_addr) 262 if (!nfs_sockaddr_match_ipaddr(addr, clap))
231 continue; 263 continue;
232 264
233 atomic_inc(&clp->cl_count); 265 atomic_inc(&clp->cl_count);
@@ -238,6 +270,11 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio
238 return NULL; 270 return NULL;
239} 271}
240 272
273struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
274{
275 return _nfs_find_client((const struct sockaddr *)addr, nfsversion);
276}
277
241/* 278/*
242 * Find an nfs_client on the list that matches the initialisation data 279 * Find an nfs_client on the list that matches the initialisation data
243 * that is supplied. 280 * that is supplied.