diff options
| author | Jeff Layton <jlayton@redhat.com> | 2009-08-14 12:57:59 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-08-21 11:27:44 -0400 |
| commit | fbf4665f41b02e757ab9d9198df65e319388e728 (patch) | |
| tree | ec0b8b4f3809ee38088504bf51440ee12f501085 | |
| parent | 7077ecbabd626cce1fcf5cc9766c83ec04d919f9 (diff) | |
nfsd: populate sin6_scope_id on callback address with scopeid from rq_addr on SETCLIENTID call
When a SETCLIENTID call comes in, one of the args given is the svc_rqst.
This struct contains an rq_addr field which holds the address that sent
the call. If this is an IPv6 address, then we can use the sin6_scope_id
field in this address to populate the sin6_scope_id field in the
callback address.
AFAICT, the rq_addr.sin6_scope_id is non-zero if and only if the client
mounted the server's link-local address.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
| -rw-r--r-- | fs/nfsd/nfs4state.c | 7 | ||||
| -rw-r--r-- | include/linux/sunrpc/clnt.h | 15 |
2 files changed, 20 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9ec0ca1ef4ea..d2a052480908 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -898,7 +898,7 @@ find_unconfirmed_client_by_str(const char *dname, unsigned int hashval, | |||
| 898 | } | 898 | } |
| 899 | 899 | ||
| 900 | static void | 900 | static void |
| 901 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) | 901 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) |
| 902 | { | 902 | { |
| 903 | struct nfs4_cb_conn *cb = &clp->cl_cb_conn; | 903 | struct nfs4_cb_conn *cb = &clp->cl_cb_conn; |
| 904 | unsigned short expected_family; | 904 | unsigned short expected_family; |
| @@ -921,6 +921,9 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) | |||
| 921 | if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family) | 921 | if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family) |
| 922 | goto out_err; | 922 | goto out_err; |
| 923 | 923 | ||
| 924 | if (cb->cb_addr.ss_family == AF_INET6) | ||
| 925 | ((struct sockaddr_in6 *) &cb->cb_addr)->sin6_scope_id = scopeid; | ||
| 926 | |||
| 924 | cb->cb_minorversion = 0; | 927 | cb->cb_minorversion = 0; |
| 925 | cb->cb_prog = se->se_callback_prog; | 928 | cb->cb_prog = se->se_callback_prog; |
| 926 | cb->cb_ident = se->se_callback_ident; | 929 | cb->cb_ident = se->se_callback_ident; |
| @@ -1621,7 +1624,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 1621 | } | 1624 | } |
| 1622 | copy_cred(&new->cl_cred, &rqstp->rq_cred); | 1625 | copy_cred(&new->cl_cred, &rqstp->rq_cred); |
| 1623 | gen_confirm(new); | 1626 | gen_confirm(new); |
| 1624 | gen_callback(new, setclid); | 1627 | gen_callback(new, setclid, rpc_get_scope_id(sa)); |
| 1625 | add_to_unconfirmed(new, strhashval); | 1628 | add_to_unconfirmed(new, strhashval); |
| 1626 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; | 1629 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; |
| 1627 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; | 1630 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 044f531aee70..3d025588e56e 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -286,5 +286,20 @@ static inline bool rpc_copy_addr(struct sockaddr *dst, | |||
| 286 | return false; | 286 | return false; |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | /** | ||
| 290 | * rpc_get_scope_id - return scopeid for a given sockaddr | ||
| 291 | * @sa: sockaddr to get scopeid from | ||
| 292 | * | ||
| 293 | * Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if | ||
| 294 | * not an AF_INET6 address. | ||
| 295 | */ | ||
| 296 | static inline u32 rpc_get_scope_id(const struct sockaddr *sa) | ||
| 297 | { | ||
| 298 | if (sa->sa_family != AF_INET6) | ||
| 299 | return 0; | ||
| 300 | |||
| 301 | return ((struct sockaddr_in6 *) sa)->sin6_scope_id; | ||
| 302 | } | ||
| 303 | |||
| 289 | #endif /* __KERNEL__ */ | 304 | #endif /* __KERNEL__ */ |
| 290 | #endif /* _LINUX_SUNRPC_CLNT_H */ | 305 | #endif /* _LINUX_SUNRPC_CLNT_H */ |
