diff options
author | Weston Andros Adamson <dros@netapp.com> | 2013-08-13 16:37:32 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-05 10:40:45 -0400 |
commit | 2031cd1af143f47dacacbb35efbef22f2fd079e6 (patch) | |
tree | d5737cb0679b190fcfd583bb74768edfa032203e /fs/nfs/nfs4xdr.c | |
parent | 92cb6c5be8134db6f7c38f25f6afd13e444cebaf (diff) |
nfs4.1: Minimal SP4_MACH_CRED implementation
This is a minimal client side implementation of SP4_MACH_CRED. It will
attempt to negotiate SP4_MACH_CRED iff the EXCHANGE_ID is using
krb5i or krb5p auth. SP4_MACH_CRED will be used if the server supports the
minimal operations:
BIND_CONN_TO_SESSION
EXCHANGE_ID
CREATE_SESSION
DESTROY_SESSION
DESTROY_CLIENTID
This patch only includes the EXCHANGE_ID negotiation code because
the client will already use the machine cred for these operations.
If the server doesn't support SP4_MACH_CRED or doesn't support the minimal
operations, the exchange id will be resent with SP4_NONE.
Signed-off-by: Weston Andros Adamson <dros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index cb5f94640be6..fbdad9e1719f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -294,7 +294,9 @@ static int nfs4_stat_to_errno(int); | |||
294 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ | 294 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ |
295 | 1 /* flags */ + \ | 295 | 1 /* flags */ + \ |
296 | 1 /* spa_how */ + \ | 296 | 1 /* spa_how */ + \ |
297 | 0 /* SP4_NONE (for now) */ + \ | 297 | /* max is SP4_MACH_CRED (for now) */ + \ |
298 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
299 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
298 | 1 /* implementation id array of size 1 */ + \ | 300 | 1 /* implementation id array of size 1 */ + \ |
299 | 1 /* nii_domain */ + \ | 301 | 1 /* nii_domain */ + \ |
300 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ | 302 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
@@ -306,7 +308,9 @@ static int nfs4_stat_to_errno(int); | |||
306 | 1 /* eir_sequenceid */ + \ | 308 | 1 /* eir_sequenceid */ + \ |
307 | 1 /* eir_flags */ + \ | 309 | 1 /* eir_flags */ + \ |
308 | 1 /* spr_how */ + \ | 310 | 1 /* spr_how */ + \ |
309 | 0 /* SP4_NONE (for now) */ + \ | 311 | /* max is SP4_MACH_CRED (for now) */ + \ |
312 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
313 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
310 | 2 /* eir_server_owner.so_minor_id */ + \ | 314 | 2 /* eir_server_owner.so_minor_id */ + \ |
311 | /* eir_server_owner.so_major_id<> */ \ | 315 | /* eir_server_owner.so_major_id<> */ \ |
312 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | 316 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
@@ -1726,6 +1730,14 @@ static void encode_bind_conn_to_session(struct xdr_stream *xdr, | |||
1726 | *p = 0; /* use_conn_in_rdma_mode = False */ | 1730 | *p = 0; /* use_conn_in_rdma_mode = False */ |
1727 | } | 1731 | } |
1728 | 1732 | ||
1733 | static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) | ||
1734 | { | ||
1735 | unsigned int i; | ||
1736 | encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS); | ||
1737 | for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) | ||
1738 | encode_uint32(xdr, op_map->u.words[i]); | ||
1739 | } | ||
1740 | |||
1729 | static void encode_exchange_id(struct xdr_stream *xdr, | 1741 | static void encode_exchange_id(struct xdr_stream *xdr, |
1730 | struct nfs41_exchange_id_args *args, | 1742 | struct nfs41_exchange_id_args *args, |
1731 | struct compound_hdr *hdr) | 1743 | struct compound_hdr *hdr) |
@@ -1739,9 +1751,20 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1739 | 1751 | ||
1740 | encode_string(xdr, args->id_len, args->id); | 1752 | encode_string(xdr, args->id_len, args->id); |
1741 | 1753 | ||
1742 | p = reserve_space(xdr, 12); | 1754 | encode_uint32(xdr, args->flags); |
1743 | *p++ = cpu_to_be32(args->flags); | 1755 | encode_uint32(xdr, args->state_protect.how); |
1744 | *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ | 1756 | |
1757 | switch (args->state_protect.how) { | ||
1758 | case SP4_NONE: | ||
1759 | break; | ||
1760 | case SP4_MACH_CRED: | ||
1761 | encode_op_map(xdr, &args->state_protect.enforce); | ||
1762 | encode_op_map(xdr, &args->state_protect.allow); | ||
1763 | break; | ||
1764 | default: | ||
1765 | WARN_ON_ONCE(1); | ||
1766 | break; | ||
1767 | } | ||
1745 | 1768 | ||
1746 | if (send_implementation_id && | 1769 | if (send_implementation_id && |
1747 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && | 1770 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && |
@@ -1752,7 +1775,7 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1752 | utsname()->version, utsname()->machine); | 1775 | utsname()->version, utsname()->machine); |
1753 | 1776 | ||
1754 | if (len > 0) { | 1777 | if (len > 0) { |
1755 | *p = cpu_to_be32(1); /* implementation id array length=1 */ | 1778 | encode_uint32(xdr, 1); /* implementation id array length=1 */ |
1756 | 1779 | ||
1757 | encode_string(xdr, | 1780 | encode_string(xdr, |
1758 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, | 1781 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, |
@@ -1763,7 +1786,7 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1763 | p = xdr_encode_hyper(p, 0); | 1786 | p = xdr_encode_hyper(p, 0); |
1764 | *p = cpu_to_be32(0); | 1787 | *p = cpu_to_be32(0); |
1765 | } else | 1788 | } else |
1766 | *p = cpu_to_be32(0); /* implementation id array length=0 */ | 1789 | encode_uint32(xdr, 0); /* implementation id array length=0 */ |
1767 | } | 1790 | } |
1768 | 1791 | ||
1769 | static void encode_create_session(struct xdr_stream *xdr, | 1792 | static void encode_create_session(struct xdr_stream *xdr, |
@@ -5374,6 +5397,23 @@ static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_re | |||
5374 | return decode_secinfo_common(xdr, res); | 5397 | return decode_secinfo_common(xdr, res); |
5375 | } | 5398 | } |
5376 | 5399 | ||
5400 | static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) | ||
5401 | { | ||
5402 | __be32 *p; | ||
5403 | uint32_t bitmap_words; | ||
5404 | unsigned int i; | ||
5405 | |||
5406 | p = xdr_inline_decode(xdr, 4); | ||
5407 | bitmap_words = be32_to_cpup(p++); | ||
5408 | if (bitmap_words > NFS4_OP_MAP_NUM_WORDS) | ||
5409 | return -EIO; | ||
5410 | p = xdr_inline_decode(xdr, 4 * bitmap_words); | ||
5411 | for (i = 0; i < bitmap_words; i++) | ||
5412 | op_map->u.words[i] = be32_to_cpup(p++); | ||
5413 | |||
5414 | return 0; | ||
5415 | } | ||
5416 | |||
5377 | static int decode_exchange_id(struct xdr_stream *xdr, | 5417 | static int decode_exchange_id(struct xdr_stream *xdr, |
5378 | struct nfs41_exchange_id_res *res) | 5418 | struct nfs41_exchange_id_res *res) |
5379 | { | 5419 | { |
@@ -5397,10 +5437,22 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5397 | res->seqid = be32_to_cpup(p++); | 5437 | res->seqid = be32_to_cpup(p++); |
5398 | res->flags = be32_to_cpup(p++); | 5438 | res->flags = be32_to_cpup(p++); |
5399 | 5439 | ||
5400 | /* We ask for SP4_NONE */ | 5440 | res->state_protect.how = be32_to_cpup(p); |
5401 | dummy = be32_to_cpup(p); | 5441 | switch (res->state_protect.how) { |
5402 | if (dummy != SP4_NONE) | 5442 | case SP4_NONE: |
5443 | break; | ||
5444 | case SP4_MACH_CRED: | ||
5445 | status = decode_op_map(xdr, &res->state_protect.enforce); | ||
5446 | if (status) | ||
5447 | return status; | ||
5448 | status = decode_op_map(xdr, &res->state_protect.allow); | ||
5449 | if (status) | ||
5450 | return status; | ||
5451 | break; | ||
5452 | default: | ||
5453 | WARN_ON_ONCE(1); | ||
5403 | return -EIO; | 5454 | return -EIO; |
5455 | } | ||
5404 | 5456 | ||
5405 | /* server_owner4.so_minor_id */ | 5457 | /* server_owner4.so_minor_id */ |
5406 | p = xdr_inline_decode(xdr, 8); | 5458 | p = xdr_inline_decode(xdr, 8); |