Commit 7b9e8522 authored by Jeff Layton's avatar Jeff Layton Committed by J. Bruce Fields

nfsd: fix IPv6 address handling in the DRC

Currently, it only stores the first 16 bytes of any address. struct
sockaddr_in6 is 28 bytes however, so we're currently ignoring the last
12 bytes of the address.

Expand the c_addr field to a sockaddr_in6, and cast it to a sockaddr_in
as necessary. Also fix the comparitor to use the existing RPC
helpers for this.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 885c91f7
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
/* /*
* Representation of a reply cache entry. * Representation of a reply cache entry.
*
* Note that we use a sockaddr_in6 to hold the address instead of the more
* typical sockaddr_storage. This is for space reasons, since sockaddr_storage
* is much larger than a sockaddr_in6.
*/ */
struct svc_cacherep { struct svc_cacherep {
struct hlist_node c_hash; struct hlist_node c_hash;
...@@ -20,7 +24,7 @@ struct svc_cacherep { ...@@ -20,7 +24,7 @@ struct svc_cacherep {
unsigned char c_state, /* unused, inprog, done */ unsigned char c_state, /* unused, inprog, done */
c_type, /* status, buffer */ c_type, /* status, buffer */
c_secure : 1; /* req came from port < 1024 */ c_secure : 1; /* req came from port < 1024 */
struct sockaddr_in c_addr; struct sockaddr_in6 c_addr;
__be32 c_xid; __be32 c_xid;
u32 c_prot; u32 c_prot;
u32 c_proc; u32 c_proc;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sunrpc/clnt.h>
#include "nfsd.h" #include "nfsd.h"
#include "cache.h" #include "cache.h"
...@@ -146,7 +147,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) ...@@ -146,7 +147,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
xid == rp->c_xid && proc == rp->c_proc && xid == rp->c_xid && proc == rp->c_proc &&
proto == rp->c_prot && vers == rp->c_vers && proto == rp->c_prot && vers == rp->c_vers &&
time_before(jiffies, rp->c_timestamp + 120*HZ) && time_before(jiffies, rp->c_timestamp + 120*HZ) &&
memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, sizeof(rp->c_addr))==0) { rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) &&
rpc_get_port(svc_addr(rqstp)) == rpc_get_port((struct sockaddr *)&rp->c_addr)) {
nfsdstats.rchits++; nfsdstats.rchits++;
goto found_entry; goto found_entry;
} }
...@@ -183,7 +185,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) ...@@ -183,7 +185,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
rp->c_state = RC_INPROG; rp->c_state = RC_INPROG;
rp->c_xid = xid; rp->c_xid = xid;
rp->c_proc = proc; rp->c_proc = proc;
memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr)); rpc_copy_addr((struct sockaddr *)&rp->c_addr, svc_addr(rqstp));
rpc_set_port((struct sockaddr *)&rp->c_addr, rpc_get_port(svc_addr(rqstp)));
rp->c_prot = proto; rp->c_prot = proto;
rp->c_vers = vers; rp->c_vers = vers;
rp->c_timestamp = jiffies; rp->c_timestamp = jiffies;
......
...@@ -263,7 +263,9 @@ static inline bool __rpc_copy_addr6(struct sockaddr *dst, ...@@ -263,7 +263,9 @@ static inline bool __rpc_copy_addr6(struct sockaddr *dst,
* @sap1: first sockaddr * @sap1: first sockaddr
* @sap2: second sockaddr * @sap2: second sockaddr
* *
* Just compares the family and address portion. Ignores port, scope, etc. * Just compares the family and address portion. Ignores port, but
* compares the scope if it's a link-local address.
*
* Returns true if the addrs are equal, false if they aren't. * Returns true if the addrs are equal, false if they aren't.
*/ */
static inline bool rpc_cmp_addr(const struct sockaddr *sap1, static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment