diff options
author | Andy Adamson <andros@netapp.com> | 2009-04-03 01:28:01 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-04-03 20:41:15 -0400 |
commit | 0733d21338747483985a5964e852af160d88e429 (patch) | |
tree | fb8014cc66d3bfc33e1b7cc6a0da369bccc34cd3 /fs/nfsd/nfs4xdr.c | |
parent | 069b6ad4bb20abf175ea7875e82e8002154773af (diff) |
nfsd41: exchange_id operation
Implement the exchange_id operation confoming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-28
Based on the client provided name, hash a client id.
If a confirmed one is found, compare the op's creds and
verifier. If the creds match and the verifier is different
then expire the old client (client re-incarnated), otherwise,
if both match, assume it's a replay and ignore it.
If an unconfirmed client is found, then copy the new creds
and verifer if need update, otherwise assume replay.
The client is moved to a confirmed state on create_session.
In the nfs41 branch set the exchange_id flags to
EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_SUPP_MOVED_REFER
(pNFS is not supported, Referrals are supported,
Migration is not.).
Address various scenarios from section 18.35 of the spec:
1. Check for EXCHGID4_FLAG_UPD_CONFIRMED_REC_A and set
EXCHGID4_FLAG_CONFIRMED_R as appropriate.
2. Return error codes per 18.35.4 scenarios.
3. Update client records or generate new client ids depending on
scenario.
Note: 18.35.4 case 3 probably still needs revisiting. The handling
seems not quite right.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Andy Adamosn <andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfsd41: use utsname for major_id (and copy to server_scope)]
[nfsd41: fix handling of various exchange id scenarios]
Signed-off-by: Mike Sager <sager@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfsd41: reverse use of EXCHGID4_INVAL_FLAG_MASK_A]
[simplify nfsd4_encode_exchange_id error handling]
[nfsd41: embed an xdr_netobj in nfsd4_exchange_id]
[nfsd41: return nfserr_serverfault for spa_how == SP4_MACH_CRED]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 147 |
1 files changed, 143 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 6973d61bedea..bebf6d249069 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/fs.h> | 45 | #include <linux/fs.h> |
46 | #include <linux/namei.h> | 46 | #include <linux/namei.h> |
47 | #include <linux/vfs.h> | 47 | #include <linux/vfs.h> |
48 | #include <linux/utsname.h> | ||
48 | #include <linux/sunrpc/xdr.h> | 49 | #include <linux/sunrpc/xdr.h> |
49 | #include <linux/sunrpc/svc.h> | 50 | #include <linux/sunrpc/svc.h> |
50 | #include <linux/sunrpc/clnt.h> | 51 | #include <linux/sunrpc/clnt.h> |
@@ -998,9 +999,100 @@ nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_rel | |||
998 | 999 | ||
999 | static __be32 | 1000 | static __be32 |
1000 | nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, | 1001 | nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, |
1001 | struct nfsd4_exchange_id *clid) | 1002 | struct nfsd4_exchange_id *exid) |
1002 | { | 1003 | { |
1003 | return nfserr_opnotsupp; /* stub */ | 1004 | int dummy; |
1005 | DECODE_HEAD; | ||
1006 | |||
1007 | READ_BUF(NFS4_VERIFIER_SIZE); | ||
1008 | COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE); | ||
1009 | |||
1010 | READ_BUF(4); | ||
1011 | READ32(exid->clname.len); | ||
1012 | |||
1013 | READ_BUF(exid->clname.len); | ||
1014 | SAVEMEM(exid->clname.data, exid->clname.len); | ||
1015 | |||
1016 | READ_BUF(4); | ||
1017 | READ32(exid->flags); | ||
1018 | |||
1019 | /* Ignore state_protect4_a */ | ||
1020 | READ_BUF(4); | ||
1021 | READ32(exid->spa_how); | ||
1022 | switch (exid->spa_how) { | ||
1023 | case SP4_NONE: | ||
1024 | break; | ||
1025 | case SP4_MACH_CRED: | ||
1026 | /* spo_must_enforce */ | ||
1027 | READ_BUF(4); | ||
1028 | READ32(dummy); | ||
1029 | READ_BUF(dummy * 4); | ||
1030 | p += dummy; | ||
1031 | |||
1032 | /* spo_must_allow */ | ||
1033 | READ_BUF(4); | ||
1034 | READ32(dummy); | ||
1035 | READ_BUF(dummy * 4); | ||
1036 | p += dummy; | ||
1037 | break; | ||
1038 | case SP4_SSV: | ||
1039 | /* ssp_ops */ | ||
1040 | READ_BUF(4); | ||
1041 | READ32(dummy); | ||
1042 | READ_BUF(dummy * 4); | ||
1043 | p += dummy; | ||
1044 | |||
1045 | READ_BUF(4); | ||
1046 | READ32(dummy); | ||
1047 | READ_BUF(dummy * 4); | ||
1048 | p += dummy; | ||
1049 | |||
1050 | /* ssp_hash_algs<> */ | ||
1051 | READ_BUF(4); | ||
1052 | READ32(dummy); | ||
1053 | READ_BUF(dummy); | ||
1054 | p += XDR_QUADLEN(dummy); | ||
1055 | |||
1056 | /* ssp_encr_algs<> */ | ||
1057 | READ_BUF(4); | ||
1058 | READ32(dummy); | ||
1059 | READ_BUF(dummy); | ||
1060 | p += XDR_QUADLEN(dummy); | ||
1061 | |||
1062 | /* ssp_window and ssp_num_gss_handles */ | ||
1063 | READ_BUF(8); | ||
1064 | READ32(dummy); | ||
1065 | READ32(dummy); | ||
1066 | break; | ||
1067 | default: | ||
1068 | goto xdr_error; | ||
1069 | } | ||
1070 | |||
1071 | /* Ignore Implementation ID */ | ||
1072 | READ_BUF(4); /* nfs_impl_id4 array length */ | ||
1073 | READ32(dummy); | ||
1074 | |||
1075 | if (dummy > 1) | ||
1076 | goto xdr_error; | ||
1077 | |||
1078 | if (dummy == 1) { | ||
1079 | /* nii_domain */ | ||
1080 | READ_BUF(4); | ||
1081 | READ32(dummy); | ||
1082 | READ_BUF(dummy); | ||
1083 | p += XDR_QUADLEN(dummy); | ||
1084 | |||
1085 | /* nii_name */ | ||
1086 | READ_BUF(4); | ||
1087 | READ32(dummy); | ||
1088 | READ_BUF(dummy); | ||
1089 | p += XDR_QUADLEN(dummy); | ||
1090 | |||
1091 | /* nii_date */ | ||
1092 | READ_BUF(12); | ||
1093 | p += 3; | ||
1094 | } | ||
1095 | DECODE_TAIL; | ||
1004 | } | 1096 | } |
1005 | 1097 | ||
1006 | static __be32 | 1098 | static __be32 |
@@ -2665,8 +2757,55 @@ static __be32 | |||
2665 | nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, int nfserr, | 2757 | nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, int nfserr, |
2666 | struct nfsd4_exchange_id *exid) | 2758 | struct nfsd4_exchange_id *exid) |
2667 | { | 2759 | { |
2668 | /* stub */ | 2760 | ENCODE_HEAD; |
2669 | return nfserr; | 2761 | char *major_id; |
2762 | char *server_scope; | ||
2763 | int major_id_sz; | ||
2764 | int server_scope_sz; | ||
2765 | uint64_t minor_id = 0; | ||
2766 | |||
2767 | if (nfserr) | ||
2768 | return nfserr; | ||
2769 | |||
2770 | major_id = utsname()->nodename; | ||
2771 | major_id_sz = strlen(major_id); | ||
2772 | server_scope = utsname()->nodename; | ||
2773 | server_scope_sz = strlen(server_scope); | ||
2774 | |||
2775 | RESERVE_SPACE( | ||
2776 | 8 /* eir_clientid */ + | ||
2777 | 4 /* eir_sequenceid */ + | ||
2778 | 4 /* eir_flags */ + | ||
2779 | 4 /* spr_how (SP4_NONE) */ + | ||
2780 | 8 /* so_minor_id */ + | ||
2781 | 4 /* so_major_id.len */ + | ||
2782 | (XDR_QUADLEN(major_id_sz) * 4) + | ||
2783 | 4 /* eir_server_scope.len */ + | ||
2784 | (XDR_QUADLEN(server_scope_sz) * 4) + | ||
2785 | 4 /* eir_server_impl_id.count (0) */); | ||
2786 | |||
2787 | WRITEMEM(&exid->clientid, 8); | ||
2788 | WRITE32(exid->seqid); | ||
2789 | WRITE32(exid->flags); | ||
2790 | |||
2791 | /* state_protect4_r. Currently only support SP4_NONE */ | ||
2792 | BUG_ON(exid->spa_how != SP4_NONE); | ||
2793 | WRITE32(exid->spa_how); | ||
2794 | |||
2795 | /* The server_owner struct */ | ||
2796 | WRITE64(minor_id); /* Minor id */ | ||
2797 | /* major id */ | ||
2798 | WRITE32(major_id_sz); | ||
2799 | WRITEMEM(major_id, major_id_sz); | ||
2800 | |||
2801 | /* Server scope */ | ||
2802 | WRITE32(server_scope_sz); | ||
2803 | WRITEMEM(server_scope, server_scope_sz); | ||
2804 | |||
2805 | /* Implementation id */ | ||
2806 | WRITE32(0); /* zero length nfs_impl_id4 array */ | ||
2807 | ADJUST_ARGS(); | ||
2808 | return 0; | ||
2670 | } | 2809 | } |
2671 | 2810 | ||
2672 | static __be32 | 2811 | static __be32 |