knfsd: nfsd4: implement secinfo
Implement the secinfo operation. (Thanks to Usha Ketineni wrote an earlier version of this support.) Cc: Usha Ketineni <uketinen@us.ibm.com> Signed-off-by: Andy Adamson <andros@citi.umich.edu> Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
ae4c40b1d8
commit
dcb488a3b7
4 changed files with 113 additions and 0 deletions
|
@ -47,6 +47,7 @@
|
||||||
#include <linux/nfsd/state.h>
|
#include <linux/nfsd/state.h>
|
||||||
#include <linux/nfsd/xdr4.h>
|
#include <linux/nfsd/xdr4.h>
|
||||||
#include <linux/nfs4_acl.h>
|
#include <linux/nfs4_acl.h>
|
||||||
|
#include <linux/sunrpc/gss_api.h>
|
||||||
|
|
||||||
#define NFSDDBG_FACILITY NFSDDBG_PROC
|
#define NFSDDBG_FACILITY NFSDDBG_PROC
|
||||||
|
|
||||||
|
@ -609,6 +610,30 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
|
struct nfsd4_secinfo *secinfo)
|
||||||
|
{
|
||||||
|
struct svc_fh resfh;
|
||||||
|
struct svc_export *exp;
|
||||||
|
struct dentry *dentry;
|
||||||
|
__be32 err;
|
||||||
|
|
||||||
|
fh_init(&resfh, NFS4_FHSIZE);
|
||||||
|
err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
|
||||||
|
secinfo->si_name, secinfo->si_namelen,
|
||||||
|
&exp, &dentry);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (dentry->d_inode == NULL) {
|
||||||
|
exp_put(exp);
|
||||||
|
err = nfserr_noent;
|
||||||
|
} else
|
||||||
|
secinfo->si_exp = exp;
|
||||||
|
dput(dentry);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
struct nfsd4_setattr *setattr)
|
struct nfsd4_setattr *setattr)
|
||||||
|
@ -1008,6 +1033,9 @@ static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
|
||||||
[OP_SAVEFH] = {
|
[OP_SAVEFH] = {
|
||||||
.op_func = (nfsd4op_func)nfsd4_savefh,
|
.op_func = (nfsd4op_func)nfsd4_savefh,
|
||||||
},
|
},
|
||||||
|
[OP_SECINFO] = {
|
||||||
|
.op_func = (nfsd4op_func)nfsd4_secinfo,
|
||||||
|
},
|
||||||
[OP_SETATTR] = {
|
[OP_SETATTR] = {
|
||||||
.op_func = (nfsd4op_func)nfsd4_setattr,
|
.op_func = (nfsd4op_func)nfsd4_setattr,
|
||||||
},
|
},
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include <linux/nfsd_idmap.h>
|
#include <linux/nfsd_idmap.h>
|
||||||
#include <linux/nfs4.h>
|
#include <linux/nfs4.h>
|
||||||
#include <linux/nfs4_acl.h>
|
#include <linux/nfs4_acl.h>
|
||||||
|
#include <linux/sunrpc/gss_api.h>
|
||||||
|
|
||||||
#define NFSDDBG_FACILITY NFSDDBG_XDR
|
#define NFSDDBG_FACILITY NFSDDBG_XDR
|
||||||
|
|
||||||
|
@ -818,6 +819,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
|
||||||
DECODE_TAIL;
|
DECODE_TAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
|
||||||
|
struct nfsd4_secinfo *secinfo)
|
||||||
|
{
|
||||||
|
DECODE_HEAD;
|
||||||
|
|
||||||
|
READ_BUF(4);
|
||||||
|
READ32(secinfo->si_namelen);
|
||||||
|
READ_BUF(secinfo->si_namelen);
|
||||||
|
SAVEMEM(secinfo->si_name, secinfo->si_namelen);
|
||||||
|
status = check_filename(secinfo->si_name, secinfo->si_namelen,
|
||||||
|
nfserr_noent);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
DECODE_TAIL;
|
||||||
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
|
nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
|
||||||
{
|
{
|
||||||
|
@ -1131,6 +1149,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||||
case OP_SAVEFH:
|
case OP_SAVEFH:
|
||||||
op->status = nfs_ok;
|
op->status = nfs_ok;
|
||||||
break;
|
break;
|
||||||
|
case OP_SECINFO:
|
||||||
|
op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
|
||||||
|
break;
|
||||||
case OP_SETATTR:
|
case OP_SETATTR:
|
||||||
op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
|
op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
|
||||||
break;
|
break;
|
||||||
|
@ -1847,11 +1868,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
|
||||||
if (d_mountpoint(dentry)) {
|
if (d_mountpoint(dentry)) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Why the heck aren't we just using nfsd_lookup??
|
||||||
|
* Different "."/".." handling? Something else?
|
||||||
|
* At least, add a comment here to explain....
|
||||||
|
*/
|
||||||
err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
|
err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
|
||||||
if (err) {
|
if (err) {
|
||||||
nfserr = nfserrno(err);
|
nfserr = nfserrno(err);
|
||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
nfserr = check_nfsd_access(exp, cd->rd_rqstp);
|
||||||
|
if (nfserr)
|
||||||
|
goto out_put;
|
||||||
|
|
||||||
}
|
}
|
||||||
nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
|
nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
|
||||||
|
@ -2419,6 +2448,49 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
|
||||||
|
struct nfsd4_secinfo *secinfo)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
struct svc_export *exp = secinfo->si_exp;
|
||||||
|
ENCODE_HEAD;
|
||||||
|
|
||||||
|
if (nfserr)
|
||||||
|
goto out;
|
||||||
|
RESERVE_SPACE(4);
|
||||||
|
WRITE32(exp->ex_nflavors);
|
||||||
|
ADJUST_ARGS();
|
||||||
|
for (i = 0; i < exp->ex_nflavors; i++) {
|
||||||
|
u32 flav = exp->ex_flavors[i].pseudoflavor;
|
||||||
|
struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
|
||||||
|
|
||||||
|
if (gm) {
|
||||||
|
RESERVE_SPACE(4);
|
||||||
|
WRITE32(RPC_AUTH_GSS);
|
||||||
|
ADJUST_ARGS();
|
||||||
|
RESERVE_SPACE(4 + gm->gm_oid.len);
|
||||||
|
WRITE32(gm->gm_oid.len);
|
||||||
|
WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
|
||||||
|
ADJUST_ARGS();
|
||||||
|
RESERVE_SPACE(4);
|
||||||
|
WRITE32(0); /* qop */
|
||||||
|
ADJUST_ARGS();
|
||||||
|
RESERVE_SPACE(4);
|
||||||
|
WRITE32(gss_pseudoflavor_to_service(gm, flav));
|
||||||
|
ADJUST_ARGS();
|
||||||
|
gss_mech_put(gm);
|
||||||
|
} else {
|
||||||
|
RESERVE_SPACE(4);
|
||||||
|
WRITE32(flav);
|
||||||
|
ADJUST_ARGS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (exp)
|
||||||
|
exp_put(exp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The SETATTR encode routine is special -- it always encodes a bitmap,
|
* The SETATTR encode routine is special -- it always encodes a bitmap,
|
||||||
* regardless of the error status.
|
* regardless of the error status.
|
||||||
|
@ -2559,6 +2631,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||||
break;
|
break;
|
||||||
case OP_SAVEFH:
|
case OP_SAVEFH:
|
||||||
break;
|
break;
|
||||||
|
case OP_SECINFO:
|
||||||
|
nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
|
||||||
|
break;
|
||||||
case OP_SETATTR:
|
case OP_SETATTR:
|
||||||
nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
|
nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -71,6 +71,9 @@ int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
||||||
struct svc_export **expp);
|
struct svc_export **expp);
|
||||||
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
|
||||||
const char *, int, struct svc_fh *);
|
const char *, int, struct svc_fh *);
|
||||||
|
__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
|
||||||
|
const char *, int,
|
||||||
|
struct svc_export **, struct dentry **);
|
||||||
__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
|
||||||
struct iattr *, int, time_t);
|
struct iattr *, int, time_t);
|
||||||
#ifdef CONFIG_NFSD_V4
|
#ifdef CONFIG_NFSD_V4
|
||||||
|
|
|
@ -293,6 +293,12 @@ struct nfsd4_rename {
|
||||||
struct nfsd4_change_info rn_tinfo; /* response */
|
struct nfsd4_change_info rn_tinfo; /* response */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nfsd4_secinfo {
|
||||||
|
u32 si_namelen; /* request */
|
||||||
|
char *si_name; /* request */
|
||||||
|
struct svc_export *si_exp; /* response */
|
||||||
|
};
|
||||||
|
|
||||||
struct nfsd4_setattr {
|
struct nfsd4_setattr {
|
||||||
stateid_t sa_stateid; /* request */
|
stateid_t sa_stateid; /* request */
|
||||||
u32 sa_bmval[2]; /* request */
|
u32 sa_bmval[2]; /* request */
|
||||||
|
@ -365,6 +371,7 @@ struct nfsd4_op {
|
||||||
struct nfsd4_remove remove;
|
struct nfsd4_remove remove;
|
||||||
struct nfsd4_rename rename;
|
struct nfsd4_rename rename;
|
||||||
clientid_t renew;
|
clientid_t renew;
|
||||||
|
struct nfsd4_secinfo secinfo;
|
||||||
struct nfsd4_setattr setattr;
|
struct nfsd4_setattr setattr;
|
||||||
struct nfsd4_setclientid setclientid;
|
struct nfsd4_setclientid setclientid;
|
||||||
struct nfsd4_setclientid_confirm setclientid_confirm;
|
struct nfsd4_setclientid_confirm setclientid_confirm;
|
||||||
|
|
Loading…
Add table
Reference in a new issue