Skip to content

Commit

Permalink
nfsd: fix IPv6 address handling in the DRC
Browse files Browse the repository at this point in the history
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: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
  • Loading branch information
Jeff Layton authored and J. Bruce Fields committed Feb 4, 2013
1 parent 885c91f commit 7b9e852
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 4 deletions.
6 changes: 5 additions & 1 deletion fs/nfsd/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

/*
* 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 hlist_node c_hash;
Expand All @@ -20,7 +24,7 @@ struct svc_cacherep {
unsigned char c_state, /* unused, inprog, done */
c_type, /* status, buffer */
c_secure : 1; /* req came from port < 1024 */
struct sockaddr_in c_addr;
struct sockaddr_in6 c_addr;
__be32 c_xid;
u32 c_prot;
u32 c_proc;
Expand Down
7 changes: 5 additions & 2 deletions fs/nfsd/nfscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

#include <linux/slab.h>
#include <linux/sunrpc/clnt.h>

#include "nfsd.h"
#include "cache.h"
Expand Down Expand Up @@ -146,7 +147,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
xid == rp->c_xid && proc == rp->c_proc &&
proto == rp->c_prot && vers == rp->c_vers &&
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++;
goto found_entry;
}
Expand Down Expand Up @@ -183,7 +185,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
rp->c_state = RC_INPROG;
rp->c_xid = xid;
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_vers = vers;
rp->c_timestamp = jiffies;
Expand Down
4 changes: 3 additions & 1 deletion include/linux/sunrpc/clnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@ static inline bool __rpc_copy_addr6(struct sockaddr *dst,
* @sap1: first 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.
*/
static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
Expand Down

0 comments on commit 7b9e852

Please sign in to comment.