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: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Родитель
885c91f746
Коммит
7b9e8522a6
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
|
||||
#include "nfsd.h"
|
||||
#include "cache.h"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче