aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Adamson <andros@citi.umich.edu>2007-07-17 07:04:51 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:08 -0400
commitdcb488a3b7ac3987e21148f44f641c9b2e734232 (patch)
treeedc9fe889094768068d8ea8c214076e40313a297
parentae4c40b1d81f5299c04330306736b2f0f0539f4b (diff)
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>
-rw-r--r--fs/nfsd/nfs4proc.c28
-rw-r--r--fs/nfsd/nfs4xdr.c75
-rw-r--r--include/linux/nfsd/nfsd.h3
-rw-r--r--include/linux/nfsd/xdr4.h7
4 files changed, 113 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index a106e3be7c13..3c627128e205 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -47,6 +47,7 @@
47#include <linux/nfsd/state.h> 47#include <linux/nfsd/state.h>
48#include <linux/nfsd/xdr4.h> 48#include <linux/nfsd/xdr4.h>
49#include <linux/nfs4_acl.h> 49#include <linux/nfs4_acl.h>
50#include <linux/sunrpc/gss_api.h>
50 51
51#define NFSDDBG_FACILITY NFSDDBG_PROC 52#define NFSDDBG_FACILITY NFSDDBG_PROC
52 53
@@ -610,6 +611,30 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
610} 611}
611 612
612static __be32 613static __be32
614nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
615 struct nfsd4_secinfo *secinfo)
616{
617 struct svc_fh resfh;
618 struct svc_export *exp;
619 struct dentry *dentry;
620 __be32 err;
621
622 fh_init(&resfh, NFS4_FHSIZE);
623 err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
624 secinfo->si_name, secinfo->si_namelen,
625 &exp, &dentry);
626 if (err)
627 return err;
628 if (dentry->d_inode == NULL) {
629 exp_put(exp);
630 err = nfserr_noent;
631 } else
632 secinfo->si_exp = exp;
633 dput(dentry);
634 return err;
635}
636
637static __be32
613nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 638nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
614 struct nfsd4_setattr *setattr) 639 struct nfsd4_setattr *setattr)
615{ 640{
@@ -1008,6 +1033,9 @@ static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
1008 [OP_SAVEFH] = { 1033 [OP_SAVEFH] = {
1009 .op_func = (nfsd4op_func)nfsd4_savefh, 1034 .op_func = (nfsd4op_func)nfsd4_savefh,
1010 }, 1035 },
1036 [OP_SECINFO] = {
1037 .op_func = (nfsd4op_func)nfsd4_secinfo,
1038 },
1011 [OP_SETATTR] = { 1039 [OP_SETATTR] = {
1012 .op_func = (nfsd4op_func)nfsd4_setattr, 1040 .op_func = (nfsd4op_func)nfsd4_setattr,
1013 }, 1041 },
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index b0bfbda375e1..864498f8f2d9 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -56,6 +56,7 @@
56#include <linux/nfsd_idmap.h> 56#include <linux/nfsd_idmap.h>
57#include <linux/nfs4.h> 57#include <linux/nfs4.h>
58#include <linux/nfs4_acl.h> 58#include <linux/nfs4_acl.h>
59#include <linux/sunrpc/gss_api.h>
59 60
60#define NFSDDBG_FACILITY NFSDDBG_XDR 61#define NFSDDBG_FACILITY NFSDDBG_XDR
61 62
@@ -819,6 +820,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
819} 820}
820 821
821static __be32 822static __be32
823nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
824 struct nfsd4_secinfo *secinfo)
825{
826 DECODE_HEAD;
827
828 READ_BUF(4);
829 READ32(secinfo->si_namelen);
830 READ_BUF(secinfo->si_namelen);
831 SAVEMEM(secinfo->si_name, secinfo->si_namelen);
832 status = check_filename(secinfo->si_name, secinfo->si_namelen,
833 nfserr_noent);
834 if (status)
835 return status;
836 DECODE_TAIL;
837}
838
839static __be32
822nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 840nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
823{ 841{
824 DECODE_HEAD; 842 DECODE_HEAD;
@@ -1131,6 +1149,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1131 case OP_SAVEFH: 1149 case OP_SAVEFH:
1132 op->status = nfs_ok; 1150 op->status = nfs_ok;
1133 break; 1151 break;
1152 case OP_SECINFO:
1153 op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
1154 break;
1134 case OP_SETATTR: 1155 case OP_SETATTR:
1135 op->status = nfsd4_decode_setattr(argp, &op->u.setattr); 1156 op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
1136 break; 1157 break;
@@ -1847,11 +1868,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
1847 if (d_mountpoint(dentry)) { 1868 if (d_mountpoint(dentry)) {
1848 int err; 1869 int err;
1849 1870
1871 /*
1872 * Why the heck aren't we just using nfsd_lookup??
1873 * Different "."/".." handling? Something else?
1874 * At least, add a comment here to explain....
1875 */
1850 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); 1876 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
1851 if (err) { 1877 if (err) {
1852 nfserr = nfserrno(err); 1878 nfserr = nfserrno(err);
1853 goto out_put; 1879 goto out_put;
1854 } 1880 }
1881 nfserr = check_nfsd_access(exp, cd->rd_rqstp);
1882 if (nfserr)
1883 goto out_put;
1855 1884
1856 } 1885 }
1857 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, 1886 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_
2419 } 2448 }
2420} 2449}
2421 2450
2451static void
2452nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
2453 struct nfsd4_secinfo *secinfo)
2454{
2455 int i = 0;
2456 struct svc_export *exp = secinfo->si_exp;
2457 ENCODE_HEAD;
2458
2459 if (nfserr)
2460 goto out;
2461 RESERVE_SPACE(4);
2462 WRITE32(exp->ex_nflavors);
2463 ADJUST_ARGS();
2464 for (i = 0; i < exp->ex_nflavors; i++) {
2465 u32 flav = exp->ex_flavors[i].pseudoflavor;
2466 struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
2467
2468 if (gm) {
2469 RESERVE_SPACE(4);
2470 WRITE32(RPC_AUTH_GSS);
2471 ADJUST_ARGS();
2472 RESERVE_SPACE(4 + gm->gm_oid.len);
2473 WRITE32(gm->gm_oid.len);
2474 WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
2475 ADJUST_ARGS();
2476 RESERVE_SPACE(4);
2477 WRITE32(0); /* qop */
2478 ADJUST_ARGS();
2479 RESERVE_SPACE(4);
2480 WRITE32(gss_pseudoflavor_to_service(gm, flav));
2481 ADJUST_ARGS();
2482 gss_mech_put(gm);
2483 } else {
2484 RESERVE_SPACE(4);
2485 WRITE32(flav);
2486 ADJUST_ARGS();
2487 }
2488 }
2489out:
2490 if (exp)
2491 exp_put(exp);
2492}
2493
2422/* 2494/*
2423 * The SETATTR encode routine is special -- it always encodes a bitmap, 2495 * The SETATTR encode routine is special -- it always encodes a bitmap,
2424 * regardless of the error status. 2496 * regardless of the error status.
@@ -2559,6 +2631,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2559 break; 2631 break;
2560 case OP_SAVEFH: 2632 case OP_SAVEFH:
2561 break; 2633 break;
2634 case OP_SECINFO:
2635 nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
2636 break;
2562 case OP_SETATTR: 2637 case OP_SETATTR:
2563 nfsd4_encode_setattr(resp, op->status, &op->u.setattr); 2638 nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
2564 break; 2639 break;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 54ef1a18a56c..e452256d3f72 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -71,6 +71,9 @@ int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
71 struct svc_export **expp); 71 struct svc_export **expp);
72__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *, 72__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
73 const char *, int, struct svc_fh *); 73 const char *, int, struct svc_fh *);
74__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
75 const char *, int,
76 struct svc_export **, struct dentry **);
74__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, 77__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
75 struct iattr *, int, time_t); 78 struct iattr *, int, time_t);
76#ifdef CONFIG_NFSD_V4 79#ifdef CONFIG_NFSD_V4
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 09799bcee0ac..1b653267133a 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -293,6 +293,12 @@ struct nfsd4_rename {
293 struct nfsd4_change_info rn_tinfo; /* response */ 293 struct nfsd4_change_info rn_tinfo; /* response */
294}; 294};
295 295
296struct nfsd4_secinfo {
297 u32 si_namelen; /* request */
298 char *si_name; /* request */
299 struct svc_export *si_exp; /* response */
300};
301
296struct nfsd4_setattr { 302struct nfsd4_setattr {
297 stateid_t sa_stateid; /* request */ 303 stateid_t sa_stateid; /* request */
298 u32 sa_bmval[2]; /* request */ 304 u32 sa_bmval[2]; /* request */
@@ -365,6 +371,7 @@ struct nfsd4_op {
365 struct nfsd4_remove remove; 371 struct nfsd4_remove remove;
366 struct nfsd4_rename rename; 372 struct nfsd4_rename rename;
367 clientid_t renew; 373 clientid_t renew;
374 struct nfsd4_secinfo secinfo;
368 struct nfsd4_setattr setattr; 375 struct nfsd4_setattr setattr;
369 struct nfsd4_setclientid setclientid; 376 struct nfsd4_setclientid setclientid;
370 struct nfsd4_setclientid_confirm setclientid_confirm; 377 struct nfsd4_setclientid_confirm setclientid_confirm;