aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2011-03-24 13:12:29 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-24 13:52:41 -0400
commit5a5ea0d485c9715c86bf858bbdc5f6d373b3db88 (patch)
tree0aef824c36b7eb6eac6ea706c4c9a33930128ee3 /fs
parent7c5130588d691a3b34d02312f1bd1b6d56fe0100 (diff)
NFS: Add secinfo procedure
This patch adds the nfs4 operation secinfo as a valid nfs rpc operation. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4proc.c35
-rw-r--r--fs/nfs/nfs4xdr.c135
2 files changed, 170 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 448657456b68..0b8bae119976 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4639,6 +4639,40 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
4639 return status; 4639 return status;
4640} 4640}
4641 4641
4642static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
4643{
4644 int status;
4645 struct nfs4_secinfo_arg args = {
4646 .dir_fh = NFS_FH(dir),
4647 .name = name,
4648 };
4649 struct nfs4_secinfo_res res = {
4650 .flavors = flavors,
4651 };
4652 struct rpc_message msg = {
4653 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO],
4654 .rpc_argp = &args,
4655 .rpc_resp = &res,
4656 };
4657
4658 dprintk("NFS call secinfo %s\n", name->name);
4659 status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
4660 dprintk("NFS reply secinfo: %d\n", status);
4661 return status;
4662}
4663
4664int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
4665{
4666 struct nfs4_exception exception = { };
4667 int err;
4668 do {
4669 err = nfs4_handle_exception(NFS_SERVER(dir),
4670 _nfs4_proc_secinfo(dir, name, flavors),
4671 &exception);
4672 } while (exception.retry);
4673 return err;
4674}
4675
4642#ifdef CONFIG_NFS_V4_1 4676#ifdef CONFIG_NFS_V4_1
4643/* 4677/*
4644 * Check the exchange flags returned by the server for invalid flags, having 4678 * Check the exchange flags returned by the server for invalid flags, having
@@ -5756,6 +5790,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
5756 .close_context = nfs4_close_context, 5790 .close_context = nfs4_close_context,
5757 .open_context = nfs4_atomic_open, 5791 .open_context = nfs4_atomic_open,
5758 .init_client = nfs4_init_client, 5792 .init_client = nfs4_init_client,
5793 .secinfo = nfs4_proc_secinfo,
5759}; 5794};
5760 5795
5761static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { 5796static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 0cf560f77884..98afcf947aa4 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -46,6 +46,7 @@
46#include <linux/kdev_t.h> 46#include <linux/kdev_t.h>
47#include <linux/sunrpc/clnt.h> 47#include <linux/sunrpc/clnt.h>
48#include <linux/sunrpc/msg_prot.h> 48#include <linux/sunrpc/msg_prot.h>
49#include <linux/sunrpc/gss_api.h>
49#include <linux/nfs.h> 50#include <linux/nfs.h>
50#include <linux/nfs4.h> 51#include <linux/nfs4.h>
51#include <linux/nfs_fs.h> 52#include <linux/nfs_fs.h>
@@ -253,6 +254,8 @@ static int nfs4_stat_to_errno(int);
253 (encode_getattr_maxsz) 254 (encode_getattr_maxsz)
254#define decode_fs_locations_maxsz \ 255#define decode_fs_locations_maxsz \
255 (0) 256 (0)
257#define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
258#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)))
256 259
257#if defined(CONFIG_NFS_V4_1) 260#if defined(CONFIG_NFS_V4_1)
258#define NFS4_MAX_MACHINE_NAME_LEN (64) 261#define NFS4_MAX_MACHINE_NAME_LEN (64)
@@ -676,6 +679,14 @@ static int nfs4_stat_to_errno(int);
676 decode_putfh_maxsz + \ 679 decode_putfh_maxsz + \
677 decode_lookup_maxsz + \ 680 decode_lookup_maxsz + \
678 decode_fs_locations_maxsz) 681 decode_fs_locations_maxsz)
682#define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \
683 encode_sequence_maxsz + \
684 encode_putfh_maxsz + \
685 encode_secinfo_maxsz)
686#define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \
687 decode_sequence_maxsz + \
688 decode_putfh_maxsz + \
689 decode_secinfo_maxsz)
679#if defined(CONFIG_NFS_V4_1) 690#if defined(CONFIG_NFS_V4_1)
680#define NFS4_enc_exchange_id_sz \ 691#define NFS4_enc_exchange_id_sz \
681 (compound_encode_hdr_maxsz + \ 692 (compound_encode_hdr_maxsz + \
@@ -1620,6 +1631,18 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state
1620 hdr->replen += decode_delegreturn_maxsz; 1631 hdr->replen += decode_delegreturn_maxsz;
1621} 1632}
1622 1633
1634static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
1635{
1636 int len = name->len;
1637 __be32 *p;
1638
1639 p = reserve_space(xdr, 8 + len);
1640 *p++ = cpu_to_be32(OP_SECINFO);
1641 xdr_encode_opaque(p, name->name, len);
1642 hdr->nops++;
1643 hdr->replen += decode_secinfo_maxsz;
1644}
1645
1623#if defined(CONFIG_NFS_V4_1) 1646#if defined(CONFIG_NFS_V4_1)
1624/* NFSv4.1 operations */ 1647/* NFSv4.1 operations */
1625static void encode_exchange_id(struct xdr_stream *xdr, 1648static void encode_exchange_id(struct xdr_stream *xdr,
@@ -2465,6 +2488,24 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
2465 encode_nops(&hdr); 2488 encode_nops(&hdr);
2466} 2489}
2467 2490
2491/*
2492 * Encode SECINFO request
2493 */
2494static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req,
2495 struct xdr_stream *xdr,
2496 struct nfs4_secinfo_arg *args)
2497{
2498 struct compound_hdr hdr = {
2499 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2500 };
2501
2502 encode_compound_hdr(xdr, req, &hdr);
2503 encode_sequence(xdr, &args->seq_args, &hdr);
2504 encode_putfh(xdr, args->dir_fh, &hdr);
2505 encode_secinfo(xdr, args->name, &hdr);
2506 encode_nops(&hdr);
2507}
2508
2468#if defined(CONFIG_NFS_V4_1) 2509#if defined(CONFIG_NFS_V4_1)
2469/* 2510/*
2470 * EXCHANGE_ID request 2511 * EXCHANGE_ID request
@@ -4680,6 +4721,73 @@ static int decode_delegreturn(struct xdr_stream *xdr)
4680 return decode_op_hdr(xdr, OP_DELEGRETURN); 4721 return decode_op_hdr(xdr, OP_DELEGRETURN);
4681} 4722}
4682 4723
4724static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor)
4725{
4726 __be32 *p;
4727
4728 p = xdr_inline_decode(xdr, 4);
4729 if (unlikely(!p))
4730 goto out_overflow;
4731 flavor->gss.sec_oid4.len = be32_to_cpup(p);
4732 if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN)
4733 goto out_err;
4734
4735 p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len);
4736 if (unlikely(!p))
4737 goto out_overflow;
4738 memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len);
4739
4740 p = xdr_inline_decode(xdr, 8);
4741 if (unlikely(!p))
4742 goto out_overflow;
4743 flavor->gss.qop4 = be32_to_cpup(p++);
4744 flavor->gss.service = be32_to_cpup(p);
4745
4746 return 0;
4747
4748out_overflow:
4749 print_overflow_msg(__func__, xdr);
4750 return -EIO;
4751out_err:
4752 return -EINVAL;
4753}
4754
4755static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
4756{
4757 struct nfs4_secinfo_flavor *sec_flavor;
4758 int status;
4759 __be32 *p;
4760 int i;
4761
4762 status = decode_op_hdr(xdr, OP_SECINFO);
4763 p = xdr_inline_decode(xdr, 4);
4764 if (unlikely(!p))
4765 goto out_overflow;
4766 res->flavors->num_flavors = be32_to_cpup(p);
4767
4768 for (i = 0; i < res->flavors->num_flavors; i++) {
4769 sec_flavor = &res->flavors->flavors[i];
4770 if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE)
4771 break;
4772
4773 p = xdr_inline_decode(xdr, 4);
4774 if (unlikely(!p))
4775 goto out_overflow;
4776 sec_flavor->flavor = be32_to_cpup(p);
4777
4778 if (sec_flavor->flavor == RPC_AUTH_GSS) {
4779 if (decode_secinfo_gss(xdr, sec_flavor))
4780 break;
4781 }
4782 }
4783
4784 return 0;
4785
4786out_overflow:
4787 print_overflow_msg(__func__, xdr);
4788 return -EIO;
4789}
4790
4683#if defined(CONFIG_NFS_V4_1) 4791#if defined(CONFIG_NFS_V4_1)
4684static int decode_exchange_id(struct xdr_stream *xdr, 4792static int decode_exchange_id(struct xdr_stream *xdr,
4685 struct nfs41_exchange_id_res *res) 4793 struct nfs41_exchange_id_res *res)
@@ -5919,6 +6027,32 @@ out:
5919 return status; 6027 return status;
5920} 6028}
5921 6029
6030/*
6031 * Decode SECINFO response
6032 */
6033static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp,
6034 struct xdr_stream *xdr,
6035 struct nfs4_secinfo_res *res)
6036{
6037 struct compound_hdr hdr;
6038 int status;
6039
6040 status = decode_compound_hdr(xdr, &hdr);
6041 if (status)
6042 goto out;
6043 status = decode_sequence(xdr, &res->seq_res, rqstp);
6044 if (status)
6045 goto out;
6046 status = decode_putfh(xdr);
6047 if (status)
6048 goto out;
6049 status = decode_secinfo(xdr, res);
6050 if (status)
6051 goto out;
6052out:
6053 return status;
6054}
6055
5922#if defined(CONFIG_NFS_V4_1) 6056#if defined(CONFIG_NFS_V4_1)
5923/* 6057/*
5924 * Decode EXCHANGE_ID response 6058 * Decode EXCHANGE_ID response
@@ -6258,6 +6392,7 @@ struct rpc_procinfo nfs4_procedures[] = {
6258 PROC(SETACL, enc_setacl, dec_setacl), 6392 PROC(SETACL, enc_setacl, dec_setacl),
6259 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 6393 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
6260 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), 6394 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
6395 PROC(SECINFO, enc_secinfo, dec_secinfo),
6261#if defined(CONFIG_NFS_V4_1) 6396#if defined(CONFIG_NFS_V4_1)
6262 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 6397 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
6263 PROC(CREATE_SESSION, enc_create_session, dec_create_session), 6398 PROC(CREATE_SESSION, enc_create_session, dec_create_session),