xref: /reactos/base/services/nfsd/nfs41_xdr.c (revision c2c66aff)
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 
unexpected_op(uint32_t op,uint32_t expected)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<> */
xdr_bitmap4(XDR * xdr,bitmap4 * bitmap)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 */
xdr_nfstime4(XDR * xdr,nfstime4 * nt)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 */
settime_how(nfstime4 * newtime,const nfstime4 * time_delta)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 
xdr_settime4(XDR * xdr,nfstime4 * nt,const nfstime4 * time_delta)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 */
xdr_stateid4(XDR * xdr,stateid4 * si)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 */
xdr_fattr4(XDR * xdr,fattr4 * fattr)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 */
xdr_fh(XDR * xdr,nfs41_fh * 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 */
xdr_fsid(XDR * xdr,nfs41_fsid * 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 */
encode_component(XDR * xdr,const nfs41_component * 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 
decode_component(XDR * xdr,nfs41_component * component)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 */
xdr_state_owner4(XDR * xdr,state_owner4 * so)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 
xdr_layout_types(XDR * xdr,uint32_t * layout_type)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 
xdr_threshold_item(XDR * xdr,threshold_item4 * item)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 
xdr_mdsthreshold(XDR * xdr,mdsthreshold4 * mdsthreshold)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 
xdr_nfsace4(XDR * xdr,nfsace4 * ace)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 
xdr_nfsdacl41(XDR * xdr,nfsacl41 * acl)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 
xdr_nfsacl41(XDR * xdr,nfsacl41 * acl)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 
nfsacl41_free(nfsacl41 * acl)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 */
decode_pathname4(XDR * xdr,nfs41_abs_path * 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 */
decode_fs_location4(XDR * xdr,fs_location4 * location)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 */
decode_fs_locations4(XDR * xdr,fs_locations4 * locations)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  */
xdr_client_owner4(XDR * xdr,client_owner4 * co)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 
xdr_state_protect4_a(XDR * xdr,state_protect4_a * spa)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 
xdr_nfs_impl_id4(XDR * xdr,nfs_impl_id4 * nii)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 
encode_op_exchange_id(XDR * xdr,nfs_argop4 * argop)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 
xdr_state_protect4_r(XDR * xdr,state_protect4_r * spr)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 
xdr_server_owner4(XDR * xdr,server_owner4 * so)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 
decode_op_exchange_id(XDR * xdr,nfs_resop4 * resop)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  */
xdr_channel_attrs4(XDR * xdr,nfs41_channel_attrs * attrs)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 
encode_backchannel_sec_parms(XDR * xdr,nfs41_callback_secparms * args)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 
encode_op_create_session(XDR * xdr,nfs_argop4 * argop)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 
decode_op_create_session(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_bind_conn_to_session(XDR * xdr,nfs_argop4 * argop)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 
decode_op_bind_conn_to_session(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_destroy_session(XDR * xdr,nfs_argop4 * argop)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 
decode_op_destroy_session(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_destroy_clientid(XDR * xdr,nfs_argop4 * argop)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 
decode_op_destroy_clientid(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_sequence(XDR * xdr,nfs_argop4 * argop)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 
xdr_sequence_res_ok(XDR * xdr,nfs41_sequence_res_ok * res)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 
decode_op_sequence(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_reclaim_complete(XDR * xdr,nfs_argop4 * argop)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 
decode_op_reclaim_complete(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_putfh(XDR * xdr,nfs_argop4 * argop)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 
decode_op_putfh(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_putrootfh(XDR * xdr,nfs_argop4 * argop)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 
decode_op_putrootfh(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_getfh(XDR * xdr,nfs_argop4 * argop)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 
decode_op_getfh(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_lookup(XDR * xdr,nfs_argop4 * argop)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 
decode_op_lookup(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_access(XDR * xdr,nfs_argop4 * argop)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 
decode_op_access(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_close(XDR * xdr,nfs_argop4 * argop)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 
decode_op_close(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_commit(XDR * xdr,nfs_argop4 * argop)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 
decode_op_commit(XDR * xdr,nfs_resop4 * resop)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  */
encode_createtype4(XDR * xdr,createtype4 * ct)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 
encode_createattrs4(XDR * xdr,nfs41_file_info * createattrs)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 
encode_op_create(XDR * xdr,nfs_argop4 * argop)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 
xdr_change_info4(XDR * xdr,change_info4 * cinfo)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 
decode_op_create(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_link(XDR * xdr,nfs_argop4 * argop)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 
decode_op_link(XDR * xdr,nfs_resop4 * resop)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  */
xdr_locker4(XDR * xdr,locker4 * locker)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 
encode_op_lock(XDR * xdr,nfs_argop4 * argop)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 
decode_lock_res_denied(XDR * xdr,lock_res_denied * denied)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 
decode_op_lock(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_lockt(XDR * xdr,nfs_argop4 * argop)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 
decode_op_lockt(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_locku(XDR * xdr,nfs_argop4 * argop)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 
decode_op_locku(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_delegpurge(XDR * xdr,nfs_argop4 * argop)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 
decode_op_delegpurge(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_delegreturn(XDR * xdr,nfs_argop4 * argop)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 
decode_op_delegreturn(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_getattr(XDR * xdr,nfs_argop4 * argop)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 
decode_file_attrs(XDR * xdr,fattr4 * attrs,nfs41_file_info * info)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 
decode_op_getattr(XDR * xdr,nfs_resop4 * resop)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  */
encode_createhow4(XDR * xdr,createhow4 * ch)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 
encode_openflag4(XDR * xdr,openflag4 * of)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 
encode_claim_deleg_cur(XDR * xdr,stateid4 * stateid,nfs41_component * name)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 
encode_open_claim4(XDR * xdr,open_claim4 * oc)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 
encode_op_open(XDR * xdr,nfs_argop4 * argop)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 
decode_open_none_delegation4(XDR * xdr,open_delegation4 * delegation)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 
decode_open_read_delegation4(XDR * xdr,open_delegation4 * delegation)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 
decode_modified_limit4(XDR * xdr,uint64_t * filesize)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 
decode_space_limit4(XDR * xdr,uint64_t * filesize)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 
decode_open_write_delegation4(XDR * xdr,open_delegation4 * delegation)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 
decode_open_res_ok(XDR * xdr,nfs41_op_open_res_ok * res)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 
decode_op_open(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_openattr(XDR * xdr,nfs_argop4 * argop)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 
decode_op_openattr(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_read(XDR * xdr,nfs_argop4 * argop)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 
decode_read_res_ok(XDR * xdr,nfs41_read_res_ok * res)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 
decode_op_read(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_readdir(XDR * xdr,nfs_argop4 * argop)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 
decode_readdir_entry(XDR * xdr,readdir_entry_iterator * it)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 
decode_readdir_list(XDR * xdr,nfs41_readdir_list * dirs)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 
decode_op_readdir(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_readlink(XDR * xdr,nfs_argop4 * argop)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 
decode_op_readlink(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_remove(XDR * xdr,nfs_argop4 * argop)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 
decode_op_remove(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_rename(XDR * xdr,nfs_argop4 * argop)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 
decode_op_rename(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_restorefh(XDR * xdr,nfs_argop4 * argop)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 
decode_op_restorefh(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_savefh(XDR * xdr,nfs_argop4 * argop)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 
decode_op_savefh(XDR * xdr,nfs_resop4 * resop)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  */
encode_file_attrs(fattr4 * attrs,nfs41_file_info * info)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 
encode_op_setattr(XDR * xdr,nfs_argop4 * argop)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 
decode_op_setattr(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_want_delegation(XDR * xdr,nfs_argop4 * argop)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 
decode_op_want_delegation(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_free_stateid(XDR * xdr,nfs_argop4 * argop)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 
decode_op_free_stateid(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_test_stateid(XDR * xdr,nfs_argop4 * argop)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 
decode_op_test_stateid(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_write(XDR * xdr,nfs_argop4 * argop)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 
xdr_write_verf(XDR * xdr,nfs41_write_verf * verf)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 
xdr_write_res_ok(XDR * xdr,nfs41_write_res_ok * res)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 
decode_op_write(XDR * xdr,nfs_resop4 * resop)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  */
xdr_secinfo(XDR * xdr,nfs41_secinfo_info * secinfo)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 
encode_op_secinfo_noname(XDR * xdr,nfs_argop4 * argop)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 
decode_op_secinfo_noname(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_secinfo(XDR * xdr,nfs_argop4 * argop)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 
decode_op_secinfo(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_getdeviceinfo(XDR * xdr,nfs_argop4 * argop)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 
xdr_stripe_indices(XDR * xdr,pnfs_stripe_indices * indices)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 
xdr_pnfs_addr(XDR * xdr,netaddr4 * addr)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 
xdr_multi_addr(XDR * xdr,multi_addr4 * list)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 
xdr_data_server_list(XDR * xdr,pnfs_data_server_list * servers)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 
xdr_file_device(XDR * xdr,pnfs_file_device * device)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 
decode_getdeviceinfo_ok(XDR * xdr,pnfs_getdeviceinfo_res_ok * res_ok)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 
decode_op_getdeviceinfo(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_layoutcommit(XDR * xdr,nfs_argop4 * argop)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 
decode_op_layoutcommit(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_layoutget(XDR * xdr,nfs_argop4 * argop)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 
decode_file_layout_handles(XDR * xdr,pnfs_file_layout_handles * handles)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 
decode_file_layout(XDR * xdr,struct list_entry * list,pnfs_layout * base)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 
decode_layout(XDR * xdr,struct list_entry * list)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 
decode_layout_res_ok(XDR * xdr,pnfs_layoutget_res_ok * res)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 
decode_op_layoutget(XDR * xdr,nfs_resop4 * resop)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  */
encode_op_layoutreturn(XDR * xdr,nfs_argop4 * argop)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 
decode_op_layoutreturn(XDR * xdr,nfs_resop4 * resop)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 
op_table_find(uint32_t op)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  */
nfs_encode_compound(XDR * xdr,caddr_t * pargs)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 
nfs_decode_compound(XDR * xdr,caddr_t * pres)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 }
3680