1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include "nfs41_compound.h"
26 #include "nfs41_ops.h"
27 #include "nfs41_xdr.h"
29 #include "daemon_debug.h"
32 static bool_t
encode_file_attrs(
34 nfs41_file_info
*info
);
36 static __inline
int unexpected_op(uint32_t op
, uint32_t expected
)
41 eprintf("Op table mismatch. Got %s (%d), expected %s (%d).\n",
42 nfs_opnum_to_string(op
), op
,
43 nfs_opnum_to_string(expected
), expected
);
47 /* typedef uint32_t bitmap4<> */
54 if (xdr
->x_op
== XDR_ENCODE
) {
55 if (bitmap
->count
> 3) {
56 eprintf("encode_bitmap4: count (%d) must be <= 3\n",
60 if (!xdr_u_int32_t(xdr
, &bitmap
->count
))
63 for (i
= 0; i
< bitmap
->count
; i
++)
64 if (!xdr_u_int32_t(xdr
, &bitmap
->arr
[i
]))
67 } else if (xdr
->x_op
== XDR_DECODE
) {
68 if (!xdr_u_int32_t(xdr
, &bitmap
->count
))
70 if (bitmap
->count
> 3) {
71 eprintf("decode_bitmap4: count (%d) must be <= 3\n",
76 for (i
= 0; i
< bitmap
->count
; i
++)
77 if (!xdr_u_int32_t(xdr
, &bitmap
->arr
[i
]))
86 static bool_t
xdr_nfstime4(
90 if (!xdr_hyper(xdr
, &nt
->seconds
))
93 return xdr_u_int32_t(xdr
, &nt
->nseconds
);
98 static uint32_t settime_how(
100 const nfstime4
*time_delta
)
103 get_nfs_time(¤t
);
104 /* get the absolute difference between current and newtime */
105 nfstime_diff(¤t
, newtime
, ¤t
);
106 nfstime_abs(¤t
, ¤t
);
107 /* compare the difference with time_delta */
108 nfstime_diff(time_delta
, ¤t
, ¤t
);
109 /* use client time if diff > delta (i.e. time_delta - current < 0) */
110 return current
.seconds
< 0 ? SET_TO_CLIENT_TIME4
: SET_TO_SERVER_TIME4
;
113 static bool_t
xdr_settime4(
116 const nfstime4
*time_delta
)
118 uint32_t how
= settime_how(nt
, time_delta
);
120 if (xdr
->x_op
!= XDR_ENCODE
) /* not used for decode */
123 if (!xdr_u_int32_t(xdr
, &how
))
126 if (how
== SET_TO_CLIENT_TIME4
)
127 return xdr_nfstime4(xdr
, nt
);
133 static bool_t
xdr_stateid4(
137 if (!xdr_u_int32_t(xdr
, &si
->seqid
))
140 return xdr_opaque(xdr
, (char *)si
->other
, NFS4_STATEID_OTHER
);
148 unsigned char *attr_vals
= fattr
->attr_vals
;
150 if (!xdr_bitmap4(xdr
, &fattr
->attrmask
))
153 return xdr_bytes(xdr
, (char **)&attr_vals
, &fattr
->attr_vals_len
, NFS4_OPAQUE_LIMIT
);
157 static bool_t
xdr_fh(
161 unsigned char *pfh
= fh
->fh
;
162 return xdr_bytes(xdr
, (char **)&pfh
, &fh
->len
, NFS4_FHSIZE
);
166 static bool_t
xdr_fsid(
170 if (!xdr_u_hyper(xdr
, &fsid
->major
))
173 return xdr_u_hyper(xdr
, &fsid
->minor
);
177 /* nfs41_component */
178 static bool_t
encode_component(
180 const nfs41_component
*component
)
182 uint32_t len
= component
->len
;
183 return xdr_bytes(xdr
, (char **)&component
->name
, &len
, NFS4_OPAQUE_LIMIT
);
186 static bool_t
decode_component(
188 nfs41_component
*component
)
193 result
= xdr_bytes(xdr
, (char **)&component
->name
, &len
, NFS4_OPAQUE_LIMIT
);
194 component
->len
= (result
== FALSE
) ? 0 : (unsigned short)len
;
200 static bool_t
xdr_state_owner4(
204 u_quad_t clientid
= 0;
205 unsigned char *owner
= so
->owner
;
207 /* 18.16.3. "The client can set the clientid field to any value and
208 * the server MUST ignore it. Instead the server MUST derive the
209 * client ID from the session ID of the SEQUENCE operation of the
210 * COMPOUND request. */
211 if (xdr
->x_op
== XDR_ENCODE
) {
212 if (!xdr_u_hyper(xdr
, &clientid
)) /* clientid = 0 */
214 } else if (xdr
->x_op
== XDR_DECODE
) {
215 if (!xdr_u_hyper(xdr
, &clientid
))
219 return xdr_bytes(xdr
, (char **)&owner
, &so
->owner_len
, NFS4_OPAQUE_LIMIT
);
222 static bool_t
xdr_layout_types(
224 uint32_t *layout_type
)
226 u_int32_t i
, count
, type
;
228 if (xdr
->x_op
!= XDR_DECODE
) {
229 eprintf("xdr_layout_types: xdr->x_op is not XDR_DECODE! "
230 "x_op %d not supported.\n", xdr
->x_op
);
236 if (!xdr_u_int32_t(xdr
, &count
))
239 for (i
= 0; i
< count
; i
++) {
240 if (!xdr_u_int32_t(xdr
, &type
))
243 *layout_type
|= 1 << (type
- 1);
248 static bool_t
xdr_threshold_item(
250 threshold_item4
*item
)
254 if (!xdr_u_int32_t(xdr
, &item
->type
))
257 if (!xdr_bitmap4(xdr
, &bitmap
))
260 if (!xdr_u_int32_t(xdr
, &bitmap
.count
))
264 if (bitmap
.arr
[0] & 0x1 && !xdr_u_hyper(xdr
, &item
->hints
[0]))
266 if (bitmap
.arr
[0] & 0x2 && !xdr_u_hyper(xdr
, &item
->hints
[1]))
268 if (bitmap
.arr
[0] & 0x4 && !xdr_u_hyper(xdr
, &item
->hints
[2]))
270 if (bitmap
.arr
[0] & 0x8 && !xdr_u_hyper(xdr
, &item
->hints
[3]))
276 static bool_t
xdr_mdsthreshold(
278 mdsthreshold4
*mdsthreshold
)
282 if (!xdr_u_int32_t(xdr
, &mdsthreshold
->count
))
285 if (mdsthreshold
->count
> MAX_MDSTHRESHOLD_ITEMS
)
288 for (i
= 0; i
< mdsthreshold
->count
; i
++)
289 if (!xdr_threshold_item(xdr
, &mdsthreshold
->items
[i
]))
294 static bool_t
xdr_nfsace4(
298 char *who
= ace
->who
;
300 if (!xdr_u_int32_t(xdr
, &ace
->acetype
))
303 if (!xdr_u_int32_t(xdr
, &ace
->aceflag
))
306 if (!xdr_u_int32_t(xdr
, &ace
->acemask
))
309 /* 'who' is a static array, so don't try to free it */
310 if (xdr
->x_op
== XDR_FREE
)
313 return xdr_string(xdr
, &who
, NFS4_OPAQUE_LIMIT
);
316 static bool_t
xdr_nfsdacl41(
320 if (!xdr_u_int32_t(xdr
, &acl
->flag
))
323 return xdr_array(xdr
, (char**)&acl
->aces
, &acl
->count
,
324 32, sizeof(nfsace4
), (xdrproc_t
)xdr_nfsace4
);
327 static bool_t
xdr_nfsacl41(
331 return xdr_array(xdr
, (char**)&acl
->aces
, &acl
->count
,
332 32, sizeof(nfsace4
), (xdrproc_t
)xdr_nfsace4
);
335 void nfsacl41_free(nfsacl41
*acl
)
337 XDR xdr
= { XDR_FREE
};
338 xdr_nfsacl41(&xdr
, acl
);
342 * decode a variable array of components into a nfs41_abs_path */
343 static bool_t
decode_pathname4(
345 nfs41_abs_path
*path
)
348 u_int32_t i
, count
, len
, remaining
;
350 /* decode the number of components */
351 if (!xdr_u_int32_t(xdr
, &count
))
354 pos
= (char *)path
->path
;
355 remaining
= NFS41_MAX_PATH_LEN
;
357 /* decode each component */
358 for (i
= 0; i
< count
; i
++) {
360 if (!xdr_bytes(xdr
, (char **)&pos
, &len
, NFS41_MAX_PATH_LEN
))
365 if (i
< count
-1) { /* add a \ between components */
372 path
->len
= (unsigned short)(NFS41_MAX_PATH_LEN
- remaining
);
377 static bool_t
decode_fs_location4(
379 fs_location4
*location
)
381 fs_location_server
*arr
;
383 u_int32_t i
, count
, len
;
385 /* decode the number of servers */
386 if (!xdr_u_int32_t(xdr
, &count
))
389 /* allocate the fs_location_server array */
391 free(location
->servers
);
393 } else if (count
!= location
->server_count
) {
394 arr
= realloc(location
->servers
, count
* sizeof(fs_location_server
));
397 ZeroMemory(arr
, count
* sizeof(fs_location_server
));
399 arr
= location
->servers
;
402 location
->servers
= arr
;
403 location
->server_count
= count
;
405 for (i
= 0; i
< count
; i
++) {
406 len
= NFS41_HOSTNAME_LEN
;
407 address
= arr
[i
].address
;
408 if (!xdr_bytes(xdr
, &address
, &len
, NFS41_HOSTNAME_LEN
)) {
412 arr
[i
].address
[len
] = '\0';
415 return decode_pathname4(xdr
, &location
->path
);
419 static bool_t
decode_fs_locations4(
421 fs_locations4
*locations
)
426 if (!decode_pathname4(xdr
, &locations
->path
))
429 if (!xdr_u_int32_t(xdr
, &count
))
432 /* allocate the fs_location array */
434 free(locations
->locations
);
436 } else if (count
!= locations
->location_count
) {
437 arr
= realloc(locations
->locations
, count
* sizeof(fs_location4
));
440 ZeroMemory(arr
, count
* sizeof(fs_location4
));
442 arr
= locations
->locations
;
445 locations
->locations
= arr
;
446 locations
->location_count
= count
;
448 for (i
= 0; i
< count
; i
++) {
449 if (!decode_fs_location4(xdr
, &arr
[i
])) {
460 static bool_t
xdr_client_owner4(
464 unsigned char *co_ownerid
= co
->co_ownerid
;
465 if (!xdr_opaque(xdr
, (char *)&co
->co_verifier
[0], NFS4_VERIFIER_SIZE
))
468 return xdr_bytes(xdr
, (char **)&co_ownerid
, &co
->co_ownerid_len
, NFS4_OPAQUE_LIMIT
);
472 static bool_t
encode_state_protect_ops4(
474 state_protect_ops4
*spo
)
476 if (!xdr_bitmap4(xdr
, &spo
->spo_must_enforce
))
479 return xdr_bitmap4(xdr
, &spo
->spo_must_allow
);
482 static bool_t
encode_ssv_sp_parms4(
486 if (!encode_state_protect_ops4(xdr
, &spp
->ssp_ops
))
489 if (!xdr_bytes(xdr
, &spp
->ssp_hash_algs
,
490 &spp
->ssp_hash_algs_len
, NFS4_OPAQUE_LIMIT
))
493 if (!xdr_bytes(xdr
, &spp
->ssp_encr_algs
,
494 &spp
->ssp_encr_algs_len
, NFS4_OPAQUE_LIMIT
))
497 if (!xdr_u_int32_t(xdr
, &spp
->ssp_window
))
500 return xdr_u_int32_t(xdr
, &spp
->ssp_num_gss_handles
);
504 static bool_t
xdr_state_protect4_a(
506 state_protect4_a
*spa
)
508 bool_t result
= TRUE
;
510 if (!xdr_u_int32_t(xdr
, (u_int32_t
*)&spa
->spa_how
))
513 switch (spa
->spa_how
)
519 result
= xdr_state_protect_ops4(xdr
, &spa
->u
.spa_mach_ops
);
522 result
= xdr_ssv_sp_parms4(xdr
, &spa
->u
.spa_ssv_parms
);
526 eprintf("encode_state_protect4_a: state protect "
527 "type %d not supported.\n", spa
->spa_how
);
534 static bool_t
xdr_nfs_impl_id4(
538 unsigned char *nii_domain
= nii
->nii_domain
;
539 unsigned char *nii_name
= nii
->nii_name
;
541 if (!xdr_bytes(xdr
, (char **)&nii_domain
, &nii
->nii_domain_len
, NFS4_OPAQUE_LIMIT
))
544 if (!xdr_bytes(xdr
, (char **)&nii_name
, &nii
->nii_name_len
, NFS4_OPAQUE_LIMIT
))
547 return xdr_nfstime4(xdr
, &nii
->nii_date
);
551 static bool_t
encode_op_exchange_id(
558 nfs41_exchange_id_args
*args
= (nfs41_exchange_id_args
*)argop
->arg
;
560 if (unexpected_op(argop
->op
, OP_EXCHANGE_ID
))
563 if (!xdr_client_owner4(xdr
, args
->eia_clientowner
))
566 if (!xdr_u_int32_t(xdr
, &args
->eia_flags
))
569 if (!xdr_state_protect4_a(xdr
, &args
->eia_state_protect
))
572 if (args
->eia_client_impl_id
)
574 if (!xdr_u_int32_t(xdr
, &one
))
576 return xdr_nfs_impl_id4(xdr
, args
->eia_client_impl_id
);
579 return xdr_u_int32_t(xdr
, &zero
);
584 static bool_t
decode_state_protect_ops4(
586 state_protect_ops4
*spo
)
588 if (!xdr_bitmap4(xdr
, &spo
->spo_must_enforce
))
591 return xdr_bitmap4(xdr
, &spo
->spo_must_allow
);
594 static bool_t
decode_ssv_prot_info4(
600 if (!decode_state_protect_ops4(xdr
, &spi
->spi_ops
))
603 if (!xdr_u_int32_t(xdr
, &spi
->spi_hash_alg
))
606 if (!xdr_u_int32_t(xdr
, &spi
->spi_encr_alg
))
609 if (!xdr_u_int32_t(xdr
, &spi
->spi_ssv_len
))
612 if (!xdr_u_int32_t(xdr
, &spi
->spi_window
))
615 /* TODO: spi->spi_handles */
616 return xdr_u_int32_t(xdr
, 0);
618 if (!xdr_u_int32_t(xdr, &spi->spi_handles.count))
621 for (i = 0; i < spi->spi_handles.count; i++)
622 if (!xdr_opaque(xdr, &spi->spi_handles.arr[i])
629 static bool_t
xdr_state_protect4_r(
631 state_protect4_r
*spr
)
633 bool_t result
= TRUE
;
635 if (!xdr_u_int32_t(xdr
, (uint32_t *)&spr
->spr_how
))
638 switch (spr
->spr_how
)
644 result
= decode_state_protect_ops4(xdr
, &spr
->u
.spr_mach_ops
);
647 result
= decode_ssv_prot_info4(xdr
, &spr
->u
.spr_ssv_info
);
651 eprintf("decode_state_protect4_r: state protect "
652 "type %d not supported.\n", spr
->spr_how
);
659 static bool_t
xdr_server_owner4(
663 char *so_major_id
= so
->so_major_id
;
665 if (!xdr_u_hyper(xdr
, &so
->so_minor_id
))
668 return xdr_bytes(xdr
, (char **)&so_major_id
,
669 &so
->so_major_id_len
, NFS4_OPAQUE_LIMIT
);
672 static bool_t
decode_op_exchange_id(
676 nfs41_exchange_id_res
*res
= (nfs41_exchange_id_res
*)resop
->res
;
677 char *server_scope
= (char *)res
->server_scope
;
679 if (unexpected_op(resop
->op
, OP_EXCHANGE_ID
))
682 if (!xdr_u_int32_t(xdr
, &res
->status
))
685 if (res
->status
!= NFS4_OK
)
688 if (!xdr_u_hyper(xdr
, &res
->clientid
))
691 if (!xdr_u_int32_t(xdr
, &res
->sequenceid
))
694 if (!xdr_u_int32_t(xdr
, &res
->flags
))
697 if (!xdr_state_protect4_r(xdr
, &res
->state_protect
))
700 if (!xdr_server_owner4(xdr
, &res
->server_owner
))
703 return xdr_bytes(xdr
, &server_scope
,
704 &res
->server_scope_len
, NFS4_OPAQUE_LIMIT
);
710 static bool_t
xdr_channel_attrs4(
712 nfs41_channel_attrs
*attrs
)
717 /* count4 ca_headerpadsize */
718 if (!xdr_u_int32_t(xdr
, &attrs
->ca_headerpadsize
))
721 /* count4 ca_maxrequestsize */
722 if (!xdr_u_int32_t(xdr
, &attrs
->ca_maxrequestsize
))
725 /* count4 ca_maxresponsesize */
726 if (!xdr_u_int32_t(xdr
, &attrs
->ca_maxresponsesize
))
729 /* count4 ca_maxresponsesize_cached */
730 if (!xdr_u_int32_t(xdr
, &attrs
->ca_maxresponsesize_cached
))
733 /* count4 ca_maxoperations */
734 if (!xdr_u_int32_t(xdr
, &attrs
->ca_maxoperations
))
737 /* count4 ca_maxrequests */
738 if (!xdr_u_int32_t(xdr
, &attrs
->ca_maxrequests
))
741 if (xdr
->x_op
== XDR_ENCODE
) {
742 /* uint32_t ca_rdma_ird<1> */
743 if (attrs
->ca_rdma_ird
)
745 if (!xdr_u_int32_t(xdr
, &one
))
747 return xdr_u_int32_t(xdr
, attrs
->ca_rdma_ird
);
750 return xdr_u_int32_t(xdr
, &zero
);
753 else if (xdr
->x_op
== XDR_DECODE
) {
756 /* uint32_t ca_rdma_ird<1> */
757 if (!xdr_u_int32_t(xdr
, &count
))
762 return xdr_u_int32_t(xdr
, attrs
->ca_rdma_ird
);
768 eprintf("%s: xdr->x_op %d not supported.\n",
769 "xdr_channel_attrs4", xdr
->x_op
);
774 static bool_t
encode_backchannel_sec_parms(
776 nfs41_callback_secparms
*args
)
780 if (!xdr_u_int32_t(xdr
, &args
->type
))
783 switch (args
->type
) {
784 case AUTH_NONE
: return TRUE
;
786 if (!xdr_u_int32_t(xdr
, &args
->u
.auth_sys
.stamp
))
788 if (!xdr_string(xdr
, &args
->u
.auth_sys
.machinename
, NI_MAXHOST
))
790 return xdr_u_int32_t(xdr
, &zero
) && xdr_u_int32_t(xdr
, &zero
) &&
791 xdr_u_int32_t(xdr
, &zero
);
798 static bool_t
encode_op_create_session(
802 nfs41_create_session_args
*args
= (nfs41_create_session_args
*)argop
->arg
;
803 nfs41_callback_secparms
*cb_secparams
= args
->csa_cb_secparams
;
804 uint32_t cb_count
= 2;
806 if (unexpected_op(argop
->op
, OP_CREATE_SESSION
))
809 /* clientid4 csa_clientid */
810 if (!xdr_u_hyper(xdr
, &args
->csa_clientid
))
813 /* sequenceid4 csa_sequence */
814 if (!xdr_u_int32_t(xdr
, &args
->csa_sequence
))
817 /* TODO: uint32_t csa_flags = 0 */
818 if (!xdr_u_int32_t(xdr
, &args
->csa_flags
))
821 /* channel_attrs4 csa_fore_chan_attrs */
822 if (!xdr_channel_attrs4(xdr
, &args
->csa_fore_chan_attrs
))
825 /* channel_attrs4 csa_back_chan_attrs */
826 if (!xdr_channel_attrs4(xdr
, &args
->csa_back_chan_attrs
))
829 /* TODO: uint32_t csa_cb_program = 1234 */
830 if (!xdr_u_int32_t(xdr
, &args
->csa_cb_program
))
833 return xdr_array(xdr
, (char **)&cb_secparams
, &cb_count
,
834 3, sizeof(nfs41_callback_secparms
), (xdrproc_t
) encode_backchannel_sec_parms
);
837 static bool_t
decode_op_create_session(
842 nfs41_create_session_res
*res
= (nfs41_create_session_res
*)resop
->res
;
844 if (unexpected_op(resop
->op
, OP_CREATE_SESSION
))
847 if (!xdr_u_int32_t(xdr
, &opstatus
))
850 if (opstatus
!= NFS4_OK
)
853 if (!xdr_opaque(xdr
, (char *)res
->csr_sessionid
, NFS4_SESSIONID_SIZE
))
856 /* sequenceid4 csr_sequence */
857 if (!xdr_u_int32_t(xdr
, &res
->csr_sequence
))
860 /* uint32_t csr_flags */
861 if (!xdr_u_int32_t(xdr
, &res
->csr_flags
))
864 /* channel_attrs4 csr_fore_chan_attrs */
865 if (!xdr_channel_attrs4(xdr
, res
->csr_fore_chan_attrs
))
868 /* channel_attrs4 csr_back_chan_attrs */
869 return xdr_channel_attrs4(xdr
, res
->csr_back_chan_attrs
);
874 * OP_BIND_CONN_TO_SESSION
876 static bool_t
encode_op_bind_conn_to_session(
882 nfs41_bind_conn_to_session_args
*args
=
883 (nfs41_bind_conn_to_session_args
*)argop
->arg
;
885 if (unexpected_op(argop
->op
, OP_BIND_CONN_TO_SESSION
))
888 if (!xdr_opaque(xdr
, (char *)args
->sessionid
, NFS4_SESSIONID_SIZE
))
891 if (!xdr_enum(xdr
, (enum_t
*)&args
->dir
))
894 return xdr_u_int32_t(xdr
, &zero
); /* bctsa_use_conn_in_rdma_mode = false */
897 static bool_t
decode_op_bind_conn_to_session(
901 unsigned char sessionid_ignored
[NFS4_SESSIONID_SIZE
];
902 nfs41_bind_conn_to_session_res
*res
=
903 (nfs41_bind_conn_to_session_res
*)resop
->res
;
904 bool_t use_rdma_ignored
;
906 if (unexpected_op(resop
->op
, OP_BIND_CONN_TO_SESSION
))
909 if (!xdr_enum(xdr
, (enum_t
*)&res
->status
))
912 if (res
->status
== NFS4_OK
) {
913 if (!xdr_opaque(xdr
, (char *)&sessionid_ignored
, NFS4_SESSIONID_SIZE
))
916 if (!xdr_enum(xdr
, (enum_t
*)&res
->dir
))
919 return xdr_bool(xdr
, &use_rdma_ignored
);
928 static bool_t
encode_op_destroy_session(
932 nfs41_destroy_session_args
*args
= (nfs41_destroy_session_args
*)argop
->arg
;
934 if (unexpected_op(argop
->op
, OP_DESTROY_SESSION
))
937 return xdr_opaque(xdr
, (char *)args
->dsa_sessionid
, NFS4_SESSIONID_SIZE
);
940 static bool_t
decode_op_destroy_session(
944 nfs41_destroy_session_res
*res
= (nfs41_destroy_session_res
*)resop
->res
;
946 if (unexpected_op(resop
->op
, OP_DESTROY_SESSION
))
949 return xdr_u_int32_t(xdr
, &res
->dsr_status
);
953 * OP_DESTROY_CLIENTID
955 static bool_t
encode_op_destroy_clientid(
959 nfs41_destroy_clientid_args
*args
= (nfs41_destroy_clientid_args
*)argop
->arg
;
961 if (unexpected_op(argop
->op
, OP_DESTROY_CLIENTID
))
964 return xdr_u_hyper(xdr
, &args
->dca_clientid
);
967 static bool_t
decode_op_destroy_clientid(
971 nfs41_destroy_clientid_res
*res
= (nfs41_destroy_clientid_res
*)resop
->res
;
973 if (unexpected_op(resop
->op
, OP_DESTROY_CLIENTID
))
976 return xdr_u_int32_t(xdr
, &res
->dcr_status
);
983 static bool_t
encode_op_sequence(
987 nfs41_sequence_args
*args
= (nfs41_sequence_args
*)argop
->arg
;
989 if (unexpected_op(argop
->op
, OP_SEQUENCE
))
992 if (!xdr_opaque(xdr
, (char *)args
->sa_sessionid
, NFS4_SESSIONID_SIZE
))
995 if (!xdr_u_int32_t(xdr
, &args
->sa_sequenceid
))
998 if (!xdr_u_int32_t(xdr
, &args
->sa_slotid
))
1001 if (!xdr_u_int32_t(xdr
, &args
->sa_highest_slotid
))
1004 return xdr_bool(xdr
, &args
->sa_cachethis
);
1007 static bool_t
xdr_sequence_res_ok(
1009 nfs41_sequence_res_ok
*res
)
1011 if (!xdr_opaque(xdr
, (char *)res
->sr_sessionid
, NFS4_SESSIONID_SIZE
))
1014 if (!xdr_u_int32_t(xdr
, &res
->sr_sequenceid
))
1017 if (!xdr_u_int32_t(xdr
, &res
->sr_slotid
))
1020 if (!xdr_u_int32_t(xdr
, &res
->sr_highest_slotid
))
1023 if (!xdr_u_int32_t(xdr
, &res
->sr_target_highest_slotid
))
1026 return xdr_u_int32_t(xdr
, &res
->sr_status_flags
);
1029 static bool_t
decode_op_sequence(
1033 nfs41_sequence_res
*res
= (nfs41_sequence_res
*)resop
->res
;
1035 if (unexpected_op(resop
->op
, OP_SEQUENCE
))
1038 if (!xdr_u_int32_t(xdr
, &res
->sr_status
))
1041 if (res
->sr_status
== NFS4_OK
)
1042 return xdr_sequence_res_ok(xdr
, &res
->sr_resok4
);
1049 * OP_RECLAIM_COMPLETE
1051 static bool_t
encode_op_reclaim_complete(
1055 bool_t zero
= FALSE
;
1057 if (unexpected_op(argop
->op
, OP_RECLAIM_COMPLETE
))
1060 /* rca_one_fs = 0 indicates that the reclaim applies to all filesystems */
1061 return xdr_bool(xdr
, &zero
);
1064 static bool_t
decode_op_reclaim_complete(
1068 nfs41_reclaim_complete_res
*res
= (nfs41_reclaim_complete_res
*)resop
->res
;
1070 if (unexpected_op(resop
->op
, OP_RECLAIM_COMPLETE
))
1073 return xdr_enum(xdr
, (enum_t
*)&res
->status
);
1080 static bool_t
encode_op_putfh(
1084 nfs41_putfh_args
*args
= (nfs41_putfh_args
*)argop
->arg
;
1086 if (unexpected_op(argop
->op
, OP_PUTFH
))
1089 return xdr_fh(xdr
, &args
->file
->fh
);
1092 static bool_t
decode_op_putfh(
1096 nfs41_putfh_res
*res
= (nfs41_putfh_res
*)resop
->res
;
1098 if (unexpected_op(resop
->op
, OP_PUTFH
))
1101 return xdr_u_int32_t(xdr
, &res
->status
);
1108 static bool_t
encode_op_putrootfh(
1112 if (unexpected_op(argop
->op
, OP_PUTROOTFH
))
1118 static bool_t
decode_op_putrootfh(
1122 nfs41_putrootfh_res
*res
= (nfs41_putrootfh_res
*)resop
->res
;
1124 if (unexpected_op(resop
->op
, OP_PUTROOTFH
))
1127 return xdr_u_int32_t(xdr
, &res
->status
);
1134 static bool_t
encode_op_getfh(
1138 if (unexpected_op(argop
->op
, OP_GETFH
))
1145 static bool_t
decode_op_getfh(
1149 nfs41_getfh_res
*res
= (nfs41_getfh_res
*)resop
->res
;
1151 if (unexpected_op(resop
->op
, OP_GETFH
))
1154 if (!xdr_u_int32_t(xdr
, &res
->status
))
1157 if (res
->status
== NFS4_OK
)
1158 return xdr_fh(xdr
, res
->fh
);
1167 static bool_t
encode_op_lookup(
1171 nfs41_lookup_args
*args
= (nfs41_lookup_args
*)argop
->arg
;
1173 if (unexpected_op(argop
->op
, OP_LOOKUP
))
1176 return encode_component(xdr
, args
->name
);
1179 static bool_t
decode_op_lookup(
1183 nfs41_lookup_res
*res
= (nfs41_lookup_res
*)resop
->res
;
1185 if (unexpected_op(resop
->op
, OP_LOOKUP
))
1188 return xdr_u_int32_t(xdr
, &res
->status
);
1195 static bool_t
encode_op_access(
1199 nfs41_access_args
*args
= (nfs41_access_args
*)argop
->arg
;
1201 if (unexpected_op(argop
->op
, OP_ACCESS
))
1204 return xdr_u_int32_t(xdr
, &args
->access
);
1207 static bool_t
decode_op_access(
1211 nfs41_access_res
*res
= (nfs41_access_res
*)resop
->res
;
1213 if (unexpected_op(resop
->op
, OP_ACCESS
))
1216 if (!xdr_u_int32_t(xdr
, &res
->status
))
1219 if (res
->status
== NFS4_OK
)
1221 if (!xdr_u_int32_t(xdr
, &res
->supported
))
1224 return xdr_u_int32_t(xdr
, &res
->access
);
1233 static bool_t
encode_op_close(
1237 nfs41_op_close_args
*args
= (nfs41_op_close_args
*)argop
->arg
;
1240 if (unexpected_op(argop
->op
, OP_CLOSE
))
1243 if (!xdr_u_int32_t(xdr
, &zero
)) // This should be ignored by server
1246 return xdr_stateid4(xdr
, &args
->stateid
->stateid
);
1249 static bool_t
decode_op_close(
1254 nfs41_op_close_res
*res
= (nfs41_op_close_res
*)resop
->res
;
1256 if (unexpected_op(resop
->op
, OP_CLOSE
))
1259 if (!xdr_u_int32_t(xdr
, &res
->status
))
1262 if (res
->status
== NFS4_OK
)
1263 return xdr_stateid4(xdr
, &ignored
);
1272 static bool_t
encode_op_commit(
1276 nfs41_commit_args
*args
= (nfs41_commit_args
*)argop
->arg
;
1278 if (unexpected_op(argop
->op
, OP_COMMIT
))
1281 if (!xdr_u_hyper(xdr
, &args
->offset
))
1284 return xdr_u_int32_t(xdr
, &args
->count
);
1287 static bool_t
decode_op_commit(
1291 nfs41_commit_res
*res
= (nfs41_commit_res
*)resop
->res
;
1293 if (unexpected_op(resop
->op
, OP_COMMIT
))
1296 if (!xdr_u_int32_t(xdr
, &res
->status
))
1299 if (res
->status
== NFS4_OK
)
1300 return xdr_opaque(xdr
, (char *)res
->verf
->verf
, NFS4_VERIFIER_SIZE
);
1309 static bool_t
encode_createtype4(
1313 bool_t result
= TRUE
;
1314 const char *linkdata
;
1316 if (!xdr_u_int32_t(xdr
, &ct
->type
))
1322 linkdata
= ct
->u
.lnk
.linkdata
;
1323 result
= xdr_bytes(xdr
, (char**)&linkdata
, &ct
->u
.lnk
.linkdata_len
,
1328 result
= xdr_u_int32_t(xdr
, &ct
->u
.devdata
.specdata1
);
1330 result
= xdr_u_int32_t(xdr
, &ct
->u
.devdata
.specdata2
);
1333 // Some types need no further action
1339 static bool_t
encode_createattrs4(
1341 nfs41_file_info
* createattrs
)
1345 /* encode attribute values from createattrs->info into attrs.attr_vals */
1346 attrs
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1347 if (!encode_file_attrs(&attrs
, createattrs
))
1350 return xdr_fattr4(xdr
, &attrs
);
1353 static bool_t
encode_op_create(
1357 nfs41_create_args
*args
= (nfs41_create_args
*)argop
->arg
;
1359 if (unexpected_op(argop
->op
, OP_CREATE
))
1362 if (!encode_createtype4(xdr
, &args
->objtype
))
1365 if (!encode_component(xdr
, args
->name
))
1368 return encode_createattrs4(xdr
, args
->createattrs
);
1371 static bool_t
xdr_change_info4(
1373 change_info4
*cinfo
)
1375 if (!xdr_bool(xdr
, &cinfo
->atomic
))
1378 if (!xdr_u_hyper(xdr
, &cinfo
->before
))
1381 return xdr_u_hyper(xdr
, &cinfo
->after
);
1384 static bool_t
decode_op_create(
1388 nfs41_create_res
*res
= (nfs41_create_res
*)resop
->res
;
1390 if (unexpected_op(resop
->op
, OP_CREATE
))
1393 if (!xdr_u_int32_t(xdr
, &res
->status
))
1396 if (res
->status
== NFS4_OK
)
1398 if (!xdr_change_info4(xdr
, &res
->cinfo
))
1400 return xdr_bitmap4(xdr
, &res
->attrset
);
1409 static bool_t
encode_op_link(
1413 nfs41_link_args
*args
= (nfs41_link_args
*)argop
->arg
;
1415 if (unexpected_op(argop
->op
, OP_LINK
))
1418 return encode_component(xdr
, args
->newname
);
1421 static bool_t
decode_op_link(
1425 nfs41_link_res
*res
= (nfs41_link_res
*)resop
->res
;
1427 if (unexpected_op(resop
->op
, OP_LINK
))
1430 if (!xdr_u_int32_t(xdr
, &res
->status
))
1433 if (res
->status
== NFS4_OK
)
1434 return xdr_change_info4(xdr
, &res
->cinfo
);
1443 static bool_t
xdr_locker4(
1447 if (xdr
->x_op
!= XDR_ENCODE
) {
1448 eprintf("%s: xdr->x_op %d is not supported!\n",
1449 "xdr_locker4", xdr
->x_op
);
1453 if (!xdr_bool(xdr
, &locker
->new_lock_owner
))
1456 if (locker
->new_lock_owner
) {
1457 /* open_to_lock_owner4 open_owner */
1458 if (!xdr_u_int32_t(xdr
, &locker
->u
.open_owner
.open_seqid
))
1461 if (!xdr_stateid4(xdr
, &locker
->u
.open_owner
.open_stateid
->stateid
))
1464 if (!xdr_u_int32_t(xdr
, &locker
->u
.open_owner
.lock_seqid
))
1467 return xdr_state_owner4(xdr
, locker
->u
.open_owner
.lock_owner
);
1469 /* exist_lock_owner4 lock_owner */
1470 if (!xdr_stateid4(xdr
, &locker
->u
.lock_owner
.lock_stateid
->stateid
))
1473 return xdr_u_int32_t(xdr
, &locker
->u
.lock_owner
.lock_seqid
);
1477 static bool_t
encode_op_lock(
1481 nfs41_lock_args
*args
= (nfs41_lock_args
*)argop
->arg
;
1483 if (unexpected_op(argop
->op
, OP_LOCK
))
1486 if (!xdr_u_int32_t(xdr
, &args
->locktype
))
1489 if (!xdr_bool(xdr
, &args
->reclaim
))
1492 if (!xdr_u_hyper(xdr
, &args
->offset
))
1495 if (!xdr_u_hyper(xdr
, &args
->length
))
1498 return xdr_locker4(xdr
, &args
->locker
);
1501 static bool_t
decode_lock_res_denied(
1503 lock_res_denied
*denied
)
1505 if (!xdr_u_hyper(xdr
, &denied
->offset
))
1508 if (!xdr_u_hyper(xdr
, &denied
->length
))
1511 if (!xdr_u_int32_t(xdr
, &denied
->locktype
))
1514 return xdr_state_owner4(xdr
, &denied
->owner
);
1517 static bool_t
decode_op_lock(
1521 nfs41_lock_res
*res
= (nfs41_lock_res
*)resop
->res
;
1523 if (unexpected_op(resop
->op
, OP_LOCK
))
1526 if (!xdr_u_int32_t(xdr
, &res
->status
))
1529 switch (res
->status
) {
1531 return xdr_stateid4(xdr
, res
->u
.resok4
.lock_stateid
);
1533 case NFS4ERR_DENIED
:
1534 return decode_lock_res_denied(xdr
, &res
->u
.denied
);
1547 static bool_t
encode_op_lockt(
1551 nfs41_lockt_args
*args
= (nfs41_lockt_args
*)argop
->arg
;
1553 if (unexpected_op(argop
->op
, OP_LOCKT
))
1556 if (!xdr_u_int32_t(xdr
, &args
->locktype
))
1559 if (!xdr_u_hyper(xdr
, &args
->offset
))
1562 if (!xdr_u_hyper(xdr
, &args
->length
))
1565 return xdr_state_owner4(xdr
, args
->owner
);
1568 static bool_t
decode_op_lockt(
1572 nfs41_lockt_res
*res
= (nfs41_lockt_res
*)resop
->res
;
1574 if (unexpected_op(resop
->op
, OP_LOCKT
))
1577 if (!xdr_u_int32_t(xdr
, &res
->status
))
1580 if (res
->status
== NFS4ERR_DENIED
)
1581 return decode_lock_res_denied(xdr
, &res
->denied
);
1590 static bool_t
encode_op_locku(
1594 nfs41_locku_args
*args
= (nfs41_locku_args
*)argop
->arg
;
1596 if (unexpected_op(argop
->op
, OP_LOCKU
))
1599 if (!xdr_u_int32_t(xdr
, &args
->locktype
))
1602 if (!xdr_u_int32_t(xdr
, &args
->seqid
))
1605 if (!xdr_stateid4(xdr
, &args
->lock_stateid
->stateid
))
1608 if (!xdr_u_hyper(xdr
, &args
->offset
))
1611 return xdr_u_hyper(xdr
, &args
->length
);
1614 static bool_t
decode_op_locku(
1618 nfs41_locku_res
*res
= (nfs41_locku_res
*)resop
->res
;
1620 if (unexpected_op(resop
->op
, OP_LOCKU
))
1623 if (!xdr_u_int32_t(xdr
, &res
->status
))
1626 if (res
->status
== NFS4_OK
)
1627 return xdr_stateid4(xdr
, res
->lock_stateid
);
1636 static bool_t
encode_op_delegpurge(
1642 if (unexpected_op(argop
->op
, OP_DELEGPURGE
))
1645 /* The client SHOULD set the client field to zero,
1646 * and the server MUST ignore the clientid field. */
1647 return xdr_u_int64_t(xdr
, &zero
);
1650 static bool_t
decode_op_delegpurge(
1654 nfs41_delegpurge_res
*res
= (nfs41_delegpurge_res
*)resop
->res
;
1656 if (unexpected_op(resop
->op
, OP_DELEGPURGE
))
1659 return xdr_u_int32_t(xdr
, &res
->status
);
1666 static bool_t
encode_op_delegreturn(
1670 nfs41_delegreturn_args
*args
= (nfs41_delegreturn_args
*)argop
->arg
;
1672 if (unexpected_op(argop
->op
, OP_DELEGRETURN
))
1675 return xdr_stateid4(xdr
, &args
->stateid
->stateid
);
1678 static bool_t
decode_op_delegreturn(
1682 nfs41_delegreturn_res
*res
= (nfs41_delegreturn_res
*)resop
->res
;
1684 if (unexpected_op(resop
->op
, OP_DELEGRETURN
))
1687 return xdr_u_int32_t(xdr
, &res
->status
);
1694 static bool_t
encode_op_getattr(
1698 nfs41_getattr_args
*args
= (nfs41_getattr_args
*)argop
->arg
;
1700 if (unexpected_op(argop
->op
, OP_GETATTR
))
1703 return xdr_bitmap4(xdr
, args
->attr_request
);
1706 static bool_t
decode_file_attrs(
1709 nfs41_file_info
*info
)
1711 if (attrs
->attrmask
.count
>= 1) {
1712 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_SUPPORTED_ATTRS
) {
1713 if (!xdr_bitmap4(xdr
, info
->supported_attrs
))
1716 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_TYPE
) {
1717 if (!xdr_u_int32_t(xdr
, &info
->type
))
1720 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_CHANGE
) {
1721 if (!xdr_u_hyper(xdr
, &info
->change
))
1724 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_SIZE
) {
1725 if (!xdr_u_hyper(xdr
, &info
->size
))
1728 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_LINK_SUPPORT
) {
1729 if (!xdr_bool(xdr
, &info
->link_support
))
1732 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_SYMLINK_SUPPORT
) {
1733 if (!xdr_bool(xdr
, &info
->symlink_support
))
1736 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_FSID
) {
1737 if (!xdr_fsid(xdr
, &info
->fsid
))
1740 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_LEASE_TIME
) {
1741 if (!xdr_u_int32_t(xdr
, &info
->lease_time
))
1744 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_RDATTR_ERROR
) {
1745 if (!xdr_u_int32_t(xdr
, &info
->rdattr_error
))
1748 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_ACL
) {
1749 nfsacl41
*acl
= info
->acl
;
1750 if (!xdr_array(xdr
, (char**)&acl
->aces
, &acl
->count
,
1751 32, sizeof(nfsace4
), (xdrproc_t
)xdr_nfsace4
))
1754 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_ACLSUPPORT
) {
1755 if (!xdr_u_int32_t(xdr
, &info
->aclsupport
))
1758 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_ARCHIVE
) {
1759 if (!xdr_bool(xdr
, &info
->archive
))
1762 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_CANSETTIME
) {
1763 if (!xdr_bool(xdr
, &info
->cansettime
))
1766 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_CASE_INSENSITIVE
) {
1767 if (!xdr_bool(xdr
, &info
->case_insensitive
))
1770 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_CASE_PRESERVING
) {
1771 if (!xdr_bool(xdr
, &info
->case_preserving
))
1774 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_FILEID
) {
1775 if (!xdr_u_hyper(xdr
, &info
->fileid
))
1778 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_FS_LOCATIONS
) {
1779 if (!decode_fs_locations4(xdr
, info
->fs_locations
))
1782 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_HIDDEN
) {
1783 if (!xdr_bool(xdr
, &info
->hidden
))
1786 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_MAXREAD
) {
1787 if (!xdr_u_hyper(xdr
, &info
->maxread
))
1790 if (attrs
->attrmask
.arr
[0] & FATTR4_WORD0_MAXWRITE
) {
1791 if (!xdr_u_hyper(xdr
, &info
->maxwrite
))
1795 if (attrs
->attrmask
.count
>= 2) {
1796 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_MODE
) {
1797 if (!xdr_u_int32_t(xdr
, &info
->mode
))
1800 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_NUMLINKS
) {
1801 if (!xdr_u_int32_t(xdr
, &info
->numlinks
))
1804 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_OWNER
) {
1805 char *ptr
= &info
->owner
[0];
1807 if (!xdr_bytes(xdr
, &ptr
, &owner_len
,
1810 info
->owner
[owner_len
] = '\0';
1812 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_OWNER_GROUP
) {
1813 char *ptr
= &info
->owner_group
[0];
1814 uint32_t owner_group_len
;
1815 if (!xdr_bytes(xdr
, &ptr
, &owner_group_len
,
1818 info
->owner_group
[owner_group_len
] = '\0';
1820 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_SPACE_AVAIL
) {
1821 if (!xdr_u_hyper(xdr
, &info
->space_avail
))
1824 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_SPACE_FREE
) {
1825 if (!xdr_u_hyper(xdr
, &info
->space_free
))
1828 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_SPACE_TOTAL
) {
1829 if (!xdr_u_hyper(xdr
, &info
->space_total
))
1832 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_SYSTEM
) {
1833 if (!xdr_bool(xdr
, &info
->system
))
1836 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_ACCESS
) {
1837 if (!xdr_nfstime4(xdr
, &info
->time_access
))
1840 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_CREATE
) {
1841 if (!xdr_nfstime4(xdr
, &info
->time_create
))
1844 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_DELTA
) {
1845 if (!xdr_nfstime4(xdr
, info
->time_delta
))
1848 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_MODIFY
) {
1849 if (!xdr_nfstime4(xdr
, &info
->time_modify
))
1852 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_DACL
) {
1853 if (!xdr_nfsdacl41(xdr
, info
->acl
))
1856 if (attrs
->attrmask
.arr
[1] & FATTR4_WORD1_FS_LAYOUT_TYPE
) {
1857 if (!xdr_layout_types(xdr
, &info
->fs_layout_types
))
1861 if (attrs
->attrmask
.count
>= 3) {
1862 if (attrs
->attrmask
.arr
[2] & FATTR4_WORD2_MDSTHRESHOLD
) {
1863 if (!xdr_mdsthreshold(xdr
, &info
->mdsthreshold
))
1866 if (attrs
->attrmask
.arr
[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT
) {
1867 if (!xdr_bitmap4(xdr
, info
->suppattr_exclcreat
))
1874 static bool_t
decode_op_getattr(
1878 nfs41_getattr_res
*res
= (nfs41_getattr_res
*)resop
->res
;
1880 if (unexpected_op(resop
->op
, OP_GETATTR
))
1883 if (!xdr_u_int32_t(xdr
, &res
->status
))
1886 if (res
->status
== NFS4_OK
)
1890 if (!xdr_fattr4(xdr
, &res
->obj_attributes
))
1892 xdrmem_create(&attr_xdr
, (char *)res
->obj_attributes
.attr_vals
, res
->obj_attributes
.attr_vals_len
, XDR_DECODE
);
1893 return decode_file_attrs(&attr_xdr
, &res
->obj_attributes
, res
->info
);
1902 static bool_t
encode_createhow4(
1906 bool_t result
= TRUE
;
1908 if (!xdr_u_int32_t(xdr
, &ch
->mode
))
1915 result
= encode_createattrs4(xdr
, ch
->createattrs
);
1918 result
= xdr_opaque(xdr
, (char *)ch
->createverf
, NFS4_VERIFIER_SIZE
);
1921 if (!xdr_opaque(xdr
, (char *)ch
->createverf
, NFS4_VERIFIER_SIZE
))
1923 if (!encode_createattrs4(xdr
, ch
->createattrs
))
1930 static bool_t
encode_openflag4(
1934 bool_t result
= TRUE
;
1936 if (!xdr_u_int32_t(xdr
, &of
->opentype
))
1939 switch (of
->opentype
)
1942 result
= encode_createhow4(xdr
, &of
->how
);
1950 static bool_t
encode_claim_deleg_cur(
1953 nfs41_component
*name
)
1955 if (!xdr_stateid4(xdr
, stateid
))
1957 return encode_component(xdr
, name
);
1960 static bool_t
encode_open_claim4(
1964 if (!xdr_u_int32_t(xdr
, &oc
->claim
))
1970 return encode_component(xdr
, oc
->u
.null
.filename
);
1971 case CLAIM_PREVIOUS
:
1972 return xdr_u_int32_t(xdr
, &oc
->u
.prev
.delegate_type
);
1974 return TRUE
; /* use current file handle */
1975 case CLAIM_DELEGATE_CUR
:
1976 return encode_claim_deleg_cur(xdr
,
1977 &oc
->u
.deleg_cur
.delegate_stateid
->stateid
,
1978 oc
->u
.deleg_cur
.name
);
1979 case CLAIM_DELEG_CUR_FH
:
1980 return xdr_stateid4(xdr
,
1981 &oc
->u
.deleg_cur_fh
.delegate_stateid
->stateid
);
1982 case CLAIM_DELEGATE_PREV
:
1983 return encode_component(xdr
, oc
->u
.deleg_prev
.filename
);
1984 case CLAIM_DELEG_PREV_FH
:
1985 return TRUE
; /* use current file handle */
1987 eprintf("encode_open_claim4: unsupported claim %d.\n",
1993 static bool_t
encode_op_open(
1997 nfs41_op_open_args
*args
= (nfs41_op_open_args
*)argop
->arg
;
1999 if (unexpected_op(argop
->op
, OP_OPEN
))
2002 if (!xdr_u_int32_t(xdr
, &args
->seqid
))
2005 if (!xdr_u_int32_t(xdr
, &args
->share_access
))
2008 if (!xdr_u_int32_t(xdr
, &args
->share_deny
))
2011 if (!xdr_state_owner4(xdr
, args
->owner
))
2014 if (!encode_openflag4(xdr
, &args
->openhow
))
2017 return encode_open_claim4(xdr
, args
->claim
);
2020 static bool_t
decode_open_none_delegation4(
2022 open_delegation4
*delegation
)
2024 enum_t why_no_deleg
;
2027 if (!xdr_enum(xdr
, (enum_t
*)&why_no_deleg
))
2030 switch (why_no_deleg
)
2032 case WND4_CONTENTION
:
2034 return xdr_bool(xdr
, &will_signal
);
2040 static bool_t
decode_open_read_delegation4(
2042 open_delegation4
*delegation
)
2044 if (!xdr_stateid4(xdr
, &delegation
->stateid
))
2047 if (!xdr_bool(xdr
, &delegation
->recalled
))
2050 return xdr_nfsace4(xdr
, &delegation
->permissions
);
2053 static bool_t
decode_modified_limit4(
2057 uint32_t blocks
, bytes_per_block
;
2059 if (!xdr_u_int32_t(xdr
, &blocks
))
2062 if (!xdr_u_int32_t(xdr
, &bytes_per_block
))
2065 *filesize
= blocks
* bytes_per_block
;
2071 NFS_LIMIT_BLOCKS
= 2
2074 static bool_t
decode_space_limit4(
2080 if (!xdr_u_int32_t(xdr
, &limitby
))
2085 case NFS_LIMIT_SIZE
:
2086 return xdr_u_hyper(xdr
, filesize
);
2087 case NFS_LIMIT_BLOCKS
:
2088 return decode_modified_limit4(xdr
, filesize
);
2090 eprintf("decode_space_limit4: limitby %d invalid\n", limitby
);
2095 static bool_t
decode_open_write_delegation4(
2097 open_delegation4
*delegation
)
2099 uint64_t size_limit
;
2101 if (!xdr_stateid4(xdr
, &delegation
->stateid
))
2104 if (!xdr_bool(xdr
, &delegation
->recalled
))
2107 if (!decode_space_limit4(xdr
, &size_limit
))
2110 return xdr_nfsace4(xdr
, &delegation
->permissions
);
2113 static bool_t
decode_open_res_ok(
2115 nfs41_op_open_res_ok
*res
)
2117 if (!xdr_stateid4(xdr
, res
->stateid
))
2120 if (!xdr_change_info4(xdr
, &res
->cinfo
))
2123 if (!xdr_u_int32_t(xdr
, &res
->rflags
))
2126 if (!xdr_bitmap4(xdr
, &res
->attrset
))
2129 if (!xdr_enum(xdr
, (enum_t
*)&res
->delegation
->type
))
2132 switch (res
->delegation
->type
)
2134 case OPEN_DELEGATE_NONE
:
2136 case OPEN_DELEGATE_NONE_EXT
:
2137 return decode_open_none_delegation4(xdr
, res
->delegation
);
2138 case OPEN_DELEGATE_READ
:
2139 return decode_open_read_delegation4(xdr
, res
->delegation
);
2140 case OPEN_DELEGATE_WRITE
:
2141 return decode_open_write_delegation4(xdr
, res
->delegation
);
2143 eprintf("decode_open_res_ok: delegation type %d not "
2144 "supported.\n", res
->delegation
->type
);
2149 static bool_t
decode_op_open(
2153 nfs41_op_open_res
*res
= (nfs41_op_open_res
*)resop
->res
;
2155 if (unexpected_op(resop
->op
, OP_OPEN
))
2158 if (!xdr_u_int32_t(xdr
, &res
->status
))
2161 if (res
->status
== NFS4_OK
)
2162 return decode_open_res_ok(xdr
, &res
->resok4
);
2171 static bool_t
encode_op_openattr(
2175 nfs41_openattr_args
*args
= (nfs41_openattr_args
*)argop
->arg
;
2177 if (unexpected_op(argop
->op
, OP_OPENATTR
))
2180 return xdr_bool(xdr
, &args
->createdir
);
2183 static bool_t
decode_op_openattr(
2187 nfs41_openattr_res
*res
= (nfs41_openattr_res
*)resop
->res
;
2189 if (unexpected_op(resop
->op
, OP_OPENATTR
))
2192 return xdr_u_int32_t(xdr
, &res
->status
);
2199 static bool_t
encode_op_read(
2203 nfs41_read_args
*args
= (nfs41_read_args
*)argop
->arg
;
2205 if (unexpected_op(argop
->op
, OP_READ
))
2208 if (!xdr_stateid4(xdr
, &args
->stateid
->stateid
))
2211 if (!xdr_u_hyper(xdr
, &args
->offset
))
2214 return xdr_u_int32_t(xdr
, &args
->count
);
2217 static bool_t
decode_read_res_ok(
2219 nfs41_read_res_ok
*res
)
2221 unsigned char *data
= res
->data
;
2223 if (!xdr_bool(xdr
, &res
->eof
))
2226 return xdr_bytes(xdr
, (char **)&data
, &res
->data_len
, NFS41_MAX_FILEIO_SIZE
);
2229 static bool_t
decode_op_read(
2233 nfs41_read_res
*res
= (nfs41_read_res
*)resop
->res
;
2235 if (unexpected_op(resop
->op
, OP_READ
))
2238 if (!xdr_u_int32_t(xdr
, &res
->status
))
2241 if (res
->status
== NFS4_OK
)
2242 return decode_read_res_ok(xdr
, &res
->resok4
);
2251 static bool_t
encode_op_readdir(
2255 nfs41_readdir_args
*args
= (nfs41_readdir_args
*)argop
->arg
;
2257 if (unexpected_op(argop
->op
, OP_READDIR
))
2260 if (!xdr_u_hyper(xdr
, &args
->cookie
.cookie
))
2263 if (!xdr_opaque(xdr
, (char *)args
->cookie
.verf
, NFS4_VERIFIER_SIZE
))
2266 if (!xdr_u_int32_t(xdr
, &args
->dircount
))
2269 if (!xdr_u_int32_t(xdr
, &args
->maxcount
))
2272 return xdr_bitmap4(xdr
, args
->attr_request
);
2275 typedef struct __readdir_entry_iterator
{
2276 unsigned char *buf_pos
;
2277 uint32_t remaining_len
;
2278 uint32_t *last_entry_offset
;
2279 bool_t ignore_the_rest
;
2280 bool_t has_next_entry
;
2281 } readdir_entry_iterator
;
2283 static bool_t
decode_readdir_entry(
2285 readdir_entry_iterator
*it
)
2288 unsigned char name
[NFS4_OPAQUE_LIMIT
];
2289 unsigned char *nameptr
= &name
[0];
2290 uint32_t name_len
, entry_len
;
2293 /* decode into temporaries so we can determine if there's enough
2294 * room in the buffer for this entry */
2295 ZeroMemory(name
, NFS4_OPAQUE_LIMIT
);
2296 name_len
= NFS4_OPAQUE_LIMIT
;
2297 entry_len
= (uint32_t)FIELD_OFFSET(nfs41_readdir_entry
, name
);
2298 attrs
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
2300 if (!xdr_u_hyper(xdr
, &cookie
))
2303 if (!xdr_bytes(xdr
, (char **)&nameptr
, &name_len
, NFS4_OPAQUE_LIMIT
))
2306 if (!xdr_fattr4(xdr
, &attrs
))
2309 if (!xdr_bool(xdr
, &it
->has_next_entry
))
2312 if (it
->ignore_the_rest
)
2315 name_len
+= 1; /* account for null terminator */
2316 if (entry_len
+ name_len
<= it
->remaining_len
)
2319 nfs41_readdir_entry
*entry
= (nfs41_readdir_entry
*)it
->buf_pos
;
2320 entry
->cookie
= cookie
;
2321 entry
->name_len
= name_len
;
2323 if (it
->has_next_entry
)
2324 entry
->next_entry_offset
= entry_len
+ name_len
;
2326 entry
->next_entry_offset
= 0;
2328 xdrmem_create(&fattr_xdr
, (char *)attrs
.attr_vals
, attrs
.attr_vals_len
, XDR_DECODE
);
2329 if (!(decode_file_attrs(&fattr_xdr
, &attrs
, &entry
->attr_info
)))
2330 entry
->attr_info
.rdattr_error
= NFS4ERR_BADXDR
;
2331 StringCchCopyA(entry
->name
, name_len
, (STRSAFE_LPCSTR
)name
);
2333 it
->buf_pos
+= entry_len
+ name_len
;
2334 it
->remaining_len
-= entry_len
+ name_len
;
2335 it
->last_entry_offset
= &entry
->next_entry_offset
;
2337 else if (it
->last_entry_offset
)
2339 *(it
->last_entry_offset
) = 0;
2340 it
->ignore_the_rest
= 1;
2346 static bool_t
decode_readdir_list(
2348 nfs41_readdir_list
*dirs
)
2350 readdir_entry_iterator iter
;
2351 iter
.buf_pos
= dirs
->entries
;
2352 iter
.remaining_len
= dirs
->entries_len
;
2353 iter
.last_entry_offset
= NULL
;
2354 iter
.ignore_the_rest
= 0;
2355 iter
.has_next_entry
= 0;
2357 if (!xdr_bool(xdr
, &dirs
->has_entries
))
2360 if (dirs
->has_entries
)
2363 if (!decode_readdir_entry(xdr
, &iter
))
2366 } while (iter
.has_next_entry
);
2368 dirs
->entries_len
-= iter
.remaining_len
;
2370 if (!xdr_bool(xdr
, &dirs
->eof
))
2373 /* reset eof if we couldn't fit everything in the buffer */
2374 if (iter
.ignore_the_rest
)
2379 static bool_t
decode_op_readdir(
2383 nfs41_readdir_res
*res
= (nfs41_readdir_res
*)resop
->res
;
2385 if (unexpected_op(resop
->op
, OP_READDIR
))
2388 if (!xdr_u_int32_t(xdr
, &res
->status
))
2391 if (res
->status
== NFS4_OK
) {
2392 if (!xdr_opaque(xdr
, (char *)res
->cookieverf
, NFS4_VERIFIER_SIZE
))
2394 return decode_readdir_list(xdr
, &res
->reply
);
2403 static bool_t
encode_op_readlink(
2407 if (unexpected_op(argop
->op
, OP_READLINK
))
2414 static bool_t
decode_op_readlink(
2418 nfs41_readlink_res
*res
= (nfs41_readlink_res
*)resop
->res
;
2420 if (unexpected_op(resop
->op
, OP_READLINK
))
2423 if (!xdr_u_int32_t(xdr
, &res
->status
))
2426 if (res
->status
== NFS4_OK
) {
2427 char *link
= res
->link
;
2428 return xdr_bytes(xdr
, &link
, &res
->link_len
, res
->link_len
);
2438 static bool_t
encode_op_remove(
2442 nfs41_remove_args
*args
= (nfs41_remove_args
*)argop
->arg
;
2444 if (unexpected_op(argop
->op
, OP_REMOVE
))
2447 return encode_component(xdr
, args
->target
);
2450 static bool_t
decode_op_remove(
2454 nfs41_remove_res
*res
= (nfs41_remove_res
*)resop
->res
;
2456 if (unexpected_op(resop
->op
, OP_REMOVE
))
2459 if (!xdr_u_int32_t(xdr
, &res
->status
))
2462 if (res
->status
== NFS4_OK
)
2463 return xdr_change_info4(xdr
, &res
->cinfo
);
2472 static bool_t
encode_op_rename(
2476 nfs41_rename_args
*args
= (nfs41_rename_args
*)argop
->arg
;
2478 if (unexpected_op(argop
->op
, OP_RENAME
))
2481 if (!encode_component(xdr
, args
->oldname
))
2484 return encode_component(xdr
, args
->newname
);
2487 static bool_t
decode_op_rename(
2491 nfs41_rename_res
*res
= (nfs41_rename_res
*)resop
->res
;
2493 if (unexpected_op(resop
->op
, OP_RENAME
))
2496 if (!xdr_u_int32_t(xdr
, &res
->status
))
2499 if (res
->status
== NFS4_OK
)
2501 if (!xdr_change_info4(xdr
, &res
->source_cinfo
))
2503 return xdr_change_info4(xdr
, &res
->target_cinfo
);
2512 static bool_t
encode_op_restorefh(
2516 if (unexpected_op(argop
->op
, OP_RESTOREFH
))
2523 static bool_t
decode_op_restorefh(
2527 nfs41_restorefh_res
*res
= (nfs41_restorefh_res
*)resop
->res
;
2529 if (unexpected_op(resop
->op
, OP_RESTOREFH
))
2532 return xdr_u_int32_t(xdr
, &res
->status
);
2539 static bool_t
encode_op_savefh(
2543 if (unexpected_op(argop
->op
, OP_SAVEFH
))
2550 static bool_t
decode_op_savefh(
2554 nfs41_savefh_res
*res
= (nfs41_savefh_res
*)resop
->res
;
2556 if (unexpected_op(resop
->op
, OP_SAVEFH
))
2559 return xdr_u_int32_t(xdr
, &res
->status
);
2566 static bool_t
encode_file_attrs(
2568 nfs41_file_info
*info
)
2573 xdrmem_create(&localxdr
, (char *)attrs
->attr_vals
, NFS4_OPAQUE_LIMIT
, XDR_ENCODE
);
2575 attrs
->attr_vals_len
= 0;
2576 ZeroMemory(&attrs
->attrmask
, sizeof(bitmap4
));
2577 attrs
->attrmask
.count
= info
->attrmask
.count
;
2579 if (info
->attrmask
.count
> 0) {
2580 if (info
->attrmask
.arr
[0] & FATTR4_WORD0_SIZE
) {
2581 if (!xdr_u_hyper(&localxdr
, &info
->size
))
2583 attrs
->attrmask
.arr
[0] |= FATTR4_WORD0_SIZE
;
2585 if (info
->attrmask
.arr
[0] & FATTR4_WORD0_ACL
) {
2586 if (!xdr_nfsacl41(&localxdr
, info
->acl
))
2588 attrs
->attrmask
.arr
[0] |= FATTR4_WORD0_ACL
;
2590 if (info
->attrmask
.arr
[0] & FATTR4_WORD0_ARCHIVE
) {
2591 if (!xdr_bool(&localxdr
, &info
->archive
))
2593 attrs
->attrmask
.arr
[0] |= FATTR4_WORD0_ARCHIVE
;
2595 if (info
->attrmask
.arr
[0] & FATTR4_WORD0_HIDDEN
) {
2596 if (!xdr_bool(&localxdr
, &info
->hidden
))
2598 attrs
->attrmask
.arr
[0] |= FATTR4_WORD0_HIDDEN
;
2601 if (info
->attrmask
.count
> 1) {
2602 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_MODE
) {
2603 if (!xdr_u_int32_t(&localxdr
, &info
->mode
))
2605 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_MODE
;
2607 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_SYSTEM
) {
2608 if (!xdr_bool(&localxdr
, &info
->system
))
2610 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_SYSTEM
;
2612 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_ACCESS_SET
) {
2613 if (!xdr_settime4(&localxdr
, &info
->time_access
, info
->time_delta
))
2615 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_TIME_ACCESS_SET
;
2617 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_CREATE
) {
2618 if (!xdr_nfstime4(&localxdr
, &info
->time_create
))
2620 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_TIME_CREATE
;
2622 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_TIME_MODIFY_SET
) {
2623 if (!xdr_settime4(&localxdr
, &info
->time_modify
, info
->time_delta
))
2625 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_TIME_MODIFY_SET
;
2627 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_OWNER
) {
2628 char *ptr
= &info
->owner
[0];
2629 uint32_t owner_len
= (uint32_t)strlen(info
->owner
);
2630 if (!xdr_bytes(&localxdr
, &ptr
, &owner_len
,
2633 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_OWNER
;
2635 if (info
->attrmask
.arr
[1] & FATTR4_WORD1_OWNER_GROUP
) {
2636 char *ptr
= &info
->owner_group
[0];
2637 uint32_t owner_group_len
= (uint32_t)strlen(info
->owner_group
);
2638 if (!xdr_bytes(&localxdr
, &ptr
, &owner_group_len
,
2641 attrs
->attrmask
.arr
[1] |= FATTR4_WORD1_OWNER_GROUP
;
2644 if (info
->attrmask
.count
> 2) {
2645 if (info
->attrmask
.arr
[2] & FATTR4_WORD2_MODE_SET_MASKED
) {
2646 if (!xdr_u_int32_t(&localxdr
, &info
->mode
))
2648 if (!xdr_u_int32_t(&localxdr
, &info
->mode_mask
))
2650 attrs
->attrmask
.arr
[2] |= FATTR4_WORD2_MODE_SET_MASKED
;
2654 /* warn if we try to set attributes that aren't handled */
2655 for (i
= 0; i
< info
->attrmask
.count
; i
++)
2656 if (attrs
->attrmask
.arr
[i
] != info
->attrmask
.arr
[i
])
2657 eprintf("encode_file_attrs() attempted to encode extra "
2658 "attributes in arr[%d]: encoded %d, but wanted %d.\n",
2659 i
, attrs
->attrmask
.arr
[i
], info
->attrmask
.arr
[i
]);
2661 attrs
->attr_vals_len
= xdr_getpos(&localxdr
);
2665 static bool_t
encode_op_setattr(
2669 nfs41_setattr_args
*args
= (nfs41_setattr_args
*)argop
->arg
;
2672 if (unexpected_op(argop
->op
, OP_SETATTR
))
2675 if (!xdr_stateid4(xdr
, &args
->stateid
->stateid
))
2678 /* encode attribute values from args->info into attrs.attr_vals */
2679 attrs
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
2680 if (!encode_file_attrs(&attrs
, args
->info
))
2683 return xdr_fattr4(xdr
, &attrs
);
2686 static bool_t
decode_op_setattr(
2690 nfs41_setattr_res
*res
= (nfs41_setattr_res
*)resop
->res
;
2692 if (unexpected_op(resop
->op
, OP_SETATTR
))
2695 if (!xdr_u_int32_t(xdr
, &res
->status
))
2698 if (res
->status
== NFS4_OK
)
2699 return xdr_bitmap4(xdr
, &res
->attrsset
);
2706 * OP_WANT_DELEGATION
2708 static bool_t
encode_op_want_delegation(
2712 nfs41_want_delegation_args
*args
= (nfs41_want_delegation_args
*)argop
->arg
;
2714 if (unexpected_op(argop
->op
, OP_WANT_DELEGATION
))
2717 if (!xdr_u_int32_t(xdr
, &args
->want
))
2720 if (!xdr_u_int32_t(xdr
, &args
->claim
->claim
))
2723 return args
->claim
->claim
!= CLAIM_PREVIOUS
||
2724 xdr_u_int32_t(xdr
, &args
->claim
->prev_delegate_type
);
2727 static bool_t
decode_op_want_delegation(
2731 nfs41_want_delegation_res
*res
= (nfs41_want_delegation_res
*)resop
->res
;
2733 if (unexpected_op(resop
->op
, OP_WANT_DELEGATION
))
2736 if (!xdr_u_int32_t(xdr
, &res
->status
))
2742 if (!xdr_enum(xdr
, (enum_t
*)&res
->delegation
->type
))
2745 switch (res
->delegation
->type
)
2747 case OPEN_DELEGATE_NONE
:
2749 case OPEN_DELEGATE_NONE_EXT
:
2750 return decode_open_none_delegation4(xdr
, res
->delegation
);
2751 case OPEN_DELEGATE_READ
:
2752 return decode_open_read_delegation4(xdr
, res
->delegation
);
2753 case OPEN_DELEGATE_WRITE
:
2754 return decode_open_write_delegation4(xdr
, res
->delegation
);
2756 eprintf("decode_open_res_ok: delegation type %d not "
2757 "supported.\n", res
->delegation
->type
);
2766 static bool_t
encode_op_free_stateid(
2770 nfs41_free_stateid_args
*args
= (nfs41_free_stateid_args
*)argop
->arg
;
2772 if (unexpected_op(argop
->op
, OP_FREE_STATEID
))
2775 return xdr_stateid4(xdr
, args
->stateid
);
2778 static bool_t
decode_op_free_stateid(
2782 nfs41_free_stateid_res
*res
= (nfs41_free_stateid_res
*)resop
->res
;
2784 if (unexpected_op(resop
->op
, OP_FREE_STATEID
))
2787 return xdr_u_int32_t(xdr
, &res
->status
);
2794 static bool_t
encode_op_test_stateid(
2798 nfs41_test_stateid_args
*args
= (nfs41_test_stateid_args
*)argop
->arg
;
2800 if (unexpected_op(argop
->op
, OP_TEST_STATEID
))
2803 return xdr_array(xdr
, (char**)&args
->stateids
, &args
->count
,
2804 args
->count
, sizeof(stateid_arg
), (xdrproc_t
)xdr_stateid4
);
2807 static bool_t
decode_op_test_stateid(
2811 nfs41_test_stateid_res
*res
= (nfs41_test_stateid_res
*)resop
->res
;
2813 if (unexpected_op(resop
->op
, OP_TEST_STATEID
))
2816 if (!xdr_u_int32_t(xdr
, &res
->status
))
2819 if (res
->status
== NFS4_OK
) {
2820 return xdr_array(xdr
, (char**)&res
->resok
.status
, &res
->resok
.count
,
2821 res
->resok
.count
, sizeof(uint32_t), (xdrproc_t
)xdr_u_int32_t
);
2830 static bool_t
encode_op_write(
2834 nfs41_write_args
*args
= (nfs41_write_args
*)argop
->arg
;
2835 unsigned char *data
= args
->data
;
2837 if (unexpected_op(argop
->op
, OP_WRITE
))
2840 if (!xdr_stateid4(xdr
, &args
->stateid
->stateid
))
2843 if (!xdr_u_hyper(xdr
, &args
->offset
))
2846 if (!xdr_u_int32_t(xdr
, &args
->stable
))
2849 return xdr_bytes(xdr
, (char **)&data
, &args
->data_len
, NFS41_MAX_FILEIO_SIZE
);
2852 static bool_t
xdr_write_verf(
2854 nfs41_write_verf
*verf
)
2856 if (!xdr_enum(xdr
, (enum_t
*)&verf
->committed
))
2859 return xdr_opaque(xdr
, (char *)verf
->verf
, NFS4_VERIFIER_SIZE
);
2862 static bool_t
xdr_write_res_ok(
2864 nfs41_write_res_ok
*res
)
2866 if (!xdr_u_int32_t(xdr
, &res
->count
))
2869 return xdr_write_verf(xdr
, res
->verf
);
2872 static bool_t
decode_op_write(
2876 nfs41_write_res
*res
= (nfs41_write_res
*)resop
->res
;
2878 if (unexpected_op(resop
->op
, OP_WRITE
))
2881 if (!xdr_u_int32_t(xdr
, &res
->status
))
2884 if (res
->status
== NFS4_OK
)
2885 return xdr_write_res_ok(xdr
, &res
->resok4
);
2891 * OP_SECINFO_NO_NAME
2893 static bool_t
xdr_secinfo(
2895 nfs41_secinfo_info
*secinfo
)
2897 if (!xdr_u_int32_t(xdr
, &secinfo
->sec_flavor
))
2899 if (secinfo
->sec_flavor
== RPCSEC_GSS
) {
2900 char *p
= secinfo
->oid
;
2901 if (!xdr_bytes(xdr
, (char **)&p
, &secinfo
->oid_len
, MAX_OID_LEN
))
2903 if (!xdr_u_int32_t(xdr
, &secinfo
->qop
))
2905 if (!xdr_enum(xdr
, (enum_t
*)&secinfo
->type
))
2911 static bool_t
encode_op_secinfo_noname(
2915 nfs41_secinfo_noname_args
*args
= (nfs41_secinfo_noname_args
*)argop
->arg
;
2917 if (unexpected_op(argop
->op
, OP_SECINFO_NO_NAME
))
2920 if (!xdr_enum(xdr
, (enum_t
*)&args
->type
))
2926 static bool_t
decode_op_secinfo_noname(
2930 nfs41_secinfo_noname_res
*res
= (nfs41_secinfo_noname_res
*)resop
->res
;
2931 nfs41_secinfo_info
*secinfo
= res
->secinfo
;
2932 if (unexpected_op(resop
->op
, OP_SECINFO_NO_NAME
))
2935 if (!xdr_u_int32_t(xdr
, &res
->status
))
2938 if (res
->status
== NFS4_OK
)
2939 return xdr_array(xdr
, (char**)&secinfo
, &res
->count
,
2940 MAX_SECINFOS
, sizeof(nfs41_secinfo_info
), (xdrproc_t
)xdr_secinfo
);
2948 static bool_t
encode_op_secinfo(
2952 nfs41_secinfo_args
*args
= (nfs41_secinfo_args
*)argop
->arg
;
2954 if (unexpected_op(argop
->op
, OP_SECINFO
))
2957 if (!encode_component(xdr
, args
->name
))
2963 static bool_t
decode_op_secinfo(
2967 nfs41_secinfo_noname_res
*res
= (nfs41_secinfo_noname_res
*)resop
->res
;
2968 nfs41_secinfo_info
*secinfo
= res
->secinfo
;
2970 if (unexpected_op(resop
->op
, OP_SECINFO
))
2973 if (!xdr_u_int32_t(xdr
, &res
->status
))
2976 if (res
->status
== NFS4_OK
)
2977 return xdr_array(xdr
, (char**)&secinfo
, &res
->count
,
2978 MAX_SECINFOS
, sizeof(nfs41_secinfo_info
), (xdrproc_t
)xdr_secinfo
);
2985 static bool_t
encode_op_getdeviceinfo(
2989 pnfs_getdeviceinfo_args
*args
= (pnfs_getdeviceinfo_args
*)argop
->arg
;
2991 if (unexpected_op(argop
->op
, OP_GETDEVICEINFO
))
2994 if (!xdr_opaque(xdr
, (char *)args
->deviceid
, PNFS_DEVICEID_SIZE
))
2997 if (!xdr_enum(xdr
, (enum_t
*)&args
->layout_type
))
3000 if (!xdr_u_int32_t(xdr
, &args
->maxcount
))
3003 return xdr_bitmap4(xdr
, &args
->notify_types
);
3006 static bool_t
xdr_stripe_indices(
3008 pnfs_stripe_indices
*indices
)
3012 if (!xdr_u_int32_t(xdr
, &count
))
3015 if (count
&& count
!= indices
->count
) {
3017 tmp
= realloc(indices
->arr
, count
* sizeof(uint32_t));
3021 ZeroMemory(indices
->arr
, count
* sizeof(uint32_t));
3022 indices
->count
= count
;
3025 for (i
= 0; i
< indices
->count
; i
++) {
3026 if (!xdr_u_int32_t(xdr
, &indices
->arr
[i
]))
3032 static bool_t
xdr_pnfs_addr(
3037 char *netid
= addr
->netid
;
3038 char *uaddr
= addr
->uaddr
;
3040 if (xdr
->x_op
== XDR_ENCODE
)
3041 len
= sizeof(addr
->netid
);
3042 if (!xdr_bytes(xdr
, &netid
, &len
, NFS41_NETWORK_ID_LEN
))
3045 if (xdr
->x_op
== XDR_DECODE
) {
3046 if (len
< NFS41_NETWORK_ID_LEN
)
3047 addr
->netid
[len
] = 0;
3049 addr
->netid
[NFS41_NETWORK_ID_LEN
] = 0;
3052 if (xdr
->x_op
== XDR_ENCODE
)
3053 len
= sizeof(addr
->uaddr
);
3054 if (!xdr_bytes(xdr
, &uaddr
, &len
, NFS41_UNIVERSAL_ADDR_LEN
))
3057 if (xdr
->x_op
== XDR_DECODE
){
3058 if (len
< NFS41_UNIVERSAL_ADDR_LEN
)
3059 addr
->uaddr
[len
] = 0;
3061 addr
->uaddr
[NFS41_UNIVERSAL_ADDR_LEN
] = 0;
3067 static bool_t
xdr_multi_addr(
3071 netaddr4 dummy
, *dest
;
3074 if (!xdr_u_int32_t(xdr
, &list
->count
))
3077 for (i
= 0; i
< list
->count
; i
++) {
3078 /* if there are too many addrs, decode the extras into 'dummy' */
3079 dest
= i
< NFS41_ADDRS_PER_SERVER
? &list
->arr
[i
] : &dummy
;
3081 if (!xdr_pnfs_addr(xdr
, dest
))
3087 static bool_t
xdr_data_server_list(
3089 pnfs_data_server_list
*servers
)
3093 if (!xdr_u_int32_t(xdr
, &count
))
3096 if (count
&& count
!= servers
->count
) {
3097 pnfs_data_server
*tmp
;
3098 /* clear data server clients; they're still cached with nfs41_root,
3099 * so pnfs_data_server_client() will look them up again */
3100 for (i
= 0; i
< servers
->count
; i
++)
3101 servers
->arr
[i
].client
= NULL
;
3103 tmp
= realloc(servers
->arr
, count
* sizeof(pnfs_data_server
));
3107 ZeroMemory(servers
->arr
, count
* sizeof(pnfs_data_server
));
3108 for (i
= servers
->count
; i
< count
; i
++) /* initialize new elements */
3109 InitializeSRWLock(&servers
->arr
[i
].lock
);
3110 servers
->count
= count
;
3113 for (i
= 0; i
< servers
->count
; i
++) {
3114 if (!xdr_multi_addr(xdr
, &servers
->arr
[i
].addrs
))
3120 static bool_t
xdr_file_device(
3122 pnfs_file_device
*device
)
3124 if (!xdr_stripe_indices(xdr
, &device
->stripes
))
3127 return xdr_data_server_list(xdr
, &device
->servers
);
3130 static bool_t
decode_getdeviceinfo_ok(
3132 pnfs_getdeviceinfo_res_ok
*res_ok
)
3134 u_int32_t len_ignored
;
3136 if (!xdr_enum(xdr
, (enum_t
*)&res_ok
->device
->device
.type
))
3139 if (res_ok
->device
->device
.type
!= PNFS_LAYOUTTYPE_FILE
)
3142 if (!xdr_u_int32_t(xdr
, &len_ignored
))
3145 if (!xdr_file_device(xdr
, res_ok
->device
))
3148 return xdr_bitmap4(xdr
, &res_ok
->notification
);
3151 static bool_t
decode_op_getdeviceinfo(
3155 pnfs_getdeviceinfo_res
*res
= (pnfs_getdeviceinfo_res
*)resop
->res
;
3157 if (unexpected_op(resop
->op
, OP_GETDEVICEINFO
))
3160 if (!xdr_u_int32_t(xdr
, (uint32_t *)&res
->status
))
3163 switch (res
->status
) {
3165 return decode_getdeviceinfo_ok(xdr
, &res
->u
.res_ok
);
3167 case NFS4ERR_TOOSMALL
:
3170 return xdr_u_int32_t(xdr
, &ignored
);
3181 static bool_t
encode_op_layoutcommit(
3185 pnfs_layoutcommit_args
*args
= (pnfs_layoutcommit_args
*)argop
->arg
;
3186 bool_t false_bool
= FALSE
;
3187 bool_t true_bool
= TRUE
;
3188 enum_t pnfs_layout
= PNFS_LAYOUTTYPE_FILE
;
3191 if (unexpected_op(argop
->op
, OP_LAYOUTCOMMIT
))
3194 if (!xdr_u_hyper(xdr
, &args
->offset
))
3197 if (!xdr_u_hyper(xdr
, &args
->length
))
3200 if (!xdr_bool(xdr
, &false_bool
)) /* loca_reclaim = 0 */
3203 if (!xdr_stateid4(xdr
, args
->stateid
))
3206 /* loca_last_write_offset */
3207 if (args
->new_offset
) {
3208 if (!xdr_bool(xdr
, &true_bool
))
3211 if (!xdr_u_hyper(xdr
, args
->new_offset
))
3214 if (!xdr_bool(xdr
, &false_bool
))
3218 /* loca_time_modify */
3219 if (args
->new_time
) {
3220 if (!xdr_bool(xdr
, &true_bool
))
3223 if (!xdr_nfstime4(xdr
, args
->new_time
))
3226 if (!xdr_bool(xdr
, &false_bool
))
3230 /* loca_layoutupdate */
3231 if (!xdr_enum(xdr
, &pnfs_layout
))
3234 return xdr_u_int32_t(xdr
, &zero
);
3237 static bool_t
decode_op_layoutcommit(
3241 pnfs_layoutcommit_res
*res
= (pnfs_layoutcommit_res
*)resop
->res
;
3243 if (unexpected_op(resop
->op
, OP_LAYOUTCOMMIT
))
3246 if (!xdr_u_int32_t(xdr
, &res
->status
))
3249 if (res
->status
== NFS4_OK
) {
3250 if (!xdr_bool(xdr
, &res
->has_new_size
))
3253 if (res
->has_new_size
)
3254 if (!xdr_u_hyper(xdr
, &res
->new_size
))
3263 static bool_t
encode_op_layoutget(
3267 pnfs_layoutget_args
*args
= (pnfs_layoutget_args
*)argop
->arg
;
3269 if (unexpected_op(argop
->op
, OP_LAYOUTGET
))
3272 if (!xdr_bool(xdr
, &args
->signal_layout_avail
))
3275 if (!xdr_u_int32_t(xdr
, (u_int32_t
*)&args
->layout_type
))
3278 if (!xdr_u_int32_t(xdr
, (u_int32_t
*)&args
->iomode
))
3281 if (!xdr_u_hyper(xdr
, &args
->offset
))
3284 if (!xdr_u_hyper(xdr
, &args
->length
))
3287 if (!xdr_u_hyper(xdr
, &args
->minlength
))
3290 if (!xdr_stateid4(xdr
, &args
->stateid
->stateid
))
3293 return xdr_u_int32_t(xdr
, &args
->maxcount
);
3296 static bool_t
decode_file_layout_handles(
3298 pnfs_file_layout_handles
*handles
)
3302 if (!xdr_u_int32_t(xdr
, &count
))
3305 if (count
&& count
!= handles
->count
) {
3307 tmp
= realloc(handles
->arr
, count
* sizeof(nfs41_path_fh
));
3311 ZeroMemory(handles
->arr
, count
* sizeof(nfs41_path_fh
));
3312 handles
->count
= count
;
3315 for (i
= 0; i
< handles
->count
; i
++) {
3316 if (!xdr_fh(xdr
, &handles
->arr
[i
].fh
))
3322 static bool_t
decode_file_layout(
3324 struct list_entry
*list
,
3327 pnfs_file_layout
*layout
;
3328 u_int32_t len_ignored
;
3330 if (!xdr_u_int32_t(xdr
, &len_ignored
))
3333 layout
= calloc(1, sizeof(pnfs_file_layout
));
3337 layout
->layout
.offset
= base
->offset
;
3338 layout
->layout
.length
= base
->length
;
3339 layout
->layout
.iomode
= base
->iomode
;
3340 layout
->layout
.type
= base
->type
;
3341 list_init(&layout
->layout
.entry
);
3343 if (!xdr_opaque(xdr
, (char *)layout
->deviceid
, PNFS_DEVICEID_SIZE
))
3346 if (!xdr_u_int32_t(xdr
, &layout
->util
))
3349 if (!xdr_u_int32_t(xdr
, &layout
->first_index
))
3352 if (!xdr_u_hyper(xdr
, &layout
->pattern_offset
))
3355 if (!decode_file_layout_handles(xdr
, &layout
->filehandles
))
3358 list_add_tail(list
, &layout
->layout
.entry
);
3366 static bool_t
decode_layout(
3368 struct list_entry
*list
)
3372 if (!xdr_u_hyper(xdr
, &layout
.offset
))
3375 if (!xdr_u_hyper(xdr
, &layout
.length
))
3378 if (!xdr_enum(xdr
, (enum_t
*)&layout
.iomode
))
3381 if (!xdr_enum(xdr
, (enum_t
*)&layout
.type
))
3384 switch (layout
.type
) {
3385 case PNFS_LAYOUTTYPE_FILE
:
3386 return decode_file_layout(xdr
, list
, &layout
);
3389 eprintf("%s: received non-FILE layout type, %d\n",
3390 "decode_file_layout", layout
.type
);
3395 static bool_t
decode_layout_res_ok(
3397 pnfs_layoutget_res_ok
*res
)
3401 if (!xdr_bool(xdr
, &res
->return_on_close
))
3404 if (!xdr_stateid4(xdr
, &res
->stateid
))
3407 if (!xdr_u_int32_t(xdr
, &res
->count
))
3410 for (i
= 0; i
< res
->count
; i
++)
3411 if (!decode_layout(xdr
, &res
->layouts
))
3416 static bool_t
decode_op_layoutget(
3420 pnfs_layoutget_res
*res
= (pnfs_layoutget_res
*)resop
->res
;
3422 if (unexpected_op(resop
->op
, OP_LAYOUTGET
))
3425 if (!xdr_u_int32_t(xdr
, (uint32_t *)&res
->status
))
3428 switch (res
->status
) {
3430 return decode_layout_res_ok(xdr
, res
->u
.res_ok
);
3431 case NFS4ERR_LAYOUTTRYLATER
:
3432 return xdr_bool(xdr
, &res
->u
.will_signal_layout_avail
);
3441 static bool_t
encode_op_layoutreturn(
3445 pnfs_layoutreturn_args
*args
= (pnfs_layoutreturn_args
*)argop
->arg
;
3447 if (unexpected_op(argop
->op
, OP_LAYOUTRETURN
))
3450 if (!xdr_bool(xdr
, &args
->reclaim
))
3453 if (!xdr_enum(xdr
, (enum_t
*)&args
->type
))
3456 if (!xdr_enum(xdr
, (enum_t
*)&args
->iomode
))
3459 if (!xdr_enum(xdr
, (enum_t
*)&args
->return_type
))
3462 if (args
->return_type
== PNFS_RETURN_FILE
) {
3465 if (!xdr_u_hyper(xdr
, &args
->offset
))
3468 if (!xdr_u_hyper(xdr
, &args
->length
))
3471 if (!xdr_stateid4(xdr
, args
->stateid
))
3474 return xdr_u_int32_t(xdr
, &zero
); /* size of lrf_body is 0 */
3476 eprintf("%s: layout type (%d) is not PNFS_RETURN_FILE!\n",
3477 "encode_op_layoutreturn", args
->return_type
);
3482 static bool_t
decode_op_layoutreturn(
3486 pnfs_layoutreturn_res
*res
= (pnfs_layoutreturn_res
*)resop
->res
;
3488 if (unexpected_op(resop
->op
, OP_LAYOUTRETURN
))
3491 if (!xdr_u_int32_t(xdr
, (uint32_t *)&res
->status
))
3494 if (res
->status
== NFS4_OK
) {
3495 if (!xdr_bool(xdr
, &res
->stateid_present
))
3498 if (res
->stateid_present
)
3499 return xdr_stateid4(xdr
, &res
->stateid
);
3505 /* op encode/decode table */
3506 typedef bool_t (*nfs_op_encode_proc
)(XDR
*, nfs_argop4
*);
3507 typedef bool_t (*nfs_op_decode_proc
)(XDR
*, nfs_resop4
*);
3509 typedef struct __op_table_entry
{
3510 nfs_op_encode_proc encode
;
3511 nfs_op_decode_proc decode
;
3514 /* table of encode/decode functions, indexed by operation number */
3515 static const op_table_entry g_op_table
[] = {
3516 { NULL
, NULL
}, /* 0 unused */
3517 { NULL
, NULL
}, /* 1 unused */
3518 { NULL
, NULL
}, /* 2 unused */
3519 { encode_op_access
, decode_op_access
}, /* OP_ACCESS = 3 */
3520 { encode_op_close
, decode_op_close
}, /* OP_CLOSE = 4 */
3521 { encode_op_commit
, decode_op_commit
}, /* OP_COMMIT = 5 */
3522 { encode_op_create
, decode_op_create
}, /* OP_CREATE = 6 */
3523 { encode_op_delegpurge
, decode_op_delegpurge
}, /* OP_DELEGPURGE = 7 */
3524 { encode_op_delegreturn
, decode_op_delegreturn
}, /* OP_DELEGRETURN = 8 */
3525 { encode_op_getattr
, decode_op_getattr
}, /* OP_GETATTR = 9 */
3526 { encode_op_getfh
, decode_op_getfh
}, /* OP_GETFH = 10 */
3527 { encode_op_link
, decode_op_link
}, /* OP_LINK = 11 */
3528 { encode_op_lock
, decode_op_lock
}, /* OP_LOCK = 12 */
3529 { encode_op_lockt
, decode_op_lockt
}, /* OP_LOCKT = 13 */
3530 { encode_op_locku
, decode_op_locku
}, /* OP_LOCKU = 14 */
3531 { encode_op_lookup
, decode_op_lookup
}, /* OP_LOOKUP = 15 */
3532 { NULL
, NULL
}, /* OP_LOOKUPP = 16 */
3533 { NULL
, NULL
}, /* OP_NVERIFY = 17 */
3534 { encode_op_open
, decode_op_open
}, /* OP_OPEN = 18 */
3535 { encode_op_openattr
, decode_op_openattr
}, /* OP_OPENATTR = 19 */
3536 { NULL
, NULL
}, /* OP_OPEN_CONFIRM = 20 */
3537 { NULL
, NULL
}, /* OP_OPEN_DOWNGRADE = 21 */
3538 { encode_op_putfh
, decode_op_putfh
}, /* OP_PUTFH = 22 */
3539 { NULL
, NULL
}, /* OP_PUTPUBFH = 23 */
3540 { encode_op_putrootfh
, decode_op_putrootfh
}, /* OP_PUTROOTFH = 24 */
3541 { encode_op_read
, decode_op_read
}, /* OP_READ = 25 */
3542 { encode_op_readdir
, decode_op_readdir
}, /* OP_READDIR = 26 */
3543 { encode_op_readlink
, decode_op_readlink
}, /* OP_READLINK = 27 */
3544 { encode_op_remove
, decode_op_remove
}, /* OP_REMOVE = 28 */
3545 { encode_op_rename
, decode_op_rename
}, /* OP_RENAME = 29 */
3546 { NULL
, NULL
}, /* OP_RENEW = 30 */
3547 { encode_op_restorefh
, decode_op_restorefh
}, /* OP_RESTOREFH = 31 */
3548 { encode_op_savefh
, decode_op_savefh
}, /* OP_SAVEFH = 32 */
3549 { encode_op_secinfo
, decode_op_secinfo
}, /* OP_SECINFO = 33 */
3550 { encode_op_setattr
, decode_op_setattr
}, /* OP_SETATTR = 34 */
3551 { NULL
, NULL
}, /* OP_SETCLIENTID = 35 */
3552 { NULL
, NULL
}, /* OP_SETCLIENTID_CONFIRM = 36 */
3553 { NULL
, NULL
}, /* OP_VERIFY = 37 */
3554 { encode_op_write
, decode_op_write
}, /* OP_WRITE = 38 */
3555 { NULL
, NULL
}, /* OP_RELEASE_LOCKOWNER = 39 */
3556 { NULL
, NULL
}, /* OP_BACKCHANNEL_CTL = 40 */
3557 { encode_op_bind_conn_to_session
, decode_op_bind_conn_to_session
}, /* OP_BIND_CONN_TO_SESSION = 41 */
3558 { encode_op_exchange_id
, decode_op_exchange_id
}, /* OP_EXCHANGE_ID = 42 */
3559 { encode_op_create_session
, decode_op_create_session
}, /* OP_CREATE_SESSION = 43 */
3560 { encode_op_destroy_session
, decode_op_destroy_session
}, /* OP_DESTROY_SESSION = 44 */
3561 { encode_op_free_stateid
, decode_op_free_stateid
}, /* OP_FREE_STATEID = 45 */
3562 { NULL
, NULL
}, /* OP_GET_DIR_DELEGATION = 46 */
3563 { encode_op_getdeviceinfo
, decode_op_getdeviceinfo
}, /* OP_GETDEVICEINFO = 47 */
3564 { NULL
, NULL
}, /* OP_GETDEVICELIST = 48 */
3565 { encode_op_layoutcommit
, decode_op_layoutcommit
}, /* OP_LAYOUTCOMMIT = 49 */
3566 { encode_op_layoutget
, decode_op_layoutget
}, /* OP_LAYOUTGET = 50 */
3567 { encode_op_layoutreturn
, decode_op_layoutreturn
}, /* OP_LAYOUTRETURN = 51 */
3568 { encode_op_secinfo_noname
, decode_op_secinfo_noname
}, /* OP_SECINFO_NO_NAME = 52 */
3569 { encode_op_sequence
, decode_op_sequence
}, /* OP_SEQUENCE = 53 */
3570 { NULL
, NULL
}, /* OP_SET_SSV = 54 */
3571 { encode_op_test_stateid
, decode_op_test_stateid
}, /* OP_TEST_STATEID = 55 */
3572 { encode_op_want_delegation
, decode_op_want_delegation
}, /* OP_WANT_DELEGATION = 56 */
3573 { encode_op_destroy_clientid
, decode_op_destroy_clientid
}, /* OP_DESTROY_CLIENTID = 57 */
3574 { encode_op_reclaim_complete
, decode_op_reclaim_complete
}, /* OP_RECLAIM_COMPLETE = 58 */
3577 static const uint32_t g_op_table_size
= (sizeof(g_op_table
) / sizeof(g_op_table
[0]));
3579 static const uint32_t g_op_table_size
= ARRAYSIZE(g_op_table
);
3582 static const op_table_entry
* op_table_find(uint32_t op
)
3584 return op
>= g_op_table_size
? NULL
: &g_op_table
[op
];
3591 bool_t
nfs_encode_compound(
3597 nfs41_compound_args
*args
= (nfs41_compound_args
*)pargs
;
3599 const op_table_entry
*entry
;
3602 if (!xdr_bytes(xdr
, (char **)&tag
, &args
->tag_len
, NFS4_OPAQUE_LIMIT
))
3605 if (!xdr_u_int32_t(xdr
, &args
->minorversion
))
3608 if (!xdr_u_int32_t(xdr
, &args
->argarray_count
))
3611 for (i
= 0; i
< args
->argarray_count
; i
++)
3613 entry
= op_table_find(args
->argarray
[i
].op
);
3614 if (entry
== NULL
|| entry
->encode
== NULL
)
3617 if (!xdr_u_int32_t(xdr
, &args
->argarray
[i
].op
))
3619 if (!entry
->encode(xdr
, &args
->argarray
[i
]))
3625 bool_t
nfs_decode_compound(
3629 nfs41_compound_res
*res
= (nfs41_compound_res
*)pres
;
3630 uint32_t i
, expected_count
, expected_op
;
3631 const op_table_entry
*entry
;
3632 unsigned char *tag
= res
->tag
;
3634 if (!xdr_u_int32_t(xdr
, &res
->status
))
3637 if (!xdr_bytes(xdr
, (char **)&tag
, &res
->tag_len
, NFS4_OPAQUE_LIMIT
))
3640 expected_count
= res
->resarray_count
;
3641 if (!xdr_u_int32_t(xdr
, &res
->resarray_count
))
3644 /* validate the number of operations against what we sent */
3645 if (res
->resarray_count
> expected_count
) {
3646 eprintf("reply with %u operations, only sent %u!\n",
3647 res
->resarray_count
, expected_count
);
3649 } else if (res
->resarray_count
< expected_count
&&
3650 res
->status
== NFS4_OK
) {
3651 /* illegal for a server to reply with less operations,
3652 * unless one of them fails */
3653 eprintf("successful reply with only %u operations, sent %u!\n",
3654 res
->resarray_count
, expected_count
);
3658 for (i
= 0; i
< res
->resarray_count
; i
++)
3660 expected_op
= res
->resarray
[i
].op
;
3661 if (!xdr_u_int32_t(xdr
, &res
->resarray
[i
].op
))
3664 /* validate each operation number against what we sent */
3665 if (res
->resarray
[i
].op
!= expected_op
) {
3666 eprintf("reply with %s in operation %u, expected %s!\n",
3667 nfs_opnum_to_string(res
->resarray
[i
].op
), i
+1,
3668 nfs_opnum_to_string(expected_op
));
3672 entry
= op_table_find(res
->resarray
[i
].op
);
3673 if (entry
== NULL
|| entry
->decode
== NULL
)
3675 if (!entry
->decode(xdr
, &res
->resarray
[i
]))