[CMAKE/CLANG-CL] Silence some clang-cl warnings in consistency with our gcc build.
[reactos.git] / base / services / nfsd / nfs41_xdr.c
1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
3 *
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <windows.h>
23 #include <strsafe.h>
24
25 #include "nfs41_compound.h"
26 #include "nfs41_ops.h"
27 #include "nfs41_xdr.h"
28 #include "util.h"
29 #include "daemon_debug.h"
30 #include "rpc/rpc.h"
31
32 static bool_t encode_file_attrs(
33 fattr4 *attrs,
34 nfs41_file_info *info);
35
36 static __inline int unexpected_op(uint32_t op, uint32_t expected)
37 {
38 if (op == expected)
39 return 0;
40
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);
44 return 1;
45 }
46
47 /* typedef uint32_t bitmap4<> */
48 bool_t xdr_bitmap4(
49 XDR *xdr,
50 bitmap4 *bitmap)
51 {
52 uint32_t i;
53
54 if (xdr->x_op == XDR_ENCODE) {
55 if (bitmap->count > 3) {
56 eprintf("encode_bitmap4: count (%d) must be <= 3\n",
57 bitmap->count);
58 return FALSE;
59 }
60 if (!xdr_u_int32_t(xdr, &bitmap->count))
61 return FALSE;
62
63 for (i = 0; i < bitmap->count; i++)
64 if (!xdr_u_int32_t(xdr, &bitmap->arr[i]))
65 return FALSE;
66
67 } else if (xdr->x_op == XDR_DECODE) {
68 if (!xdr_u_int32_t(xdr, &bitmap->count))
69 return FALSE;
70 if (bitmap->count > 3) {
71 eprintf("decode_bitmap4: count (%d) must be <= 3\n",
72 bitmap->count);
73 return FALSE;
74 }
75
76 for (i = 0; i < bitmap->count; i++)
77 if (!xdr_u_int32_t(xdr, &bitmap->arr[i]))
78 return FALSE;
79 } else
80 return FALSE;
81
82 return TRUE;
83 }
84
85 /* nfstime4 */
86 static bool_t xdr_nfstime4(
87 XDR *xdr,
88 nfstime4 *nt)
89 {
90 if (!xdr_hyper(xdr, &nt->seconds))
91 return FALSE;
92
93 return xdr_u_int32_t(xdr, &nt->nseconds);
94 }
95
96
97 /* settime4 */
98 static uint32_t settime_how(
99 nfstime4 *newtime,
100 const nfstime4 *time_delta)
101 {
102 nfstime4 current;
103 get_nfs_time(&current);
104 /* get the absolute difference between current and newtime */
105 nfstime_diff(&current, newtime, &current);
106 nfstime_abs(&current, &current);
107 /* compare the difference with time_delta */
108 nfstime_diff(time_delta, &current, &current);
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;
111 }
112
113 static bool_t xdr_settime4(
114 XDR *xdr,
115 nfstime4 *nt,
116 const nfstime4 *time_delta)
117 {
118 uint32_t how = settime_how(nt, time_delta);
119
120 if (xdr->x_op != XDR_ENCODE) /* not used for decode */
121 return FALSE;
122
123 if (!xdr_u_int32_t(xdr, &how))
124 return FALSE;
125
126 if (how == SET_TO_CLIENT_TIME4)
127 return xdr_nfstime4(xdr, nt);
128
129 return TRUE;
130 }
131
132 /* stateid4 */
133 static bool_t xdr_stateid4(
134 XDR *xdr,
135 stateid4 *si)
136 {
137 if (!xdr_u_int32_t(xdr, &si->seqid))
138 return FALSE;
139
140 return xdr_opaque(xdr, (char *)si->other, NFS4_STATEID_OTHER);
141 }
142
143 /* fattr4 */
144 bool_t xdr_fattr4(
145 XDR *xdr,
146 fattr4 *fattr)
147 {
148 unsigned char *attr_vals = fattr->attr_vals;
149
150 if (!xdr_bitmap4(xdr, &fattr->attrmask))
151 return FALSE;
152
153 return xdr_bytes(xdr, (char **)&attr_vals, &fattr->attr_vals_len, NFS4_OPAQUE_LIMIT);
154 }
155
156 /* nfs41_fh */
157 static bool_t xdr_fh(
158 XDR *xdr,
159 nfs41_fh *fh)
160 {
161 unsigned char *pfh = fh->fh;
162 return xdr_bytes(xdr, (char **)&pfh, &fh->len, NFS4_FHSIZE);
163 }
164
165 /* nfs41_fsid */
166 static bool_t xdr_fsid(
167 XDR *xdr,
168 nfs41_fsid *fsid)
169 {
170 if (!xdr_u_hyper(xdr, &fsid->major))
171 return FALSE;
172
173 return xdr_u_hyper(xdr, &fsid->minor);
174 }
175
176
177 /* nfs41_component */
178 static bool_t encode_component(
179 XDR *xdr,
180 const nfs41_component *component)
181 {
182 uint32_t len = component->len;
183 return xdr_bytes(xdr, (char **)&component->name, &len, NFS4_OPAQUE_LIMIT);
184 }
185
186 static bool_t decode_component(
187 XDR *xdr,
188 nfs41_component *component)
189 {
190 bool_t result;
191 uint32_t len;
192
193 result = xdr_bytes(xdr, (char **)&component->name, &len, NFS4_OPAQUE_LIMIT);
194 component->len = (result == FALSE) ? 0 : (unsigned short)len;
195 return result;
196 }
197
198
199 /* state_owner4 */
200 static bool_t xdr_state_owner4(
201 XDR *xdr,
202 state_owner4 *so)
203 {
204 u_quad_t clientid = 0;
205 unsigned char *owner = so->owner;
206
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 */
213 return FALSE;
214 } else if (xdr->x_op == XDR_DECODE) {
215 if (!xdr_u_hyper(xdr, &clientid))
216 return FALSE;
217 } else return FALSE;
218
219 return xdr_bytes(xdr, (char **)&owner, &so->owner_len, NFS4_OPAQUE_LIMIT);
220 }
221
222 static bool_t xdr_layout_types(
223 XDR *xdr,
224 uint32_t *layout_type)
225 {
226 u_int32_t i, count, type;
227
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);
231 return FALSE;
232 }
233
234 *layout_type = 0;
235
236 if (!xdr_u_int32_t(xdr, &count))
237 return FALSE;
238
239 for (i = 0; i < count; i++) {
240 if (!xdr_u_int32_t(xdr, &type))
241 return FALSE;
242
243 *layout_type |= 1 << (type - 1);
244 }
245 return TRUE;
246 }
247
248 static bool_t xdr_threshold_item(
249 XDR *xdr,
250 threshold_item4 *item)
251 {
252 bitmap4 bitmap;
253
254 if (!xdr_u_int32_t(xdr, &item->type))
255 return FALSE;
256
257 if (!xdr_bitmap4(xdr, &bitmap))
258 return FALSE;
259
260 if (!xdr_u_int32_t(xdr, &bitmap.count))
261 return FALSE;
262
263 if (bitmap.count) {
264 if (bitmap.arr[0] & 0x1 && !xdr_u_hyper(xdr, &item->hints[0]))
265 return FALSE;
266 if (bitmap.arr[0] & 0x2 && !xdr_u_hyper(xdr, &item->hints[1]))
267 return FALSE;
268 if (bitmap.arr[0] & 0x4 && !xdr_u_hyper(xdr, &item->hints[2]))
269 return FALSE;
270 if (bitmap.arr[0] & 0x8 && !xdr_u_hyper(xdr, &item->hints[3]))
271 return FALSE;
272 }
273 return TRUE;
274 }
275
276 static bool_t xdr_mdsthreshold(
277 XDR *xdr,
278 mdsthreshold4 *mdsthreshold)
279 {
280 uint32_t i;
281
282 if (!xdr_u_int32_t(xdr, &mdsthreshold->count))
283 return FALSE;
284
285 if (mdsthreshold->count > MAX_MDSTHRESHOLD_ITEMS)
286 return FALSE;
287
288 for (i = 0; i < mdsthreshold->count; i++)
289 if (!xdr_threshold_item(xdr, &mdsthreshold->items[i]))
290 return FALSE;
291 return TRUE;
292 }
293
294 static bool_t xdr_nfsace4(
295 XDR *xdr,
296 nfsace4 *ace)
297 {
298 char *who = ace->who;
299
300 if (!xdr_u_int32_t(xdr, &ace->acetype))
301 return FALSE;
302
303 if (!xdr_u_int32_t(xdr, &ace->aceflag))
304 return FALSE;
305
306 if (!xdr_u_int32_t(xdr, &ace->acemask))
307 return FALSE;
308
309 /* 'who' is a static array, so don't try to free it */
310 if (xdr->x_op == XDR_FREE)
311 return TRUE;
312
313 return xdr_string(xdr, &who, NFS4_OPAQUE_LIMIT);
314 }
315
316 static bool_t xdr_nfsdacl41(
317 XDR *xdr,
318 nfsacl41 *acl)
319 {
320 if (!xdr_u_int32_t(xdr, &acl->flag))
321 return FALSE;
322
323 return xdr_array(xdr, (char**)&acl->aces, &acl->count,
324 32, sizeof(nfsace4), (xdrproc_t)xdr_nfsace4);
325 }
326
327 static bool_t xdr_nfsacl41(
328 XDR *xdr,
329 nfsacl41 *acl)
330 {
331 return xdr_array(xdr, (char**)&acl->aces, &acl->count,
332 32, sizeof(nfsace4), (xdrproc_t)xdr_nfsace4);
333 }
334
335 void nfsacl41_free(nfsacl41 *acl)
336 {
337 XDR xdr = { XDR_FREE };
338 xdr_nfsacl41(&xdr, acl);
339 }
340
341 /* pathname4
342 * decode a variable array of components into a nfs41_abs_path */
343 static bool_t decode_pathname4(
344 XDR *xdr,
345 nfs41_abs_path *path)
346 {
347 char *pos;
348 u_int32_t i, count, len, remaining;
349
350 /* decode the number of components */
351 if (!xdr_u_int32_t(xdr, &count))
352 return FALSE;
353
354 pos = (char *)path->path;
355 remaining = NFS41_MAX_PATH_LEN;
356
357 /* decode each component */
358 for (i = 0; i < count; i++) {
359 len = remaining;
360 if (!xdr_bytes(xdr, (char **)&pos, &len, NFS41_MAX_PATH_LEN))
361 return FALSE;
362 remaining -= len;
363 pos += len;
364
365 if (i < count-1) { /* add a \ between components */
366 if (remaining < 1)
367 return FALSE;
368 *pos++ = '\\';
369 remaining--;
370 }
371 }
372 path->len = (unsigned short)(NFS41_MAX_PATH_LEN - remaining);
373 return TRUE;
374 }
375
376 /* fs_location4 */
377 static bool_t decode_fs_location4(
378 XDR *xdr,
379 fs_location4 *location)
380 {
381 fs_location_server *arr;
382 char *address;
383 u_int32_t i, count, len;
384
385 /* decode the number of servers */
386 if (!xdr_u_int32_t(xdr, &count))
387 return FALSE;
388
389 /* allocate the fs_location_server array */
390 if (count == 0) {
391 free(location->servers);
392 arr = NULL;
393 } else if (count != location->server_count) {
394 arr = realloc(location->servers, count * sizeof(fs_location_server));
395 if (arr == NULL)
396 return FALSE;
397 ZeroMemory(arr, count * sizeof(fs_location_server));
398 } else {
399 arr = location->servers;
400 }
401
402 location->servers = arr;
403 location->server_count = count;
404
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)) {
409 free(arr);
410 return FALSE;
411 }
412 arr[i].address[len] = '\0';
413 }
414
415 return decode_pathname4(xdr, &location->path);
416 }
417
418 /* fs_locations4 */
419 static bool_t decode_fs_locations4(
420 XDR *xdr,
421 fs_locations4 *locations)
422 {
423 u_int32_t i, count;
424 fs_location4 *arr;
425
426 if (!decode_pathname4(xdr, &locations->path))
427 return FALSE;
428
429 if (!xdr_u_int32_t(xdr, &count))
430 return FALSE;
431
432 /* allocate the fs_location array */
433 if (count == 0) {
434 free(locations->locations);
435 arr = NULL;
436 } else if (count != locations->location_count) {
437 arr = realloc(locations->locations, count * sizeof(fs_location4));
438 if (arr == NULL)
439 return FALSE;
440 ZeroMemory(arr, count * sizeof(fs_location4));
441 } else {
442 arr = locations->locations;
443 }
444
445 locations->locations = arr;
446 locations->location_count = count;
447
448 for (i = 0; i < count; i++) {
449 if (!decode_fs_location4(xdr, &arr[i])) {
450 free(arr);
451 return FALSE;
452 }
453 }
454 return TRUE;
455 }
456
457 /*
458 * OP_EXCHANGE_ID
459 */
460 static bool_t xdr_client_owner4(
461 XDR *xdr,
462 client_owner4 *co)
463 {
464 unsigned char *co_ownerid = co->co_ownerid;
465 if (!xdr_opaque(xdr, (char *)&co->co_verifier[0], NFS4_VERIFIER_SIZE))
466 return FALSE;
467
468 return xdr_bytes(xdr, (char **)&co_ownerid, &co->co_ownerid_len, NFS4_OPAQUE_LIMIT);
469 }
470
471 #if 0
472 static bool_t encode_state_protect_ops4(
473 XDR *xdr,
474 state_protect_ops4 *spo)
475 {
476 if (!xdr_bitmap4(xdr, &spo->spo_must_enforce))
477 return FALSE;
478
479 return xdr_bitmap4(xdr, &spo->spo_must_allow);
480 }
481
482 static bool_t encode_ssv_sp_parms4(
483 XDR *xdr,
484 ssv_sp_parms4 *spp)
485 {
486 if (!encode_state_protect_ops4(xdr, &spp->ssp_ops))
487 return FALSE;
488
489 if (!xdr_bytes(xdr, &spp->ssp_hash_algs,
490 &spp->ssp_hash_algs_len, NFS4_OPAQUE_LIMIT))
491 return FALSE;
492
493 if (!xdr_bytes(xdr, &spp->ssp_encr_algs,
494 &spp->ssp_encr_algs_len, NFS4_OPAQUE_LIMIT))
495 return FALSE;
496
497 if (!xdr_u_int32_t(xdr, &spp->ssp_window))
498 return FALSE;
499
500 return xdr_u_int32_t(xdr, &spp->ssp_num_gss_handles);
501 }
502 #endif
503
504 static bool_t xdr_state_protect4_a(
505 XDR *xdr,
506 state_protect4_a *spa)
507 {
508 bool_t result = TRUE;
509
510 if (!xdr_u_int32_t(xdr, (u_int32_t *)&spa->spa_how))
511 return FALSE;
512
513 switch (spa->spa_how)
514 {
515 case SP4_NONE:
516 break;
517 #if 0
518 case SP4_MACH_CRED:
519 result = xdr_state_protect_ops4(xdr, &spa->u.spa_mach_ops);
520 break;
521 case SP4_SSV:
522 result = xdr_ssv_sp_parms4(xdr, &spa->u.spa_ssv_parms);
523 break;
524 #endif
525 default:
526 eprintf("encode_state_protect4_a: state protect "
527 "type %d not supported.\n", spa->spa_how);
528 result = FALSE;
529 break;
530 }
531 return result;
532 }
533
534 static bool_t xdr_nfs_impl_id4(
535 XDR *xdr,
536 nfs_impl_id4 *nii)
537 {
538 unsigned char *nii_domain = nii->nii_domain;
539 unsigned char *nii_name = nii->nii_name;
540
541 if (!xdr_bytes(xdr, (char **)&nii_domain, &nii->nii_domain_len, NFS4_OPAQUE_LIMIT))
542 return FALSE;
543
544 if (!xdr_bytes(xdr, (char **)&nii_name, &nii->nii_name_len, NFS4_OPAQUE_LIMIT))
545 return FALSE;
546
547 return xdr_nfstime4(xdr, &nii->nii_date);
548 }
549
550
551 static bool_t encode_op_exchange_id(
552 XDR *xdr,
553 nfs_argop4 *argop)
554 {
555 uint32_t zero = 0;
556 uint32_t one = 1;
557
558 nfs41_exchange_id_args *args = (nfs41_exchange_id_args*)argop->arg;
559
560 if (unexpected_op(argop->op, OP_EXCHANGE_ID))
561 return FALSE;
562
563 if (!xdr_client_owner4(xdr, args->eia_clientowner))
564 return FALSE;
565
566 if (!xdr_u_int32_t(xdr, &args->eia_flags))
567 return FALSE;
568
569 if (!xdr_state_protect4_a(xdr, &args->eia_state_protect))
570 return FALSE;
571
572 if (args->eia_client_impl_id)
573 {
574 if (!xdr_u_int32_t(xdr, &one))
575 return FALSE;
576 return xdr_nfs_impl_id4(xdr, args->eia_client_impl_id);
577 }
578 else
579 return xdr_u_int32_t(xdr, &zero);
580 }
581
582 #if 0
583
584 static bool_t decode_state_protect_ops4(
585 XDR *xdr,
586 state_protect_ops4 *spo)
587 {
588 if (!xdr_bitmap4(xdr, &spo->spo_must_enforce))
589 return FALSE;
590
591 return xdr_bitmap4(xdr, &spo->spo_must_allow);
592 }
593
594 static bool_t decode_ssv_prot_info4(
595 XDR *xdr,
596 ssv_prot_info4 *spi)
597 {
598 /* uint32_t i; */
599
600 if (!decode_state_protect_ops4(xdr, &spi->spi_ops))
601 return FALSE;
602
603 if (!xdr_u_int32_t(xdr, &spi->spi_hash_alg))
604 return FALSE;
605
606 if (!xdr_u_int32_t(xdr, &spi->spi_encr_alg))
607 return FALSE;
608
609 if (!xdr_u_int32_t(xdr, &spi->spi_ssv_len))
610 return FALSE;
611
612 if (!xdr_u_int32_t(xdr, &spi->spi_window))
613 return FALSE;
614
615 /* TODO: spi->spi_handles */
616 return xdr_u_int32_t(xdr, 0);
617 /*
618 if (!xdr_u_int32_t(xdr, &spi->spi_handles.count))
619 return FALSE;
620
621 for (i = 0; i < spi->spi_handles.count; i++)
622 if (!xdr_opaque(xdr, &spi->spi_handles.arr[i])
623 return FALSE;
624 */
625 return TRUE;
626 }
627 #endif
628
629 static bool_t xdr_state_protect4_r(
630 XDR *xdr,
631 state_protect4_r *spr)
632 {
633 bool_t result = TRUE;
634
635 if (!xdr_u_int32_t(xdr, (uint32_t *)&spr->spr_how))
636 return FALSE;
637
638 switch (spr->spr_how)
639 {
640 case SP4_NONE:
641 break;
642 #if 0
643 case SP4_MACH_CRED:
644 result = decode_state_protect_ops4(xdr, &spr->u.spr_mach_ops);
645 break;
646 case SP4_SSV:
647 result = decode_ssv_prot_info4(xdr, &spr->u.spr_ssv_info);
648 break;
649 #endif
650 default:
651 eprintf("decode_state_protect4_r: state protect "
652 "type %d not supported.\n", spr->spr_how);
653 result = FALSE;
654 break;
655 }
656 return result;
657 }
658
659 static bool_t xdr_server_owner4(
660 XDR *xdr,
661 server_owner4 *so)
662 {
663 char *so_major_id = so->so_major_id;
664
665 if (!xdr_u_hyper(xdr, &so->so_minor_id))
666 return FALSE;
667
668 return xdr_bytes(xdr, (char **)&so_major_id,
669 &so->so_major_id_len, NFS4_OPAQUE_LIMIT);
670 }
671
672 static bool_t decode_op_exchange_id(
673 XDR *xdr,
674 nfs_resop4 *resop)
675 {
676 nfs41_exchange_id_res *res = (nfs41_exchange_id_res*)resop->res;
677 char *server_scope = (char *)res->server_scope;
678
679 if (unexpected_op(resop->op, OP_EXCHANGE_ID))
680 return FALSE;
681
682 if (!xdr_u_int32_t(xdr, &res->status))
683 return FALSE;
684
685 if (res->status != NFS4_OK)
686 return TRUE;
687
688 if (!xdr_u_hyper(xdr, &res->clientid))
689 return FALSE;
690
691 if (!xdr_u_int32_t(xdr, &res->sequenceid))
692 return FALSE;
693
694 if (!xdr_u_int32_t(xdr, &res->flags))
695 return FALSE;
696
697 if (!xdr_state_protect4_r(xdr, &res->state_protect))
698 return FALSE;
699
700 if (!xdr_server_owner4(xdr, &res->server_owner))
701 return FALSE;
702
703 return xdr_bytes(xdr, &server_scope,
704 &res->server_scope_len, NFS4_OPAQUE_LIMIT);
705 }
706
707 /*
708 * OP_CREATE_SESSION
709 */
710 static bool_t xdr_channel_attrs4(
711 XDR *xdr,
712 nfs41_channel_attrs *attrs)
713 {
714 uint32_t zero = 0;
715 uint32_t one = 1;
716
717 /* count4 ca_headerpadsize */
718 if (!xdr_u_int32_t(xdr, &attrs->ca_headerpadsize))
719 return FALSE;
720
721 /* count4 ca_maxrequestsize */
722 if (!xdr_u_int32_t(xdr, &attrs->ca_maxrequestsize))
723 return FALSE;
724
725 /* count4 ca_maxresponsesize */
726 if (!xdr_u_int32_t(xdr, &attrs->ca_maxresponsesize))
727 return FALSE;
728
729 /* count4 ca_maxresponsesize_cached */
730 if (!xdr_u_int32_t(xdr, &attrs->ca_maxresponsesize_cached))
731 return FALSE;
732
733 /* count4 ca_maxoperations */
734 if (!xdr_u_int32_t(xdr, &attrs->ca_maxoperations))
735 return FALSE;
736
737 /* count4 ca_maxrequests */
738 if (!xdr_u_int32_t(xdr, &attrs->ca_maxrequests))
739 return FALSE;
740
741 if (xdr->x_op == XDR_ENCODE) {
742 /* uint32_t ca_rdma_ird<1> */
743 if (attrs->ca_rdma_ird)
744 {
745 if (!xdr_u_int32_t(xdr, &one))
746 return FALSE;
747 return xdr_u_int32_t(xdr, attrs->ca_rdma_ird);
748 }
749 else {
750 return xdr_u_int32_t(xdr, &zero);
751 }
752 }
753 else if (xdr->x_op == XDR_DECODE) {
754 #if 0
755 u_int32_t count;
756 /* uint32_t ca_rdma_ird<1> */
757 if (!xdr_u_int32_t(xdr, &count))
758 return FALSE;
759 if (count > 1)
760 return FALSE;
761 if (count)
762 return xdr_u_int32_t(xdr, attrs->ca_rdma_ird);
763 else
764 #endif
765 return TRUE;
766 }
767 else {
768 eprintf("%s: xdr->x_op %d not supported.\n",
769 "xdr_channel_attrs4", xdr->x_op);
770 return FALSE;
771 }
772 }
773
774 static bool_t encode_backchannel_sec_parms(
775 XDR *xdr,
776 nfs41_callback_secparms *args)
777 {
778 uint32_t zero = 0;
779
780 if (!xdr_u_int32_t(xdr, &args->type))
781 return FALSE;
782
783 switch (args->type) {
784 case AUTH_NONE: return TRUE;
785 case AUTH_SYS:
786 if (!xdr_u_int32_t(xdr, &args->u.auth_sys.stamp))
787 return FALSE;
788 if (!xdr_string(xdr, &args->u.auth_sys.machinename, NI_MAXHOST))
789 return FALSE;
790 return xdr_u_int32_t(xdr, &zero) && xdr_u_int32_t(xdr, &zero) &&
791 xdr_u_int32_t(xdr, &zero);
792 case RPCSEC_GSS:
793 default:
794 return FALSE;
795 }
796 }
797
798 static bool_t encode_op_create_session(
799 XDR *xdr,
800 nfs_argop4 *argop)
801 {
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;
805
806 if (unexpected_op(argop->op, OP_CREATE_SESSION))
807 return FALSE;
808
809 /* clientid4 csa_clientid */
810 if (!xdr_u_hyper(xdr, &args->csa_clientid))
811 return FALSE;
812
813 /* sequenceid4 csa_sequence */
814 if (!xdr_u_int32_t(xdr, &args->csa_sequence))
815 return FALSE;
816
817 /* TODO: uint32_t csa_flags = 0 */
818 if (!xdr_u_int32_t(xdr, &args->csa_flags))
819 return FALSE;
820
821 /* channel_attrs4 csa_fore_chan_attrs */
822 if (!xdr_channel_attrs4(xdr, &args->csa_fore_chan_attrs))
823 return FALSE;
824
825 /* channel_attrs4 csa_back_chan_attrs */
826 if (!xdr_channel_attrs4(xdr, &args->csa_back_chan_attrs))
827 return FALSE;
828
829 /* TODO: uint32_t csa_cb_program = 1234 */
830 if (!xdr_u_int32_t(xdr, &args->csa_cb_program))
831 return FALSE;
832
833 return xdr_array(xdr, (char **)&cb_secparams, &cb_count,
834 3, sizeof(nfs41_callback_secparms), (xdrproc_t) encode_backchannel_sec_parms);
835 }
836
837 static bool_t decode_op_create_session(
838 XDR *xdr,
839 nfs_resop4 *resop)
840 {
841 uint32_t opstatus;
842 nfs41_create_session_res *res = (nfs41_create_session_res*)resop->res;
843
844 if (unexpected_op(resop->op, OP_CREATE_SESSION))
845 return FALSE;
846
847 if (!xdr_u_int32_t(xdr, &opstatus))
848 return FALSE;
849
850 if (opstatus != NFS4_OK)
851 return TRUE;
852
853 if (!xdr_opaque(xdr, (char *)res->csr_sessionid, NFS4_SESSIONID_SIZE))
854 return FALSE;
855
856 /* sequenceid4 csr_sequence */
857 if (!xdr_u_int32_t(xdr, &res->csr_sequence))
858 return FALSE;
859
860 /* uint32_t csr_flags */
861 if (!xdr_u_int32_t(xdr, &res->csr_flags))
862 return FALSE;
863
864 /* channel_attrs4 csr_fore_chan_attrs */
865 if (!xdr_channel_attrs4(xdr, res->csr_fore_chan_attrs))
866 return FALSE;
867
868 /* channel_attrs4 csr_back_chan_attrs */
869 return xdr_channel_attrs4(xdr, res->csr_back_chan_attrs);
870 }
871
872
873 /*
874 * OP_BIND_CONN_TO_SESSION
875 */
876 static bool_t encode_op_bind_conn_to_session(
877 XDR *xdr,
878 nfs_argop4 *argop)
879 {
880 uint32_t zero = 0;
881
882 nfs41_bind_conn_to_session_args *args =
883 (nfs41_bind_conn_to_session_args*)argop->arg;
884
885 if (unexpected_op(argop->op, OP_BIND_CONN_TO_SESSION))
886 return FALSE;
887
888 if (!xdr_opaque(xdr, (char *)args->sessionid, NFS4_SESSIONID_SIZE))
889 return FALSE;
890
891 if (!xdr_enum(xdr, (enum_t *)&args->dir))
892 return FALSE;
893
894 return xdr_u_int32_t(xdr, &zero); /* bctsa_use_conn_in_rdma_mode = false */
895 }
896
897 static bool_t decode_op_bind_conn_to_session(
898 XDR *xdr,
899 nfs_resop4 *resop)
900 {
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;
905
906 if (unexpected_op(resop->op, OP_BIND_CONN_TO_SESSION))
907 return FALSE;
908
909 if (!xdr_enum(xdr, (enum_t *)&res->status))
910 return FALSE;
911
912 if (res->status == NFS4_OK) {
913 if (!xdr_opaque(xdr, (char *)&sessionid_ignored, NFS4_SESSIONID_SIZE))
914 return FALSE;
915
916 if (!xdr_enum(xdr, (enum_t *)&res->dir))
917 return FALSE;
918
919 return xdr_bool(xdr, &use_rdma_ignored);
920 }
921 return TRUE;
922 }
923
924
925 /*
926 * OP_DESTROY_SESSION
927 */
928 static bool_t encode_op_destroy_session(
929 XDR *xdr,
930 nfs_argop4 *argop)
931 {
932 nfs41_destroy_session_args *args = (nfs41_destroy_session_args*)argop->arg;
933
934 if (unexpected_op(argop->op, OP_DESTROY_SESSION))
935 return FALSE;
936
937 return xdr_opaque(xdr, (char *)args->dsa_sessionid, NFS4_SESSIONID_SIZE);
938 }
939
940 static bool_t decode_op_destroy_session(
941 XDR *xdr,
942 nfs_resop4 *resop)
943 {
944 nfs41_destroy_session_res *res = (nfs41_destroy_session_res*)resop->res;
945
946 if (unexpected_op(resop->op, OP_DESTROY_SESSION))
947 return FALSE;
948
949 return xdr_u_int32_t(xdr, &res->dsr_status);
950 }
951
952 /*
953 * OP_DESTROY_CLIENTID
954 */
955 static bool_t encode_op_destroy_clientid(
956 XDR *xdr,
957 nfs_argop4 *argop)
958 {
959 nfs41_destroy_clientid_args *args = (nfs41_destroy_clientid_args*)argop->arg;
960
961 if (unexpected_op(argop->op, OP_DESTROY_CLIENTID))
962 return FALSE;
963
964 return xdr_u_hyper(xdr, &args->dca_clientid);
965 }
966
967 static bool_t decode_op_destroy_clientid(
968 XDR *xdr,
969 nfs_resop4 *resop)
970 {
971 nfs41_destroy_clientid_res *res = (nfs41_destroy_clientid_res*)resop->res;
972
973 if (unexpected_op(resop->op, OP_DESTROY_CLIENTID))
974 return FALSE;
975
976 return xdr_u_int32_t(xdr, &res->dcr_status);
977 }
978
979
980 /*
981 * OP_SEQUENCE
982 */
983 static bool_t encode_op_sequence(
984 XDR *xdr,
985 nfs_argop4 *argop)
986 {
987 nfs41_sequence_args *args = (nfs41_sequence_args*)argop->arg;
988
989 if (unexpected_op(argop->op, OP_SEQUENCE))
990 return FALSE;
991
992 if (!xdr_opaque(xdr, (char *)args->sa_sessionid, NFS4_SESSIONID_SIZE))
993 return FALSE;
994
995 if (!xdr_u_int32_t(xdr, &args->sa_sequenceid))
996 return FALSE;
997
998 if (!xdr_u_int32_t(xdr, &args->sa_slotid))
999 return FALSE;
1000
1001 if (!xdr_u_int32_t(xdr, &args->sa_highest_slotid))
1002 return FALSE;
1003
1004 return xdr_bool(xdr, &args->sa_cachethis);
1005 }
1006
1007 static bool_t xdr_sequence_res_ok(
1008 XDR *xdr,
1009 nfs41_sequence_res_ok *res)
1010 {
1011 if (!xdr_opaque(xdr, (char *)res->sr_sessionid, NFS4_SESSIONID_SIZE))
1012 return FALSE;
1013
1014 if (!xdr_u_int32_t(xdr, &res->sr_sequenceid))
1015 return FALSE;
1016
1017 if (!xdr_u_int32_t(xdr, &res->sr_slotid))
1018 return FALSE;
1019
1020 if (!xdr_u_int32_t(xdr, &res->sr_highest_slotid))
1021 return FALSE;
1022
1023 if (!xdr_u_int32_t(xdr, &res->sr_target_highest_slotid))
1024 return FALSE;
1025
1026 return xdr_u_int32_t(xdr, &res->sr_status_flags);
1027 }
1028
1029 static bool_t decode_op_sequence(
1030 XDR *xdr,
1031 nfs_resop4 *resop)
1032 {
1033 nfs41_sequence_res *res = (nfs41_sequence_res*)resop->res;
1034
1035 if (unexpected_op(resop->op, OP_SEQUENCE))
1036 return FALSE;
1037
1038 if (!xdr_u_int32_t(xdr, &res->sr_status))
1039 return FALSE;
1040
1041 if (res->sr_status == NFS4_OK)
1042 return xdr_sequence_res_ok(xdr, &res->sr_resok4);
1043
1044 return TRUE;
1045 }
1046
1047
1048 /*
1049 * OP_RECLAIM_COMPLETE
1050 */
1051 static bool_t encode_op_reclaim_complete(
1052 XDR *xdr,
1053 nfs_argop4 *argop)
1054 {
1055 bool_t zero = FALSE;
1056
1057 if (unexpected_op(argop->op, OP_RECLAIM_COMPLETE))
1058 return FALSE;
1059
1060 /* rca_one_fs = 0 indicates that the reclaim applies to all filesystems */
1061 return xdr_bool(xdr, &zero);
1062 }
1063
1064 static bool_t decode_op_reclaim_complete(
1065 XDR *xdr,
1066 nfs_resop4 *resop)
1067 {
1068 nfs41_reclaim_complete_res *res = (nfs41_reclaim_complete_res*)resop->res;
1069
1070 if (unexpected_op(resop->op, OP_RECLAIM_COMPLETE))
1071 return FALSE;
1072
1073 return xdr_enum(xdr, (enum_t *)&res->status);
1074 }
1075
1076
1077 /*
1078 * OP_PUTFH
1079 */
1080 static bool_t encode_op_putfh(
1081 XDR *xdr,
1082 nfs_argop4 *argop)
1083 {
1084 nfs41_putfh_args *args = (nfs41_putfh_args*)argop->arg;
1085
1086 if (unexpected_op(argop->op, OP_PUTFH))
1087 return FALSE;
1088
1089 return xdr_fh(xdr, &args->file->fh);
1090 }
1091
1092 static bool_t decode_op_putfh(
1093 XDR *xdr,
1094 nfs_resop4 *resop)
1095 {
1096 nfs41_putfh_res *res = (nfs41_putfh_res*)resop->res;
1097
1098 if (unexpected_op(resop->op, OP_PUTFH))
1099 return FALSE;
1100
1101 return xdr_u_int32_t(xdr, &res->status);
1102 }
1103
1104
1105 /*
1106 * OP_PUTROOTFH
1107 */
1108 static bool_t encode_op_putrootfh(
1109 XDR *xdr,
1110 nfs_argop4* argop)
1111 {
1112 if (unexpected_op(argop->op, OP_PUTROOTFH))
1113 return FALSE;
1114 /* void */
1115 return TRUE;
1116 }
1117
1118 static bool_t decode_op_putrootfh(
1119 XDR *xdr,
1120 nfs_resop4 *resop)
1121 {
1122 nfs41_putrootfh_res *res = (nfs41_putrootfh_res*)resop->res;
1123
1124 if (unexpected_op(resop->op, OP_PUTROOTFH))
1125 return FALSE;
1126
1127 return xdr_u_int32_t(xdr, &res->status);
1128 }
1129
1130
1131 /*
1132 * OP_GETFH
1133 */
1134 static bool_t encode_op_getfh(
1135 XDR *xdr,
1136 nfs_argop4 *argop)
1137 {
1138 if (unexpected_op(argop->op, OP_GETFH))
1139 return FALSE;
1140
1141 /* void */
1142 return TRUE;
1143 }
1144
1145 static bool_t decode_op_getfh(
1146 XDR *xdr,
1147 nfs_resop4 *resop)
1148 {
1149 nfs41_getfh_res *res = (nfs41_getfh_res*)resop->res;
1150
1151 if (unexpected_op(resop->op, OP_GETFH))
1152 return FALSE;
1153
1154 if (!xdr_u_int32_t(xdr, &res->status))
1155 return FALSE;
1156
1157 if (res->status == NFS4_OK)
1158 return xdr_fh(xdr, res->fh);
1159
1160 return TRUE;
1161 }
1162
1163
1164 /*
1165 * OP_LOOKUP
1166 */
1167 static bool_t encode_op_lookup(
1168 XDR *xdr,
1169 nfs_argop4 *argop)
1170 {
1171 nfs41_lookup_args *args = (nfs41_lookup_args*)argop->arg;
1172
1173 if (unexpected_op(argop->op, OP_LOOKUP))
1174 return FALSE;
1175
1176 return encode_component(xdr, args->name);
1177 }
1178
1179 static bool_t decode_op_lookup(
1180 XDR *xdr,
1181 nfs_resop4 *resop)
1182 {
1183 nfs41_lookup_res *res = (nfs41_lookup_res*)resop->res;
1184
1185 if (unexpected_op(resop->op, OP_LOOKUP))
1186 return FALSE;
1187
1188 return xdr_u_int32_t(xdr, &res->status);
1189 }
1190
1191
1192 /*
1193 * OP_ACCESS
1194 */
1195 static bool_t encode_op_access(
1196 XDR *xdr,
1197 nfs_argop4 *argop)
1198 {
1199 nfs41_access_args *args = (nfs41_access_args*)argop->arg;
1200
1201 if (unexpected_op(argop->op, OP_ACCESS))
1202 return FALSE;
1203
1204 return xdr_u_int32_t(xdr, &args->access);
1205 }
1206
1207 static bool_t decode_op_access(
1208 XDR *xdr,
1209 nfs_resop4 *resop)
1210 {
1211 nfs41_access_res *res = (nfs41_access_res*)resop->res;
1212
1213 if (unexpected_op(resop->op, OP_ACCESS))
1214 return FALSE;
1215
1216 if (!xdr_u_int32_t(xdr, &res->status))
1217 return FALSE;
1218
1219 if (res->status == NFS4_OK)
1220 {
1221 if (!xdr_u_int32_t(xdr, &res->supported))
1222 return FALSE;
1223
1224 return xdr_u_int32_t(xdr, &res->access);
1225 }
1226 return TRUE;
1227 }
1228
1229
1230 /*
1231 * OP_CLOSE
1232 */
1233 static bool_t encode_op_close(
1234 XDR *xdr,
1235 nfs_argop4 *argop)
1236 {
1237 nfs41_op_close_args *args = (nfs41_op_close_args*)argop->arg;
1238 uint32_t zero = 0;
1239
1240 if (unexpected_op(argop->op, OP_CLOSE))
1241 return FALSE;
1242
1243 if (!xdr_u_int32_t(xdr, &zero)) // This should be ignored by server
1244 return FALSE;
1245
1246 return xdr_stateid4(xdr, &args->stateid->stateid);
1247 }
1248
1249 static bool_t decode_op_close(
1250 XDR *xdr,
1251 nfs_resop4 *resop)
1252 {
1253 stateid4 ignored;
1254 nfs41_op_close_res *res = (nfs41_op_close_res*)resop->res;
1255
1256 if (unexpected_op(resop->op, OP_CLOSE))
1257 return FALSE;
1258
1259 if (!xdr_u_int32_t(xdr, &res->status))
1260 return FALSE;
1261
1262 if (res->status == NFS4_OK)
1263 return xdr_stateid4(xdr, &ignored);
1264
1265 return TRUE;
1266 }
1267
1268
1269 /*
1270 * OP_COMMIT
1271 */
1272 static bool_t encode_op_commit(
1273 XDR *xdr,
1274 nfs_argop4 *argop)
1275 {
1276 nfs41_commit_args *args = (nfs41_commit_args*)argop->arg;
1277
1278 if (unexpected_op(argop->op, OP_COMMIT))
1279 return FALSE;
1280
1281 if (!xdr_u_hyper(xdr, &args->offset))
1282 return FALSE;
1283
1284 return xdr_u_int32_t(xdr, &args->count);
1285 }
1286
1287 static bool_t decode_op_commit(
1288 XDR *xdr,
1289 nfs_resop4 *resop)
1290 {
1291 nfs41_commit_res *res = (nfs41_commit_res*)resop->res;
1292
1293 if (unexpected_op(resop->op, OP_COMMIT))
1294 return FALSE;
1295
1296 if (!xdr_u_int32_t(xdr, &res->status))
1297 return FALSE;
1298
1299 if (res->status == NFS4_OK)
1300 return xdr_opaque(xdr, (char *)res->verf->verf, NFS4_VERIFIER_SIZE);
1301
1302 return TRUE;
1303 }
1304
1305
1306 /*
1307 * OP_CREATE
1308 */
1309 static bool_t encode_createtype4(
1310 XDR *xdr,
1311 createtype4 *ct)
1312 {
1313 bool_t result = TRUE;
1314 const char *linkdata;
1315
1316 if (!xdr_u_int32_t(xdr, &ct->type))
1317 return FALSE;
1318
1319 switch (ct->type)
1320 {
1321 case NF4LNK:
1322 linkdata = ct->u.lnk.linkdata;
1323 result = xdr_bytes(xdr, (char**)&linkdata, &ct->u.lnk.linkdata_len,
1324 NFS4_OPAQUE_LIMIT);
1325 break;
1326 case NF4BLK:
1327 case NF4CHR:
1328 result = xdr_u_int32_t(xdr, &ct->u.devdata.specdata1);
1329 if (result == TRUE)
1330 result = xdr_u_int32_t(xdr, &ct->u.devdata.specdata2);
1331 break;
1332 default:
1333 // Some types need no further action
1334 break;
1335 }
1336 return result;
1337 }
1338
1339 static bool_t encode_createattrs4(
1340 XDR *xdr,
1341 nfs41_file_info* createattrs)
1342 {
1343 fattr4 attrs;
1344
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))
1348 return FALSE;
1349
1350 return xdr_fattr4(xdr, &attrs);
1351 }
1352
1353 static bool_t encode_op_create(
1354 XDR *xdr,
1355 nfs_argop4 *argop)
1356 {
1357 nfs41_create_args *args = (nfs41_create_args*)argop->arg;
1358
1359 if (unexpected_op(argop->op, OP_CREATE))
1360 return FALSE;
1361
1362 if (!encode_createtype4(xdr, &args->objtype))
1363 return FALSE;
1364
1365 if (!encode_component(xdr, args->name))
1366 return FALSE;
1367
1368 return encode_createattrs4(xdr, args->createattrs);
1369 }
1370
1371 static bool_t xdr_change_info4(
1372 XDR *xdr,
1373 change_info4 *cinfo)
1374 {
1375 if (!xdr_bool(xdr, &cinfo->atomic))
1376 return FALSE;
1377
1378 if (!xdr_u_hyper(xdr, &cinfo->before))
1379 return FALSE;
1380
1381 return xdr_u_hyper(xdr, &cinfo->after);
1382 }
1383
1384 static bool_t decode_op_create(
1385 XDR *xdr,
1386 nfs_resop4 *resop)
1387 {
1388 nfs41_create_res *res = (nfs41_create_res*)resop->res;
1389
1390 if (unexpected_op(resop->op, OP_CREATE))
1391 return FALSE;
1392
1393 if (!xdr_u_int32_t(xdr, &res->status))
1394 return FALSE;
1395
1396 if (res->status == NFS4_OK)
1397 {
1398 if (!xdr_change_info4(xdr, &res->cinfo))
1399 return FALSE;
1400 return xdr_bitmap4(xdr, &res->attrset);
1401 }
1402 return TRUE;
1403 }
1404
1405
1406 /*
1407 * OP_LINK
1408 */
1409 static bool_t encode_op_link(
1410 XDR *xdr,
1411 nfs_argop4 *argop)
1412 {
1413 nfs41_link_args *args = (nfs41_link_args*)argop->arg;
1414
1415 if (unexpected_op(argop->op, OP_LINK))
1416 return FALSE;
1417
1418 return encode_component(xdr, args->newname);
1419 }
1420
1421 static bool_t decode_op_link(
1422 XDR *xdr,
1423 nfs_resop4 *resop)
1424 {
1425 nfs41_link_res *res = (nfs41_link_res*)resop->res;
1426
1427 if (unexpected_op(resop->op, OP_LINK))
1428 return FALSE;
1429
1430 if (!xdr_u_int32_t(xdr, &res->status))
1431 return FALSE;
1432
1433 if (res->status == NFS4_OK)
1434 return xdr_change_info4(xdr, &res->cinfo);
1435
1436 return TRUE;
1437 }
1438
1439
1440 /*
1441 * OP_LOCK
1442 */
1443 static bool_t xdr_locker4(
1444 XDR *xdr,
1445 locker4 *locker)
1446 {
1447 if (xdr->x_op != XDR_ENCODE) {
1448 eprintf("%s: xdr->x_op %d is not supported!\n",
1449 "xdr_locker4", xdr->x_op);
1450 return FALSE;
1451 }
1452
1453 if (!xdr_bool(xdr, &locker->new_lock_owner))
1454 return FALSE;
1455
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))
1459 return FALSE;
1460
1461 if (!xdr_stateid4(xdr, &locker->u.open_owner.open_stateid->stateid))
1462 return FALSE;
1463
1464 if (!xdr_u_int32_t(xdr, &locker->u.open_owner.lock_seqid))
1465 return FALSE;
1466
1467 return xdr_state_owner4(xdr, locker->u.open_owner.lock_owner);
1468 } else {
1469 /* exist_lock_owner4 lock_owner */
1470 if (!xdr_stateid4(xdr, &locker->u.lock_owner.lock_stateid->stateid))
1471 return FALSE;
1472
1473 return xdr_u_int32_t(xdr, &locker->u.lock_owner.lock_seqid);
1474 }
1475 }
1476
1477 static bool_t encode_op_lock(
1478 XDR *xdr,
1479 nfs_argop4 *argop)
1480 {
1481 nfs41_lock_args *args = (nfs41_lock_args*)argop->arg;
1482
1483 if (unexpected_op(argop->op, OP_LOCK))
1484 return FALSE;
1485
1486 if (!xdr_u_int32_t(xdr, &args->locktype))
1487 return FALSE;
1488
1489 if (!xdr_bool(xdr, &args->reclaim))
1490 return FALSE;
1491
1492 if (!xdr_u_hyper(xdr, &args->offset))
1493 return FALSE;
1494
1495 if (!xdr_u_hyper(xdr, &args->length))
1496 return FALSE;
1497
1498 return xdr_locker4(xdr, &args->locker);
1499 }
1500
1501 static bool_t decode_lock_res_denied(
1502 XDR *xdr,
1503 lock_res_denied *denied)
1504 {
1505 if (!xdr_u_hyper(xdr, &denied->offset))
1506 return FALSE;
1507
1508 if (!xdr_u_hyper(xdr, &denied->length))
1509 return FALSE;
1510
1511 if (!xdr_u_int32_t(xdr, &denied->locktype))
1512 return FALSE;
1513
1514 return xdr_state_owner4(xdr, &denied->owner);
1515 }
1516
1517 static bool_t decode_op_lock(
1518 XDR *xdr,
1519 nfs_resop4 *resop)
1520 {
1521 nfs41_lock_res *res = (nfs41_lock_res*)resop->res;
1522
1523 if (unexpected_op(resop->op, OP_LOCK))
1524 return FALSE;
1525
1526 if (!xdr_u_int32_t(xdr, &res->status))
1527 return FALSE;
1528
1529 switch (res->status) {
1530 case NFS4_OK:
1531 return xdr_stateid4(xdr, res->u.resok4.lock_stateid);
1532 break;
1533 case NFS4ERR_DENIED:
1534 return decode_lock_res_denied(xdr, &res->u.denied);
1535 break;
1536 default:
1537 break;
1538 }
1539
1540 return TRUE;
1541 }
1542
1543
1544 /*
1545 * OP_LOCKT
1546 */
1547 static bool_t encode_op_lockt(
1548 XDR *xdr,
1549 nfs_argop4 *argop)
1550 {
1551 nfs41_lockt_args *args = (nfs41_lockt_args*)argop->arg;
1552
1553 if (unexpected_op(argop->op, OP_LOCKT))
1554 return FALSE;
1555
1556 if (!xdr_u_int32_t(xdr, &args->locktype))
1557 return FALSE;
1558
1559 if (!xdr_u_hyper(xdr, &args->offset))
1560 return FALSE;
1561
1562 if (!xdr_u_hyper(xdr, &args->length))
1563 return FALSE;
1564
1565 return xdr_state_owner4(xdr, args->owner);
1566 }
1567
1568 static bool_t decode_op_lockt(
1569 XDR *xdr,
1570 nfs_resop4 *resop)
1571 {
1572 nfs41_lockt_res *res = (nfs41_lockt_res*)resop->res;
1573
1574 if (unexpected_op(resop->op, OP_LOCKT))
1575 return FALSE;
1576
1577 if (!xdr_u_int32_t(xdr, &res->status))
1578 return FALSE;
1579
1580 if (res->status == NFS4ERR_DENIED)
1581 return decode_lock_res_denied(xdr, &res->denied);
1582
1583 return TRUE;
1584 }
1585
1586
1587 /*
1588 * OP_LOCKU
1589 */
1590 static bool_t encode_op_locku(
1591 XDR *xdr,
1592 nfs_argop4 *argop)
1593 {
1594 nfs41_locku_args *args = (nfs41_locku_args*)argop->arg;
1595
1596 if (unexpected_op(argop->op, OP_LOCKU))
1597 return FALSE;
1598
1599 if (!xdr_u_int32_t(xdr, &args->locktype))
1600 return FALSE;
1601
1602 if (!xdr_u_int32_t(xdr, &args->seqid))
1603 return FALSE;
1604
1605 if (!xdr_stateid4(xdr, &args->lock_stateid->stateid))
1606 return FALSE;
1607
1608 if (!xdr_u_hyper(xdr, &args->offset))
1609 return FALSE;
1610
1611 return xdr_u_hyper(xdr, &args->length);
1612 }
1613
1614 static bool_t decode_op_locku(
1615 XDR *xdr,
1616 nfs_resop4 *resop)
1617 {
1618 nfs41_locku_res *res = (nfs41_locku_res*)resop->res;
1619
1620 if (unexpected_op(resop->op, OP_LOCKU))
1621 return FALSE;
1622
1623 if (!xdr_u_int32_t(xdr, &res->status))
1624 return FALSE;
1625
1626 if (res->status == NFS4_OK)
1627 return xdr_stateid4(xdr, res->lock_stateid);
1628
1629 return TRUE;
1630 }
1631
1632
1633 /*
1634 * OP_DELEGPURGE
1635 */
1636 static bool_t encode_op_delegpurge(
1637 XDR *xdr,
1638 nfs_argop4 *argop)
1639 {
1640 uint64_t zero = 0;
1641
1642 if (unexpected_op(argop->op, OP_DELEGPURGE))
1643 return FALSE;
1644
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);
1648 }
1649
1650 static bool_t decode_op_delegpurge(
1651 XDR *xdr,
1652 nfs_resop4 *resop)
1653 {
1654 nfs41_delegpurge_res *res = (nfs41_delegpurge_res*)resop->res;
1655
1656 if (unexpected_op(resop->op, OP_DELEGPURGE))
1657 return FALSE;
1658
1659 return xdr_u_int32_t(xdr, &res->status);
1660 }
1661
1662
1663 /*
1664 * OP_DELEGRETURN
1665 */
1666 static bool_t encode_op_delegreturn(
1667 XDR *xdr,
1668 nfs_argop4 *argop)
1669 {
1670 nfs41_delegreturn_args *args = (nfs41_delegreturn_args*)argop->arg;
1671
1672 if (unexpected_op(argop->op, OP_DELEGRETURN))
1673 return FALSE;
1674
1675 return xdr_stateid4(xdr, &args->stateid->stateid);
1676 }
1677
1678 static bool_t decode_op_delegreturn(
1679 XDR *xdr,
1680 nfs_resop4 *resop)
1681 {
1682 nfs41_delegreturn_res *res = (nfs41_delegreturn_res*)resop->res;
1683
1684 if (unexpected_op(resop->op, OP_DELEGRETURN))
1685 return FALSE;
1686
1687 return xdr_u_int32_t(xdr, &res->status);
1688 }
1689
1690
1691 /*
1692 * OP_GETATTR
1693 */
1694 static bool_t encode_op_getattr(
1695 XDR *xdr,
1696 nfs_argop4 *argop)
1697 {
1698 nfs41_getattr_args *args = (nfs41_getattr_args*)argop->arg;
1699
1700 if (unexpected_op(argop->op, OP_GETATTR))
1701 return FALSE;
1702
1703 return xdr_bitmap4(xdr, args->attr_request);
1704 }
1705
1706 static bool_t decode_file_attrs(
1707 XDR *xdr,
1708 fattr4 *attrs,
1709 nfs41_file_info *info)
1710 {
1711 if (attrs->attrmask.count >= 1) {
1712 if (attrs->attrmask.arr[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
1713 if (!xdr_bitmap4(xdr, info->supported_attrs))
1714 return FALSE;
1715 }
1716 if (attrs->attrmask.arr[0] & FATTR4_WORD0_TYPE) {
1717 if (!xdr_u_int32_t(xdr, &info->type))
1718 return FALSE;
1719 }
1720 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CHANGE) {
1721 if (!xdr_u_hyper(xdr, &info->change))
1722 return FALSE;
1723 }
1724 if (attrs->attrmask.arr[0] & FATTR4_WORD0_SIZE) {
1725 if (!xdr_u_hyper(xdr, &info->size))
1726 return FALSE;
1727 }
1728 if (attrs->attrmask.arr[0] & FATTR4_WORD0_LINK_SUPPORT) {
1729 if (!xdr_bool(xdr, &info->link_support))
1730 return FALSE;
1731 }
1732 if (attrs->attrmask.arr[0] & FATTR4_WORD0_SYMLINK_SUPPORT) {
1733 if (!xdr_bool(xdr, &info->symlink_support))
1734 return FALSE;
1735 }
1736 if (attrs->attrmask.arr[0] & FATTR4_WORD0_FSID) {
1737 if (!xdr_fsid(xdr, &info->fsid))
1738 return FALSE;
1739 }
1740 if (attrs->attrmask.arr[0] & FATTR4_WORD0_LEASE_TIME) {
1741 if (!xdr_u_int32_t(xdr, &info->lease_time))
1742 return FALSE;
1743 }
1744 if (attrs->attrmask.arr[0] & FATTR4_WORD0_RDATTR_ERROR) {
1745 if (!xdr_u_int32_t(xdr, &info->rdattr_error))
1746 return FALSE;
1747 }
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))
1752 return FALSE;
1753 }
1754 if (attrs->attrmask.arr[0] & FATTR4_WORD0_ACLSUPPORT) {
1755 if (!xdr_u_int32_t(xdr, &info->aclsupport))
1756 return FALSE;
1757 }
1758 if (attrs->attrmask.arr[0] & FATTR4_WORD0_ARCHIVE) {
1759 if (!xdr_bool(xdr, &info->archive))
1760 return FALSE;
1761 }
1762 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CANSETTIME) {
1763 if (!xdr_bool(xdr, &info->cansettime))
1764 return FALSE;
1765 }
1766 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CASE_INSENSITIVE) {
1767 if (!xdr_bool(xdr, &info->case_insensitive))
1768 return FALSE;
1769 }
1770 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CASE_PRESERVING) {
1771 if (!xdr_bool(xdr, &info->case_preserving))
1772 return FALSE;
1773 }
1774 if (attrs->attrmask.arr[0] & FATTR4_WORD0_FILEID) {
1775 if (!xdr_u_hyper(xdr, &info->fileid))
1776 return FALSE;
1777 }
1778 if (attrs->attrmask.arr[0] & FATTR4_WORD0_FS_LOCATIONS) {
1779 if (!decode_fs_locations4(xdr, info->fs_locations))
1780 return FALSE;
1781 }
1782 if (attrs->attrmask.arr[0] & FATTR4_WORD0_HIDDEN) {
1783 if (!xdr_bool(xdr, &info->hidden))
1784 return FALSE;
1785 }
1786 if (attrs->attrmask.arr[0] & FATTR4_WORD0_MAXREAD) {
1787 if (!xdr_u_hyper(xdr, &info->maxread))
1788 return FALSE;
1789 }
1790 if (attrs->attrmask.arr[0] & FATTR4_WORD0_MAXWRITE) {
1791 if (!xdr_u_hyper(xdr, &info->maxwrite))
1792 return FALSE;
1793 }
1794 }
1795 if (attrs->attrmask.count >= 2) {
1796 if (attrs->attrmask.arr[1] & FATTR4_WORD1_MODE) {
1797 if (!xdr_u_int32_t(xdr, &info->mode))
1798 return FALSE;
1799 }
1800 if (attrs->attrmask.arr[1] & FATTR4_WORD1_NUMLINKS) {
1801 if (!xdr_u_int32_t(xdr, &info->numlinks))
1802 return FALSE;
1803 }
1804 if (attrs->attrmask.arr[1] & FATTR4_WORD1_OWNER) {
1805 char *ptr = &info->owner[0];
1806 uint32_t owner_len;
1807 if (!xdr_bytes(xdr, &ptr, &owner_len,
1808 NFS4_OPAQUE_LIMIT))
1809 return FALSE;
1810 info->owner[owner_len] = '\0';
1811 }
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,
1816 NFS4_OPAQUE_LIMIT))
1817 return FALSE;
1818 info->owner_group[owner_group_len] = '\0';
1819 }
1820 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SPACE_AVAIL) {
1821 if (!xdr_u_hyper(xdr, &info->space_avail))
1822 return FALSE;
1823 }
1824 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SPACE_FREE) {
1825 if (!xdr_u_hyper(xdr, &info->space_free))
1826 return FALSE;
1827 }
1828 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SPACE_TOTAL) {
1829 if (!xdr_u_hyper(xdr, &info->space_total))
1830 return FALSE;
1831 }
1832 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SYSTEM) {
1833 if (!xdr_bool(xdr, &info->system))
1834 return FALSE;
1835 }
1836 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_ACCESS) {
1837 if (!xdr_nfstime4(xdr, &info->time_access))
1838 return FALSE;
1839 }
1840 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_CREATE) {
1841 if (!xdr_nfstime4(xdr, &info->time_create))
1842 return FALSE;
1843 }
1844 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_DELTA) {
1845 if (!xdr_nfstime4(xdr, info->time_delta))
1846 return FALSE;
1847 }
1848 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_MODIFY) {
1849 if (!xdr_nfstime4(xdr, &info->time_modify))
1850 return FALSE;
1851 }
1852 if (attrs->attrmask.arr[1] & FATTR4_WORD1_DACL) {
1853 if (!xdr_nfsdacl41(xdr, info->acl))
1854 return FALSE;
1855 }
1856 if (attrs->attrmask.arr[1] & FATTR4_WORD1_FS_LAYOUT_TYPE) {
1857 if (!xdr_layout_types(xdr, &info->fs_layout_types))
1858 return FALSE;
1859 }
1860 }
1861 if (attrs->attrmask.count >= 3) {
1862 if (attrs->attrmask.arr[2] & FATTR4_WORD2_MDSTHRESHOLD) {
1863 if (!xdr_mdsthreshold(xdr, &info->mdsthreshold))
1864 return FALSE;
1865 }
1866 if (attrs->attrmask.arr[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
1867 if (!xdr_bitmap4(xdr, info->suppattr_exclcreat))
1868 return FALSE;
1869 }
1870 }
1871 return TRUE;
1872 }
1873
1874 static bool_t decode_op_getattr(
1875 XDR *xdr,
1876 nfs_resop4 *resop)
1877 {
1878 nfs41_getattr_res *res = (nfs41_getattr_res*)resop->res;
1879
1880 if (unexpected_op(resop->op, OP_GETATTR))
1881 return FALSE;
1882
1883 if (!xdr_u_int32_t(xdr, &res->status))
1884 return FALSE;
1885
1886 if (res->status == NFS4_OK)
1887 {
1888 XDR attr_xdr;
1889
1890 if (!xdr_fattr4(xdr, &res->obj_attributes))
1891 return FALSE;
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);
1894 }
1895 return TRUE;
1896 }
1897
1898
1899 /*
1900 * OP_OPEN
1901 */
1902 static bool_t encode_createhow4(
1903 XDR *xdr,
1904 createhow4 *ch)
1905 {
1906 bool_t result = TRUE;
1907
1908 if (!xdr_u_int32_t(xdr, &ch->mode))
1909 return FALSE;
1910
1911 switch (ch->mode)
1912 {
1913 case UNCHECKED4:
1914 case GUARDED4:
1915 result = encode_createattrs4(xdr, ch->createattrs);
1916 break;
1917 case EXCLUSIVE4:
1918 result = xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE);
1919 break;
1920 case EXCLUSIVE4_1:
1921 if (!xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE))
1922 return FALSE;
1923 if (!encode_createattrs4(xdr, ch->createattrs))
1924 return FALSE;
1925 break;
1926 }
1927 return result;
1928 }
1929
1930 static bool_t encode_openflag4(
1931 XDR *xdr,
1932 openflag4 *of)
1933 {
1934 bool_t result = TRUE;
1935
1936 if (!xdr_u_int32_t(xdr, &of->opentype))
1937 return FALSE;
1938
1939 switch (of->opentype)
1940 {
1941 case OPEN4_CREATE:
1942 result = encode_createhow4(xdr, &of->how);
1943 break;
1944 default:
1945 break;
1946 }
1947 return result;
1948 }
1949
1950 static bool_t encode_claim_deleg_cur(
1951 XDR *xdr,
1952 stateid4 *stateid,
1953 nfs41_component *name)
1954 {
1955 if (!xdr_stateid4(xdr, stateid))
1956 return FALSE;
1957 return encode_component(xdr, name);
1958 }
1959
1960 static bool_t encode_open_claim4(
1961 XDR *xdr,
1962 open_claim4 *oc)
1963 {
1964 if (!xdr_u_int32_t(xdr, &oc->claim))
1965 return FALSE;
1966
1967 switch (oc->claim)
1968 {
1969 case CLAIM_NULL:
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);
1973 case CLAIM_FH:
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 */
1986 default:
1987 eprintf("encode_open_claim4: unsupported claim %d.\n",
1988 oc->claim);
1989 return FALSE;
1990 }
1991 }
1992
1993 static bool_t encode_op_open(
1994 XDR *xdr,
1995 nfs_argop4 *argop)
1996 {
1997 nfs41_op_open_args *args = (nfs41_op_open_args*)argop->arg;
1998
1999 if (unexpected_op(argop->op, OP_OPEN))
2000 return FALSE;
2001
2002 if (!xdr_u_int32_t(xdr, &args->seqid))
2003 return FALSE;
2004
2005 if (!xdr_u_int32_t(xdr, &args->share_access))
2006 return FALSE;
2007
2008 if (!xdr_u_int32_t(xdr, &args->share_deny))
2009 return FALSE;
2010
2011 if (!xdr_state_owner4(xdr, args->owner))
2012 return FALSE;
2013
2014 if (!encode_openflag4(xdr, &args->openhow))
2015 return FALSE;
2016
2017 return encode_open_claim4(xdr, args->claim);
2018 }
2019
2020 static bool_t decode_open_none_delegation4(
2021 XDR *xdr,
2022 open_delegation4 *delegation)
2023 {
2024 enum_t why_no_deleg;
2025 bool_t will_signal;
2026
2027 if (!xdr_enum(xdr, (enum_t*)&why_no_deleg))
2028 return FALSE;
2029
2030 switch (why_no_deleg)
2031 {
2032 case WND4_CONTENTION:
2033 case WND4_RESOURCE:
2034 return xdr_bool(xdr, &will_signal);
2035 default:
2036 return TRUE;
2037 }
2038 }
2039
2040 static bool_t decode_open_read_delegation4(
2041 XDR *xdr,
2042 open_delegation4 *delegation)
2043 {
2044 if (!xdr_stateid4(xdr, &delegation->stateid))
2045 return FALSE;
2046
2047 if (!xdr_bool(xdr, &delegation->recalled))
2048 return FALSE;
2049
2050 return xdr_nfsace4(xdr, &delegation->permissions);
2051 }
2052
2053 static bool_t decode_modified_limit4(
2054 XDR *xdr,
2055 uint64_t *filesize)
2056 {
2057 uint32_t blocks, bytes_per_block;
2058
2059 if (!xdr_u_int32_t(xdr, &blocks))
2060 return FALSE;
2061
2062 if (!xdr_u_int32_t(xdr, &bytes_per_block))
2063 return FALSE;
2064
2065 *filesize = blocks * bytes_per_block;
2066 return TRUE;
2067 }
2068
2069 enum limit_by4 {
2070 NFS_LIMIT_SIZE = 1,
2071 NFS_LIMIT_BLOCKS = 2
2072 };
2073
2074 static bool_t decode_space_limit4(
2075 XDR *xdr,
2076 uint64_t *filesize)
2077 {
2078 uint32_t limitby;
2079
2080 if (!xdr_u_int32_t(xdr, &limitby))
2081 return FALSE;
2082
2083 switch (limitby)
2084 {
2085 case NFS_LIMIT_SIZE:
2086 return xdr_u_hyper(xdr, filesize);
2087 case NFS_LIMIT_BLOCKS:
2088 return decode_modified_limit4(xdr, filesize);
2089 default:
2090 eprintf("decode_space_limit4: limitby %d invalid\n", limitby);
2091 return FALSE;
2092 }
2093 }
2094
2095 static bool_t decode_open_write_delegation4(
2096 XDR *xdr,
2097 open_delegation4 *delegation)
2098 {
2099 uint64_t size_limit;
2100
2101 if (!xdr_stateid4(xdr, &delegation->stateid))
2102 return FALSE;
2103
2104 if (!xdr_bool(xdr, &delegation->recalled))
2105 return FALSE;
2106
2107 if (!decode_space_limit4(xdr, &size_limit))
2108 return FALSE;
2109
2110 return xdr_nfsace4(xdr, &delegation->permissions);
2111 }
2112
2113 static bool_t decode_open_res_ok(
2114 XDR *xdr,
2115 nfs41_op_open_res_ok *res)
2116 {
2117 if (!xdr_stateid4(xdr, res->stateid))
2118 return FALSE;
2119
2120 if (!xdr_change_info4(xdr, &res->cinfo))
2121 return FALSE;
2122
2123 if (!xdr_u_int32_t(xdr, &res->rflags))
2124 return FALSE;
2125
2126 if (!xdr_bitmap4(xdr, &res->attrset))
2127 return FALSE;
2128
2129 if (!xdr_enum(xdr, (enum_t*)&res->delegation->type))
2130 return FALSE;
2131
2132 switch (res->delegation->type)
2133 {
2134 case OPEN_DELEGATE_NONE:
2135 return TRUE;
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);
2142 default:
2143 eprintf("decode_open_res_ok: delegation type %d not "
2144 "supported.\n", res->delegation->type);
2145 return FALSE;
2146 }
2147 }
2148
2149 static bool_t decode_op_open(
2150 XDR *xdr,
2151 nfs_resop4 *resop)
2152 {
2153 nfs41_op_open_res *res = (nfs41_op_open_res*)resop->res;
2154
2155 if (unexpected_op(resop->op, OP_OPEN))
2156 return FALSE;
2157
2158 if (!xdr_u_int32_t(xdr, &res->status))
2159 return FALSE;
2160
2161 if (res->status == NFS4_OK)
2162 return decode_open_res_ok(xdr, &res->resok4);
2163
2164 return TRUE;
2165 }
2166
2167
2168 /*
2169 * OP_OPENATTR
2170 */
2171 static bool_t encode_op_openattr(
2172 XDR *xdr,
2173 nfs_argop4 *argop)
2174 {
2175 nfs41_openattr_args *args = (nfs41_openattr_args*)argop->arg;
2176
2177 if (unexpected_op(argop->op, OP_OPENATTR))
2178 return FALSE;
2179
2180 return xdr_bool(xdr, &args->createdir);
2181 }
2182
2183 static bool_t decode_op_openattr(
2184 XDR *xdr,
2185 nfs_resop4 *resop)
2186 {
2187 nfs41_openattr_res *res = (nfs41_openattr_res*)resop->res;
2188
2189 if (unexpected_op(resop->op, OP_OPENATTR))
2190 return FALSE;
2191
2192 return xdr_u_int32_t(xdr, &res->status);
2193 }
2194
2195
2196 /*
2197 * OP_READ
2198 */
2199 static bool_t encode_op_read(
2200 XDR *xdr,
2201 nfs_argop4 *argop)
2202 {
2203 nfs41_read_args *args = (nfs41_read_args*)argop->arg;
2204
2205 if (unexpected_op(argop->op, OP_READ))
2206 return FALSE;
2207
2208 if (!xdr_stateid4(xdr, &args->stateid->stateid))
2209 return FALSE;
2210
2211 if (!xdr_u_hyper(xdr, &args->offset))
2212 return FALSE;
2213
2214 return xdr_u_int32_t(xdr, &args->count);
2215 }
2216
2217 static bool_t decode_read_res_ok(
2218 XDR *xdr,
2219 nfs41_read_res_ok *res)
2220 {
2221 unsigned char *data = res->data;
2222
2223 if (!xdr_bool(xdr, &res->eof))
2224 return FALSE;
2225
2226 return xdr_bytes(xdr, (char **)&data, &res->data_len, NFS41_MAX_FILEIO_SIZE);
2227 }
2228
2229 static bool_t decode_op_read(
2230 XDR *xdr,
2231 nfs_resop4 *resop)
2232 {
2233 nfs41_read_res *res = (nfs41_read_res*)resop->res;
2234
2235 if (unexpected_op(resop->op, OP_READ))
2236 return FALSE;
2237
2238 if (!xdr_u_int32_t(xdr, &res->status))
2239 return FALSE;
2240
2241 if (res->status == NFS4_OK)
2242 return decode_read_res_ok(xdr, &res->resok4);
2243
2244 return TRUE;
2245 }
2246
2247
2248 /*
2249 * OP_READDIR
2250 */
2251 static bool_t encode_op_readdir(
2252 XDR *xdr,
2253 nfs_argop4 *argop)
2254 {
2255 nfs41_readdir_args *args = (nfs41_readdir_args*)argop->arg;
2256
2257 if (unexpected_op(argop->op, OP_READDIR))
2258 return FALSE;
2259
2260 if (!xdr_u_hyper(xdr, &args->cookie.cookie))
2261 return FALSE;
2262
2263 if (!xdr_opaque(xdr, (char *)args->cookie.verf, NFS4_VERIFIER_SIZE))
2264 return FALSE;
2265
2266 if (!xdr_u_int32_t(xdr, &args->dircount))
2267 return FALSE;
2268
2269 if (!xdr_u_int32_t(xdr, &args->maxcount))
2270 return FALSE;
2271
2272 return xdr_bitmap4(xdr, args->attr_request);
2273 }
2274
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;
2282
2283 static bool_t decode_readdir_entry(
2284 XDR *xdr,
2285 readdir_entry_iterator *it)
2286 {
2287 uint64_t cookie;
2288 unsigned char name[NFS4_OPAQUE_LIMIT];
2289 unsigned char *nameptr = &name[0];
2290 uint32_t name_len, entry_len;
2291 fattr4 attrs;
2292
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;
2299
2300 if (!xdr_u_hyper(xdr, &cookie))
2301 return FALSE;
2302
2303 if (!xdr_bytes(xdr, (char **)&nameptr, &name_len, NFS4_OPAQUE_LIMIT))
2304 return FALSE;
2305
2306 if (!xdr_fattr4(xdr, &attrs))
2307 return FALSE;
2308
2309 if (!xdr_bool(xdr, &it->has_next_entry))
2310 return FALSE;
2311
2312 if (it->ignore_the_rest)
2313 return TRUE;
2314
2315 name_len += 1; /* account for null terminator */
2316 if (entry_len + name_len <= it->remaining_len)
2317 {
2318 XDR fattr_xdr;
2319 nfs41_readdir_entry *entry = (nfs41_readdir_entry*)it->buf_pos;
2320 entry->cookie = cookie;
2321 entry->name_len = name_len;
2322
2323 if (it->has_next_entry)
2324 entry->next_entry_offset = entry_len + name_len;
2325 else
2326 entry->next_entry_offset = 0;
2327
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);
2332
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;
2336 }
2337 else if (it->last_entry_offset)
2338 {
2339 *(it->last_entry_offset) = 0;
2340 it->ignore_the_rest = 1;
2341 }
2342
2343 return TRUE;
2344 }
2345
2346 static bool_t decode_readdir_list(
2347 XDR *xdr,
2348 nfs41_readdir_list *dirs)
2349 {
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;
2356
2357 if (!xdr_bool(xdr, &dirs->has_entries))
2358 return FALSE;
2359
2360 if (dirs->has_entries)
2361 {
2362 do {
2363 if (!decode_readdir_entry(xdr, &iter))
2364 return FALSE;
2365
2366 } while (iter.has_next_entry);
2367 }
2368 dirs->entries_len -= iter.remaining_len;
2369
2370 if (!xdr_bool(xdr, &dirs->eof))
2371 return FALSE;
2372
2373 /* reset eof if we couldn't fit everything in the buffer */
2374 if (iter.ignore_the_rest)
2375 dirs->eof = 0;
2376 return TRUE;
2377 }
2378
2379 static bool_t decode_op_readdir(
2380 XDR *xdr,
2381 nfs_resop4 *resop)
2382 {
2383 nfs41_readdir_res *res = (nfs41_readdir_res*)resop->res;
2384
2385 if (unexpected_op(resop->op, OP_READDIR))
2386 return FALSE;
2387
2388 if (!xdr_u_int32_t(xdr, &res->status))
2389 return FALSE;
2390
2391 if (res->status == NFS4_OK) {
2392 if (!xdr_opaque(xdr, (char *)res->cookieverf, NFS4_VERIFIER_SIZE))
2393 return FALSE;
2394 return decode_readdir_list(xdr, &res->reply);
2395 }
2396 return TRUE;
2397 }
2398
2399
2400 /*
2401 * OP_READLINK
2402 */
2403 static bool_t encode_op_readlink(
2404 XDR *xdr,
2405 nfs_argop4 *argop)
2406 {
2407 if (unexpected_op(argop->op, OP_READLINK))
2408 return FALSE;
2409
2410 /* void */
2411 return TRUE;
2412 }
2413
2414 static bool_t decode_op_readlink(
2415 XDR *xdr,
2416 nfs_resop4 *resop)
2417 {
2418 nfs41_readlink_res *res = (nfs41_readlink_res*)resop->res;
2419
2420 if (unexpected_op(resop->op, OP_READLINK))
2421 return FALSE;
2422
2423 if (!xdr_u_int32_t(xdr, &res->status))
2424 return FALSE;
2425
2426 if (res->status == NFS4_OK) {
2427 char *link = res->link;
2428 return xdr_bytes(xdr, &link, &res->link_len, res->link_len);
2429 }
2430
2431 return TRUE;
2432 }
2433
2434
2435 /*
2436 * OP_REMOVE
2437 */
2438 static bool_t encode_op_remove(
2439 XDR *xdr,
2440 nfs_argop4 *argop)
2441 {
2442 nfs41_remove_args *args = (nfs41_remove_args*)argop->arg;
2443
2444 if (unexpected_op(argop->op, OP_REMOVE))
2445 return FALSE;
2446
2447 return encode_component(xdr, args->target);
2448 }
2449
2450 static bool_t decode_op_remove(
2451 XDR *xdr,
2452 nfs_resop4 *resop)
2453 {
2454 nfs41_remove_res *res = (nfs41_remove_res*)resop->res;
2455
2456 if (unexpected_op(resop->op, OP_REMOVE))
2457 return FALSE;
2458
2459 if (!xdr_u_int32_t(xdr, &res->status))
2460 return FALSE;
2461
2462 if (res->status == NFS4_OK)
2463 return xdr_change_info4(xdr, &res->cinfo);
2464
2465 return TRUE;
2466 }
2467
2468
2469 /*
2470 * OP_RENAME
2471 */
2472 static bool_t encode_op_rename(
2473 XDR *xdr,
2474 nfs_argop4 *argop)
2475 {
2476 nfs41_rename_args *args = (nfs41_rename_args*)argop->arg;
2477
2478 if (unexpected_op(argop->op, OP_RENAME))
2479 return FALSE;
2480
2481 if (!encode_component(xdr, args->oldname))
2482 return FALSE;
2483
2484 return encode_component(xdr, args->newname);
2485 }
2486
2487 static bool_t decode_op_rename(
2488 XDR *xdr,
2489 nfs_resop4 *resop)
2490 {
2491 nfs41_rename_res *res = (nfs41_rename_res*)resop->res;
2492
2493 if (unexpected_op(resop->op, OP_RENAME))
2494 return FALSE;
2495
2496 if (!xdr_u_int32_t(xdr, &res->status))
2497 return FALSE;
2498
2499 if (res->status == NFS4_OK)
2500 {
2501 if (!xdr_change_info4(xdr, &res->source_cinfo))
2502 return FALSE;
2503 return xdr_change_info4(xdr, &res->target_cinfo);
2504 }
2505 return TRUE;
2506 }
2507
2508
2509 /*
2510 * OP_RESTOREFH
2511 */
2512 static bool_t encode_op_restorefh(
2513 XDR *xdr,
2514 nfs_argop4 *argop)
2515 {
2516 if (unexpected_op(argop->op, OP_RESTOREFH))
2517 return FALSE;
2518
2519 /* void */
2520 return TRUE;
2521 }
2522
2523 static bool_t decode_op_restorefh(
2524 XDR *xdr,
2525 nfs_resop4 *resop)
2526 {
2527 nfs41_restorefh_res *res = (nfs41_restorefh_res*)resop->res;
2528
2529 if (unexpected_op(resop->op, OP_RESTOREFH))
2530 return FALSE;
2531
2532 return xdr_u_int32_t(xdr, &res->status);
2533 }
2534
2535
2536 /*
2537 * OP_SAVEFH
2538 */
2539 static bool_t encode_op_savefh(
2540 XDR *xdr,
2541 nfs_argop4 *argop)
2542 {
2543 if (unexpected_op(argop->op, OP_SAVEFH))
2544 return FALSE;
2545
2546 /* void */
2547 return TRUE;
2548 }
2549
2550 static bool_t decode_op_savefh(
2551 XDR *xdr,
2552 nfs_resop4 *resop)
2553 {
2554 nfs41_savefh_res *res = (nfs41_savefh_res*)resop->res;
2555
2556 if (unexpected_op(resop->op, OP_SAVEFH))
2557 return FALSE;
2558
2559 return xdr_u_int32_t(xdr, &res->status);
2560 }
2561
2562
2563 /*
2564 * OP_SETATTR
2565 */
2566 static bool_t encode_file_attrs(
2567 fattr4 *attrs,
2568 nfs41_file_info *info)
2569 {
2570 uint32_t i;
2571 XDR localxdr;
2572
2573 xdrmem_create(&localxdr, (char *)attrs->attr_vals, NFS4_OPAQUE_LIMIT, XDR_ENCODE);
2574
2575 attrs->attr_vals_len = 0;
2576 ZeroMemory(&attrs->attrmask, sizeof(bitmap4));
2577 attrs->attrmask.count = info->attrmask.count;
2578
2579 if (info->attrmask.count > 0) {
2580 if (info->attrmask.arr[0] & FATTR4_WORD0_SIZE) {
2581 if (!xdr_u_hyper(&localxdr, &info->size))
2582 return FALSE;
2583 attrs->attrmask.arr[0] |= FATTR4_WORD0_SIZE;
2584 }
2585 if (info->attrmask.arr[0] & FATTR4_WORD0_ACL) {
2586 if (!xdr_nfsacl41(&localxdr, info->acl))
2587 return FALSE;
2588 attrs->attrmask.arr[0] |= FATTR4_WORD0_ACL;
2589 }
2590 if (info->attrmask.arr[0] & FATTR4_WORD0_ARCHIVE) {
2591 if (!xdr_bool(&localxdr, &info->archive))
2592 return FALSE;
2593 attrs->attrmask.arr[0] |= FATTR4_WORD0_ARCHIVE;
2594 }
2595 if (info->attrmask.arr[0] & FATTR4_WORD0_HIDDEN) {
2596 if (!xdr_bool(&localxdr, &info->hidden))
2597 return FALSE;
2598 attrs->attrmask.arr[0] |= FATTR4_WORD0_HIDDEN;
2599 }
2600 }
2601 if (info->attrmask.count > 1) {
2602 if (info->attrmask.arr[1] & FATTR4_WORD1_MODE) {
2603 if (!xdr_u_int32_t(&localxdr, &info->mode))
2604 return FALSE;
2605 attrs->attrmask.arr[1] |= FATTR4_WORD1_MODE;
2606 }
2607 if (info->attrmask.arr[1] & FATTR4_WORD1_SYSTEM) {
2608 if (!xdr_bool(&localxdr, &info->system))
2609 return FALSE;
2610 attrs->attrmask.arr[1] |= FATTR4_WORD1_SYSTEM;
2611 }
2612 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
2613 if (!xdr_settime4(&localxdr, &info->time_access, info->time_delta))
2614 return FALSE;
2615 attrs->attrmask.arr[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
2616 }
2617 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_CREATE) {
2618 if (!xdr_nfstime4(&localxdr, &info->time_create))
2619 return FALSE;
2620 attrs->attrmask.arr[1] |= FATTR4_WORD1_TIME_CREATE;
2621 }
2622 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
2623 if (!xdr_settime4(&localxdr, &info->time_modify, info->time_delta))
2624 return FALSE;
2625 attrs->attrmask.arr[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
2626 }
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,
2631 NFS4_OPAQUE_LIMIT))
2632 return FALSE;
2633 attrs->attrmask.arr[1] |= FATTR4_WORD1_OWNER;
2634 }
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,
2639 NFS4_OPAQUE_LIMIT))
2640 return FALSE;
2641 attrs->attrmask.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
2642 }
2643 }
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))
2647 return FALSE;
2648 if (!xdr_u_int32_t(&localxdr, &info->mode_mask))
2649 return FALSE;
2650 attrs->attrmask.arr[2] |= FATTR4_WORD2_MODE_SET_MASKED;
2651 }
2652 }
2653
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]);
2660
2661 attrs->attr_vals_len = xdr_getpos(&localxdr);
2662 return TRUE;
2663 }
2664
2665 static bool_t encode_op_setattr(
2666 XDR *xdr,
2667 nfs_argop4 *argop)
2668 {
2669 nfs41_setattr_args *args = (nfs41_setattr_args*)argop->arg;
2670 fattr4 attrs;
2671
2672 if (unexpected_op(argop->op, OP_SETATTR))
2673 return FALSE;
2674
2675 if (!xdr_stateid4(xdr, &args->stateid->stateid))
2676 return FALSE;
2677
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))
2681 return FALSE;
2682
2683 return xdr_fattr4(xdr, &attrs);
2684 }
2685
2686 static bool_t decode_op_setattr(
2687 XDR *xdr,
2688 nfs_resop4 *resop)
2689 {
2690 nfs41_setattr_res *res = (nfs41_setattr_res*)resop->res;
2691
2692 if (unexpected_op(resop->op, OP_SETATTR))
2693 return FALSE;
2694
2695 if (!xdr_u_int32_t(xdr, &res->status))
2696 return FALSE;
2697
2698 if (res->status == NFS4_OK)
2699 return xdr_bitmap4(xdr, &res->attrsset);
2700
2701 return TRUE;
2702 }
2703
2704
2705 /*
2706 * OP_WANT_DELEGATION
2707 */
2708 static bool_t encode_op_want_delegation(
2709 XDR *xdr,
2710 nfs_argop4 *argop)
2711 {
2712 nfs41_want_delegation_args *args = (nfs41_want_delegation_args*)argop->arg;
2713
2714 if (unexpected_op(argop->op, OP_WANT_DELEGATION))
2715 return FALSE;
2716
2717 if (!xdr_u_int32_t(xdr, &args->want))
2718 return FALSE;
2719
2720 if (!xdr_u_int32_t(xdr, &args->claim->claim))
2721 return FALSE;
2722
2723 return args->claim->claim != CLAIM_PREVIOUS ||
2724 xdr_u_int32_t(xdr, &args->claim->prev_delegate_type);
2725 }
2726
2727 static bool_t decode_op_want_delegation(
2728 XDR *xdr,
2729 nfs_resop4 *resop)
2730 {
2731 nfs41_want_delegation_res *res = (nfs41_want_delegation_res*)resop->res;
2732
2733 if (unexpected_op(resop->op, OP_WANT_DELEGATION))
2734 return FALSE;
2735
2736 if (!xdr_u_int32_t(xdr, &res->status))
2737 return FALSE;
2738
2739 if (res->status)
2740 return TRUE;
2741
2742 if (!xdr_enum(xdr, (enum_t*)&res->delegation->type))
2743 return FALSE;
2744
2745 switch (res->delegation->type)
2746 {
2747 case OPEN_DELEGATE_NONE:
2748 return TRUE;
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);
2755 default:
2756 eprintf("decode_open_res_ok: delegation type %d not "
2757 "supported.\n", res->delegation->type);
2758 return FALSE;
2759 }
2760 }
2761
2762
2763 /*
2764 * OP_FREE_STATEID
2765 */
2766 static bool_t encode_op_free_stateid(
2767 XDR *xdr,
2768 nfs_argop4 *argop)
2769 {
2770 nfs41_free_stateid_args *args = (nfs41_free_stateid_args*)argop->arg;
2771
2772 if (unexpected_op(argop->op, OP_FREE_STATEID))
2773 return FALSE;
2774
2775 return xdr_stateid4(xdr, args->stateid);
2776 }
2777
2778 static bool_t decode_op_free_stateid(
2779 XDR *xdr,
2780 nfs_resop4 *resop)
2781 {
2782 nfs41_free_stateid_res *res = (nfs41_free_stateid_res*)resop->res;
2783
2784 if (unexpected_op(resop->op, OP_FREE_STATEID))
2785 return FALSE;
2786
2787 return xdr_u_int32_t(xdr, &res->status);
2788 }
2789
2790
2791 /*
2792 * OP_TEST_STATEID
2793 */
2794 static bool_t encode_op_test_stateid(
2795 XDR *xdr,
2796 nfs_argop4 *argop)
2797 {
2798 nfs41_test_stateid_args *args = (nfs41_test_stateid_args*)argop->arg;
2799
2800 if (unexpected_op(argop->op, OP_TEST_STATEID))
2801 return FALSE;
2802
2803 return xdr_array(xdr, (char**)&args->stateids, &args->count,
2804 args->count, sizeof(stateid_arg), (xdrproc_t)xdr_stateid4);
2805 }
2806
2807 static bool_t decode_op_test_stateid(
2808 XDR *xdr,
2809 nfs_resop4 *resop)
2810 {
2811 nfs41_test_stateid_res *res = (nfs41_test_stateid_res*)resop->res;
2812
2813 if (unexpected_op(resop->op, OP_TEST_STATEID))
2814 return FALSE;
2815
2816 if (!xdr_u_int32_t(xdr, &res->status))
2817 return FALSE;
2818
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);
2822 }
2823 return TRUE;
2824 }
2825
2826
2827 /*
2828 * OP_WRITE
2829 */
2830 static bool_t encode_op_write(
2831 XDR *xdr,
2832 nfs_argop4 *argop)
2833 {
2834 nfs41_write_args *args = (nfs41_write_args*)argop->arg;
2835 unsigned char *data = args->data;
2836
2837 if (unexpected_op(argop->op, OP_WRITE))
2838 return FALSE;
2839
2840 if (!xdr_stateid4(xdr, &args->stateid->stateid))
2841 return FALSE;
2842
2843 if (!xdr_u_hyper(xdr, &args->offset))
2844 return FALSE;
2845
2846 if (!xdr_u_int32_t(xdr, &args->stable))
2847 return FALSE;
2848
2849 return xdr_bytes(xdr, (char **)&data, &args->data_len, NFS41_MAX_FILEIO_SIZE);
2850 }
2851
2852 static bool_t xdr_write_verf(
2853 XDR *xdr,
2854 nfs41_write_verf *verf)
2855 {
2856 if (!xdr_enum(xdr, (enum_t *)&verf->committed))
2857 return FALSE;
2858
2859 return xdr_opaque(xdr, (char *)verf->verf, NFS4_VERIFIER_SIZE);
2860 }
2861
2862 static bool_t xdr_write_res_ok(
2863 XDR *xdr,
2864 nfs41_write_res_ok *res)
2865 {
2866 if (!xdr_u_int32_t(xdr, &res->count))
2867 return FALSE;
2868
2869 return xdr_write_verf(xdr, res->verf);
2870 }
2871
2872 static bool_t decode_op_write(
2873 XDR *xdr,
2874 nfs_resop4 *resop)
2875 {
2876 nfs41_write_res *res = (nfs41_write_res*)resop->res;
2877
2878 if (unexpected_op(resop->op, OP_WRITE))
2879 return FALSE;
2880
2881 if (!xdr_u_int32_t(xdr, &res->status))
2882 return FALSE;
2883
2884 if (res->status == NFS4_OK)
2885 return xdr_write_res_ok(xdr, &res->resok4);
2886
2887 return TRUE;
2888 }
2889
2890 /*
2891 * OP_SECINFO_NO_NAME
2892 */
2893 static bool_t xdr_secinfo(
2894 XDR *xdr,
2895 nfs41_secinfo_info *secinfo)
2896 {
2897 if (!xdr_u_int32_t(xdr, &secinfo->sec_flavor))
2898 return FALSE;
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))
2902 return FALSE;
2903 if (!xdr_u_int32_t(xdr, &secinfo->qop))
2904 return FALSE;
2905 if (!xdr_enum(xdr, (enum_t *)&secinfo->type))
2906 return FALSE;
2907 }
2908 return TRUE;
2909 }
2910
2911 static bool_t encode_op_secinfo_noname(
2912 XDR *xdr,
2913 nfs_argop4 *argop)
2914 {
2915 nfs41_secinfo_noname_args *args = (nfs41_secinfo_noname_args *)argop->arg;
2916
2917 if (unexpected_op(argop->op, OP_SECINFO_NO_NAME))
2918 return FALSE;
2919
2920 if (!xdr_enum(xdr, (enum_t *)&args->type))
2921 return FALSE;
2922
2923 return TRUE;
2924 }
2925
2926 static bool_t decode_op_secinfo_noname(
2927 XDR *xdr,
2928 nfs_resop4 *resop)
2929 {
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))
2933 return FALSE;
2934
2935 if (!xdr_u_int32_t(xdr, &res->status))
2936 return FALSE;
2937
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);
2941
2942 return TRUE;
2943 }
2944
2945 /*
2946 * OP_SECINFO
2947 */
2948 static bool_t encode_op_secinfo(
2949 XDR *xdr,
2950 nfs_argop4 *argop)
2951 {
2952 nfs41_secinfo_args *args = (nfs41_secinfo_args *)argop->arg;
2953
2954 if (unexpected_op(argop->op, OP_SECINFO))
2955 return FALSE;
2956
2957 if (!encode_component(xdr, args->name))
2958 return FALSE;
2959
2960 return TRUE;
2961 }
2962
2963 static bool_t decode_op_secinfo(
2964 XDR *xdr,
2965 nfs_resop4 *resop)
2966 {
2967 nfs41_secinfo_noname_res *res = (nfs41_secinfo_noname_res *)resop->res;
2968 nfs41_secinfo_info *secinfo = res->secinfo;
2969
2970 if (unexpected_op(resop->op, OP_SECINFO))
2971 return FALSE;
2972
2973 if (!xdr_u_int32_t(xdr, &res->status))
2974 return FALSE;
2975
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);
2979
2980 return TRUE;
2981 }
2982 /*
2983 * OP_GETDEVICEINFO
2984 */
2985 static bool_t encode_op_getdeviceinfo(
2986 XDR *xdr,
2987 nfs_argop4 *argop)
2988 {
2989 pnfs_getdeviceinfo_args *args = (pnfs_getdeviceinfo_args*)argop->arg;
2990
2991 if (unexpected_op(argop->op, OP_GETDEVICEINFO))
2992 return FALSE;
2993
2994 if (!xdr_opaque(xdr, (char *)args->deviceid, PNFS_DEVICEID_SIZE))
2995 return FALSE;
2996
2997 if (!xdr_enum(xdr, (enum_t *)&args->layout_type))
2998 return FALSE;
2999
3000 if (!xdr_u_int32_t(xdr, &args->maxcount))
3001 return FALSE;
3002
3003 return xdr_bitmap4(xdr, &args->notify_types);
3004 }
3005
3006 static bool_t xdr_stripe_indices(
3007 XDR *xdr,
3008 pnfs_stripe_indices *indices)
3009 {
3010 uint32_t i, count;
3011
3012 if (!xdr_u_int32_t(xdr, &count))
3013 return FALSE;
3014
3015 if (count && count != indices->count) {
3016 uint32_t *tmp;
3017 tmp = realloc(indices->arr, count * sizeof(uint32_t));
3018 if (tmp == NULL)
3019 return FALSE;
3020 indices->arr = tmp;
3021 ZeroMemory(indices->arr, count * sizeof(uint32_t));
3022 indices->count = count;
3023 }
3024
3025 for (i = 0; i < indices->count; i++) {
3026 if (!xdr_u_int32_t(xdr, &indices->arr[i]))
3027 return FALSE;
3028 }
3029 return TRUE;
3030 }
3031
3032 static bool_t xdr_pnfs_addr(
3033 XDR *xdr,
3034 netaddr4 *addr)
3035 {
3036 uint32_t len;
3037 char *netid = addr->netid;
3038 char *uaddr = addr->uaddr;
3039
3040 if (xdr->x_op == XDR_ENCODE)
3041 len = sizeof(addr->netid);
3042 if (!xdr_bytes(xdr, &netid, &len, NFS41_NETWORK_ID_LEN))
3043 return FALSE;
3044
3045 if (xdr->x_op == XDR_DECODE) {
3046 if (len < NFS41_NETWORK_ID_LEN)
3047 addr->netid[len] = 0;
3048 else
3049 addr->netid[NFS41_NETWORK_ID_LEN] = 0;
3050 }
3051
3052 if (xdr->x_op == XDR_ENCODE)
3053 len = sizeof(addr->uaddr);
3054 if (!xdr_bytes(xdr, &uaddr, &len, NFS41_UNIVERSAL_ADDR_LEN))
3055 return FALSE;
3056
3057 if (xdr->x_op == XDR_DECODE){
3058 if (len < NFS41_UNIVERSAL_ADDR_LEN)
3059 addr->uaddr[len] = 0;
3060 else
3061 addr->uaddr[NFS41_UNIVERSAL_ADDR_LEN] = 0;
3062 }
3063
3064 return TRUE;
3065 }
3066
3067 static bool_t xdr_multi_addr(
3068 XDR *xdr,
3069 multi_addr4 *list)
3070 {
3071 netaddr4 dummy, *dest;
3072 uint32_t i;
3073
3074 if (!xdr_u_int32_t(xdr, &list->count))
3075 return FALSE;
3076
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;
3080
3081 if (!xdr_pnfs_addr(xdr, dest))
3082 return FALSE;
3083 }
3084 return TRUE;
3085 }
3086
3087 static bool_t xdr_data_server_list(
3088 XDR *xdr,
3089 pnfs_data_server_list *servers)
3090 {
3091 uint32_t i, count;
3092
3093 if (!xdr_u_int32_t(xdr, &count))
3094 return FALSE;
3095
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;
3102
3103 tmp = realloc(servers->arr, count * sizeof(pnfs_data_server));
3104 if (tmp == NULL)
3105 return FALSE;
3106 servers->arr = tmp;
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;
3111 }
3112
3113 for (i = 0; i < servers->count; i++) {
3114 if (!xdr_multi_addr(xdr, &servers->arr[i].addrs))
3115 return FALSE;
3116 }
3117 return TRUE;
3118 }
3119
3120 static bool_t xdr_file_device(
3121 XDR *xdr,
3122 pnfs_file_device *device)
3123 {
3124 if (!xdr_stripe_indices(xdr, &device->stripes))
3125 return FALSE;
3126
3127 return xdr_data_server_list(xdr, &device->servers);
3128 }
3129
3130 static bool_t decode_getdeviceinfo_ok(
3131 XDR *xdr,
3132 pnfs_getdeviceinfo_res_ok *res_ok)
3133 {
3134 u_int32_t len_ignored;
3135
3136 if (!xdr_enum(xdr, (enum_t *)&res_ok->device->device.type))
3137 return FALSE;
3138
3139 if (res_ok->device->device.type != PNFS_LAYOUTTYPE_FILE)
3140 return FALSE;
3141
3142 if (!xdr_u_int32_t(xdr, &len_ignored))
3143 return FALSE;
3144
3145 if (!xdr_file_device(xdr, res_ok->device))
3146 return FALSE;
3147
3148 return xdr_bitmap4(xdr, &res_ok->notification);
3149 }
3150
3151 static bool_t decode_op_getdeviceinfo(
3152 XDR *xdr,
3153 nfs_resop4 *resop)
3154 {
3155 pnfs_getdeviceinfo_res *res = (pnfs_getdeviceinfo_res*)resop->res;
3156
3157 if (unexpected_op(resop->op, OP_GETDEVICEINFO))
3158 return FALSE;
3159
3160 if (!xdr_u_int32_t(xdr, (uint32_t *)&res->status))
3161 return FALSE;
3162
3163 switch (res->status) {
3164 case NFS4_OK:
3165 return decode_getdeviceinfo_ok(xdr, &res->u.res_ok);
3166 break;
3167 case NFS4ERR_TOOSMALL:
3168 {
3169 uint32_t ignored;
3170 return xdr_u_int32_t(xdr, &ignored);
3171 }
3172 break;
3173 }
3174 return TRUE;
3175 }
3176
3177
3178 /*
3179 * OP_LAYOUTCOMMIT
3180 */
3181 static bool_t encode_op_layoutcommit(
3182 XDR *xdr,
3183 nfs_argop4 *argop)
3184 {
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;
3189 uint32_t zero = 0;
3190
3191 if (unexpected_op(argop->op, OP_LAYOUTCOMMIT))
3192 return FALSE;
3193
3194 if (!xdr_u_hyper(xdr, &args->offset))
3195 return FALSE;
3196
3197 if (!xdr_u_hyper(xdr, &args->length))
3198 return FALSE;
3199
3200 if (!xdr_bool(xdr, &false_bool)) /* loca_reclaim = 0 */
3201 return FALSE;
3202
3203 if (!xdr_stateid4(xdr, args->stateid))
3204 return FALSE;
3205
3206 /* loca_last_write_offset */
3207 if (args->new_offset) {
3208 if (!xdr_bool(xdr, &true_bool))
3209 return FALSE;
3210
3211 if (!xdr_u_hyper(xdr, args->new_offset))
3212 return FALSE;
3213 } else {
3214 if (!xdr_bool(xdr, &false_bool))
3215 return FALSE;
3216 }
3217
3218 /* loca_time_modify */
3219 if (args->new_time) {
3220 if (!xdr_bool(xdr, &true_bool))
3221 return FALSE;
3222
3223 if (!xdr_nfstime4(xdr, args->new_time))
3224 return FALSE;
3225 } else {
3226 if (!xdr_bool(xdr, &false_bool))
3227 return FALSE;
3228 }
3229
3230 /* loca_layoutupdate */
3231 if (!xdr_enum(xdr, &pnfs_layout))
3232 return FALSE;
3233
3234 return xdr_u_int32_t(xdr, &zero);
3235 }
3236
3237 static bool_t decode_op_layoutcommit(
3238 XDR *xdr,
3239 nfs_resop4 *resop)
3240 {
3241 pnfs_layoutcommit_res *res = (pnfs_layoutcommit_res*)resop->res;
3242
3243 if (unexpected_op(resop->op, OP_LAYOUTCOMMIT))
3244 return FALSE;
3245
3246 if (!xdr_u_int32_t(xdr, &res->status))
3247 return FALSE;
3248
3249 if (res->status == NFS4_OK) {
3250 if (!xdr_bool(xdr, &res->has_new_size))
3251 return FALSE;
3252
3253 if (res->has_new_size)
3254 if (!xdr_u_hyper(xdr, &res->new_size))
3255 return FALSE;
3256 }
3257 return TRUE;
3258 }
3259
3260 /*
3261 * OP_LAYOUTGET
3262 */
3263 static bool_t encode_op_layoutget(
3264 XDR *xdr,
3265 nfs_argop4 *argop)
3266 {
3267 pnfs_layoutget_args *args = (pnfs_layoutget_args*)argop->arg;
3268
3269 if (unexpected_op(argop->op, OP_LAYOUTGET))
3270 return FALSE;
3271
3272 if (!xdr_bool(xdr, &args->signal_layout_avail))
3273 return FALSE;
3274
3275 if (!xdr_u_int32_t(xdr, (u_int32_t *)&args->layout_type))
3276 return FALSE;
3277
3278 if (!xdr_u_int32_t(xdr, (u_int32_t *)&args->iomode))
3279 return FALSE;
3280
3281 if (!xdr_u_hyper(xdr, &args->offset))
3282 return FALSE;
3283
3284 if (!xdr_u_hyper(xdr, &args->length))
3285 return FALSE;
3286
3287 if (!xdr_u_hyper(xdr, &args->minlength))
3288 return FALSE;
3289
3290 if (!xdr_stateid4(xdr, &args->stateid->stateid))
3291 return FALSE;
3292
3293 return xdr_u_int32_t(xdr, &args->maxcount);
3294 }
3295
3296 static bool_t decode_file_layout_handles(
3297 XDR *xdr,
3298 pnfs_file_layout_handles *handles)
3299 {
3300 uint32_t i, count;
3301
3302 if (!xdr_u_int32_t(xdr, &count))
3303 return FALSE;
3304
3305 if (count && count != handles->count) {
3306 nfs41_path_fh *tmp;
3307 tmp = realloc(handles->arr, count * sizeof(nfs41_path_fh));
3308 if (tmp == NULL)
3309 return FALSE;
3310 handles->arr = tmp;
3311 ZeroMemory(handles->arr, count * sizeof(nfs41_path_fh));
3312 handles->count = count;
3313 }
3314
3315 for (i = 0; i < handles->count; i++) {
3316 if (!xdr_fh(xdr, &handles->arr[i].fh))
3317 return FALSE;
3318 }
3319 return TRUE;
3320 }
3321
3322 static bool_t decode_file_layout(
3323 XDR *xdr,
3324 struct list_entry *list,
3325 pnfs_layout *base)
3326 {
3327 pnfs_file_layout *layout;
3328 u_int32_t len_ignored;
3329
3330 if (!xdr_u_int32_t(xdr, &len_ignored))
3331 return FALSE;
3332
3333 layout = calloc(1, sizeof(pnfs_file_layout));
3334 if (layout == NULL)
3335 return FALSE;
3336
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);
3342
3343 if (!xdr_opaque(xdr, (char *)layout->deviceid, PNFS_DEVICEID_SIZE))
3344 goto out_error;
3345
3346 if (!xdr_u_int32_t(xdr, &layout->util))
3347 goto out_error;
3348
3349 if (!xdr_u_int32_t(xdr, &layout->first_index))
3350 goto out_error;
3351
3352 if (!xdr_u_hyper(xdr, &layout->pattern_offset))
3353 goto out_error;
3354
3355 if (!decode_file_layout_handles(xdr, &layout->filehandles))
3356 goto out_error;
3357
3358 list_add_tail(list, &layout->layout.entry);
3359 return TRUE;
3360
3361 out_error:
3362 free(layout);
3363 return FALSE;
3364 }
3365
3366 static bool_t decode_layout(
3367 XDR *xdr,
3368 struct list_entry *list)
3369 {
3370 pnfs_layout layout;
3371
3372 if (!xdr_u_hyper(xdr, &layout.offset))
3373 return FALSE;
3374
3375 if (!xdr_u_hyper(xdr, &layout.length))
3376 return FALSE;
3377
3378 if (!xdr_enum(xdr, (enum_t *)&layout.iomode))
3379 return FALSE;
3380
3381 if (!xdr_enum(xdr, (enum_t *)&layout.type))
3382 return FALSE;
3383
3384 switch (layout.type) {
3385 case PNFS_LAYOUTTYPE_FILE:
3386 return decode_file_layout(xdr, list, &layout);
3387
3388 default:
3389 eprintf("%s: received non-FILE layout type, %d\n",
3390 "decode_file_layout", layout.type);
3391 }
3392 return FALSE;
3393 }
3394
3395 static bool_t decode_layout_res_ok(
3396 XDR *xdr,
3397 pnfs_layoutget_res_ok *res)
3398 {
3399 uint32_t i;
3400
3401 if (!xdr_bool(xdr, &res->return_on_close))
3402 return FALSE;
3403
3404 if (!xdr_stateid4(xdr, &res->stateid))
3405 return FALSE;
3406
3407 if (!xdr_u_int32_t(xdr, &res->count))
3408 return FALSE;
3409
3410 for (i = 0; i < res->count; i++)
3411 if (!decode_layout(xdr, &res->layouts))
3412 return FALSE;
3413 return TRUE;
3414 }
3415
3416 static bool_t decode_op_layoutget(
3417 XDR *xdr,
3418 nfs_resop4 *resop)
3419 {
3420 pnfs_layoutget_res *res = (pnfs_layoutget_res*)resop->res;
3421
3422 if (unexpected_op(resop->op, OP_LAYOUTGET))
3423 return FALSE;
3424
3425 if (!xdr_u_int32_t(xdr, (uint32_t *)&res->status))
3426 return FALSE;
3427
3428 switch (res->status) {
3429 case NFS4_OK:
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);
3433 }
3434 return TRUE;
3435 }
3436
3437
3438 /*
3439 * OP_LAYOUTRETURN
3440 */
3441 static bool_t encode_op_layoutreturn(
3442 XDR *xdr,
3443 nfs_argop4 *argop)
3444 {
3445 pnfs_layoutreturn_args *args = (pnfs_layoutreturn_args*)argop->arg;
3446
3447 if (unexpected_op(argop->op, OP_LAYOUTRETURN))
3448 return FALSE;
3449
3450 if (!xdr_bool(xdr, &args->reclaim))
3451 return FALSE;
3452
3453 if (!xdr_enum(xdr, (enum_t *)&args->type))
3454 return FALSE;
3455
3456 if (!xdr_enum(xdr, (enum_t *)&args->iomode))
3457 return FALSE;
3458
3459 if (!xdr_enum(xdr, (enum_t *)&args->return_type))
3460 return FALSE;
3461
3462 if (args->return_type == PNFS_RETURN_FILE) {
3463 u_int32_t zero = 0;
3464
3465 if (!xdr_u_hyper(xdr, &args->offset))
3466 return FALSE;
3467
3468 if (!xdr_u_hyper(xdr, &args->length))
3469 return FALSE;
3470
3471 if (!xdr_stateid4(xdr, args->stateid))
3472 return FALSE;
3473
3474 return xdr_u_int32_t(xdr, &zero); /* size of lrf_body is 0 */
3475 } else {
3476 eprintf("%s: layout type (%d) is not PNFS_RETURN_FILE!\n",
3477 "encode_op_layoutreturn", args->return_type);
3478 return FALSE;
3479 }
3480 }
3481
3482 static bool_t decode_op_layoutreturn(
3483 XDR *xdr,
3484 nfs_resop4 *resop)
3485 {
3486 pnfs_layoutreturn_res *res = (pnfs_layoutreturn_res*)resop->res;
3487
3488 if (unexpected_op(resop->op, OP_LAYOUTRETURN))
3489 return FALSE;
3490
3491 if (!xdr_u_int32_t(xdr, (uint32_t *)&res->status))
3492 return FALSE;
3493
3494 if (res->status == NFS4_OK) {
3495 if (!xdr_bool(xdr, &res->stateid_present))
3496 return FALSE;
3497
3498 if (res->stateid_present)
3499 return xdr_stateid4(xdr, &res->stateid);
3500 }
3501 return TRUE;
3502 }
3503
3504
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*);
3508
3509 typedef struct __op_table_entry {
3510 nfs_op_encode_proc encode;
3511 nfs_op_decode_proc decode;
3512 } op_table_entry;
3513
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 */
3575 };
3576 #ifdef __REACTOS__
3577 static const uint32_t g_op_table_size = (sizeof(g_op_table) / sizeof(g_op_table[0]));
3578 #else
3579 static const uint32_t g_op_table_size = ARRAYSIZE(g_op_table);
3580 #endif
3581
3582 static const op_table_entry* op_table_find(uint32_t op)
3583 {
3584 return op >= g_op_table_size ? NULL : &g_op_table[op];
3585 }
3586
3587
3588 /*
3589 * COMPOUND
3590 */
3591 bool_t nfs_encode_compound(
3592 XDR *xdr,
3593 caddr_t *pargs)
3594 {
3595 unsigned char *tag;
3596
3597 nfs41_compound_args *args = (nfs41_compound_args*)pargs;
3598 uint32_t i;
3599 const op_table_entry *entry;
3600
3601 tag = args->tag;
3602 if (!xdr_bytes(xdr, (char **)&tag, &args->tag_len, NFS4_OPAQUE_LIMIT))
3603 return FALSE;
3604
3605 if (!xdr_u_int32_t(xdr, &args->minorversion))
3606 return FALSE;
3607
3608 if (!xdr_u_int32_t(xdr, &args->argarray_count))
3609 return FALSE;
3610
3611 for (i = 0; i < args->argarray_count; i++)
3612 {
3613 entry = op_table_find(args->argarray[i].op);
3614 if (entry == NULL || entry->encode == NULL)
3615 return FALSE;
3616
3617 if (!xdr_u_int32_t(xdr, &args->argarray[i].op))
3618 return FALSE;
3619 if (!entry->encode(xdr, &args->argarray[i]))
3620 return FALSE;
3621 }
3622 return TRUE;
3623 }
3624
3625 bool_t nfs_decode_compound(
3626 XDR *xdr,
3627 caddr_t *pres)
3628 {
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;
3633
3634 if (!xdr_u_int32_t(xdr, &res->status))
3635 return FALSE;
3636
3637 if (!xdr_bytes(xdr, (char **)&tag, &res->tag_len, NFS4_OPAQUE_LIMIT))
3638 return FALSE;
3639
3640 expected_count = res->resarray_count;
3641 if (!xdr_u_int32_t(xdr, &res->resarray_count))
3642 return FALSE;
3643
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);
3648 return FALSE;
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);
3655 return FALSE;
3656 }
3657
3658 for (i = 0; i < res->resarray_count; i++)
3659 {
3660 expected_op = res->resarray[i].op;
3661 if (!xdr_u_int32_t(xdr, &res->resarray[i].op))
3662 return FALSE;
3663
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));
3669 return FALSE;
3670 }
3671
3672 entry = op_table_find(res->resarray[i].op);
3673 if (entry == NULL || entry->decode == NULL)
3674 return FALSE;
3675 if (!entry->decode(xdr, &res->resarray[i]))
3676 return FALSE;
3677 }
3678 return TRUE;
3679 }