1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2020 RackTop Systems, Inc.
25 */
26
27 /*
28 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
29 * Use is subject to license terms.
30 */
31 /*
32 * Copyright (c) 2013 by Delphix. All rights reserved.
33 */
34
35 /*
36 * A handcoded version based on the original rpcgen code.
37 *
38 * Note: All future NFS4 protocol changes should be added by hand
39 * to this file.
40 *
41 * CAUTION: All protocol changes must also be propagated to:
42 * usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c
43 */
44
45 #include <sys/types.h>
46 #include <sys/sunddi.h>
47 #include <sys/dnlc.h>
48 #include <nfs/nfs.h>
49 #include <nfs/nfs4_kprot.h>
50 #include <nfs/rnode4.h>
51 #include <nfs/nfs4.h>
52 #include <nfs/nfs4_clnt.h>
53 #include <sys/sdt.h>
54 #include <sys/mkdev.h>
55 #include <rpc/rpc_rdma.h>
56 #include <rpc/xdr.h>
57
58 #define xdr_dev_t xdr_u_int
59
60 extern bool_t xdr_netbuf(XDR *, struct netbuf *);
61 extern bool_t xdr_vector(XDR *, char *, const uint_t, const uint_t,
62 const xdrproc_t);
63 bool_t xdr_knetconfig(XDR *, struct knetconfig *);
64
65 bool_t
xdr_bitmap4(XDR * xdrs,bitmap4 * objp)66 xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
67 {
68 int32_t len, size;
69 uint32_t bmval2 = 0;
70
71 if (xdrs->x_op == XDR_FREE)
72 return (TRUE);
73
74 /*
75 * Simplified bitmap4 processing, always encode from uint64_t
76 * to 2 uint32_t's, always decode first 2 uint32_t's into a
77 * uint64_t and ignore all of the rest.
78 *
79 * uint64_t was enough for NFSv4.0, but NFSv4.1 uses extra bits and
80 * uses more than 64-bit. NFSv4.1 attribute FATTR4_SUPPATTR_EXCLCREAT
81 * is 75-th bit.
82 *
83 * In order to not change all code that uses bitmap4, I decided to
84 * use fold/unfold approach - to use rest of free (currently unused)
85 * bits in bitmap4. Until this change bitmap4 was used to keep 0-55
86 * bits :
87 * FATTR4_SUPPORTED_ATTRS_MASK (1ULL << (FATTR4_WORD0 + 0))
88 * ...
89 * FATTR4_MOUNTED_ON_FILEID_MASK (1ULL << (FATTR4_WORD1 + 23))
90 * And And 56-th bit is used to fold/unfold.
91 * FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL
92 * (1ULL << (FATTR4_WORD1 + 24))
93 *
94 * FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL doesn't affect anything
95 * outside nfssrv. So this usage is purely optimisation.
96 */
97 if (xdrs->x_op == XDR_ENCODE) {
98 bitmap4 obj = *objp;
99
100 objp = &obj;
101 if (*objp & FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL) {
102 bmval2 |= 1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64);
103 *objp &= ~FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL;
104 }
105
106 len = bmval2 ? 3 : 2;
107
108 if (!XDR_PUTINT32(xdrs, &len))
109 return (FALSE);
110
111 #if defined(_LITTLE_ENDIAN)
112 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
113 BYTES_PER_XDR_UNIT)) == TRUE) {
114 if (!XDR_PUTINT32(xdrs, (int32_t *)objp))
115 return (FALSE);
116 }
117 #elif defined(_BIG_ENDIAN)
118 if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) {
119 if (!XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
120 BYTES_PER_XDR_UNIT)))
121 return (FALSE);
122 }
123 #endif
124 if (len == 3 && !XDR_PUTINT32(xdrs, (int32_t *)&bmval2))
125 return (FALSE);
126 return (TRUE);
127 }
128
129 if (!XDR_GETINT32(xdrs, &len))
130 return (FALSE);
131
132 /*
133 * Common fast DECODE cases
134 */
135 if (len == 2 || len == 3) {
136 #if defined(_LITTLE_ENDIAN)
137 if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
138 BYTES_PER_XDR_UNIT)) == TRUE) {
139 if (!XDR_GETINT32(xdrs, (int32_t *)objp))
140 return (FALSE);
141 }
142 #elif defined(_BIG_ENDIAN)
143 if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) {
144 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
145 BYTES_PER_XDR_UNIT)))
146 return (FALSE);
147 }
148 #endif
149 if (len == 3) {
150 if (!XDR_GETINT32(xdrs, (int32_t *)&bmval2))
151 return (FALSE);
152 if (bmval2 & (1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64)))
153 *objp |= FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL;
154 }
155
156 return (TRUE);
157 }
158
159 *objp = 0;
160 if (len == 0)
161 return (TRUE);
162
163 /*
164 * The not so common DECODE cases, len == 1 || len > 2
165 */
166 #if defined(_LITTLE_ENDIAN)
167 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
168 return (FALSE);
169 if (--len == 0)
170 return (TRUE);
171 if (!XDR_GETINT32(xdrs, (int32_t *)objp))
172 return (FALSE);
173 #elif defined(_BIG_ENDIAN)
174 if (!XDR_GETINT32(xdrs, (int32_t *)objp))
175 return (FALSE);
176 if (--len == 0)
177 return (TRUE);
178
179 if (!XDR_GETINT32(xdrs, (int32_t *)&bmval2))
180 return (FALSE);
181 if (bmval2 & (1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64)))
182 *objp |= FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL;
183
184 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
185 return (FALSE);
186 #else
187 return (FALSE);
188 #endif
189
190 if (--len == 0)
191 return (TRUE);
192
193 size = len * BYTES_PER_XDR_UNIT;
194 return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size));
195 }
196
197 /* Called by xdr_array, nfsid_map_xdr */
198 bool_t
xdr_utf8string(XDR * xdrs,utf8string * objp)199 xdr_utf8string(XDR *xdrs, utf8string *objp)
200 {
201 if (xdrs->x_op != XDR_FREE)
202 return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
203 (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
204
205 if (objp->utf8string_val != NULL) {
206 kmem_free(objp->utf8string_val, objp->utf8string_len);
207 objp->utf8string_val = NULL;
208 }
209 return (TRUE);
210 }
211
212 /*
213 * used by NFSv4 referrals to get info needed for NFSv4 referral mount.
214 */
215 bool_t
xdr_nfs_fsl_info(XDR * xdrs,struct nfs_fsl_info * objp)216 xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp)
217 {
218
219 if (!xdr_u_int(xdrs, &objp->netbuf_len))
220 return (FALSE);
221 if (!xdr_u_int(xdrs, &objp->netnm_len))
222 return (FALSE);
223 if (!xdr_u_int(xdrs, &objp->knconf_len))
224 return (FALSE);
225
226 #if defined(_LP64)
227 /*
228 * The object can come from a 32-bit binary; nfsmapid.
229 * To be safe we double the size of the knetconfig to
230 * allow some buffering for decoding.
231 */
232 if (xdrs->x_op == XDR_DECODE)
233 objp->knconf_len += sizeof (struct knetconfig);
234 #endif
235
236 if (!xdr_string(xdrs, &objp->netname, ~0))
237 return (FALSE);
238 if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len,
239 (xdrproc_t)xdr_netbuf))
240 return (FALSE);
241 if (!xdr_pointer(xdrs, (char **)&objp->knconf,
242 objp->knconf_len, (xdrproc_t)xdr_knetconfig))
243 return (FALSE);
244 return (TRUE);
245 }
246
247 bool_t
xdr_knetconfig(XDR * xdrs,struct knetconfig * objp)248 xdr_knetconfig(XDR *xdrs, struct knetconfig *objp)
249 {
250 rpc_inline_t *buf;
251 u_longlong_t dev64;
252 #if !defined(_LP64)
253 uint32_t major, minor;
254 #endif
255 int i;
256
257 if (!xdr_u_int(xdrs, &objp->knc_semantics))
258 return (FALSE);
259 if (xdrs->x_op == XDR_DECODE) {
260 objp->knc_protofmly = (((char *)objp) +
261 sizeof (struct knetconfig));
262 objp->knc_proto = objp->knc_protofmly + KNC_STRSIZE;
263 }
264 if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE))
265 return (FALSE);
266 if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE))
267 return (FALSE);
268
269 /*
270 * For interoperability between 32-bit daemon and 64-bit kernel,
271 * we always treat dev_t as 64-bit number and do the expanding
272 * or compression of dev_t as needed.
273 * We have to hand craft the conversion since there is no available
274 * function in ddi.c. Besides ddi.c is available only in the kernel
275 * and we want to keep both user and kernel of xdr_knetconfig() the
276 * same for consistency.
277 */
278 if (xdrs->x_op == XDR_ENCODE) {
279 #if defined(_LP64)
280 dev64 = objp->knc_rdev;
281 #else
282 major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32;
283 minor = objp->knc_rdev & MAXMIN32;
284 dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor;
285 #endif
286 if (!xdr_u_longlong_t(xdrs, &dev64))
287 return (FALSE);
288 }
289 if (xdrs->x_op == XDR_DECODE) {
290 #if defined(_LP64)
291 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev))
292 return (FALSE);
293 #else
294 if (!xdr_u_longlong_t(xdrs, &dev64))
295 return (FALSE);
296
297 major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32;
298 minor = dev64 & L_MAXMIN32;
299 objp->knc_rdev = (major << L_BITSMINOR32) | minor;
300 #endif
301 }
302
303 if (xdrs->x_op == XDR_ENCODE) {
304 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
305 if (buf == NULL) {
306 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
307 sizeof (uint_t), (xdrproc_t)xdr_u_int))
308 return (FALSE);
309 } else {
310 uint_t *genp;
311
312 for (i = 0, genp = objp->knc_unused;
313 i < 8; i++) {
314 #if defined(_LP64) || defined(_KERNEL)
315 IXDR_PUT_U_INT32(buf, *genp++);
316 #else
317 IXDR_PUT_U_LONG(buf, *genp++);
318 #endif
319 }
320 }
321 return (TRUE);
322 } else if (xdrs->x_op == XDR_DECODE) {
323 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
324 if (buf == NULL) {
325 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
326 sizeof (uint_t), (xdrproc_t)xdr_u_int))
327 return (FALSE);
328 } else {
329 uint_t *genp;
330
331 for (i = 0, genp = objp->knc_unused;
332 i < 8; i++) {
333 #if defined(_LP64) || defined(_KERNEL)
334 *genp++ = IXDR_GET_U_INT32(buf);
335 #else
336 *genp++ = IXDR_GET_U_LONG(buf);
337 #endif
338 }
339 }
340 return (TRUE);
341 }
342
343 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
344 sizeof (uint_t), (xdrproc_t)xdr_u_int))
345 return (FALSE);
346 return (TRUE);
347 }
348
349 /*
350 * XDR_INLINE decode a filehandle.
351 */
352 bool_t
xdr_inline_decode_nfs_fh4(uint32_t * ptr,nfs_fh4_fmt_t * fhp,uint32_t fhsize)353 xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *fhp, uint32_t fhsize)
354 {
355 uchar_t *bp = (uchar_t *)ptr;
356 uchar_t *cp;
357 uint32_t dsize;
358 uintptr_t resid;
359
360 /*
361 * Check to see if what the client sent us is bigger or smaller
362 * than what we can ever possibly send out. NFS_FHMAXDATA is
363 * unfortunately badly named as it is no longer the max and is
364 * really the min of what is sent over the wire.
365 */
366 if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
367 sizeof (ushort_t) + NFS_FHMAXDATA +
368 sizeof (ushort_t) + NFS_FHMAXDATA)) {
369 return (FALSE);
370 }
371
372 /*
373 * All internal parts of a filehandle are in native byte order.
374 *
375 * Decode what should be fh4_fsid, it is aligned.
376 */
377 fhp->fh4_fsid.val[0] = *(uint32_t *)bp;
378 bp += BYTES_PER_XDR_UNIT;
379 fhp->fh4_fsid.val[1] = *(uint32_t *)bp;
380 bp += BYTES_PER_XDR_UNIT;
381
382 /*
383 * Decode what should be fh4_len. fh4_len is two bytes, so we're
384 * unaligned now.
385 */
386 cp = (uchar_t *)&fhp->fh4_len;
387 *cp++ = *bp++;
388 *cp++ = *bp++;
389 fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
390
391 /*
392 * For backwards compatibility, the fid length may be less than
393 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
394 */
395 dsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
396
397 /*
398 * Make sure the client isn't sending us a bogus length for fh4_data.
399 */
400 if (fhsize < dsize)
401 return (FALSE);
402 bcopy(bp, fhp->fh4_data, dsize);
403 bp += dsize;
404 fhsize -= dsize;
405
406 if (fhsize < sizeof (ushort_t))
407 return (FALSE);
408 cp = (uchar_t *)&fhp->fh4_xlen;
409 *cp++ = *bp++;
410 *cp++ = *bp++;
411 fhsize -= sizeof (ushort_t);
412
413 dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
414
415 /*
416 * Make sure the client isn't sending us a bogus length for fh4_xdata.
417 */
418 if (fhsize < dsize)
419 return (FALSE);
420 bcopy(bp, fhp->fh4_xdata, dsize);
421 fhsize -= dsize;
422 bp += dsize;
423
424 /*
425 * We realign things on purpose, so skip any padding
426 */
427 resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
428 if (resid != 0) {
429 if (fhsize < (BYTES_PER_XDR_UNIT - resid))
430 return (FALSE);
431 bp += BYTES_PER_XDR_UNIT - resid;
432 fhsize -= BYTES_PER_XDR_UNIT - resid;
433 }
434
435 if (fhsize < BYTES_PER_XDR_UNIT)
436 return (FALSE);
437 fhp->fh4_flag = *(uint32_t *)bp;
438 bp += BYTES_PER_XDR_UNIT;
439 fhsize -= BYTES_PER_XDR_UNIT;
440
441 #ifdef VOLATILE_FH_TEST
442 if (fhsize < BYTES_PER_XDR_UNIT)
443 return (FALSE);
444 fhp->fh4_volatile_id = *(uint32_t *)bp;
445 bp += BYTES_PER_XDR_UNIT;
446 fhsize -= BYTES_PER_XDR_UNIT;
447 #endif
448 /*
449 * Make sure client didn't send extra bytes
450 */
451 if (fhsize != 0)
452 return (FALSE);
453 return (TRUE);
454 }
455
456 static bool_t
xdr_decode_nfs_fh4(XDR * xdrs,nfs_fh4 * objp)457 xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
458 {
459 uint32_t fhsize; /* filehandle size */
460 uint32_t bufsize;
461 rpc_inline_t *ptr;
462 uchar_t *bp;
463
464 ASSERT(xdrs->x_op == XDR_DECODE);
465
466 /*
467 * Retrieve the filehandle length.
468 */
469 if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
470 return (FALSE);
471
472 objp->nfs_fh4_val = NULL;
473 objp->nfs_fh4_len = 0;
474
475 /*
476 * Check to see if what the client sent us is bigger or smaller
477 * than what we can ever possibly send out. NFS_FHMAXDATA is
478 * unfortunately badly named as it is no longer the max and is
479 * really the min of what is sent over the wire.
480 */
481 if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
482 sizeof (ushort_t) + NFS_FHMAXDATA +
483 sizeof (ushort_t) + NFS_FHMAXDATA)) {
484 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
485 return (FALSE);
486 return (TRUE);
487 }
488
489 /*
490 * bring in fhsize plus any padding
491 */
492 bufsize = RNDUP(fhsize);
493 ptr = XDR_INLINE(xdrs, bufsize);
494 bp = (uchar_t *)ptr;
495 if (ptr == NULL) {
496 bp = kmem_alloc(bufsize, KM_SLEEP);
497 if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
498 kmem_free(bp, bufsize);
499 return (FALSE);
500 }
501 }
502
503 objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP);
504 objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t);
505
506 if (xdr_inline_decode_nfs_fh4((uint32_t *)bp,
507 (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) {
508 /*
509 * If in the process of decoding we find the file handle
510 * is not correctly formed, we need to continue decoding
511 * and trigger an NFS layer error. Set the nfs_fh4_len to
512 * zero so it gets caught as a bad length.
513 */
514 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
515 objp->nfs_fh4_val = NULL;
516 objp->nfs_fh4_len = 0;
517 }
518
519 if (ptr == NULL)
520 kmem_free(bp, bufsize);
521 return (TRUE);
522 }
523
524 /*
525 * XDR_INLINE encode a filehandle.
526 */
527 bool_t
xdr_inline_encode_nfs_fh4(uint32_t ** ptrp,uint32_t * ptr_redzone,nfs_fh4_fmt_t * fhp)528 xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone,
529 nfs_fh4_fmt_t *fhp)
530 {
531 uint32_t *ptr = *ptrp;
532 uchar_t *cp;
533 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */
534 uint32_t padword;
535
536 fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
537 xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
538
539 /*
540 * First get the initial and variable sized part of the filehandle.
541 */
542 otw_len = sizeof (fhp->fh4_fsid) +
543 sizeof (fhp->fh4_len) + fsize +
544 sizeof (fhp->fh4_xlen) + xsize;
545
546 /*
547 * Round out to a full word.
548 */
549 otw_len = RNDUP(otw_len);
550 padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */
551
552 /*
553 * Add in the fixed sized pieces.
554 */
555 otw_len += sizeof (fhp->fh4_flag);
556 #ifdef VOLATILE_FH_TEST
557 otw_len += sizeof (fhp->fh4_volatile_id);
558 #endif
559
560 /*
561 * Make sure we don't exceed our buffer.
562 */
563 if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
564 return (FALSE);
565
566 /*
567 * Zero out the padding.
568 */
569 ptr[padword] = 0;
570
571 IXDR_PUT_U_INT32(ptr, otw_len);
572
573 /*
574 * The rest of the filehandle is in native byteorder
575 */
576 /* fh4_fsid */
577 *ptr++ = (uint32_t)fhp->fh4_fsid.val[0];
578 *ptr++ = (uint32_t)fhp->fh4_fsid.val[1];
579
580 /*
581 * Since the next pieces are unaligned, we need to
582 * do bytewise copies.
583 */
584 cp = (uchar_t *)ptr;
585
586 /* fh4_len + fh4_data */
587 bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize);
588 cp += sizeof (fhp->fh4_len) + fsize;
589
590 /* fh4_xlen + fh4_xdata */
591 bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize);
592 cp += sizeof (fhp->fh4_xlen) + xsize;
593
594 /* do necessary rounding/padding */
595 cp = (uchar_t *)RNDUP((uintptr_t)cp);
596 ptr = (uint32_t *)cp;
597
598 /*
599 * With the above padding, we're word aligned again.
600 */
601 ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
602
603 /* fh4_flag */
604 *ptr++ = (uint32_t)fhp->fh4_flag;
605
606 #ifdef VOLATILE_FH_TEST
607 /* fh4_volatile_id */
608 *ptr++ = (uint32_t)fhp->fh4_volatile_id;
609 #endif
610 *ptrp = ptr;
611
612 return (TRUE);
613 }
614
615 static bool_t
xdr_encode_nfs_fh4(XDR * xdrs,nfs_fh4 * objp)616 xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
617 {
618 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */
619 bool_t ret;
620 rpc_inline_t *ptr;
621 rpc_inline_t *buf = NULL;
622 uint32_t *ptr_redzone;
623 nfs_fh4_fmt_t *fhp;
624
625 ASSERT(xdrs->x_op == XDR_ENCODE);
626
627 fhp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val;
628 fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
629 xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
630
631 /*
632 * First get the over the wire size, it is the 4 bytes
633 * for the length, plus the combined size of the
634 * file handle components.
635 */
636 otw_len = BYTES_PER_XDR_UNIT + sizeof (fhp->fh4_fsid) +
637 sizeof (fhp->fh4_len) + fsize +
638 sizeof (fhp->fh4_xlen) + xsize +
639 sizeof (fhp->fh4_flag);
640 #ifdef VOLATILE_FH_TEST
641 otw_len += sizeof (fhp->fh4_volatile_id);
642 #endif
643 /*
644 * Round out to a full word.
645 */
646 otw_len = RNDUP(otw_len);
647
648 /*
649 * Next try to inline the XDR stream, if that fails (rare)
650 * allocate a buffer to encode the file handle and then
651 * copy it using xdr_opaque and free the buffer.
652 */
653 ptr = XDR_INLINE(xdrs, otw_len);
654 if (ptr == NULL)
655 ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
656
657 ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
658 ret = xdr_inline_encode_nfs_fh4((uint32_t **)&ptr, ptr_redzone, fhp);
659
660 if (buf != NULL) {
661 if (ret == TRUE)
662 ret = xdr_opaque(xdrs, (char *)buf, otw_len);
663 kmem_free(buf, otw_len);
664 }
665 return (ret);
666 }
667
668 /*
669 * XDR a NFSv4 filehandle.
670 * Encoding interprets the contents (server).
671 * Decoding the contents are opaque (client).
672 */
673 bool_t
xdr_nfs_fh4(XDR * xdrs,nfs_fh4 * objp)674 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
675 {
676 switch (xdrs->x_op) {
677 case XDR_ENCODE:
678 return (xdr_encode_nfs_fh4(xdrs, objp));
679 case XDR_DECODE:
680 return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val,
681 (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE));
682 case XDR_FREE:
683 if (objp->nfs_fh4_val != NULL) {
684 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
685 objp->nfs_fh4_val = NULL;
686 }
687 return (TRUE);
688 }
689 return (FALSE);
690 }
691
692 /* Called by xdr_array */
693 static bool_t
xdr_fs_location4(XDR * xdrs,fs_location4 * objp)694 xdr_fs_location4(XDR *xdrs, fs_location4 *objp)
695 {
696 if (xdrs->x_op == XDR_DECODE) {
697 objp->server_val = NULL;
698 objp->rootpath.pathname4_val = NULL;
699 }
700 if (!xdr_array(xdrs, (char **)&objp->server_val,
701 (uint_t *)&objp->server_len, NFS4_MAX_UTF8STRING,
702 sizeof (utf8string), (xdrproc_t)xdr_utf8string))
703 return (FALSE);
704 return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val,
705 (uint_t *)&objp->rootpath.pathname4_len,
706 NFS4_MAX_PATHNAME4,
707 sizeof (utf8string), (xdrproc_t)xdr_utf8string));
708 }
709
710 /* Called by xdr_array */
711 bool_t
xdr_nfsace4(XDR * xdrs,nfsace4 * objp)712 xdr_nfsace4(XDR *xdrs, nfsace4 *objp)
713 {
714 if (xdrs->x_op != XDR_FREE) {
715 if (!xdr_u_int(xdrs, &objp->type))
716 return (FALSE);
717 if (!xdr_u_int(xdrs, &objp->flag))
718 return (FALSE);
719 if (!xdr_u_int(xdrs, &objp->access_mask))
720 return (FALSE);
721
722 if (xdrs->x_op == XDR_DECODE) {
723 objp->who.utf8string_val = NULL;
724 objp->who.utf8string_len = 0;
725 }
726
727 return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val,
728 (uint_t *)&objp->who.utf8string_len,
729 NFS4_MAX_UTF8STRING));
730 }
731
732 /*
733 * Optimized free case
734 */
735 if (objp->who.utf8string_val != NULL) {
736 kmem_free(objp->who.utf8string_val, objp->who.utf8string_len);
737 objp->who.utf8string_val = NULL;
738 }
739 return (TRUE);
740 }
741
742 /*
743 * These functions are called out of nfs4_attr.c
744 */
745 bool_t
xdr_fattr4_fsid(XDR * xdrs,fattr4_fsid * objp)746 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp)
747 {
748 if (xdrs->x_op == XDR_FREE)
749 return (TRUE);
750
751 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major))
752 return (FALSE);
753 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor));
754 }
755
756
757 bool_t
xdr_fattr4_acl(XDR * xdrs,fattr4_acl * objp)758 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp)
759 {
760 return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val,
761 (uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT,
762 sizeof (nfsace4), (xdrproc_t)xdr_nfsace4));
763 }
764
765 bool_t
xdr_fattr4_fs_locations(XDR * xdrs,fattr4_fs_locations * objp)766 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp)
767 {
768 if (xdrs->x_op == XDR_DECODE) {
769 objp->fs_root.pathname4_len = 0;
770 objp->fs_root.pathname4_val = NULL;
771 objp->locations_val = NULL;
772 }
773 if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val,
774 (uint_t *)&objp->fs_root.pathname4_len,
775 NFS4_MAX_PATHNAME4,
776 sizeof (utf8string), (xdrproc_t)xdr_utf8string))
777 return (FALSE);
778 return (xdr_array(xdrs, (char **)&objp->locations_val,
779 (uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT,
780 sizeof (fs_location4), (xdrproc_t)xdr_fs_location4));
781 }
782
783 bool_t
xdr_fattr4_rawdev(XDR * xdrs,fattr4_rawdev * objp)784 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp)
785 {
786 if (xdrs->x_op == XDR_FREE)
787 return (TRUE);
788
789 if (!xdr_u_int(xdrs, &objp->specdata1))
790 return (FALSE);
791 return (xdr_u_int(xdrs, &objp->specdata2));
792 }
793
794 bool_t
xdr_nfstime4(XDR * xdrs,nfstime4 * objp)795 xdr_nfstime4(XDR *xdrs, nfstime4 *objp)
796 {
797 if (xdrs->x_op == XDR_FREE)
798 return (TRUE);
799
800 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds))
801 return (FALSE);
802 return (xdr_u_int(xdrs, &objp->nseconds));
803 }
804
805 bool_t
xdr_fattr4_sec_label(XDR * xdrs,fattr4_sec_label * objp)806 xdr_fattr4_sec_label(XDR *xdrs, fattr4_sec_label *objp)
807 {
808 uint_t dummy = 0;
809
810 if (xdrs->x_op == XDR_FREE) {
811 /*
812 * Optimized free case
813 */
814 if (objp->slai_val != NULL)
815 kmem_free(objp->slai_val, objp->slai_len);
816 return (TRUE);
817 }
818
819 /*
820 * For now use a 0 here to indicate the null translation; in
821 * the future we place a call to translation code here.
822 */
823 if (!xdr_u_int(xdrs, &dummy)) /* lfs */
824 return (FALSE);
825
826 if (!xdr_u_int(xdrs, &dummy)) /* pi */
827 return (FALSE);
828
829 return (xdr_bytes(xdrs, (char **)&objp->slai_val,
830 (uint_t *)&objp->slai_len, NFS4_OPAQUE_LIMIT));
831 }
832
833 /*
834 * structured used for calls into xdr_ga_fattr_res() as a means
835 * to do an immediate/short-term cache of owner/group strings
836 * for callers like the readdir processing. In the case of readdir,
837 * it is likely that the directory objects will be owned by the same
838 * owner/group and if so there is no need to call into the uid/gid
839 * mapping code. While the uid/gid interfaces have their own cache
840 * having one here will reduct pathlength further.
841 */
842 #define MAX_OG_NAME 100
843 typedef struct ug_cache
844 {
845 uid_t uid;
846 gid_t gid;
847 utf8string u_curr, u_last;
848 utf8string g_curr, g_last;
849 char u_buf1[MAX_OG_NAME];
850 char u_buf2[MAX_OG_NAME];
851 char g_buf1[MAX_OG_NAME];
852 char g_buf2[MAX_OG_NAME];
853 } ug_cache_t;
854
855 #define U_SWAP_CURR_LAST(ug) \
856 (ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len; \
857 if ((ug)->u_last.utf8string_val == (ug)->u_buf1) { \
858 (ug)->u_last.utf8string_val = (ug)->u_buf2; \
859 (ug)->u_curr.utf8string_val = (ug)->u_buf1; \
860 } else { \
861 (ug)->u_last.utf8string_val = (ug)->u_buf1; \
862 (ug)->u_curr.utf8string_val = (ug)->u_buf2; \
863 }
864
865 #define G_SWAP_CURR_LAST(ug) \
866 (ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len; \
867 if ((ug)->g_last.utf8string_val == (ug)->g_buf1) { \
868 (ug)->g_last.utf8string_val = (ug)->g_buf2; \
869 (ug)->g_curr.utf8string_val = (ug)->g_buf1; \
870 } else { \
871 (ug)->g_last.utf8string_val = (ug)->g_buf1; \
872 (ug)->g_curr.utf8string_val = (ug)->g_buf2; \
873 }
874
875 static ug_cache_t *
alloc_ugcache()876 alloc_ugcache()
877 {
878 ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP);
879
880 pug->uid = pug->gid = 0;
881 pug->u_curr.utf8string_len = 0;
882 pug->u_last.utf8string_len = 0;
883 pug->g_curr.utf8string_len = 0;
884 pug->g_last.utf8string_len = 0;
885 pug->u_curr.utf8string_val = pug->u_buf1;
886 pug->u_last.utf8string_val = pug->u_buf2;
887 pug->g_curr.utf8string_val = pug->g_buf1;
888 pug->g_last.utf8string_val = pug->g_buf2;
889
890 return (pug);
891 }
892
893 static void
xdr_ga_prefill_vattr(struct nfs4_ga_res * garp,struct mntinfo4 * mi)894 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi)
895 {
896 static vattr_t s_vattr = {
897 AT_ALL, /* va_mask */
898 VNON, /* va_type */
899 0777, /* va_mode */
900 UID_NOBODY, /* va_uid */
901 GID_NOBODY, /* va_gid */
902 0, /* va_fsid */
903 0, /* va_nodeid */
904 1, /* va_nlink */
905 0, /* va_size */
906 {0, 0}, /* va_atime */
907 {0, 0}, /* va_mtime */
908 {0, 0}, /* va_ctime */
909 0, /* va_rdev */
910 MAXBSIZE, /* va_blksize */
911 0, /* va_nblocks */
912 0 /* va_seq */
913 };
914
915
916 garp->n4g_va = s_vattr;
917 garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev;
918 hrt2ts(gethrtime(), &garp->n4g_va.va_atime);
919 garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime;
920 }
921
922 static void
xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res * gesp,struct mntinfo4 * mi)923 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi)
924 {
925 static statvfs64_t s_sb = {
926 MAXBSIZE, /* f_bsize */
927 DEV_BSIZE, /* f_frsize */
928 (fsfilcnt64_t)-1, /* f_blocks */
929 (fsfilcnt64_t)-1, /* f_bfree */
930 (fsfilcnt64_t)-1, /* f_bavail */
931 (fsfilcnt64_t)-1, /* f_files */
932 (fsfilcnt64_t)-1, /* f_ffree */
933 (fsfilcnt64_t)-1, /* f_favail */
934 0, /* f_fsid */
935 "\0", /* f_basetype */
936 0, /* f_flag */
937 MAXNAMELEN, /* f_namemax */
938 "\0", /* f_fstr */
939 };
940
941 gesp->n4g_sb = s_sb;
942 gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0];
943 }
944
945 static bool_t
xdr_ga_fattr_res(XDR * xdrs,struct nfs4_ga_res * garp,bitmap4 resbmap,bitmap4 argbmap,struct mntinfo4 * mi,ug_cache_t * pug)946 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap,
947 bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
948 {
949 int truefalse;
950 struct nfs4_ga_ext_res ges, *gesp;
951 vattr_t *vap = &garp->n4g_va;
952 vsecattr_t *vsap = &garp->n4g_vsa;
953
954 ASSERT(xdrs->x_op == XDR_DECODE);
955
956 if (garp->n4g_ext_res)
957 gesp = garp->n4g_ext_res;
958 else
959 gesp = ⩾
960
961 vap->va_mask = 0;
962
963 /* Check to see if the vattr should be pre-filled */
964 if (argbmap & NFS4_VATTR_MASK)
965 xdr_ga_prefill_vattr(garp, mi);
966
967 if (argbmap & NFS4_STATFS_ATTR_MASK)
968 xdr_ga_prefill_statvfs(gesp, mi);
969
970 if (resbmap &
971 (FATTR4_SUPPORTED_ATTRS_MASK |
972 FATTR4_TYPE_MASK |
973 FATTR4_FH_EXPIRE_TYPE_MASK |
974 FATTR4_CHANGE_MASK |
975 FATTR4_SIZE_MASK |
976 FATTR4_LINK_SUPPORT_MASK |
977 FATTR4_SYMLINK_SUPPORT_MASK |
978 FATTR4_NAMED_ATTR_MASK)) {
979
980 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
981 if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs))
982 return (FALSE);
983 }
984 if (resbmap & FATTR4_TYPE_MASK) {
985 if (!XDR_GETINT32(xdrs, (int *)&vap->va_type))
986 return (FALSE);
987
988 if ((nfs_ftype4)vap->va_type < NF4REG ||
989 (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
990 vap->va_type = VBAD;
991 else
992 vap->va_type = nf4_to_vt[vap->va_type];
993 if (vap->va_type == VBLK)
994 vap->va_blksize = DEV_BSIZE;
995
996 vap->va_mask |= AT_TYPE;
997 }
998 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
999 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet))
1000 return (FALSE);
1001 }
1002 if (resbmap & FATTR4_CHANGE_MASK) {
1003 if (!xdr_u_longlong_t(xdrs,
1004 (u_longlong_t *)&garp->n4g_change))
1005 return (FALSE);
1006 garp->n4g_change_valid = 1;
1007 }
1008 if (resbmap & FATTR4_SIZE_MASK) {
1009 if (!xdr_u_longlong_t(xdrs,
1010 (u_longlong_t *)&vap->va_size))
1011 return (FALSE);
1012 if (!NFS4_SIZE_OK(vap->va_size)) {
1013 garp->n4g_attrerr = EFBIG;
1014 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1015 } else {
1016 vap->va_mask |= AT_SIZE;
1017 }
1018 }
1019 if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1020 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1021 return (FALSE);
1022 gesp->n4g_pc4.pc4_link_support =
1023 (truefalse ? TRUE : FALSE);
1024 }
1025 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1026 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1027 return (FALSE);
1028 gesp->n4g_pc4.pc4_symlink_support =
1029 (truefalse ? TRUE : FALSE);
1030 }
1031 if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1032 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1033 return (FALSE);
1034 gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1035 gesp->n4g_pc4.pc4_xattr_exists =
1036 (truefalse ? TRUE : FALSE);
1037 }
1038 }
1039 if (resbmap &
1040 (FATTR4_FSID_MASK |
1041 FATTR4_UNIQUE_HANDLES_MASK |
1042 FATTR4_LEASE_TIME_MASK |
1043 FATTR4_RDATTR_ERROR_MASK)) {
1044
1045 if (resbmap & FATTR4_FSID_MASK) {
1046 if ((!xdr_u_longlong_t(xdrs,
1047 (u_longlong_t *)&garp->n4g_fsid.major)) ||
1048 (!xdr_u_longlong_t(xdrs,
1049 (u_longlong_t *)&garp->n4g_fsid.minor)))
1050 return (FALSE);
1051 garp->n4g_fsid_valid = 1;
1052 }
1053 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1054 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1055 return (FALSE);
1056 gesp->n4g_pc4.pc4_unique_handles =
1057 (truefalse ? TRUE : FALSE);
1058 }
1059 if (resbmap & FATTR4_LEASE_TIME_MASK) {
1060 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime))
1061 return (FALSE);
1062 }
1063 if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1064 if (!XDR_GETINT32(xdrs,
1065 (int *)&gesp->n4g_rdattr_error))
1066 return (FALSE);
1067 }
1068 }
1069 if (resbmap &
1070 (FATTR4_ACL_MASK |
1071 FATTR4_ACLSUPPORT_MASK |
1072 FATTR4_ARCHIVE_MASK |
1073 FATTR4_CANSETTIME_MASK)) {
1074
1075 if (resbmap & FATTR4_ACL_MASK) {
1076 fattr4_acl acl;
1077
1078 acl.fattr4_acl_val = NULL;
1079 acl.fattr4_acl_len = 0;
1080
1081 if (!xdr_fattr4_acl(xdrs, &acl))
1082 return (FALSE);
1083
1084 vsap->vsa_aclcnt = acl.fattr4_acl_len;
1085 vsap->vsa_aclentp = acl.fattr4_acl_val;
1086 vsap->vsa_mask = VSA_ACE | VSA_ACECNT;
1087 vsap->vsa_aclentsz = vsap->vsa_aclcnt * sizeof (ace_t);
1088
1089 }
1090 if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1091 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport))
1092 return (FALSE);
1093 }
1094 if (resbmap & FATTR4_ARCHIVE_MASK) {
1095 ASSERT(0);
1096 }
1097 if (resbmap & FATTR4_CANSETTIME_MASK) {
1098 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1099 return (FALSE);
1100 gesp->n4g_pc4.pc4_cansettime =
1101 (truefalse ? TRUE : FALSE);
1102 }
1103 }
1104 if (resbmap &
1105 (FATTR4_CASE_INSENSITIVE_MASK |
1106 FATTR4_CASE_PRESERVING_MASK |
1107 FATTR4_CHOWN_RESTRICTED_MASK |
1108 FATTR4_FILEHANDLE_MASK |
1109 FATTR4_FILEID_MASK |
1110 FATTR4_FILES_AVAIL_MASK |
1111 FATTR4_FILES_FREE_MASK |
1112 FATTR4_FILES_TOTAL_MASK)) {
1113
1114 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1115 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1116 return (FALSE);
1117 gesp->n4g_pc4.pc4_case_insensitive =
1118 (truefalse ? TRUE : FALSE);
1119 }
1120 if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1121 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1122 return (FALSE);
1123 gesp->n4g_pc4.pc4_case_preserving =
1124 (truefalse ? TRUE : FALSE);
1125 }
1126 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1127 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1128 return (FALSE);
1129 gesp->n4g_pc4.pc4_chown_restricted =
1130 (truefalse ? TRUE : FALSE);
1131 }
1132 if (resbmap & FATTR4_FILEHANDLE_MASK) {
1133 gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1134 gesp->n4g_fh_u.nfs_fh4_alt.val =
1135 gesp->n4g_fh_u.nfs_fh4_alt.data;
1136 if (!xdr_bytes(xdrs,
1137 (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val,
1138 (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len,
1139 NFS4_FHSIZE))
1140 return (FALSE);
1141 }
1142 if (resbmap & FATTR4_FILEID_MASK) {
1143 if (!xdr_u_longlong_t(xdrs,
1144 (u_longlong_t *)&vap->va_nodeid))
1145 return (FALSE);
1146 vap->va_mask |= AT_NODEID;
1147 }
1148 if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1149 if (!xdr_u_longlong_t(xdrs,
1150 (u_longlong_t *)&gesp->n4g_sb.f_favail))
1151 return (FALSE);
1152 }
1153 if (resbmap & FATTR4_FILES_FREE_MASK) {
1154 if (!xdr_u_longlong_t(xdrs,
1155 (u_longlong_t *)&gesp->n4g_sb.f_ffree))
1156 return (FALSE);
1157 }
1158 if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1159 if (!xdr_u_longlong_t(xdrs,
1160 (u_longlong_t *)&gesp->n4g_sb.f_files))
1161 return (FALSE);
1162 }
1163 }
1164 if (resbmap &
1165 (FATTR4_FS_LOCATIONS_MASK |
1166 FATTR4_HIDDEN_MASK |
1167 FATTR4_HOMOGENEOUS_MASK)) {
1168
1169 if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1170 if (!xdr_fattr4_fs_locations(xdrs,
1171 &gesp->n4g_fslocations))
1172 return (FALSE);
1173 }
1174 if (resbmap & FATTR4_HIDDEN_MASK) {
1175 ASSERT(0);
1176 }
1177 if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1178 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1179 return (FALSE);
1180 gesp->n4g_pc4.pc4_homogeneous =
1181 (truefalse ? TRUE : FALSE);
1182 }
1183 }
1184 if (resbmap &
1185 (FATTR4_MAXFILESIZE_MASK |
1186 FATTR4_MAXLINK_MASK |
1187 FATTR4_MAXNAME_MASK |
1188 FATTR4_MAXREAD_MASK |
1189 FATTR4_MAXWRITE_MASK)) {
1190
1191 if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1192 if (!xdr_u_longlong_t(xdrs,
1193 (u_longlong_t *)&gesp->n4g_maxfilesize))
1194 return (FALSE);
1195 }
1196 if (resbmap & FATTR4_MAXLINK_MASK) {
1197 if (!XDR_GETINT32(xdrs,
1198 (int *)&gesp->n4g_pc4.pc4_link_max))
1199 return (FALSE);
1200 }
1201 if (resbmap & FATTR4_MAXNAME_MASK) {
1202 if (!XDR_GETINT32(xdrs,
1203 (int *)&gesp->n4g_pc4.pc4_name_max))
1204 return (FALSE);
1205 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1206 }
1207 if (resbmap & FATTR4_MAXREAD_MASK) {
1208 if (!xdr_u_longlong_t(xdrs,
1209 (u_longlong_t *)&gesp->n4g_maxread))
1210 return (FALSE);
1211 }
1212 if (resbmap & FATTR4_MAXWRITE_MASK) {
1213 if (!xdr_u_longlong_t(xdrs,
1214 (u_longlong_t *)&gesp->n4g_maxwrite))
1215 return (FALSE);
1216 }
1217 }
1218 if (resbmap &
1219 (FATTR4_MIMETYPE_MASK |
1220 FATTR4_MODE_MASK |
1221 FATTR4_NO_TRUNC_MASK |
1222 FATTR4_NUMLINKS_MASK)) {
1223
1224 if (resbmap & FATTR4_MIMETYPE_MASK) {
1225 ASSERT(0);
1226 }
1227 if (resbmap & FATTR4_MODE_MASK) {
1228 if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode))
1229 return (FALSE);
1230 vap->va_mask |= AT_MODE;
1231 }
1232 if (resbmap & FATTR4_NO_TRUNC_MASK) {
1233 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1234 return (FALSE);
1235 gesp->n4g_pc4.pc4_no_trunc =
1236 (truefalse ? TRUE : FALSE);
1237 }
1238 if (resbmap & FATTR4_NUMLINKS_MASK) {
1239 if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink))
1240 return (FALSE);
1241 vap->va_mask |= AT_NLINK;
1242 }
1243 }
1244 if (resbmap &
1245 (FATTR4_OWNER_MASK |
1246 FATTR4_OWNER_GROUP_MASK |
1247 FATTR4_QUOTA_AVAIL_HARD_MASK |
1248 FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1249
1250 if (resbmap & FATTR4_OWNER_MASK) {
1251 uint_t *owner_length, ol;
1252 char *owner_val = NULL;
1253 char *owner_alloc = NULL;
1254 utf8string ov;
1255 int error;
1256
1257 /* get the OWNER_LENGTH */
1258 if (!xdr_u_int(xdrs, &ol))
1259 return (FALSE);
1260
1261 /* Manage the owner length location */
1262 if (pug && ol <= MAX_OG_NAME) {
1263 owner_length = &pug->u_curr.utf8string_len;
1264 *owner_length = ol;
1265 } else {
1266 owner_length = &ol;
1267 }
1268
1269 /* find memory to store the decode */
1270 if (*owner_length > MAX_OG_NAME || pug == NULL)
1271 owner_val = owner_alloc =
1272 kmem_alloc(*owner_length, KM_SLEEP);
1273 else
1274 owner_val = pug->u_curr.utf8string_val;
1275
1276 /* get the OWNER string */
1277 if (!xdr_opaque(xdrs, owner_val, *owner_length)) {
1278 if (owner_alloc)
1279 kmem_free(owner_alloc, *owner_length);
1280 return (FALSE);
1281 }
1282
1283 /* Optimize for matching if called for */
1284 if (pug &&
1285 *owner_length == pug->u_last.utf8string_len &&
1286 bcmp(owner_val, pug->u_last.utf8string_val,
1287 *owner_length) == 0) {
1288 vap->va_uid = pug->uid;
1289 vap->va_mask |= AT_UID;
1290 } else {
1291 uid_t uid;
1292
1293 ov.utf8string_len = *owner_length;
1294 ov.utf8string_val = owner_val;
1295 error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1296 /*
1297 * String was mapped, but to nobody because
1298 * we are nfsmapid, indicate it should not
1299 * be cached.
1300 */
1301 if (error == ENOTSUP) {
1302 error = 0;
1303 garp->n4g_attrwhy =
1304 NFS4_GETATTR_NOCACHE_OK;
1305 }
1306
1307 if (error) {
1308 garp->n4g_attrerr = error;
1309 garp->n4g_attrwhy =
1310 NFS4_GETATTR_ATUID_ERR;
1311 } else {
1312 vap->va_uid = uid;
1313 vap->va_mask |= AT_UID;
1314 if (pug && ol <= MAX_OG_NAME) {
1315 pug->uid = uid;
1316 U_SWAP_CURR_LAST(pug);
1317 }
1318 }
1319 if (owner_alloc)
1320 kmem_free(owner_alloc, *owner_length);
1321 }
1322 }
1323 if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1324 uint_t *group_length, gl;
1325 char *group_val = NULL;
1326 char *group_alloc = NULL;
1327 utf8string gv;
1328 int error;
1329
1330 /* get the OWNER_GROUP_LENGTH */
1331 if (!xdr_u_int(xdrs, &gl))
1332 return (FALSE);
1333
1334 /* Manage the group length location */
1335 if (pug && gl <= MAX_OG_NAME) {
1336 group_length = &pug->g_curr.utf8string_len;
1337 *group_length = gl;
1338 } else {
1339 group_length = ≷
1340 }
1341
1342 /* find memory to store the decode */
1343 if (*group_length > MAX_OG_NAME || pug == NULL)
1344 group_val = group_alloc =
1345 kmem_alloc(*group_length, KM_SLEEP);
1346 else
1347 group_val = pug->g_curr.utf8string_val;
1348
1349 /* get the OWNER_GROUP string */
1350 if (!xdr_opaque(xdrs, group_val, *group_length)) {
1351 if (group_alloc)
1352 kmem_free(group_alloc, *group_length);
1353 return (FALSE);
1354 }
1355
1356 /* Optimize for matching if called for */
1357 if (pug &&
1358 *group_length == pug->g_last.utf8string_len &&
1359 bcmp(group_val, pug->g_last.utf8string_val,
1360 *group_length) == 0) {
1361 vap->va_gid = pug->gid;
1362 vap->va_mask |= AT_GID;
1363 } else {
1364 uid_t gid;
1365
1366 gv.utf8string_len = *group_length;
1367 gv.utf8string_val = group_val;
1368 error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1369 /*
1370 * String was mapped, but to nobody because
1371 * we are nfsmapid, indicate it should not
1372 * be cached.
1373 */
1374 if (error == ENOTSUP) {
1375 error = 0;
1376 garp->n4g_attrwhy =
1377 NFS4_GETATTR_NOCACHE_OK;
1378 }
1379
1380 if (error) {
1381 garp->n4g_attrerr = error;
1382 garp->n4g_attrwhy =
1383 NFS4_GETATTR_ATGID_ERR;
1384 } else {
1385 vap->va_gid = gid;
1386 vap->va_mask |= AT_GID;
1387 if (pug && gl <= MAX_OG_NAME) {
1388 pug->gid = gid;
1389 G_SWAP_CURR_LAST(pug);
1390 }
1391 }
1392 if (group_alloc) {
1393 kmem_free(group_alloc, *group_length);
1394 }
1395 }
1396 }
1397 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1398 ASSERT(0);
1399 }
1400 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1401 ASSERT(0);
1402 }
1403 }
1404 if (resbmap &
1405 (FATTR4_QUOTA_USED_MASK |
1406 FATTR4_SPACE_AVAIL_MASK |
1407 FATTR4_SPACE_FREE_MASK |
1408 FATTR4_SPACE_TOTAL_MASK |
1409 FATTR4_SPACE_USED_MASK |
1410 FATTR4_SYSTEM_MASK)) {
1411
1412 if (resbmap & FATTR4_QUOTA_USED_MASK) {
1413 ASSERT(0);
1414 }
1415 if (resbmap & FATTR4_RAWDEV_MASK) {
1416 fattr4_rawdev rawdev;
1417 if (!xdr_fattr4_rawdev(xdrs, &rawdev))
1418 return (FALSE);
1419
1420 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1421 vap->va_rdev = makedevice(rawdev.specdata1,
1422 rawdev.specdata2);
1423 } else {
1424 vap->va_rdev = 0;
1425 }
1426 vap->va_mask |= AT_RDEV;
1427 }
1428 if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1429 if (!xdr_u_longlong_t(xdrs,
1430 (u_longlong_t *)&gesp->n4g_sb.f_bavail))
1431 return (FALSE);
1432 gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1433 }
1434 if (resbmap & FATTR4_SPACE_FREE_MASK) {
1435 if (!xdr_u_longlong_t(xdrs,
1436 (u_longlong_t *)&gesp->n4g_sb.f_bfree))
1437 return (FALSE);
1438 gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1439 }
1440 if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1441 if (!xdr_u_longlong_t(xdrs,
1442 (u_longlong_t *)&gesp->n4g_sb.f_blocks))
1443 return (FALSE);
1444 gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1445 }
1446 if (resbmap & FATTR4_SPACE_USED_MASK) {
1447 uint64_t space_used;
1448 if (!xdr_u_longlong_t(xdrs,
1449 (u_longlong_t *)&space_used))
1450 return (FALSE);
1451
1452 /* Compute space depending on device type */
1453 ASSERT((vap->va_mask & AT_TYPE));
1454 if (vap->va_type == VREG || vap->va_type == VDIR ||
1455 vap->va_type == VLNK) {
1456 vap->va_nblocks = (u_longlong_t)
1457 ((space_used + (offset4)DEV_BSIZE -
1458 (offset4)1) / (offset4)DEV_BSIZE);
1459 } else {
1460 vap->va_nblocks = 0;
1461 }
1462 vap->va_mask |= AT_NBLOCKS;
1463 }
1464 if (resbmap & FATTR4_SYSTEM_MASK) {
1465 ASSERT(0);
1466 }
1467 }
1468 if (resbmap &
1469 (FATTR4_TIME_ACCESS_MASK |
1470 FATTR4_TIME_ACCESS_SET_MASK |
1471 FATTR4_TIME_BACKUP_MASK |
1472 FATTR4_TIME_CREATE_MASK |
1473 FATTR4_TIME_DELTA_MASK |
1474 FATTR4_TIME_METADATA_MASK |
1475 FATTR4_TIME_MODIFY_MASK |
1476 FATTR4_TIME_MODIFY_SET_MASK |
1477 FATTR4_MOUNTED_ON_FILEID_MASK)) {
1478
1479 if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1480 nfstime4 atime;
1481 int error;
1482
1483 if (!xdr_longlong_t(xdrs,
1484 (longlong_t *)&atime.seconds))
1485 return (FALSE);
1486 if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds))
1487 return (FALSE);
1488 error = nfs4_time_ntov(&atime, &vap->va_atime);
1489 if (error) {
1490 garp->n4g_attrerr = error;
1491 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
1492 }
1493 vap->va_mask |= AT_ATIME;
1494 }
1495 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
1496 ASSERT(0);
1497 }
1498 if (resbmap & FATTR4_TIME_BACKUP_MASK) {
1499 ASSERT(0);
1500 }
1501 if (resbmap & FATTR4_TIME_CREATE_MASK) {
1502 ASSERT(0);
1503 }
1504 if (resbmap & FATTR4_TIME_DELTA_MASK) {
1505 if ((!xdr_u_longlong_t(xdrs,
1506 (u_longlong_t *)&gesp->n4g_delta.seconds)) ||
1507 (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds)))
1508 return (FALSE);
1509 }
1510 if (resbmap & FATTR4_TIME_METADATA_MASK) {
1511 nfstime4 mdt;
1512 int error;
1513
1514 if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds))
1515 return (FALSE);
1516 if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds))
1517 return (FALSE);
1518 error = nfs4_time_ntov(&mdt, &vap->va_ctime);
1519 if (error) {
1520 garp->n4g_attrerr = error;
1521 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
1522 }
1523 vap->va_mask |= AT_CTIME;
1524 }
1525 if (resbmap & FATTR4_TIME_MODIFY_MASK) {
1526 nfstime4 mtime;
1527 int error;
1528
1529 if (!xdr_longlong_t(xdrs,
1530 (longlong_t *)&mtime.seconds))
1531 return (FALSE);
1532 if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds))
1533 return (FALSE);
1534 error = nfs4_time_ntov(&mtime, &vap->va_mtime);
1535 if (error) {
1536 garp->n4g_attrerr = error;
1537 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
1538 }
1539 vap->va_mask |= AT_MTIME;
1540 }
1541 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
1542 ASSERT(0);
1543 }
1544 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
1545 if (!xdr_u_longlong_t(xdrs,
1546 (u_longlong_t *)&garp->n4g_mon_fid))
1547 return (FALSE);
1548 garp->n4g_mon_fid_valid = 1;
1549 }
1550 }
1551
1552 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
1553 /* copy only if not provided */
1554 if (garp->n4g_ext_res == NULL) {
1555 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
1556 bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
1557 }
1558 }
1559
1560 return (TRUE);
1561 }
1562
1563 /*
1564 * Inlined version of get_bitmap4 processing
1565 */
1566 bitmap4
xdr_get_bitmap4_inline(uint32_t ** iptr)1567 xdr_get_bitmap4_inline(uint32_t **iptr)
1568 {
1569 uint32_t resbmaplen;
1570 bitmap4 bm;
1571 uint32_t *ptr = *iptr;
1572
1573 /* bitmap LENGTH */
1574 resbmaplen = IXDR_GET_U_INT32(ptr);
1575
1576 /* Inline the bitmap and attrlen for common case of two word map */
1577 if (resbmaplen == 2) {
1578 IXDR_GET_HYPER(ptr, bm);
1579 *iptr = ptr;
1580 return (bm);
1581 }
1582
1583 #if defined(_LITTLE_ENDIAN)
1584 bm = IXDR_GET_U_INT32(ptr);
1585 if (--resbmaplen == 0) {
1586 *iptr = ptr;
1587 return (bm);
1588 }
1589 *((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr);
1590 if (--resbmaplen == 0) {
1591 *iptr = ptr;
1592 return (bm);
1593 }
1594 ptr += resbmaplen;
1595 *iptr = ptr;
1596 return (bm);
1597 #elif defined(_BIG_ENDIAN)
1598 *((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr);
1599 if (--resbmaplen == 0) {
1600 *iptr = ptr;
1601 return (bm);
1602 }
1603 bm |= IXDR_GET_U_INT32(ptr);
1604 if (--resbmaplen == 0) {
1605 *iptr = ptr;
1606 return (bm);
1607 }
1608 ptr += resbmaplen;
1609 *iptr = ptr;
1610 return (bm);
1611 #else
1612 ASSERT(0);
1613 ptr += resbmaplen;
1614 *iptr = ptr;
1615 return (0);
1616 #endif
1617 }
1618
1619 static bool_t
xdr_ga_fattr_res_inline(uint32_t * ptr,struct nfs4_ga_res * garp,bitmap4 resbmap,bitmap4 argbmap,struct mntinfo4 * mi,ug_cache_t * pug)1620 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp,
1621 bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
1622 {
1623 int truefalse;
1624 struct nfs4_ga_ext_res ges, *gesp;
1625 vattr_t *vap = &garp->n4g_va;
1626
1627 if (garp->n4g_ext_res)
1628 gesp = garp->n4g_ext_res;
1629 else
1630 gesp = ⩾
1631
1632 vap->va_mask = 0;
1633
1634 /* Check to see if the vattr should be pre-filled */
1635 if (argbmap & NFS4_VATTR_MASK)
1636 xdr_ga_prefill_vattr(garp, mi);
1637
1638 if (argbmap & NFS4_STATFS_ATTR_MASK)
1639 xdr_ga_prefill_statvfs(gesp, mi);
1640
1641 if (resbmap &
1642 (FATTR4_SUPPORTED_ATTRS_MASK |
1643 FATTR4_TYPE_MASK |
1644 FATTR4_FH_EXPIRE_TYPE_MASK |
1645 FATTR4_CHANGE_MASK |
1646 FATTR4_SIZE_MASK |
1647 FATTR4_LINK_SUPPORT_MASK |
1648 FATTR4_SYMLINK_SUPPORT_MASK |
1649 FATTR4_NAMED_ATTR_MASK)) {
1650
1651 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
1652 gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr);
1653 }
1654 if (resbmap & FATTR4_TYPE_MASK) {
1655 vap->va_type = IXDR_GET_U_INT32(ptr);
1656
1657 if ((nfs_ftype4)vap->va_type < NF4REG ||
1658 (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
1659 vap->va_type = VBAD;
1660 else
1661 vap->va_type = nf4_to_vt[vap->va_type];
1662 if (vap->va_type == VBLK)
1663 vap->va_blksize = DEV_BSIZE;
1664
1665 vap->va_mask |= AT_TYPE;
1666 }
1667 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
1668 gesp->n4g_fet = IXDR_GET_U_INT32(ptr);
1669 }
1670 if (resbmap & FATTR4_CHANGE_MASK) {
1671 IXDR_GET_U_HYPER(ptr, garp->n4g_change);
1672 garp->n4g_change_valid = 1;
1673 }
1674 if (resbmap & FATTR4_SIZE_MASK) {
1675 IXDR_GET_U_HYPER(ptr, vap->va_size);
1676
1677 if (!NFS4_SIZE_OK(vap->va_size)) {
1678 garp->n4g_attrerr = EFBIG;
1679 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1680 } else {
1681 vap->va_mask |= AT_SIZE;
1682 }
1683 }
1684 if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1685 truefalse = IXDR_GET_U_INT32(ptr);
1686 gesp->n4g_pc4.pc4_link_support =
1687 (truefalse ? TRUE : FALSE);
1688 }
1689 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1690 truefalse = IXDR_GET_U_INT32(ptr);
1691 gesp->n4g_pc4.pc4_symlink_support =
1692 (truefalse ? TRUE : FALSE);
1693 }
1694 if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1695 truefalse = IXDR_GET_U_INT32(ptr);
1696 gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1697 gesp->n4g_pc4.pc4_xattr_exists =
1698 (truefalse ? TRUE : FALSE);
1699 }
1700 }
1701 if (resbmap &
1702 (FATTR4_FSID_MASK |
1703 FATTR4_UNIQUE_HANDLES_MASK |
1704 FATTR4_LEASE_TIME_MASK |
1705 FATTR4_RDATTR_ERROR_MASK)) {
1706
1707 if (resbmap & FATTR4_FSID_MASK) {
1708 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major);
1709 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor);
1710 garp->n4g_fsid_valid = 1;
1711 }
1712 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1713 truefalse = IXDR_GET_U_INT32(ptr);
1714 gesp->n4g_pc4.pc4_unique_handles =
1715 (truefalse ? TRUE : FALSE);
1716 }
1717 if (resbmap & FATTR4_LEASE_TIME_MASK) {
1718 gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr);
1719 }
1720 if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1721 gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr);
1722 }
1723 }
1724 if (resbmap &
1725 (FATTR4_ACL_MASK |
1726 FATTR4_ACLSUPPORT_MASK |
1727 FATTR4_ARCHIVE_MASK |
1728 FATTR4_CANSETTIME_MASK)) {
1729
1730 if (resbmap & FATTR4_ACL_MASK) {
1731 ASSERT(0);
1732 }
1733 if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1734 gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr);
1735 }
1736 if (resbmap & FATTR4_ARCHIVE_MASK) {
1737 ASSERT(0);
1738 }
1739 if (resbmap & FATTR4_CANSETTIME_MASK) {
1740 truefalse = IXDR_GET_U_INT32(ptr);
1741 gesp->n4g_pc4.pc4_cansettime =
1742 (truefalse ? TRUE : FALSE);
1743 }
1744 }
1745 if (resbmap &
1746 (FATTR4_CASE_INSENSITIVE_MASK |
1747 FATTR4_CASE_PRESERVING_MASK |
1748 FATTR4_CHOWN_RESTRICTED_MASK |
1749 FATTR4_FILEHANDLE_MASK |
1750 FATTR4_FILEID_MASK |
1751 FATTR4_FILES_AVAIL_MASK |
1752 FATTR4_FILES_FREE_MASK |
1753 FATTR4_FILES_TOTAL_MASK)) {
1754
1755 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1756 truefalse = IXDR_GET_U_INT32(ptr);
1757 gesp->n4g_pc4.pc4_case_insensitive =
1758 (truefalse ? TRUE : FALSE);
1759 }
1760 if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1761 truefalse = IXDR_GET_U_INT32(ptr);
1762 gesp->n4g_pc4.pc4_case_preserving =
1763 (truefalse ? TRUE : FALSE);
1764 }
1765 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1766 truefalse = IXDR_GET_U_INT32(ptr);
1767 gesp->n4g_pc4.pc4_chown_restricted =
1768 (truefalse ? TRUE : FALSE);
1769 }
1770 if (resbmap & FATTR4_FILEHANDLE_MASK) {
1771 int len = IXDR_GET_U_INT32(ptr);
1772
1773 gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1774 gesp->n4g_fh_u.nfs_fh4_alt.val =
1775 gesp->n4g_fh_u.nfs_fh4_alt.data;
1776 gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len;
1777
1778 bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len);
1779
1780 ptr += RNDUP(len) / BYTES_PER_XDR_UNIT;
1781 }
1782 if (resbmap & FATTR4_FILEID_MASK) {
1783 IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
1784 vap->va_mask |= AT_NODEID;
1785 }
1786 if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1787 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail);
1788 }
1789 if (resbmap & FATTR4_FILES_FREE_MASK) {
1790 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree);
1791 }
1792 if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1793 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files);
1794 }
1795 }
1796 if (resbmap &
1797 (FATTR4_FS_LOCATIONS_MASK |
1798 FATTR4_HIDDEN_MASK |
1799 FATTR4_HOMOGENEOUS_MASK)) {
1800
1801 if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1802 ASSERT(0);
1803 }
1804 if (resbmap & FATTR4_HIDDEN_MASK) {
1805 ASSERT(0);
1806 }
1807 if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1808 truefalse = IXDR_GET_U_INT32(ptr);
1809 gesp->n4g_pc4.pc4_homogeneous =
1810 (truefalse ? TRUE : FALSE);
1811 }
1812 }
1813 if (resbmap &
1814 (FATTR4_MAXFILESIZE_MASK |
1815 FATTR4_MAXLINK_MASK |
1816 FATTR4_MAXNAME_MASK |
1817 FATTR4_MAXREAD_MASK |
1818 FATTR4_MAXWRITE_MASK)) {
1819
1820 if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1821 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize);
1822 }
1823 if (resbmap & FATTR4_MAXLINK_MASK) {
1824 gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr);
1825 }
1826 if (resbmap & FATTR4_MAXNAME_MASK) {
1827 gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr);
1828 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1829 }
1830 if (resbmap & FATTR4_MAXREAD_MASK) {
1831 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread);
1832 }
1833 if (resbmap & FATTR4_MAXWRITE_MASK) {
1834 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite);
1835 }
1836 }
1837 if (resbmap &
1838 (FATTR4_MIMETYPE_MASK |
1839 FATTR4_MODE_MASK |
1840 FATTR4_NO_TRUNC_MASK |
1841 FATTR4_NUMLINKS_MASK)) {
1842
1843 if (resbmap & FATTR4_MIMETYPE_MASK) {
1844 ASSERT(0);
1845 }
1846 if (resbmap & FATTR4_MODE_MASK) {
1847 vap->va_mode = IXDR_GET_U_INT32(ptr);
1848 vap->va_mask |= AT_MODE;
1849 }
1850 if (resbmap & FATTR4_NO_TRUNC_MASK) {
1851 truefalse = IXDR_GET_U_INT32(ptr);
1852 gesp->n4g_pc4.pc4_no_trunc =
1853 (truefalse ? TRUE : FALSE);
1854 }
1855 if (resbmap & FATTR4_NUMLINKS_MASK) {
1856 vap->va_nlink = IXDR_GET_U_INT32(ptr);
1857 vap->va_mask |= AT_NLINK;
1858 }
1859 }
1860 if (resbmap &
1861 (FATTR4_OWNER_MASK |
1862 FATTR4_OWNER_GROUP_MASK |
1863 FATTR4_QUOTA_AVAIL_HARD_MASK |
1864 FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1865
1866 if (resbmap & FATTR4_OWNER_MASK) {
1867 uint_t *owner_length, ol;
1868 char *owner_val = NULL;
1869 utf8string ov;
1870 int error;
1871
1872 /* get the OWNER_LENGTH */
1873 ol = IXDR_GET_U_INT32(ptr);
1874
1875 /* Manage the owner length location */
1876 if (pug && ol <= MAX_OG_NAME) {
1877 owner_length = &pug->u_curr.utf8string_len;
1878 *owner_length = ol;
1879 } else {
1880 owner_length = &ol;
1881 }
1882
1883 /* find memory to store the decode */
1884 if (*owner_length > MAX_OG_NAME || pug == NULL)
1885 owner_val = (char *)ptr;
1886 else
1887 owner_val = (char *)ptr;
1888
1889 /* Optimize for matching if called for */
1890 if (pug &&
1891 *owner_length == pug->u_last.utf8string_len &&
1892 bcmp(owner_val, pug->u_last.utf8string_val,
1893 *owner_length) == 0) {
1894 vap->va_uid = pug->uid;
1895 vap->va_mask |= AT_UID;
1896 } else {
1897 uid_t uid;
1898
1899 ov.utf8string_len = *owner_length;
1900 ov.utf8string_val = owner_val;
1901 error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1902 /*
1903 * String was mapped, but to nobody because
1904 * we are nfsmapid, indicate it should not
1905 * be cached.
1906 */
1907 if (error == ENOTSUP) {
1908 error = 0;
1909 garp->n4g_attrwhy =
1910 NFS4_GETATTR_NOCACHE_OK;
1911 }
1912
1913 if (error) {
1914 garp->n4g_attrerr = error;
1915 garp->n4g_attrwhy =
1916 NFS4_GETATTR_ATUID_ERR;
1917 } else {
1918 vap->va_uid = uid;
1919 vap->va_mask |= AT_UID;
1920 /* save the results for next time */
1921 if (pug && ol <= MAX_OG_NAME) {
1922 pug->uid = uid;
1923 pug->u_curr.utf8string_len =
1924 ov.utf8string_len;
1925 bcopy(owner_val,
1926 pug->u_curr.utf8string_val,
1927 ol);
1928 U_SWAP_CURR_LAST(pug);
1929 }
1930 }
1931 }
1932 ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT;
1933 }
1934 if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1935 uint_t *group_length, gl;
1936 char *group_val = NULL;
1937 utf8string gv;
1938 int error;
1939
1940 /* get the OWNER_GROUP_LENGTH */
1941 gl = IXDR_GET_U_INT32(ptr);
1942
1943 /* Manage the group length location */
1944 if (pug && gl <= MAX_OG_NAME) {
1945 group_length = &pug->g_curr.utf8string_len;
1946 *group_length = gl;
1947 } else {
1948 group_length = ≷
1949 }
1950
1951 /* find memory to store the decode */
1952 if (*group_length > MAX_OG_NAME || pug == NULL)
1953 group_val = (char *)ptr;
1954 else
1955 group_val = (char *)ptr;
1956
1957 /* Optimize for matching if called for */
1958 if (pug &&
1959 *group_length == pug->g_last.utf8string_len &&
1960 bcmp(group_val, pug->g_last.utf8string_val,
1961 *group_length) == 0) {
1962 vap->va_gid = pug->gid;
1963 vap->va_mask |= AT_GID;
1964 } else {
1965 uid_t gid;
1966
1967 gv.utf8string_len = *group_length;
1968 gv.utf8string_val = group_val;
1969 error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1970 /*
1971 * String was mapped, but to nobody because
1972 * we are nfsmapid, indicate it should not
1973 * be cached.
1974 */
1975 if (error == ENOTSUP) {
1976 error = 0;
1977 garp->n4g_attrwhy =
1978 NFS4_GETATTR_NOCACHE_OK;
1979 }
1980
1981 if (error) {
1982 garp->n4g_attrerr = error;
1983 garp->n4g_attrwhy =
1984 NFS4_GETATTR_ATGID_ERR;
1985 } else {
1986 vap->va_gid = gid;
1987 vap->va_mask |= AT_GID;
1988 if (pug && gl <= MAX_OG_NAME) {
1989 pug->gid = gid;
1990 pug->g_curr.utf8string_len =
1991 gv.utf8string_len;
1992 bcopy(group_val,
1993 pug->g_curr.utf8string_val,
1994 gl);
1995 G_SWAP_CURR_LAST(pug);
1996 }
1997 }
1998 }
1999 ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT;
2000 }
2001 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
2002 ASSERT(0);
2003 }
2004 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
2005 ASSERT(0);
2006 }
2007 }
2008 if (resbmap &
2009 (FATTR4_QUOTA_USED_MASK |
2010 FATTR4_SPACE_AVAIL_MASK |
2011 FATTR4_SPACE_FREE_MASK |
2012 FATTR4_SPACE_TOTAL_MASK |
2013 FATTR4_SPACE_USED_MASK |
2014 FATTR4_SYSTEM_MASK)) {
2015
2016 if (resbmap & FATTR4_QUOTA_USED_MASK) {
2017 ASSERT(0);
2018 }
2019 if (resbmap & FATTR4_RAWDEV_MASK) {
2020 fattr4_rawdev rawdev;
2021
2022 rawdev.specdata1 = IXDR_GET_U_INT32(ptr);
2023 rawdev.specdata2 = IXDR_GET_U_INT32(ptr);
2024
2025 if (vap->va_type == VCHR || vap->va_type == VBLK) {
2026 vap->va_rdev = makedevice(rawdev.specdata1,
2027 rawdev.specdata2);
2028 } else {
2029 vap->va_rdev = 0;
2030 }
2031 vap->va_mask |= AT_RDEV;
2032 }
2033 if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
2034 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail);
2035 gesp->n4g_sb.f_bavail /= DEV_BSIZE;
2036 }
2037 if (resbmap & FATTR4_SPACE_FREE_MASK) {
2038 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree);
2039 gesp->n4g_sb.f_bfree /= DEV_BSIZE;
2040 }
2041 if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
2042 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks);
2043 gesp->n4g_sb.f_blocks /= DEV_BSIZE;
2044 }
2045 if (resbmap & FATTR4_SPACE_USED_MASK) {
2046 uint64_t space_used;
2047 IXDR_GET_U_HYPER(ptr, space_used);
2048
2049 /* Compute space depending on device type */
2050 ASSERT((vap->va_mask & AT_TYPE));
2051 if (vap->va_type == VREG || vap->va_type == VDIR ||
2052 vap->va_type == VLNK) {
2053 vap->va_nblocks = (u_longlong_t)
2054 ((space_used + (offset4)DEV_BSIZE -
2055 (offset4)1) / (offset4)DEV_BSIZE);
2056 } else {
2057 vap->va_nblocks = 0;
2058 }
2059 vap->va_mask |= AT_NBLOCKS;
2060 }
2061 if (resbmap & FATTR4_SYSTEM_MASK) {
2062 ASSERT(0);
2063 }
2064 }
2065 if (resbmap &
2066 (FATTR4_TIME_ACCESS_MASK |
2067 FATTR4_TIME_ACCESS_SET_MASK |
2068 FATTR4_TIME_BACKUP_MASK |
2069 FATTR4_TIME_CREATE_MASK |
2070 FATTR4_TIME_DELTA_MASK |
2071 FATTR4_TIME_METADATA_MASK |
2072 FATTR4_TIME_MODIFY_MASK |
2073 FATTR4_TIME_MODIFY_SET_MASK |
2074 FATTR4_MOUNTED_ON_FILEID_MASK)) {
2075
2076 if (resbmap & FATTR4_TIME_ACCESS_MASK) {
2077 nfstime4 atime;
2078 int error;
2079
2080 IXDR_GET_U_HYPER(ptr, atime.seconds);
2081 atime.nseconds = IXDR_GET_U_INT32(ptr);
2082
2083 error = nfs4_time_ntov(&atime, &vap->va_atime);
2084 if (error) {
2085 garp->n4g_attrerr = error;
2086 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
2087 }
2088 vap->va_mask |= AT_ATIME;
2089 }
2090 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
2091 ASSERT(0);
2092 }
2093 if (resbmap & FATTR4_TIME_BACKUP_MASK) {
2094 ASSERT(0);
2095 }
2096 if (resbmap & FATTR4_TIME_CREATE_MASK) {
2097 ASSERT(0);
2098 }
2099 if (resbmap & FATTR4_TIME_DELTA_MASK) {
2100 IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds);
2101 gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr);
2102 }
2103 if (resbmap & FATTR4_TIME_METADATA_MASK) {
2104 nfstime4 mdt;
2105 int error;
2106
2107 IXDR_GET_U_HYPER(ptr, mdt.seconds);
2108 mdt.nseconds = IXDR_GET_U_INT32(ptr);
2109
2110 error = nfs4_time_ntov(&mdt, &vap->va_ctime);
2111 if (error) {
2112 garp->n4g_attrerr = error;
2113 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
2114 }
2115 vap->va_mask |= AT_CTIME;
2116 }
2117 if (resbmap & FATTR4_TIME_MODIFY_MASK) {
2118 nfstime4 mtime;
2119 int error;
2120
2121 IXDR_GET_U_HYPER(ptr, mtime.seconds);
2122 mtime.nseconds = IXDR_GET_U_INT32(ptr);
2123
2124 error = nfs4_time_ntov(&mtime, &vap->va_mtime);
2125 if (error) {
2126 garp->n4g_attrerr = error;
2127 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
2128 }
2129 vap->va_mask |= AT_MTIME;
2130 }
2131 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
2132 ASSERT(0);
2133 }
2134 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
2135 IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid);
2136 garp->n4g_mon_fid_valid = 1;
2137 }
2138 }
2139
2140 /*
2141 * FATTR4_ACL_MASK is not yet supported by this function, but
2142 * we check against it anyway, in case it ever is.
2143 */
2144 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
2145 /* copy only if not provided */
2146 if (garp->n4g_ext_res == NULL) {
2147 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
2148 bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
2149 }
2150 }
2151
2152 return (TRUE);
2153 }
2154
2155
2156 /*
2157 * "." and ".." buffers for filling in on read and readdir
2158 * calls. Intialize the first time and fill in on every
2159 * call to to readdir.
2160 */
2161 char *nfs4_dot_entries;
2162 char *nfs4_dot_dot_entry;
2163
2164 /*
2165 * Create the "." or ".." and pad the buffer once so they are
2166 * copied out as required into the user supplied buffer everytime.
2167 * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
2168 * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
2169 */
2170 void
nfs4_init_dot_entries()2171 nfs4_init_dot_entries()
2172 {
2173 struct dirent64 *odp;
2174
2175 /*
2176 * zalloc it so it zeros the buffer out. Need
2177 * to just do it once.
2178 */
2179 nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
2180 KM_SLEEP);
2181
2182 odp = (struct dirent64 *)nfs4_dot_entries;
2183 odp->d_off = 1; /* magic cookie for "." entry */
2184 odp->d_reclen = DIRENT64_RECLEN(1);
2185 odp->d_name[0] = '.';
2186 odp->d_name[1] = '\0';
2187
2188 nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1);
2189 odp = (struct dirent64 *)nfs4_dot_dot_entry;
2190
2191 odp->d_off = 2;
2192 odp->d_reclen = DIRENT64_RECLEN(2);
2193 odp->d_name[0] = '.';
2194 odp->d_name[1] = '.';
2195 odp->d_name[2] = '\0';
2196 }
2197
2198 void
nfs4_destroy_dot_entries()2199 nfs4_destroy_dot_entries()
2200 {
2201 if (nfs4_dot_entries)
2202 kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) +
2203 DIRENT64_RECLEN(2));
2204
2205 nfs4_dot_entries = nfs4_dot_dot_entry = NULL;
2206 }
2207
2208 bool_t
xdr_READDIR4res_clnt(XDR * xdrs,READDIR4res_clnt * objp,READDIR4args * aobjp)2209 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp)
2210 {
2211 bool_t more_data;
2212 rddir4_cache *rdc = aobjp->rdc;
2213 dirent64_t *dp = NULL;
2214 int entry_length = 0;
2215 int space_left = 0;
2216 bitmap4 resbmap;
2217 uint32_t attrlen;
2218 nfs4_ga_res_t gar;
2219 struct nfs4_ga_ext_res ges;
2220 uint64_t last_cookie = 0;
2221 int skip_to_end;
2222 ug_cache_t *pug = NULL;
2223
2224 ASSERT(xdrs->x_op == XDR_DECODE);
2225 ASSERT(rdc->entries == NULL);
2226 ASSERT(aobjp->dircount > 0);
2227
2228 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2229 return (FALSE);
2230 if (objp->status != NFS4_OK)
2231 return (TRUE);
2232
2233 gar.n4g_va.va_mask = 0;
2234 gar.n4g_change_valid = 0;
2235 gar.n4g_mon_fid_valid = 0;
2236 gar.n4g_fsid_valid = 0;
2237 gar.n4g_vsa.vsa_mask = 0;
2238 gar.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2239 ges.n4g_pc4.pc4_cache_valid = 0;
2240 ges.n4g_pc4.pc4_xattr_valid = 0;
2241 gar.n4g_ext_res = ⩾
2242
2243 /* READDIR4res_clnt_free needs to kmem_free this buffer */
2244 rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP);
2245
2246 dp = (dirent64_t *)rdc->entries;
2247 rdc->entlen = rdc->buflen = space_left = aobjp->dircount;
2248
2249 /* Fill in dot and dot-dot if needed */
2250 if (rdc->nfs4_cookie == (nfs_cookie4) 0 ||
2251 rdc->nfs4_cookie == (nfs_cookie4) 1) {
2252
2253 if (rdc->nfs4_cookie == (nfs_cookie4)0) {
2254 bcopy(nfs4_dot_entries, rdc->entries,
2255 DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2256 objp->dotp = dp;
2257 dp = (struct dirent64 *)(((char *)dp) +
2258 DIRENT64_RECLEN(1));
2259 objp->dotdotp = dp;
2260 dp = (struct dirent64 *)(((char *)dp) +
2261 DIRENT64_RECLEN(2));
2262 space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2263
2264 } else { /* for ".." entry */
2265 bcopy(nfs4_dot_dot_entry, rdc->entries,
2266 DIRENT64_RECLEN(2));
2267 objp->dotp = NULL;
2268 objp->dotdotp = dp;
2269 dp = (struct dirent64 *)(((char *)dp) +
2270 DIRENT64_RECLEN(2));
2271 space_left -= DIRENT64_RECLEN(2);
2272 }
2273 /* Magic NFSv4 number for entry after start */
2274 last_cookie = 2;
2275 }
2276
2277 /* Get the cookie VERIFIER */
2278 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
2279 goto noentries;
2280
2281 /* Get the do-we-have-a-next-entry BOOL */
2282 if (!xdr_bool(xdrs, &more_data))
2283 goto noentries;
2284
2285 if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK))
2286 pug = alloc_ugcache();
2287
2288 skip_to_end = 0;
2289 while (more_data) {
2290 uint_t namelen;
2291 uint64_t cookie;
2292
2293 /* Get the COOKIE */
2294 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie))
2295 goto noentries;
2296
2297 /* Get the LENGTH of the entry name */
2298 if (!xdr_u_int(xdrs, &namelen))
2299 goto noentries;
2300
2301 if (!skip_to_end) {
2302 /*
2303 * With the length of the directory entry name
2304 * in hand, figure out if there is room left
2305 * to encode it for the requestor. If not,
2306 * that is okay, but the rest of the readdir
2307 * operation result must be decoded in the
2308 * case there are following operations
2309 * in the compound request. Therefore, mark
2310 * the rest of the response as "skip" and
2311 * decode or skip the remaining data
2312 */
2313 entry_length = DIRENT64_RECLEN(namelen);
2314 if (space_left < entry_length)
2315 skip_to_end = 1;
2316 }
2317
2318 /* Get the NAME of the entry */
2319 if (!skip_to_end) {
2320 if (!xdr_opaque(xdrs, dp->d_name, namelen))
2321 goto noentries;
2322 bzero(&dp->d_name[namelen],
2323 DIRENT64_NAMELEN(entry_length) - namelen);
2324 dp->d_off = last_cookie = cookie;
2325 dp->d_reclen = entry_length;
2326 } else {
2327 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen))
2328 goto noentries;
2329 }
2330
2331 /* Get the attribute BITMAP */
2332 if (!xdr_bitmap4(xdrs, &resbmap))
2333 goto noentries;
2334 /* Get the LENGTH of the attributes */
2335 if (!xdr_u_int(xdrs, (uint_t *)&attrlen))
2336 goto noentries;
2337
2338 /* Get the ATTRIBUTES */
2339 if (!skip_to_end) {
2340 uint32_t *ptr;
2341
2342 if (!(resbmap & FATTR4_ACL_MASK) &&
2343 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen))
2344 != NULL) {
2345 if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap,
2346 aobjp->attr_request, aobjp->mi, pug))
2347 goto noentries;
2348 } else {
2349 if (!xdr_ga_fattr_res(xdrs, &gar, resbmap,
2350 aobjp->attr_request, aobjp->mi, pug))
2351 goto noentries;
2352 }
2353
2354 /* Fill in the d_ino per the server's fid values */
2355 /*
2356 * Important to note that the mounted on fileid
2357 * is returned in d_ino if supported. This is
2358 * expected, readdir returns the mounted on fileid
2359 * while stat() returns the fileid of the object
2360 * on "top" of the mount.
2361 */
2362 if (gar.n4g_mon_fid_valid)
2363 dp->d_ino = gar.n4g_mon_fid;
2364 else if (gar.n4g_va.va_mask & AT_NODEID)
2365 dp->d_ino = gar.n4g_va.va_nodeid;
2366 else
2367 dp->d_ino = 0;
2368
2369 /* See about creating an rnode for this entry */
2370 if ((resbmap &
2371 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) ==
2372 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) {
2373 nfs4_sharedfh_t *sfhp;
2374 vnode_t *vp;
2375
2376 sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh,
2377 aobjp->mi, NULL);
2378 vp = makenfs4node(sfhp, &gar,
2379 aobjp->dvp->v_vfsp,
2380 aobjp->t,
2381 aobjp->cr,
2382 aobjp->dvp,
2383 fn_get(VTOSV(aobjp->dvp)->sv_name,
2384 dp->d_name, sfhp));
2385 sfh4_rele(&sfhp);
2386 dnlc_update(aobjp->dvp, dp->d_name, vp);
2387 VN_RELE(vp);
2388 }
2389
2390 dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen);
2391
2392 space_left -= entry_length;
2393
2394 } else {
2395 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen))
2396 goto noentries;
2397 }
2398
2399 /* Get the do-we-have-a-next-entry BOOL */
2400 if (!xdr_bool(xdrs, &more_data))
2401 goto noentries;
2402 }
2403
2404 if (pug) {
2405 kmem_free(pug, sizeof (ug_cache_t));
2406 pug = NULL;
2407 }
2408
2409 /*
2410 * Finish up the rddir cache
2411 * If no entries were returned, free up buffer &
2412 * set ncookie to the starting cookie for this
2413 * readdir request so that the direof caching
2414 * will work properly.
2415 */
2416 ASSERT(rdc->entries);
2417 if (last_cookie == 0) {
2418 kmem_free(rdc->entries, rdc->entlen);
2419 rdc->entries = NULL;
2420 last_cookie = rdc->nfs4_cookie;
2421 }
2422
2423 rdc->actlen = rdc->entlen - space_left;
2424 rdc->nfs4_ncookie = last_cookie;
2425
2426 /* Get the EOF marker */
2427 if (!xdr_bool(xdrs, &objp->eof))
2428 goto noentries;
2429
2430 /*
2431 * If the server returns eof and there were no
2432 * skipped entries, set eof
2433 */
2434 rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE;
2435
2436 /*
2437 * If we encoded entries we are done
2438 */
2439 if (rdc->entries) {
2440 rdc->error = 0;
2441 return (TRUE);
2442 }
2443
2444 /*
2445 * If there were no entries and we skipped because
2446 * there was not enough space, return EINVAL
2447 */
2448 if (skip_to_end) {
2449 rdc->error = EINVAL;
2450 return (TRUE);
2451 }
2452
2453 /*
2454 * No entries, nothing skipped, and EOF, return OK.
2455 */
2456 if (objp->eof == TRUE) {
2457 rdc->error = 0;
2458 return (TRUE);
2459 }
2460
2461 /*
2462 * No entries, nothing skipped, and not EOF
2463 * probably a bad cookie, return ENOENT.
2464 */
2465 rdc->error = ENOENT;
2466 return (TRUE);
2467
2468 noentries:
2469 if (rdc->entries) {
2470 kmem_free(rdc->entries, rdc->entlen);
2471 rdc->entries = NULL;
2472 }
2473 if (pug)
2474 kmem_free(pug, sizeof (ug_cache_t));
2475 rdc->error = EIO;
2476 return (FALSE);
2477 }
2478
2479 /*
2480 * xdr_ga_res
2481 *
2482 * Returns: FALSE on raw data processing errors, TRUE otherwise.
2483 *
2484 * This function pre-processes the OP_GETATTR response, and then
2485 * calls common routines to process the GETATTR fattr4 results into
2486 * vnode attributes and other components that the client is interested
2487 * in. If an error other than an RPC error is encountered, the details
2488 * of the error are filled into objp, although the result of the
2489 * processing is set to TRUE.
2490 */
2491 static bool_t
xdr_ga_res(XDR * xdrs,GETATTR4res * objp,GETATTR4args * aobjp)2492 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp)
2493 {
2494 #ifdef INLINE
2495 uint32_t *ptr;
2496 #endif
2497 bitmap4 resbmap;
2498 uint32_t attrlen;
2499
2500 ASSERT(xdrs->x_op == XDR_DECODE);
2501
2502 /* Initialize objp attribute error values */
2503 objp->ga_res.n4g_attrerr =
2504 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2505
2506 if (!xdr_bitmap4(xdrs, &resbmap))
2507 return (FALSE);
2508
2509 /* save the response bitmap for the caller */
2510 objp->ga_res.n4g_resbmap = resbmap;
2511
2512 /* attrlen */
2513 if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen))
2514 return (FALSE);
2515
2516 /*
2517 * Handle case where request and response bitmaps don't match.
2518 */
2519 if (aobjp->attr_request && aobjp->attr_request != resbmap) {
2520 bitmap4 deltabmap;
2521
2522 /*
2523 * Return error for case where server sent extra attributes
2524 * because the "unknown" attributes may be anywhere in the
2525 * xdr stream and can't be properly processed.
2526 */
2527 deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap);
2528 if (deltabmap) {
2529 objp->ga_res.n4g_attrerr = EINVAL;
2530 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR;
2531 return (TRUE);
2532 }
2533
2534 /*
2535 * Return error for case where there is a mandatory
2536 * attribute missing in the server response. Note that
2537 * missing recommended attributes are evaluated in the
2538 * specific routines that decode the server response.
2539 */
2540 deltabmap = ((aobjp->attr_request ^ resbmap)
2541 & aobjp->attr_request);
2542 if ((deltabmap & FATTR4_MANDATTR_MASK)) {
2543 objp->ga_res.n4g_attrerr = EINVAL;
2544 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR;
2545 return (TRUE);
2546 }
2547 }
2548
2549 /* Check to see if the attrs can be inlined and go for it if so */
2550 #ifdef INLINE
2551 if (!(resbmap & FATTR4_ACL_MASK) &&
2552 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL)
2553 return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res,
2554 resbmap, aobjp->attr_request, aobjp->mi, NULL));
2555 else
2556 #endif
2557 return (xdr_ga_fattr_res(xdrs, &objp->ga_res,
2558 resbmap, aobjp->attr_request, aobjp->mi, NULL));
2559 }
2560
2561 #if defined(DEBUG) && !defined(lint)
2562 /*
2563 * We assume that an enum is a 32-bit value, check it once
2564 */
2565 static enum szchk { SZVAL } szchkvar;
2566 #endif
2567
2568 bool_t
xdr_settime4(XDR * xdrs,settime4 * objp)2569 xdr_settime4(XDR *xdrs, settime4 *objp)
2570 {
2571 #if defined(DEBUG) && !defined(lint)
2572 ASSERT(sizeof (szchkvar) == sizeof (int32_t));
2573 #endif
2574 if (xdrs->x_op == XDR_FREE)
2575 return (TRUE);
2576
2577 if (!xdr_int(xdrs, (int *)&objp->set_it))
2578 return (FALSE);
2579 if (objp->set_it != SET_TO_CLIENT_TIME4)
2580 return (TRUE);
2581 /* xdr_nfstime4 */
2582 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds))
2583 return (FALSE);
2584 return (xdr_u_int(xdrs, &objp->time.nseconds));
2585 }
2586
2587 bool_t
xdr_fattr4(XDR * xdrs,fattr4 * objp)2588 xdr_fattr4(XDR *xdrs, fattr4 *objp)
2589 {
2590 if (xdrs->x_op != XDR_FREE) {
2591 if (!xdr_bitmap4(xdrs, &objp->attrmask))
2592 return (FALSE);
2593 return (xdr_bytes(xdrs, (char **)&objp->attrlist4,
2594 (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT));
2595 }
2596
2597 /*
2598 * Optimized free case
2599 */
2600 if (objp->attrlist4 != NULL)
2601 kmem_free(objp->attrlist4, objp->attrlist4_len);
2602 return (TRUE);
2603 }
2604
2605 static bool_t
xdr_ACCESS4res(XDR * xdrs,ACCESS4res * objp)2606 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp)
2607 {
2608 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2609 return (FALSE);
2610 if (objp->status != NFS4_OK)
2611 return (TRUE);
2612 if (!xdr_u_int(xdrs, &objp->supported))
2613 return (FALSE);
2614 return (xdr_u_int(xdrs, &objp->access));
2615 }
2616
2617 static bool_t
xdr_CLOSE4args(XDR * xdrs,CLOSE4args * objp)2618 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp)
2619 {
2620 if (!xdr_u_int(xdrs, &objp->seqid))
2621 return (FALSE);
2622 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2623 return (FALSE);
2624 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2625 }
2626
2627 static bool_t
xdr_CLOSE4res(XDR * xdrs,CLOSE4res * objp)2628 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp)
2629 {
2630 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2631 return (FALSE);
2632 if (objp->status != NFS4_OK)
2633 return (TRUE);
2634 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2635 return (FALSE);
2636 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2637 }
2638
2639 static bool_t
xdr_CREATE4args(XDR * xdrs,CREATE4args * objp)2640 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp)
2641 {
2642 if (xdrs->x_op != XDR_FREE) {
2643 if (!xdr_int(xdrs, (int32_t *)&objp->type))
2644 return (FALSE);
2645 switch (objp->type) {
2646 case NF4LNK:
2647 if (!xdr_bytes(xdrs,
2648 (char **)&objp->ftype4_u.linkdata.linktext4_val,
2649 (uint_t *)&objp->ftype4_u.linkdata.linktext4_len,
2650 NFS4_MAX_UTF8STRING))
2651 return (FALSE);
2652 break;
2653 case NF4BLK:
2654 case NF4CHR:
2655 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1))
2656 return (FALSE);
2657 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2))
2658 return (FALSE);
2659 break;
2660 case NF4SOCK:
2661 case NF4FIFO:
2662 case NF4DIR:
2663 default:
2664 break; /* server should return NFS4ERR_BADTYPE */
2665 }
2666 if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val,
2667 (uint_t *)&objp->objname.utf8string_len,
2668 NFS4_MAX_UTF8STRING))
2669 return (FALSE);
2670 return (xdr_fattr4(xdrs, &objp->createattrs));
2671 }
2672
2673 /*
2674 * Optimized free case
2675 */
2676 if (objp->type == NF4LNK) {
2677 if (objp->ftype4_u.linkdata.linktext4_val != NULL)
2678 kmem_free(objp->ftype4_u.linkdata.linktext4_val,
2679 objp->ftype4_u.linkdata.linktext4_len);
2680 }
2681 if (objp->objname.utf8string_val != NULL)
2682 kmem_free(objp->objname.utf8string_val,
2683 objp->objname.utf8string_len);
2684 return (xdr_fattr4(xdrs, &objp->createattrs));
2685 }
2686
2687 static bool_t
xdr_CREATE4cargs(XDR * xdrs,CREATE4cargs * objp)2688 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp)
2689 {
2690 int len;
2691
2692 ASSERT(xdrs->x_op == XDR_ENCODE);
2693
2694 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type))
2695 return (FALSE);
2696 switch (objp->type) {
2697 case NF4LNK:
2698 len = strlen(objp->ftype4_u.clinkdata);
2699 if (len > NFS4_MAX_UTF8STRING)
2700 return (FALSE);
2701 if (!XDR_PUTINT32(xdrs, &len))
2702 return (FALSE);
2703 if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len))
2704 return (FALSE);
2705 break;
2706 case NF4BLK:
2707 case NF4CHR:
2708 if (!XDR_PUTINT32(xdrs,
2709 (int32_t *)&objp->ftype4_u.devdata.specdata1))
2710 return (FALSE);
2711 if (!XDR_PUTINT32(xdrs,
2712 (int32_t *)&objp->ftype4_u.devdata.specdata2))
2713 return (FALSE);
2714 break;
2715 case NF4SOCK:
2716 case NF4FIFO:
2717 case NF4DIR:
2718 default:
2719 break; /* server should return NFS4ERR_BADTYPE */
2720 }
2721
2722 len = strlen(objp->cname);
2723 if (len > NFS4_MAX_UTF8STRING)
2724 return (FALSE);
2725 if (!XDR_PUTINT32(xdrs, &len))
2726 return (FALSE);
2727 if (!xdr_opaque(xdrs, objp->cname, len))
2728 return (FALSE);
2729
2730 return (xdr_fattr4(xdrs, &objp->createattrs));
2731 }
2732
2733 static bool_t
xdr_CREATE4res(XDR * xdrs,CREATE4res * objp)2734 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp)
2735 {
2736 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2737 return (FALSE);
2738 if (objp->status != NFS4_OK)
2739 return (TRUE);
2740 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2741 return (FALSE);
2742 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2743 return (FALSE);
2744 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
2745 return (FALSE);
2746 return (xdr_bitmap4(xdrs, &objp->attrset));
2747 }
2748
2749 static bool_t
xdr_LINK4res(XDR * xdrs,LINK4res * objp)2750 xdr_LINK4res(XDR *xdrs, LINK4res *objp)
2751 {
2752 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2753 return (FALSE);
2754 if (objp->status != NFS4_OK)
2755 return (TRUE);
2756 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2757 return (FALSE);
2758 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2759 return (FALSE);
2760 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after));
2761 }
2762
2763 static bool_t
xdr_LOCK4args(XDR * xdrs,LOCK4args * objp)2764 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp)
2765 {
2766 if (xdrs->x_op != XDR_FREE) {
2767 if (!xdr_int(xdrs, (int *)&objp->locktype))
2768 return (FALSE);
2769 if (!xdr_bool(xdrs, &objp->reclaim))
2770 return (FALSE);
2771 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2772 return (FALSE);
2773 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2774 return (FALSE);
2775 if (!xdr_bool(xdrs, &objp->locker.new_lock_owner))
2776 return (FALSE);
2777 if (objp->locker.new_lock_owner == TRUE) {
2778 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2779 open_seqid))
2780 return (FALSE);
2781 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2782 open_stateid.seqid))
2783 return (FALSE);
2784 if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner.
2785 open_stateid.other, NFS4_OTHER_SIZE))
2786 return (FALSE);
2787 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2788 lock_seqid))
2789 return (FALSE);
2790 if (!xdr_u_longlong_t(xdrs,
2791 (u_longlong_t *)&objp->locker.locker4_u.
2792 open_owner.lock_owner.clientid))
2793 return (FALSE);
2794 return (xdr_bytes(xdrs,
2795 (char **)&objp->locker.locker4_u.open_owner.
2796 lock_owner.owner_val,
2797 (uint_t *)&objp->locker.locker4_u.open_owner.
2798 lock_owner.owner_len,
2799 NFS4_OPAQUE_LIMIT));
2800 }
2801
2802 if (objp->locker.new_lock_owner != FALSE)
2803 return (FALSE);
2804
2805 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2806 lock_stateid.seqid))
2807 return (FALSE);
2808 if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner.
2809 lock_stateid.other, NFS4_OTHER_SIZE))
2810 return (FALSE);
2811 return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2812 lock_seqid));
2813 }
2814
2815 /*
2816 * Optimized free case
2817 */
2818 if (objp->locker.new_lock_owner == TRUE) {
2819 if (objp->locker.locker4_u.open_owner.lock_owner.owner_val !=
2820 NULL) {
2821 kmem_free(objp->locker.locker4_u.open_owner.lock_owner.
2822 owner_val,
2823 objp->locker.locker4_u.open_owner.lock_owner.
2824 owner_len);
2825 }
2826 }
2827
2828 return (TRUE);
2829 }
2830
2831 static bool_t
xdr_LOCK4res(XDR * xdrs,LOCK4res * objp)2832 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp)
2833 {
2834 if (xdrs->x_op != XDR_FREE) {
2835 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2836 return (FALSE);
2837 if (objp->status == NFS4_OK) {
2838 if (!xdr_u_int(xdrs,
2839 &objp->LOCK4res_u.lock_stateid.seqid))
2840 return (FALSE);
2841 return (xdr_opaque(xdrs,
2842 objp->LOCK4res_u.lock_stateid.other,
2843 NFS4_OTHER_SIZE));
2844 }
2845 if (objp->status != NFS4ERR_DENIED)
2846 return (TRUE);
2847
2848 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2849 denied.offset))
2850 return (FALSE);
2851 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2852 denied.length))
2853 return (FALSE);
2854 if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype))
2855 return (FALSE);
2856 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2857 denied.owner.clientid))
2858 return (FALSE);
2859 return (xdr_bytes(xdrs,
2860 (char **)&objp->LOCK4res_u.denied.owner.owner_val,
2861 (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len,
2862 NFS4_OPAQUE_LIMIT));
2863 }
2864
2865 /*
2866 * Optimized free case
2867 */
2868 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2869 return (TRUE);
2870
2871 if (objp->LOCK4res_u.denied.owner.owner_val != NULL)
2872 kmem_free(objp->LOCK4res_u.denied.owner.owner_val,
2873 objp->LOCK4res_u.denied.owner.owner_len);
2874 return (TRUE);
2875 }
2876
2877 static bool_t
xdr_LOCKT4args(XDR * xdrs,LOCKT4args * objp)2878 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp)
2879 {
2880 if (xdrs->x_op != XDR_FREE) {
2881 if (!xdr_int(xdrs, (int *)&objp->locktype))
2882 return (FALSE);
2883 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2884 return (FALSE);
2885 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2886 return (FALSE);
2887 if (!xdr_u_longlong_t(xdrs,
2888 (u_longlong_t *)&objp->owner.clientid))
2889 return (FALSE);
2890 return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2891 (uint_t *)&objp->owner.owner_len,
2892 NFS4_OPAQUE_LIMIT));
2893 }
2894
2895 /*
2896 * Optimized free case
2897 */
2898 if (objp->owner.owner_val != NULL)
2899 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2900 return (TRUE);
2901 }
2902
2903 static bool_t
xdr_LOCKT4res(XDR * xdrs,LOCKT4res * objp)2904 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp)
2905 {
2906 if (xdrs->x_op != XDR_FREE) {
2907 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2908 return (FALSE);
2909 if (objp->status == NFS4_OK)
2910 return (TRUE);
2911 if (objp->status != NFS4ERR_DENIED)
2912 return (TRUE);
2913 /* xdr_LOCK4denied */
2914 if (!xdr_u_longlong_t(xdrs,
2915 (u_longlong_t *)&objp->denied.offset))
2916 return (FALSE);
2917 if (!xdr_u_longlong_t(xdrs,
2918 (u_longlong_t *)&objp->denied.length))
2919 return (FALSE);
2920 if (!xdr_int(xdrs, (int *)&objp->denied.locktype))
2921 return (FALSE);
2922 if (!xdr_u_longlong_t(xdrs,
2923 (u_longlong_t *)&objp->denied.owner.clientid))
2924 return (FALSE);
2925 return (xdr_bytes(xdrs,
2926 (char **)&objp->denied.owner.owner_val,
2927 (uint_t *)&objp->denied.owner.owner_len,
2928 NFS4_OPAQUE_LIMIT));
2929 }
2930
2931 /*
2932 * Optimized free case
2933 */
2934 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2935 return (TRUE);
2936 if (objp->denied.owner.owner_val != NULL)
2937 kmem_free(objp->denied.owner.owner_val,
2938 objp->denied.owner.owner_len);
2939 return (TRUE);
2940 }
2941
2942 static bool_t
xdr_LOCKU4args(XDR * xdrs,LOCKU4args * objp)2943 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
2944 {
2945 if (!xdr_int(xdrs, (int *)&objp->locktype))
2946 return (FALSE);
2947 if (!xdr_u_int(xdrs, &objp->seqid))
2948 return (FALSE);
2949 if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid))
2950 return (FALSE);
2951 if (!xdr_opaque(xdrs, objp->lock_stateid.other, NFS4_OTHER_SIZE))
2952 return (FALSE);
2953 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2954 return (FALSE);
2955 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length));
2956 }
2957
2958 static bool_t
xdr_share_access(XDR * xdrs,uint32_t * share_access,uint32_t * deleg_want)2959 xdr_share_access(XDR *xdrs, uint32_t *share_access, uint32_t *deleg_want)
2960 {
2961 uint32_t w;
2962
2963 switch (xdrs->x_op) {
2964 case XDR_DECODE:
2965 if (!xdr_u_int(xdrs, &w))
2966 break;
2967
2968 *share_access = w & OPEN4_SHARE_ACCESS_MASK;
2969 *deleg_want = w & OPEN4_SHARE_WANT_MASK;
2970 return (TRUE);
2971
2972 case XDR_ENCODE:
2973 return (xdr_u_int(xdrs, share_access));
2974
2975 case XDR_FREE:
2976 return (TRUE);
2977 }
2978
2979 return (FALSE);
2980 }
2981
2982 static bool_t
xdr_OPEN4args(XDR * xdrs,OPEN4args * objp)2983 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2984 {
2985 if (xdrs->x_op != XDR_FREE) {
2986 if (!xdr_u_int(xdrs, &objp->seqid))
2987 return (FALSE);
2988 if (!xdr_share_access(xdrs, &objp->share_access,
2989 &objp->deleg_want))
2990 return (FALSE);
2991 if (!xdr_u_int(xdrs, &objp->share_deny))
2992 return (FALSE);
2993
2994 /* xdr_open_owner4 */
2995 if (!xdr_u_longlong_t(xdrs,
2996 (u_longlong_t *)&objp->owner.clientid))
2997 return (FALSE);
2998 if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2999 (uint_t *)&objp->owner.owner_len,
3000 NFS4_OPAQUE_LIMIT))
3001 return (FALSE);
3002
3003 /* xdr_openflag4 */
3004 if (!xdr_int(xdrs, (int *)&objp->opentype))
3005 return (FALSE);
3006 if (objp->opentype == OPEN4_CREATE) {
3007
3008 /* xdr_createhow4 */
3009 if (!xdr_int(xdrs, (int *)&objp->mode))
3010 return (FALSE);
3011 switch (objp->mode) {
3012 case UNCHECKED4:
3013 case GUARDED4:
3014 if (!xdr_fattr4(xdrs,
3015 &objp->createhow4_u.createattrs))
3016 return (FALSE);
3017 break;
3018 case EXCLUSIVE4:
3019 if (!xdr_u_longlong_t(xdrs,
3020 (u_longlong_t *)&objp->createhow4_u.
3021 createverf))
3022 return (FALSE);
3023 break;
3024 case EXCLUSIVE4_1:
3025 if (!xdr_creatverfattr(xdrs,
3026 &objp->createhow4_u.ch_createboth))
3027 return (FALSE);
3028 break;
3029 default:
3030 return (FALSE);
3031 }
3032 }
3033
3034 /* xdr_open_claim4 */
3035 if (!xdr_open_claim4(xdrs, &objp->claim))
3036 return (FALSE);
3037
3038 return (TRUE);
3039 }
3040
3041 /*
3042 * Optimized free case
3043 */
3044 if (objp->owner.owner_val != NULL)
3045 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
3046
3047 if (objp->opentype == OPEN4_CREATE) {
3048 switch (objp->mode) {
3049 case UNCHECKED4:
3050 case GUARDED4:
3051 (void) xdr_fattr4(xdrs,
3052 &objp->createhow4_u.createattrs);
3053 break;
3054 case EXCLUSIVE4:
3055 default:
3056 break;
3057 }
3058 }
3059
3060 (void) xdr_open_claim4(xdrs, &objp->claim);
3061 return (TRUE);
3062 }
3063
3064 static bool_t
xdr_OPEN4cargs(XDR * xdrs,OPEN4cargs * objp)3065 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3066 {
3067 int op;
3068 int len;
3069 rpc_inline_t *ptr;
3070
3071 ASSERT(xdrs->x_op == XDR_ENCODE);
3072
3073 /*
3074 * We must always define the client's open_owner to be
3075 * 4 byte aligned and sized.
3076 */
3077 ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3078 ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3079
3080 len = objp->owner.owner_len;
3081 if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3082 int i;
3083 int32_t *ip;
3084
3085 IXDR_PUT_U_INT32(ptr, OP_OPEN);
3086 IXDR_PUT_U_INT32(ptr, objp->seqid);
3087 IXDR_PUT_U_INT32(ptr, objp->share_access);
3088 IXDR_PUT_U_INT32(ptr, objp->share_deny);
3089
3090 /* xdr_open_owner4 */
3091 IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3092 IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3093 /* We know this is very short so don't bcopy */
3094 ip = (int32_t *)objp->owner.owner_val;
3095 len /= BYTES_PER_XDR_UNIT;
3096 for (i = 0; i < len; i++)
3097 *ptr++ = *ip++;
3098
3099 /* xdr_openflag4 */
3100 IXDR_PUT_U_INT32(ptr, objp->opentype);
3101 } else {
3102 op = OP_OPEN;
3103 if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3104 return (FALSE);
3105 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3106 return (FALSE);
3107 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3108 return (FALSE);
3109 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3110 return (FALSE);
3111
3112 /* xdr_open_owner4 */
3113 if (!xdr_u_longlong_t(xdrs,
3114 (u_longlong_t *)&objp->owner.clientid))
3115 return (FALSE);
3116 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3117 return (FALSE);
3118 if (!xdr_opaque(xdrs, objp->owner.owner_val,
3119 objp->owner.owner_len))
3120 return (FALSE);
3121
3122 /* xdr_openflag4 */
3123 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype))
3124 return (FALSE);
3125 }
3126
3127 if (objp->opentype == OPEN4_CREATE) {
3128 /* xdr_createhow4 */
3129 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode))
3130 return (FALSE);
3131 switch (objp->mode) {
3132 case UNCHECKED4:
3133 case GUARDED4:
3134 if (!xdr_fattr4(xdrs,
3135 &objp->createhow4_u.createattrs))
3136 return (FALSE);
3137 break;
3138 case EXCLUSIVE4:
3139 if (!xdr_u_longlong_t(xdrs,
3140 (u_longlong_t *)&objp->createhow4_u.
3141 createverf))
3142 return (FALSE);
3143 break;
3144 default:
3145 return (FALSE);
3146 }
3147 }
3148
3149 /* xdr_open_claim4 */
3150 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim))
3151 return (FALSE);
3152
3153 switch (objp->claim) {
3154 case CLAIM_NULL:
3155 len = strlen(objp->open_claim4_u.cfile);
3156 if (len > NFS4_MAX_UTF8STRING)
3157 return (FALSE);
3158 if (XDR_PUTINT32(xdrs, &len)) {
3159 return (xdr_opaque(xdrs,
3160 objp->open_claim4_u.cfile, len));
3161 }
3162 return (FALSE);
3163 case CLAIM_PREVIOUS:
3164 return (XDR_PUTINT32(xdrs,
3165 (int32_t *)&objp->open_claim4_u.delegate_type));
3166 case CLAIM_DELEGATE_CUR:
3167 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u.
3168 delegate_cur_info.delegate_stateid.seqid))
3169 return (FALSE);
3170 if (!xdr_opaque(xdrs, objp->open_claim4_u.
3171 delegate_cur_info.delegate_stateid.other,
3172 NFS4_OTHER_SIZE))
3173 return (FALSE);
3174 len = strlen(objp->open_claim4_u.delegate_cur_info.cfile);
3175 if (len > NFS4_MAX_UTF8STRING)
3176 return (FALSE);
3177 if (XDR_PUTINT32(xdrs, &len)) {
3178 return (xdr_opaque(xdrs,
3179 objp->open_claim4_u.delegate_cur_info.cfile,
3180 len));
3181 }
3182 return (FALSE);
3183 case CLAIM_DELEGATE_PREV:
3184 len = strlen(objp->open_claim4_u.cfile_delegate_prev);
3185 if (len > NFS4_MAX_UTF8STRING)
3186 return (FALSE);
3187 if (XDR_PUTINT32(xdrs, &len)) {
3188 return (xdr_opaque(xdrs,
3189 objp->open_claim4_u.cfile_delegate_prev, len));
3190 }
3191 return (FALSE);
3192 default:
3193 return (FALSE);
3194 }
3195 }
3196
3197 static bool_t
xdr_OPEN4res(XDR * xdrs,OPEN4res * objp)3198 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp)
3199 {
3200 if (xdrs->x_op != XDR_FREE) {
3201 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3202 return (FALSE);
3203 if (objp->status != NFS4_OK)
3204 return (TRUE);
3205 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3206 return (FALSE);
3207 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3208 return (FALSE);
3209 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3210 return (FALSE);
3211 if (!xdr_u_longlong_t(xdrs,
3212 (u_longlong_t *)&objp->cinfo.before))
3213 return (FALSE);
3214 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
3215 return (FALSE);
3216 if (!xdr_u_int(xdrs, &objp->rflags))
3217 return (FALSE);
3218 if (!xdr_bitmap4(xdrs, &objp->attrset))
3219 return (FALSE);
3220 if (!xdr_int(xdrs,
3221 (int *)&objp->delegation.delegation_type))
3222 return (FALSE);
3223 switch (objp->delegation.delegation_type) {
3224 case OPEN_DELEGATE_NONE:
3225 return (TRUE);
3226 case OPEN_DELEGATE_READ:
3227 if (!xdr_u_int(xdrs, &objp->delegation.
3228 open_delegation4_u.read.stateid.seqid))
3229 return (FALSE);
3230 if (!xdr_opaque(xdrs, objp->delegation.
3231 open_delegation4_u.read.stateid.other,
3232 NFS4_OTHER_SIZE))
3233 return (FALSE);
3234 if (!xdr_bool(xdrs, &objp->delegation.
3235 open_delegation4_u.read.recall))
3236 return (FALSE);
3237 return (xdr_nfsace4(xdrs, &objp->delegation.
3238 open_delegation4_u.read.permissions));
3239 case OPEN_DELEGATE_WRITE:
3240 if (!xdr_u_int(xdrs, &objp->delegation.
3241 open_delegation4_u.write.stateid.seqid))
3242 return (FALSE);
3243 if (!xdr_opaque(xdrs, objp->delegation.
3244 open_delegation4_u.write.stateid.other,
3245 NFS4_OTHER_SIZE))
3246 return (FALSE);
3247 if (!xdr_bool(xdrs, &objp->delegation.
3248 open_delegation4_u.write.recall))
3249 return (FALSE);
3250 if (!xdr_int(xdrs, (int *)&objp->delegation.
3251 open_delegation4_u.write.space_limit.
3252 limitby))
3253 return (FALSE);
3254 switch (objp->delegation.
3255 open_delegation4_u.write.space_limit.
3256 limitby) {
3257 case NFS_LIMIT_SIZE:
3258 if (!xdr_u_longlong_t(xdrs,
3259 (u_longlong_t *)&objp->delegation.
3260 open_delegation4_u.write.space_limit.
3261 nfs_space_limit4_u.filesize))
3262 return (FALSE);
3263 break;
3264 case NFS_LIMIT_BLOCKS:
3265 if (!xdr_u_int(xdrs,
3266 &objp->delegation.open_delegation4_u.write.
3267 space_limit.nfs_space_limit4_u.
3268 mod_blocks.num_blocks))
3269 return (FALSE);
3270 if (!xdr_u_int(xdrs, &objp->delegation.
3271 open_delegation4_u.write.space_limit.
3272 nfs_space_limit4_u.mod_blocks.
3273 bytes_per_block))
3274 return (FALSE);
3275 break;
3276 default:
3277 return (FALSE);
3278 }
3279 return (xdr_nfsace4(xdrs, &objp->delegation.
3280 open_delegation4_u.write.permissions));
3281 }
3282 return (FALSE);
3283 }
3284
3285 /*
3286 * Optimized free case
3287 */
3288 if (objp->status != NFS4_OK)
3289 return (TRUE);
3290
3291 switch (objp->delegation.delegation_type) {
3292 case OPEN_DELEGATE_NONE:
3293 return (TRUE);
3294 case OPEN_DELEGATE_READ:
3295 return (xdr_nfsace4(xdrs, &objp->delegation.
3296 open_delegation4_u.read.permissions));
3297 case OPEN_DELEGATE_WRITE:
3298 switch (objp->delegation.
3299 open_delegation4_u.write.space_limit.limitby) {
3300 case NFS_LIMIT_SIZE:
3301 case NFS_LIMIT_BLOCKS:
3302 break;
3303 default:
3304 return (FALSE);
3305 }
3306 return (xdr_nfsace4(xdrs, &objp->delegation.
3307 open_delegation4_u.write.permissions));
3308 }
3309 return (FALSE);
3310 }
3311
3312 static bool_t
xdr_OPEN_CONFIRM4res(XDR * xdrs,OPEN_CONFIRM4res * objp)3313 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp)
3314 {
3315 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3316 return (FALSE);
3317 if (objp->status != NFS4_OK)
3318 return (TRUE);
3319 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3320 return (FALSE);
3321 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3322 }
3323
3324 static bool_t
xdr_OPEN_DOWNGRADE4args(XDR * xdrs,OPEN_DOWNGRADE4args * objp)3325 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
3326 {
3327 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3328 return (FALSE);
3329 if (!xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE))
3330 return (FALSE);
3331 if (!xdr_u_int(xdrs, &objp->seqid))
3332 return (FALSE);
3333 if (!xdr_share_access(xdrs, &objp->share_access, &objp->deleg_want))
3334 return (FALSE);
3335 return (xdr_u_int(xdrs, &objp->share_deny));
3336 }
3337
3338 static bool_t
xdr_OPEN_DOWNGRADE4res(XDR * xdrs,OPEN_DOWNGRADE4res * objp)3339 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp)
3340 {
3341 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3342 return (FALSE);
3343 if (objp->status != NFS4_OK)
3344 return (TRUE);
3345 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3346 return (FALSE);
3347 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3348 }
3349
3350 static bool_t
xdr_READ4args(XDR * xdrs,READ4args * objp)3351 xdr_READ4args(XDR *xdrs, READ4args *objp)
3352 {
3353 rdma_chunkinfo_t rci;
3354 rdma_wlist_conn_info_t rwci;
3355 struct xdr_ops *xops = xdrrdma_xops();
3356
3357 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3358 return (FALSE);
3359 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3360 return (FALSE);
3361 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3362 return (FALSE);
3363 if (!xdr_u_int(xdrs, &objp->count))
3364 return (FALSE);
3365
3366 DTRACE_PROBE1(xdr__i__read4args_buf_len,
3367 int, objp->count);
3368
3369 objp->wlist = NULL;
3370
3371 if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
3372 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3373 rci.rci_len = objp->count;
3374 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3375 }
3376
3377 if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
3378 return (TRUE);
3379
3380 if (xdrs->x_op == XDR_ENCODE) {
3381 if (objp->res_uiop != NULL) {
3382 rci.rci_type = RCI_WRITE_UIO_CHUNK;
3383 rci.rci_a.rci_uiop = objp->res_uiop;
3384 rci.rci_len = objp->count;
3385 rci.rci_clpp = &objp->wlist;
3386 } else {
3387 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3388 rci.rci_a.rci_addr = objp->res_data_val_alt;
3389 rci.rci_len = objp->count;
3390 rci.rci_clpp = &objp->wlist;
3391 }
3392
3393 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
3394 }
3395
3396 /* XDR_DECODE case */
3397 (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
3398 objp->wlist = rwci.rwci_wlist;
3399 objp->conn = rwci.rwci_conn;
3400
3401 return (TRUE);
3402 }
3403
3404 static bool_t
xdr_READ4res(XDR * xdrs,READ4res * objp)3405 xdr_READ4res(XDR *xdrs, READ4res *objp)
3406 {
3407 mblk_t *mp;
3408
3409 if (xdrs->x_op == XDR_DECODE)
3410 return (FALSE);
3411
3412 if (xdrs->x_op == XDR_FREE) {
3413 /*
3414 * Optimized free case
3415 */
3416 if (objp->status != NFS4_OK)
3417 return (TRUE);
3418 if (objp->data_val != NULL)
3419 kmem_free(objp->data_val, objp->data_len);
3420 return (TRUE);
3421 }
3422
3423 /* on with ENCODE paths */
3424 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status))
3425 return (FALSE);
3426 if (objp->status != NFS4_OK)
3427 return (TRUE);
3428
3429 if (!XDR_PUTINT32(xdrs, &objp->eof))
3430 return (FALSE);
3431
3432 mp = objp->mblk;
3433 if (mp != NULL) {
3434 if (xdrs->x_ops == &xdrmblk_ops) {
3435 if (xdrmblk_putmblk(xdrs, mp, objp->data_len)) {
3436 objp->mblk = NULL;
3437 return (TRUE);
3438 } else {
3439 return (FALSE);
3440 }
3441 } else if (mp->b_cont != NULL) {
3442 /*
3443 * See xdr_READ3res() for an explanation of why we need
3444 * to do a pullup here.
3445 */
3446 if (pullupmsg(mp, -1) == 0)
3447 return (FALSE);
3448 objp->data_val = (caddr_t)mp->b_rptr;
3449 }
3450 } else {
3451 if (xdr_u_int(xdrs, &objp->data_len) == FALSE) {
3452 return (FALSE);
3453 }
3454 /*
3455 * If read data sent by wlist (RDMA_WRITE), don't do
3456 * xdr_bytes() below. RDMA_WRITE transfers the data.
3457 * Note: this is encode-only because the client code
3458 * uses xdr_READ4res_clnt to decode results.
3459 */
3460 if (objp->wlist) {
3461 if (objp->data_len != 0) {
3462 return (xdrrdma_send_read_data(
3463 xdrs, objp->data_len, objp->wlist));
3464 }
3465 return (TRUE);
3466 }
3467 }
3468
3469 return (xdr_bytes(xdrs, (char **)&objp->data_val,
3470 (uint_t *)&objp->data_len,
3471 objp->data_len));
3472 }
3473
3474 static bool_t
xdr_READ4res_clnt(XDR * xdrs,READ4res * objp,READ4args * aobjp)3475 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp)
3476 {
3477 mblk_t *mp;
3478 size_t n;
3479 int error;
3480 uint_t size = aobjp->res_maxsize;
3481 count4 ocount;
3482
3483 if (xdrs->x_op == XDR_ENCODE)
3484 return (FALSE);
3485
3486 if (xdrs->x_op == XDR_FREE) {
3487 /*
3488 * Optimized free case
3489 */
3490 if (objp->status != NFS4_OK)
3491 return (TRUE);
3492 if (objp->data_val != NULL)
3493 kmem_free(objp->data_val, objp->data_len);
3494 return (TRUE);
3495 }
3496
3497 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
3498 return (FALSE);
3499 if (objp->status != NFS4_OK)
3500 return (TRUE);
3501
3502 if (!XDR_GETINT32(xdrs, &objp->eof))
3503 return (FALSE);
3504
3505
3506 /*
3507 * This is a special case such that the caller is providing a
3508 * uio as a guide to eventual data location; this is used for
3509 * handling DIRECTIO reads.
3510 */
3511 if (aobjp->res_uiop != NULL) {
3512 struct uio *uiop = aobjp->res_uiop;
3513 int32_t *ptr;
3514
3515 if (xdrs->x_ops == &xdrmblk_ops) {
3516 if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len))
3517 return (FALSE);
3518
3519 if (objp->data_len == 0)
3520 return (TRUE);
3521
3522 if (objp->data_len > size)
3523 return (FALSE);
3524
3525 size = objp->data_len;
3526 do {
3527 n = MIN(size, mp->b_wptr - mp->b_rptr);
3528 if ((n = MIN(uiop->uio_resid, n)) != 0) {
3529
3530 error = uiomove((char *)mp->b_rptr, n,
3531 UIO_READ, uiop);
3532 if (error)
3533 return (FALSE);
3534 mp->b_rptr += n;
3535 size -= n;
3536 }
3537
3538 while (mp && (mp->b_rptr >= mp->b_wptr))
3539 mp = mp->b_cont;
3540 } while (mp && size > 0 && uiop->uio_resid > 0);
3541
3542 return (TRUE);
3543 }
3544
3545 if (xdrs->x_ops == &xdrrdma_ops) {
3546 struct clist *cl;
3547
3548 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3549
3550 objp->wlist = cl;
3551
3552 if (objp->wlist) {
3553 /* opaque count */
3554 if (!xdr_u_int(xdrs, &ocount)) {
3555 objp->wlist = NULL;
3556 return (FALSE);
3557 }
3558
3559 objp->wlist_len = clist_len(cl);
3560 objp->data_len = ocount;
3561
3562 if (objp->wlist_len !=
3563 roundup(
3564 objp->data_len, BYTES_PER_XDR_UNIT)) {
3565 DTRACE_PROBE2(
3566 xdr__e__read4resuio_clnt_fail,
3567 int, ocount,
3568 int, objp->data_len);
3569 objp->wlist = NULL;
3570 return (FALSE);
3571 }
3572
3573 uiop->uio_resid -= objp->data_len;
3574 uiop->uio_iov->iov_len -= objp->data_len;
3575 uiop->uio_iov->iov_base += objp->data_len;
3576 uiop->uio_loffset += objp->data_len;
3577
3578 objp->wlist = NULL;
3579 return (TRUE);
3580 }
3581 }
3582
3583 /*
3584 * This isn't an xdrmblk stream nor RDMA.
3585 * Handle the likely case that it can be
3586 * inlined (ex. xdrmem).
3587 */
3588 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len))
3589 return (FALSE);
3590
3591 if (objp->data_len == 0)
3592 return (TRUE);
3593
3594 if (objp->data_len > size)
3595 return (FALSE);
3596
3597 size = (int)objp->data_len;
3598 if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
3599 return (uiomove(ptr, size, UIO_READ, uiop) ?
3600 FALSE : TRUE);
3601
3602 /*
3603 * Handle some other (unlikely) stream type that will
3604 * need a copy.
3605 */
3606 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
3607 return (FALSE);
3608
3609 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
3610 kmem_free(ptr, size);
3611 return (FALSE);
3612 }
3613 error = uiomove(ptr, size, UIO_READ, uiop);
3614 kmem_free(ptr, size);
3615
3616 return (error ? FALSE : TRUE);
3617 }
3618
3619 /*
3620 * Check for the other special case of the caller providing
3621 * the target area for the data.
3622 */
3623 if (aobjp->res_data_val_alt == NULL)
3624 return (FALSE);
3625
3626 /*
3627 * If read data received via RDMA_WRITE, don't do xdr_bytes().
3628 * RDMA_WRITE already moved the data so decode length of
3629 * RDMA_WRITE.
3630 */
3631 if (xdrs->x_ops == &xdrrdma_ops) {
3632 struct clist *cl;
3633
3634 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3635
3636 objp->wlist = cl;
3637
3638 /*
3639 * Data transferred through inline if
3640 * objp->wlist == NULL
3641 */
3642 if (objp->wlist) {
3643 /* opaque count */
3644 if (!xdr_u_int(xdrs, &ocount)) {
3645 objp->wlist = NULL;
3646 return (FALSE);
3647 }
3648
3649 objp->wlist_len = clist_len(cl);
3650 objp->data_len = ocount;
3651
3652 if (objp->wlist_len !=
3653 roundup(
3654 objp->data_len, BYTES_PER_XDR_UNIT)) {
3655 DTRACE_PROBE2(
3656 xdr__e__read4res_clnt_fail,
3657 int, ocount,
3658 int, objp->data_len);
3659 objp->wlist = NULL;
3660 return (FALSE);
3661 }
3662
3663 objp->wlist = NULL;
3664 return (TRUE);
3665 }
3666 }
3667
3668 return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt,
3669 (uint_t *)&objp->data_len,
3670 aobjp->res_maxsize));
3671 }
3672
3673 static bool_t
xdr_READDIR4args(XDR * xdrs,READDIR4args * objp)3674 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp)
3675 {
3676 rdma_chunkinfo_t rci;
3677 struct xdr_ops *xops = xdrrdma_xops();
3678
3679 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
3680 xdrs->x_op == XDR_ENCODE) {
3681 rci.rci_type = RCI_REPLY_CHUNK;
3682 rci.rci_len = objp->maxcount;
3683 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3684 }
3685
3686 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie))
3687 return (FALSE);
3688 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
3689 return (FALSE);
3690 if (!xdr_u_int(xdrs, &objp->dircount))
3691 return (FALSE);
3692 if (!xdr_u_int(xdrs, &objp->maxcount))
3693 return (FALSE);
3694 return (xdr_bitmap4(xdrs, &objp->attr_request));
3695 }
3696
3697 bool_t
xdr_READDIR4res(XDR * xdrs,READDIR4res * objp)3698 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp)
3699 {
3700 mblk_t *mp = objp->mblk;
3701 bool_t ret_val;
3702 uint_t flags = 0;
3703
3704 ASSERT(xdrs->x_op == XDR_ENCODE);
3705
3706 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3707 return (FALSE);
3708 if (objp->status != NFS4_OK)
3709 return (TRUE);
3710 if (mp == NULL)
3711 return (FALSE);
3712
3713 if (xdrs->x_ops == &xdrmblk_ops) {
3714 if (xdrmblk_putmblk_raw(xdrs, mp)
3715 == TRUE) {
3716 /* mblk successfully inserted into outgoing chain */
3717 objp->mblk = NULL;
3718 return (TRUE);
3719 }
3720 }
3721
3722 ASSERT(mp->b_cont == NULL);
3723
3724 /*
3725 * If transport is RDMA, the pre-encoded m_blk needs to be moved
3726 * without being chunked.
3727 * Check if chunking is enabled for the xdr stream.
3728 * If it is enabled, disable it temporarily for this op,
3729 * then re-enable.
3730 */
3731 XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags);
3732
3733 if (!(flags & XDR_RDMA_CHUNK))
3734 return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len));
3735
3736 flags &= ~XDR_RDMA_CHUNK;
3737
3738 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3739
3740 ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len);
3741
3742 flags |= XDR_RDMA_CHUNK;
3743
3744 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3745
3746 return (ret_val);
3747 }
3748
3749 static bool_t
xdr_READLINK4res(XDR * xdrs,READLINK4res * objp)3750 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp)
3751 {
3752 if (xdrs->x_op != XDR_FREE) {
3753 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3754 return (FALSE);
3755 if (objp->status != NFS4_OK)
3756 return (TRUE);
3757 return (xdr_bytes(xdrs, (char **)&objp->link.linktext4_val,
3758 (uint_t *)&objp->link.linktext4_len,
3759 NFS4_MAX_UTF8STRING));
3760 }
3761
3762 /*
3763 * Optimized free case
3764 */
3765 if (objp->status != NFS4_OK)
3766 return (TRUE);
3767 if (objp->link.linktext4_val != NULL)
3768 kmem_free(objp->link.linktext4_val, objp->link.linktext4_len);
3769 return (TRUE);
3770 }
3771
3772 static bool_t
xdr_REMOVE4res(XDR * xdrs,REMOVE4res * objp)3773 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp)
3774 {
3775 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3776 return (FALSE);
3777 if (objp->status != NFS4_OK)
3778 return (TRUE);
3779 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3780 return (FALSE);
3781 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
3782 return (FALSE);
3783 return (xdr_u_longlong_t(xdrs,
3784 (u_longlong_t *)&objp->cinfo.after));
3785 }
3786
3787 static bool_t
xdr_RENAME4res(XDR * xdrs,RENAME4res * objp)3788 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp)
3789 {
3790 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3791 return (FALSE);
3792 if (objp->status != NFS4_OK)
3793 return (TRUE);
3794 if (!xdr_bool(xdrs, &objp->source_cinfo.atomic))
3795 return (FALSE);
3796 if (!xdr_u_longlong_t(xdrs,
3797 (u_longlong_t *)&objp->source_cinfo.before))
3798 return (FALSE);
3799 if (!xdr_u_longlong_t(xdrs,
3800 (u_longlong_t *)&objp->source_cinfo.after))
3801 return (FALSE);
3802 if (!xdr_bool(xdrs, &objp->target_cinfo.atomic))
3803 return (FALSE);
3804 if (!xdr_u_longlong_t(xdrs,
3805 (u_longlong_t *)&objp->target_cinfo.before))
3806 return (FALSE);
3807 return (xdr_u_longlong_t(xdrs,
3808 (u_longlong_t *)&objp->target_cinfo.after));
3809 }
3810
3811 static bool_t
xdr_secinfo4(XDR * xdrs,secinfo4 * objp)3812 xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
3813 {
3814 if (xdrs->x_op != XDR_FREE) {
3815 if (!xdr_u_int(xdrs, &objp->flavor))
3816 return (FALSE);
3817 if (objp->flavor != RPCSEC_GSS)
3818 return (TRUE);
3819 if (!xdr_bytes(xdrs,
3820 (char **)&objp->flavor_info.oid.sec_oid4_val,
3821 (uint_t *)&objp->flavor_info.oid.sec_oid4_len,
3822 NFS4_MAX_SECOID4))
3823 return (FALSE);
3824 if (!xdr_u_int(xdrs, &objp->flavor_info.qop))
3825 return (FALSE);
3826 return (xdr_int(xdrs, (int *)&objp->flavor_info.service));
3827 }
3828
3829 /*
3830 * Optimized free path
3831 */
3832 if (objp->flavor != RPCSEC_GSS)
3833 return (TRUE);
3834
3835 if (objp->flavor_info.oid.sec_oid4_val != NULL)
3836 kmem_free(objp->flavor_info.oid.sec_oid4_val,
3837 objp->flavor_info.oid.sec_oid4_len);
3838 return (TRUE);
3839 }
3840
3841 bool_t
xdr_SECINFO4res(XDR * xdrs,SECINFO4res * objp)3842 xdr_SECINFO4res(XDR *xdrs, SECINFO4res *objp)
3843 {
3844 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3845 return (FALSE);
3846 if (objp->status != NFS4_OK)
3847 return (TRUE);
3848 return (xdr_array(xdrs, (char **)&objp->SECINFO4resok_val,
3849 (uint_t *)&objp->SECINFO4resok_len, ~0, sizeof (secinfo4),
3850 (xdrproc_t)xdr_secinfo4));
3851 }
3852
3853 static bool_t
xdr_SETCLIENTID4args(XDR * xdrs,SETCLIENTID4args * objp)3854 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
3855 {
3856 if (xdrs->x_op != XDR_FREE) {
3857 if (!xdr_u_longlong_t(xdrs,
3858 (u_longlong_t *)&objp->client.verifier))
3859 return (FALSE);
3860 if (!xdr_bytes(xdrs, (char **)&objp->client.id_val,
3861 (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT))
3862 return (FALSE);
3863 if (!xdr_u_int(xdrs, &objp->callback.cb_program))
3864 return (FALSE);
3865 if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3866 NFS4_OPAQUE_LIMIT))
3867 return (FALSE);
3868 if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3869 NFS4_OPAQUE_LIMIT))
3870 return (FALSE);
3871 return (xdr_u_int(xdrs, &objp->callback_ident));
3872 }
3873
3874 /*
3875 * Optimized free case
3876 */
3877 if (objp->client.id_val != NULL)
3878 kmem_free(objp->client.id_val, objp->client.id_len);
3879 (void) xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3880 NFS4_OPAQUE_LIMIT);
3881 return (xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3882 NFS4_OPAQUE_LIMIT));
3883 }
3884
3885 static bool_t
xdr_SETCLIENTID4res(XDR * xdrs,SETCLIENTID4res * objp)3886 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp)
3887 {
3888 if (xdrs->x_op != XDR_FREE) {
3889 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3890 return (FALSE);
3891 switch (objp->status) {
3892 case NFS4_OK:
3893 if (!xdr_u_longlong_t(xdrs,
3894 (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4.
3895 clientid))
3896 return (FALSE);
3897 return (xdr_u_longlong_t(xdrs,
3898 (u_longlong_t *)&objp->SETCLIENTID4res_u.
3899 resok4.setclientid_confirm));
3900 case NFS4ERR_CLID_INUSE:
3901 if (!xdr_string(xdrs,
3902 &objp->SETCLIENTID4res_u.client_using.
3903 r_netid, NFS4_OPAQUE_LIMIT))
3904 return (FALSE);
3905 return (xdr_string(xdrs,
3906 &objp->SETCLIENTID4res_u.client_using.
3907 r_addr, NFS4_OPAQUE_LIMIT));
3908 }
3909 return (TRUE);
3910 }
3911
3912 /*
3913 * Optimized free case
3914 */
3915 if (objp->status != NFS4ERR_CLID_INUSE)
3916 return (TRUE);
3917
3918 if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid,
3919 NFS4_OPAQUE_LIMIT))
3920 return (FALSE);
3921 return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr,
3922 NFS4_OPAQUE_LIMIT));
3923 }
3924
3925 static bool_t
xdr_WRITE4args(XDR * xdrs,WRITE4args * objp)3926 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp)
3927 {
3928 if (xdrs->x_op != XDR_FREE) {
3929 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3930 return (FALSE);
3931 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3932 return (FALSE);
3933 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3934 return (FALSE);
3935 if (!xdr_int(xdrs, (int *)&objp->stable))
3936 return (FALSE);
3937 if (xdrs->x_op == XDR_DECODE) {
3938 if (xdrs->x_ops == &xdrmblk_ops) {
3939 objp->data_val = NULL;
3940 return (xdrmblk_getmblk(xdrs, &objp->mblk,
3941 &objp->data_len));
3942 }
3943 objp->mblk = NULL;
3944 if (xdrs->x_ops == &xdrrdmablk_ops) {
3945 int retval;
3946 retval = xdrrdma_getrdmablk(xdrs,
3947 &objp->rlist,
3948 &objp->data_len,
3949 &objp->conn, NFS4_DATA_LIMIT);
3950 if (retval == FALSE)
3951 return (FALSE);
3952 return (xdrrdma_read_from_client(objp->rlist,
3953 &objp->conn, objp->data_len));
3954 }
3955 }
3956 /* Else fall thru for the xdr_bytes(). */
3957 return (xdr_bytes(xdrs, (char **)&objp->data_val,
3958 (uint_t *)&objp->data_len, NFS4_DATA_LIMIT));
3959 }
3960 if (objp->rlist != NULL) {
3961 (void) xdrrdma_free_clist(objp->conn, objp->rlist);
3962 objp->rlist = NULL;
3963 objp->data_val = NULL;
3964
3965 return (TRUE);
3966 }
3967
3968 /*
3969 * Optimized free case
3970 */
3971 if (objp->data_val != NULL)
3972 kmem_free(objp->data_val, objp->data_len);
3973 return (TRUE);
3974 }
3975
3976 static bool_t
xdr_WRITE4res(XDR * xdrs,WRITE4res * objp)3977 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp)
3978 {
3979 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3980 return (FALSE);
3981 if (objp->status != NFS4_OK)
3982 return (TRUE);
3983 if (!xdr_u_int(xdrs, &objp->count))
3984 return (FALSE);
3985 if (!xdr_int(xdrs, (int *)&objp->committed))
3986 return (FALSE);
3987 return (xdr_u_longlong_t(xdrs,
3988 (u_longlong_t *)&objp->writeverf));
3989 }
3990
3991 static bool_t
xdr_snfs_argop4_free(XDR * xdrs,nfs_argop4 ** arrayp,int len)3992 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
3993 {
3994 int i;
3995 nfs_argop4 *array = *arrayp;
3996
3997 /*
3998 * Optimized XDR_FREE only args array
3999 */
4000 ASSERT(xdrs->x_op == XDR_FREE);
4001
4002 /*
4003 * Nothing to do?
4004 */
4005 if (array == NULL)
4006 return (TRUE);
4007
4008 for (i = 0; i < len; i++) {
4009 /* Freeing for nfs4.x */
4010 if (array[i].argop >= OP_BACKCHANNEL_CTL &&
4011 array[i].argop != OP_ILLEGAL) {
4012 xdr_nfs4x_argop4(xdrs, &array[i]);
4013 continue;
4014 }
4015
4016 /*
4017 * These should be ordered by frequency of use
4018 */
4019 switch (array[i].argop) {
4020 case OP_PUTFH: {
4021 nfs_fh4 *objp = &array[i].nfs_argop4_u.opputfh.object;
4022
4023 if (objp->nfs_fh4_val != NULL) {
4024 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
4025 }
4026 continue;
4027 }
4028 case OP_GETATTR:
4029 case OP_GETFH:
4030 continue;
4031 case OP_LOOKUP:
4032 if (array[i].nfs_argop4_u.oplookup.objname.
4033 utf8string_val != NULL) {
4034 kmem_free(array[i].nfs_argop4_u.oplookup.
4035 objname.utf8string_val,
4036 array[i].nfs_argop4_u.oplookup.
4037 objname.utf8string_len);
4038 }
4039 continue;
4040 case OP_OPEN:
4041 (void) xdr_OPEN4args(xdrs,
4042 &array[i].nfs_argop4_u.opopen);
4043 continue;
4044 case OP_CLOSE:
4045 case OP_ACCESS:
4046 case OP_READ:
4047 continue;
4048 case OP_WRITE:
4049 (void) xdr_WRITE4args(xdrs,
4050 &array[i].nfs_argop4_u.opwrite);
4051 continue;
4052 case OP_DELEGRETURN:
4053 case OP_LOOKUPP:
4054 case OP_READDIR:
4055 continue;
4056 case OP_REMOVE:
4057 if (array[i].nfs_argop4_u.opremove.target.
4058 utf8string_val != NULL) {
4059 kmem_free(array[i].nfs_argop4_u.opremove.target.
4060 utf8string_val,
4061 array[i].nfs_argop4_u.opremove.target.
4062 utf8string_len);
4063 }
4064 continue;
4065 case OP_COMMIT:
4066 continue;
4067 case OP_CREATE:
4068 (void) xdr_CREATE4args(xdrs,
4069 &array[i].nfs_argop4_u.opcreate);
4070 continue;
4071 case OP_DELEGPURGE:
4072 continue;
4073 case OP_LINK:
4074 if (array[i].nfs_argop4_u.oplink.newname.
4075 utf8string_val != NULL) {
4076 kmem_free(array[i].nfs_argop4_u.oplink.newname.
4077 utf8string_val,
4078 array[i].nfs_argop4_u.oplink.newname.
4079 utf8string_len);
4080 }
4081 continue;
4082 case OP_LOCK:
4083 (void) xdr_LOCK4args(xdrs,
4084 &array[i].nfs_argop4_u.oplock);
4085 continue;
4086 case OP_LOCKT:
4087 (void) xdr_LOCKT4args(xdrs,
4088 &array[i].nfs_argop4_u.oplockt);
4089 continue;
4090 case OP_LOCKU:
4091 continue;
4092 case OP_NVERIFY:
4093 (void) xdr_fattr4(xdrs,
4094 &array[i].nfs_argop4_u.opnverify.obj_attributes);
4095 continue;
4096 case OP_OPENATTR:
4097 case OP_OPEN_CONFIRM:
4098 case OP_OPEN_DOWNGRADE:
4099 case OP_PUTPUBFH:
4100 case OP_PUTROOTFH:
4101 case OP_READLINK:
4102 continue;
4103 case OP_RENAME:
4104 if (array[i].nfs_argop4_u.oprename.oldname.
4105 utf8string_val != NULL) {
4106 kmem_free(array[i].nfs_argop4_u.oprename.
4107 oldname.utf8string_val,
4108 array[i].nfs_argop4_u.oprename.
4109 oldname.utf8string_len);
4110 }
4111 if (array[i].nfs_argop4_u.oprename.newname.
4112 utf8string_val != NULL) {
4113 kmem_free(array[i].nfs_argop4_u.oprename.
4114 newname.utf8string_val,
4115 array[i].nfs_argop4_u.oprename.
4116 newname.utf8string_len);
4117 }
4118 continue;
4119 case OP_RENEW:
4120 case OP_RESTOREFH:
4121 case OP_SAVEFH:
4122 continue;
4123 case OP_SECINFO:
4124 if (array[i].nfs_argop4_u.opsecinfo.name.
4125 utf8string_val != NULL) {
4126 kmem_free(array[i].nfs_argop4_u.opsecinfo.name.
4127 utf8string_val,
4128 array[i].nfs_argop4_u.opsecinfo.name.
4129 utf8string_len);
4130 }
4131 continue;
4132 case OP_SETATTR:
4133 (void) xdr_fattr4(xdrs,
4134 &array[i].nfs_argop4_u.opsetattr.obj_attributes);
4135 continue;
4136 case OP_SETCLIENTID:
4137 (void) xdr_SETCLIENTID4args(xdrs,
4138 &array[i].nfs_argop4_u.opsetclientid);
4139 continue;
4140 case OP_SETCLIENTID_CONFIRM:
4141 continue;
4142 case OP_VERIFY:
4143 (void) xdr_fattr4(xdrs,
4144 &array[i].nfs_argop4_u.opverify.obj_attributes);
4145 continue;
4146 case OP_RELEASE_LOCKOWNER:
4147 if (array[i].nfs_argop4_u.oprelease_lockowner.
4148 lock_owner.owner_val != NULL) {
4149 kmem_free(array[i].nfs_argop4_u.
4150 oprelease_lockowner.lock_owner.owner_val,
4151 array[i].nfs_argop4_u.
4152 oprelease_lockowner.lock_owner.owner_len);
4153 }
4154 continue;
4155 case OP_ILLEGAL:
4156 continue;
4157 default:
4158 /*
4159 * An invalid op is a coding error, it should never
4160 * have been decoded.
4161 * Don't error because the caller cannot finish
4162 * freeing the residual memory of the array.
4163 */
4164 continue;
4165 }
4166 }
4167
4168 kmem_free(*arrayp, len * sizeof (nfs_argop4));
4169 *arrayp = NULL;
4170 return (TRUE);
4171 }
4172
4173 static bool_t
xdr_nfs_argop4(XDR * xdrs,nfs_argop4 * objp)4174 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4175 {
4176 rdma_chunkinfo_t rci;
4177 struct xdr_ops *xops = xdrrdma_xops();
4178
4179 /*
4180 * These should be ordered by frequency of use
4181 */
4182 switch (objp->argop) {
4183 case OP_PUTFH:
4184 return (xdr_bytes(xdrs,
4185 (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val,
4186 (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len,
4187 NFS4_FHSIZE));
4188 case OP_GETATTR:
4189 /*
4190 * ACLs can become relatively large ( > 8K) and the default
4191 * 8K reply chunk of RDMA may not suffice. Check for
4192 * get ACL bit and if it's RDMA, add a chunk equal the size
4193 * of the transfer size to the reply chunk list.
4194 */
4195 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4196 (xdrs->x_op == XDR_ENCODE) &&
4197 (objp->nfs_argop4_u.opgetattr.attr_request &
4198 FATTR4_ACL_MASK)) {
4199 rci.rci_type = RCI_REPLY_CHUNK;
4200 rci.rci_len = objp->nfs_argop4_u.opgetattr.mi->mi_tsize;
4201 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4202
4203 DTRACE_PROBE1(xdr__i__argop4__getattr, int,
4204 rci.rci_len);
4205 }
4206 return (xdr_bitmap4(xdrs,
4207 &objp->nfs_argop4_u.opgetattr.attr_request));
4208 case OP_GETFH:
4209 return (TRUE);
4210 case OP_LOOKUP:
4211 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup.
4212 objname.utf8string_val,
4213 (uint_t *)&objp->nfs_argop4_u.oplookup.
4214 objname.utf8string_len,
4215 NFS4_MAX_UTF8STRING));
4216 case OP_OPEN:
4217 return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen));
4218 case OP_CLOSE:
4219 return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose));
4220 case OP_ACCESS:
4221 return (xdr_u_int(xdrs,
4222 &objp->nfs_argop4_u.opaccess.access));
4223 case OP_READ:
4224 return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread));
4225 case OP_WRITE:
4226 return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite));
4227 case OP_DELEGRETURN:
4228 if (!xdr_u_int(xdrs,
4229 &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid))
4230 return (FALSE);
4231 return (xdr_opaque(xdrs,
4232 objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other,
4233 NFS4_OTHER_SIZE));
4234 case OP_LOOKUPP:
4235 return (TRUE);
4236 case OP_READDIR:
4237 return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir));
4238 case OP_REMOVE:
4239 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove.
4240 target.utf8string_val,
4241 (uint_t *)&objp->nfs_argop4_u.opremove.
4242 target.utf8string_len,
4243 NFS4_MAX_UTF8STRING));
4244 case OP_COMMIT:
4245 if (!xdr_u_longlong_t(xdrs,
4246 (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset))
4247 return (FALSE);
4248 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count));
4249 case OP_CREATE:
4250 return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate));
4251 case OP_DELEGPURGE:
4252 return (xdr_u_longlong_t(xdrs,
4253 (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid));
4254 case OP_LINK:
4255 return (xdr_bytes(xdrs,
4256 (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val,
4257 (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len,
4258 NFS4_MAX_UTF8STRING));
4259 case OP_LOCK:
4260 return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock));
4261 case OP_LOCKT:
4262 return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt));
4263 case OP_LOCKU:
4264 return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku));
4265 case OP_NVERIFY:
4266 return (xdr_fattr4(xdrs,
4267 &objp->nfs_argop4_u.opnverify.obj_attributes));
4268 case OP_OPENATTR:
4269 return (xdr_bool(xdrs,
4270 &objp->nfs_argop4_u.opopenattr.createdir));
4271 case OP_OPEN_CONFIRM:
4272 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4273 open_stateid.seqid))
4274 return (FALSE);
4275 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm.
4276 open_stateid.other, NFS4_OTHER_SIZE))
4277 return (FALSE);
4278 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4279 seqid));
4280 case OP_OPEN_DOWNGRADE:
4281 return (xdr_OPEN_DOWNGRADE4args(xdrs,
4282 &objp->nfs_argop4_u.opopen_downgrade));
4283 case OP_PUTPUBFH:
4284 return (TRUE);
4285 case OP_PUTROOTFH:
4286 return (TRUE);
4287 case OP_READLINK:
4288 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4289 xdrs->x_op == XDR_ENCODE) {
4290 rci.rci_type = RCI_REPLY_CHUNK;
4291 rci.rci_len = MAXPATHLEN;
4292 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4293 }
4294 return (TRUE);
4295 case OP_RENAME:
4296 if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4297 oldname.utf8string_val,
4298 (uint_t *)&objp->nfs_argop4_u.oprename.
4299 oldname.utf8string_len,
4300 NFS4_MAX_UTF8STRING))
4301 return (FALSE);
4302 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4303 newname.utf8string_val,
4304 (uint_t *)&objp->nfs_argop4_u.oprename.
4305 newname.utf8string_len,
4306 NFS4_MAX_UTF8STRING));
4307 case OP_RENEW:
4308 return (xdr_u_longlong_t(xdrs,
4309 (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid));
4310 case OP_RESTOREFH:
4311 return (TRUE);
4312 case OP_SAVEFH:
4313 return (TRUE);
4314 case OP_SECINFO:
4315 return (xdr_bytes(xdrs,
4316 (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val,
4317 (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len,
4318 NFS4_MAX_UTF8STRING));
4319 case OP_SETATTR:
4320 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr.
4321 stateid.seqid))
4322 return (FALSE);
4323 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr.
4324 stateid.other, NFS4_OTHER_SIZE))
4325 return (FALSE);
4326 return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr.
4327 obj_attributes));
4328 case OP_SETCLIENTID:
4329 return (xdr_SETCLIENTID4args(xdrs,
4330 &objp->nfs_argop4_u.opsetclientid));
4331 case OP_SETCLIENTID_CONFIRM:
4332 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u.
4333 opsetclientid_confirm.clientid))
4334 return (FALSE);
4335 return (xdr_u_longlong_t(xdrs,
4336 (u_longlong_t *)&objp->nfs_argop4_u.
4337 opsetclientid_confirm.setclientid_confirm));
4338 case OP_VERIFY:
4339 return (xdr_fattr4(xdrs,
4340 &objp->nfs_argop4_u.opverify.obj_attributes));
4341 case OP_RELEASE_LOCKOWNER:
4342 if (!xdr_u_longlong_t(xdrs,
4343 (u_longlong_t *)&objp->nfs_argop4_u.
4344 oprelease_lockowner.lock_owner.clientid))
4345 return (FALSE);
4346 return (xdr_bytes(xdrs,
4347 (char **)&objp->nfs_argop4_u.oprelease_lockowner.
4348 lock_owner.owner_val,
4349 (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner.
4350 lock_owner.owner_len, NFS4_OPAQUE_LIMIT));
4351 case OP_ILLEGAL:
4352 return (TRUE);
4353 }
4354 return (FALSE);
4355 }
4356
4357 static bool_t
xdr_cnfs_argop4_wrap(XDR * xdrs,nfs_argop4 * objp)4358 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp)
4359 {
4360 if (!xdr_int(xdrs, (int *)&objp->argop))
4361 return (FALSE);
4362
4363 return (xdr_nfs_argop4(xdrs, objp));
4364 }
4365
4366 static bool_t
xdr_snfs_argop4(XDR * xdrs,nfs_argop4 * objp)4367 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4368 {
4369 if (!xdr_int(xdrs, (int *)&objp->argop))
4370 return (FALSE);
4371
4372 switch (objp->argop) {
4373 case OP_PUTFH:
4374 return (xdr_decode_nfs_fh4(xdrs,
4375 &objp->nfs_argop4_u.opputfh.object));
4376 default:
4377 if (objp->argop >= OP_BACKCHANNEL_CTL &&
4378 objp->argop != OP_ILLEGAL)
4379 return (xdr_nfs4x_argop4(xdrs, objp));
4380
4381 return (xdr_nfs_argop4(xdrs, objp));
4382 }
4383 }
4384
4385 /*
4386 * Client side encode only arg op processing
4387 */
4388 static bool_t
xdr_cnfs_argop4(XDR * xdrs,nfs_argop4 * objp)4389 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4390 {
4391 int len;
4392 int op;
4393 nfs4_sharedfh_t *sfh;
4394 mntinfo4_t *mi;
4395 rpc_inline_t *ptr;
4396
4397 ASSERT(xdrs->x_op == XDR_ENCODE);
4398
4399 /*
4400 * Special case the private pseudo ops
4401 */
4402 if (!(objp->argop & SUNW_PRIVATE_OP))
4403 return (xdr_cnfs_argop4_wrap(xdrs, objp));
4404
4405 /*
4406 * These should be ordered by frequency of use
4407 */
4408 switch (objp->argop) {
4409 case OP_CPUTFH:
4410 /*
4411 * We are passed in the file handle as a nfs4_sharedfh_t *
4412 * We need to acquire the correct locks so we can copy it out.
4413 */
4414 sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh;
4415 mi = sfh->sfh_mi;
4416 (void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0);
4417
4418 len = sfh->sfh_fh.nfs_fh4_len;
4419 ASSERT(len <= NFS4_FHSIZE);
4420
4421 /*
4422 * First try and inline the copy
4423 * Must first be a multiple of BYTES_PER_XDR_UNIT
4424 */
4425 if (!(len % BYTES_PER_XDR_UNIT) &&
4426 (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) !=
4427 NULL) {
4428 IXDR_PUT_U_INT32(ptr, OP_PUTFH);
4429 IXDR_PUT_U_INT32(ptr, len);
4430 bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len);
4431 nfs_rw_exit(&mi->mi_fh_lock);
4432 return (TRUE);
4433 }
4434
4435 op = OP_PUTFH;
4436 if (!XDR_PUTINT32(xdrs, &op)) {
4437 nfs_rw_exit(&mi->mi_fh_lock);
4438 return (FALSE);
4439 }
4440 if (!XDR_PUTINT32(xdrs, &len)) {
4441 nfs_rw_exit(&mi->mi_fh_lock);
4442 return (FALSE);
4443 }
4444 if (!(len % BYTES_PER_XDR_UNIT)) {
4445 if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4446 nfs_rw_exit(&mi->mi_fh_lock);
4447 return (TRUE);
4448 }
4449 } else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4450 nfs_rw_exit(&mi->mi_fh_lock);
4451 return (TRUE);
4452 }
4453 nfs_rw_exit(&mi->mi_fh_lock);
4454 return (FALSE);
4455 case OP_CLOOKUP:
4456 len = strlen(objp->nfs_argop4_u.opclookup.cname);
4457 if (len > NFS4_MAX_UTF8STRING)
4458 return (FALSE);
4459 op = OP_LOOKUP;
4460 if (XDR_PUTINT32(xdrs, &op)) {
4461 if (XDR_PUTINT32(xdrs, &len)) {
4462 return (xdr_opaque(xdrs,
4463 objp->nfs_argop4_u.opclookup.cname,
4464 len));
4465 }
4466 }
4467 return (FALSE);
4468 case OP_COPEN:
4469 /* op processing inlined in xdr_OPEN4cargs */
4470 return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen));
4471 case OP_CREMOVE:
4472 len = strlen(objp->nfs_argop4_u.opcremove.ctarget);
4473 if (len > NFS4_MAX_UTF8STRING)
4474 return (FALSE);
4475 op = OP_REMOVE;
4476 if (XDR_PUTINT32(xdrs, &op)) {
4477 if (XDR_PUTINT32(xdrs, &len)) {
4478 return (xdr_opaque(xdrs,
4479 objp->nfs_argop4_u.opcremove.ctarget,
4480 len));
4481 }
4482 }
4483 return (FALSE);
4484 case OP_CCREATE:
4485 op = OP_CREATE;
4486 if (!XDR_PUTINT32(xdrs, &op))
4487 return (FALSE);
4488 return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate));
4489 case OP_CLINK:
4490 len = strlen(objp->nfs_argop4_u.opclink.cnewname);
4491 if (len > NFS4_MAX_UTF8STRING)
4492 return (FALSE);
4493 op = OP_LINK;
4494 if (XDR_PUTINT32(xdrs, &op)) {
4495 if (XDR_PUTINT32(xdrs, &len)) {
4496 return (xdr_opaque(xdrs,
4497 objp->nfs_argop4_u.opclink.cnewname,
4498 len));
4499 }
4500 }
4501 return (FALSE);
4502 case OP_CRENAME:
4503 len = strlen(objp->nfs_argop4_u.opcrename.coldname);
4504 if (len > NFS4_MAX_UTF8STRING)
4505 return (FALSE);
4506 op = OP_RENAME;
4507 if (!XDR_PUTINT32(xdrs, &op))
4508 return (FALSE);
4509 if (!XDR_PUTINT32(xdrs, &len))
4510 return (FALSE);
4511 if (!xdr_opaque(xdrs,
4512 objp->nfs_argop4_u.opcrename.coldname, len))
4513 return (FALSE);
4514 len = strlen(objp->nfs_argop4_u.opcrename.cnewname);
4515 if (len > NFS4_MAX_UTF8STRING)
4516 return (FALSE);
4517 if (XDR_PUTINT32(xdrs, &len)) {
4518 return (xdr_opaque(xdrs,
4519 objp->nfs_argop4_u.opcrename.cnewname, len));
4520 }
4521 return (FALSE);
4522 case OP_CSECINFO:
4523 len = strlen(objp->nfs_argop4_u.opcsecinfo.cname);
4524 if (len > NFS4_MAX_UTF8STRING)
4525 return (FALSE);
4526 op = OP_SECINFO;
4527 if (XDR_PUTINT32(xdrs, &op)) {
4528 if (XDR_PUTINT32(xdrs, &len)) {
4529 return (xdr_opaque(xdrs,
4530 objp->nfs_argop4_u.opcsecinfo.cname,
4531 len));
4532 }
4533 }
4534 return (FALSE);
4535 }
4536 return (FALSE);
4537 }
4538
4539 /*
4540 * Note that the len and decode_len will only be different in the case
4541 * of the client's use of this free function. If the server is
4542 * freeing results, then the len/decode_len will always match.
4543 */
4544 static bool_t
xdr_nfs_resop4_free(XDR * xdrs,nfs_resop4 ** arrayp,int len,int decode_len)4545 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4546 {
4547 int i;
4548 nfs_resop4 *array = *arrayp;
4549 nfs4_ga_res_t *gr;
4550
4551 /*
4552 * Optimized XDR_FREE only results array
4553 */
4554 ASSERT(xdrs->x_op == XDR_FREE);
4555
4556 if (array == NULL)
4557 return (TRUE);
4558
4559 for (i = 0; i < decode_len; i++) {
4560 /*
4561 * These should be ordered by frequency of use
4562 */
4563 switch (array[i].resop) {
4564 case OP_PUTFH:
4565 continue;
4566 case OP_GETATTR:
4567 if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK)
4568 continue;
4569
4570 gr = &array[i].nfs_resop4_u.opgetattr.ga_res;
4571 if (gr->n4g_ext_res) {
4572 if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK)
4573 (void) xdr_fattr4_fs_locations(xdrs,
4574 &gr->n4g_ext_res->n4g_fslocations);
4575 kmem_free(gr->n4g_ext_res,
4576 sizeof (struct nfs4_ga_ext_res));
4577 }
4578 continue;
4579 case OP_GETFH:
4580 if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK)
4581 continue;
4582 if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val !=
4583 NULL) {
4584 kmem_free(array[i].nfs_resop4_u.opgetfh.object.
4585 nfs_fh4_val,
4586 array[i].nfs_resop4_u.opgetfh.object.
4587 nfs_fh4_len);
4588 }
4589 continue;
4590 case OP_LOOKUP:
4591 continue;
4592 case OP_OPEN:
4593 (void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u.
4594 opopen);
4595 continue;
4596 case OP_CLOSE:
4597 case OP_ACCESS:
4598 continue;
4599 case OP_READ:
4600 (void) xdr_READ4res(xdrs,
4601 &array[i].nfs_resop4_u.opread);
4602 continue;
4603 case OP_WRITE:
4604 case OP_DELEGRETURN:
4605 case OP_LOOKUPP:
4606 case OP_READDIR:
4607 case OP_REMOVE:
4608 case OP_COMMIT:
4609 case OP_CREATE:
4610 case OP_DELEGPURGE:
4611 case OP_LINK:
4612 continue;
4613 case OP_LOCK:
4614 (void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u.
4615 oplock);
4616 continue;
4617 case OP_LOCKT:
4618 (void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u.
4619 oplockt);
4620 continue;
4621 case OP_LOCKU:
4622 case OP_NVERIFY:
4623 case OP_OPENATTR:
4624 case OP_OPEN_CONFIRM:
4625 case OP_OPEN_DOWNGRADE:
4626 case OP_PUTPUBFH:
4627 case OP_PUTROOTFH:
4628 case OP_RENAME:
4629 case OP_RENEW:
4630 case OP_RESTOREFH:
4631 case OP_SAVEFH:
4632 continue;
4633 case OP_READLINK:
4634 (void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u.
4635 opreadlink);
4636 continue;
4637 case OP_SECINFO:
4638 (void) xdr_array(xdrs,
4639 (char **)&array[i].nfs_resop4_u.opsecinfo.
4640 SECINFO4resok_val,
4641 (uint_t *)&array[i].nfs_resop4_u.opsecinfo.
4642 SECINFO4resok_len,
4643 NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4644 (xdrproc_t)xdr_secinfo4);
4645 continue;
4646 case OP_SETCLIENTID:
4647 (void) xdr_SETCLIENTID4res(xdrs,
4648 &array[i].nfs_resop4_u.opsetclientid);
4649 continue;
4650 case OP_SETATTR:
4651 case OP_SETCLIENTID_CONFIRM:
4652 case OP_VERIFY:
4653 case OP_RELEASE_LOCKOWNER:
4654 case OP_ILLEGAL:
4655 continue;
4656 default:
4657 /*
4658 * An invalid op is a coding error, it should never
4659 * have been decoded.
4660 * Don't error because the caller cannot finish
4661 * freeing the residual memory of the array.
4662 */
4663 continue;
4664 }
4665 }
4666
4667 kmem_free(*arrayp, len * sizeof (nfs_resop4));
4668 *arrayp = NULL;
4669 return (TRUE);
4670 }
4671
4672 static bool_t
xdr_snfs_resop4_free(XDR * xdrs,nfs_resop4 ** arrayp,int len,int decode_len)4673 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4674 {
4675 return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len));
4676 }
4677
4678 static bool_t
xdr_nfs_resop4(XDR * xdrs,nfs_resop4 * objp)4679 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4680 {
4681 /*
4682 * These should be ordered by frequency of use
4683 */
4684 switch (objp->resop) {
4685 case OP_PUTFH:
4686 return (xdr_int(xdrs,
4687 (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4688 case OP_GETATTR:
4689 if (!xdr_int(xdrs,
4690 (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4691 return (FALSE);
4692 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4693 return (TRUE);
4694 return (xdr_fattr4(xdrs,
4695 &objp->nfs_resop4_u.opgetattr.obj_attributes));
4696 case OP_GETFH:
4697 if (!xdr_int(xdrs,
4698 (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4699 return (FALSE);
4700 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4701 return (TRUE);
4702 return (xdr_bytes(xdrs,
4703 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4704 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4705 NFS4_FHSIZE));
4706 case OP_LOOKUP:
4707 return (xdr_int(xdrs,
4708 (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4709 case OP_OPEN:
4710 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4711 case OP_CLOSE:
4712 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4713 case OP_ACCESS:
4714 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4715 case OP_READ:
4716 return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread));
4717 case OP_WRITE:
4718 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4719 case OP_DELEGRETURN:
4720 return (xdr_int(xdrs,
4721 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4722 case OP_LOOKUPP:
4723 return (xdr_int(xdrs,
4724 (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4725 case OP_READDIR:
4726 return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir));
4727 case OP_REMOVE:
4728 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4729
4730 case OP_COMMIT:
4731 if (!xdr_int(xdrs,
4732 (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4733 return (FALSE);
4734 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4735 return (TRUE);
4736 return (xdr_u_longlong_t(xdrs,
4737 (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4738 writeverf));
4739 case OP_CREATE:
4740 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4741 case OP_DELEGPURGE:
4742 return (xdr_int(xdrs,
4743 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4744 case OP_LINK:
4745 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4746 case OP_LOCK:
4747 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4748 case OP_LOCKT:
4749 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4750 case OP_LOCKU:
4751 if (!xdr_int(xdrs,
4752 (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4753 return (FALSE);
4754 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4755 return (TRUE);
4756 if (!xdr_u_int(xdrs,
4757 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4758 return (FALSE);
4759 return (xdr_opaque(xdrs,
4760 objp->nfs_resop4_u.oplocku.lock_stateid.other,
4761 NFS4_OTHER_SIZE));
4762 case OP_NVERIFY:
4763 return (xdr_int(xdrs,
4764 (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4765 case OP_OPENATTR:
4766 return (xdr_int(xdrs,
4767 (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4768 case OP_OPEN_CONFIRM:
4769 return (xdr_OPEN_CONFIRM4res(xdrs,
4770 &objp->nfs_resop4_u.opopen_confirm));
4771 case OP_OPEN_DOWNGRADE:
4772 return (xdr_OPEN_DOWNGRADE4res(xdrs,
4773 &objp->nfs_resop4_u.opopen_downgrade));
4774 case OP_PUTPUBFH:
4775 return (xdr_int(xdrs,
4776 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4777 case OP_PUTROOTFH:
4778 return (xdr_int(xdrs,
4779 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4780 case OP_READLINK:
4781 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4782 case OP_RENAME:
4783 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4784 case OP_RENEW:
4785 return (xdr_int(xdrs,
4786 (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4787 case OP_RESTOREFH:
4788 return (xdr_int(xdrs,
4789 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4790 case OP_SAVEFH:
4791 return (xdr_int(xdrs,
4792 (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4793 case OP_SECINFO:
4794 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4795 status))
4796 return (FALSE);
4797 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4798 return (TRUE);
4799 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4800 SECINFO4resok_val,
4801 (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4802 SECINFO4resok_len,
4803 NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4804 (xdrproc_t)xdr_secinfo4));
4805 case OP_SETATTR:
4806 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4807 status))
4808 return (FALSE);
4809 return (xdr_bitmap4(xdrs,
4810 &objp->nfs_resop4_u.opsetattr.attrsset));
4811 case OP_SETCLIENTID:
4812 return (xdr_SETCLIENTID4res(xdrs,
4813 &objp->nfs_resop4_u.opsetclientid));
4814 case OP_SETCLIENTID_CONFIRM:
4815 return (xdr_int(xdrs,
4816 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4817 status));
4818 case OP_VERIFY:
4819 return (xdr_int(xdrs,
4820 (int32_t *)&objp->nfs_resop4_u.opverify.status));
4821 case OP_RELEASE_LOCKOWNER:
4822 return (xdr_int(xdrs,
4823 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4824 case OP_ILLEGAL:
4825 return (xdr_int(xdrs,
4826 (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4827 }
4828 return (FALSE);
4829 }
4830
4831 static bool_t
xdr_snfs_resop4(XDR * xdrs,nfs_resop4 * objp)4832 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4833 {
4834 if (!xdr_int(xdrs, (int *)&objp->resop))
4835 return (FALSE);
4836
4837 switch (objp->resop) {
4838 case OP_GETFH:
4839 if (!XDR_PUTINT32(xdrs,
4840 (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4841 return (FALSE);
4842 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4843 return (TRUE);
4844 return (xdr_encode_nfs_fh4(xdrs,
4845 &objp->nfs_resop4_u.opgetfh.object));
4846 default:
4847 if (objp->resop >= OP_BACKCHANNEL_CTL &&
4848 objp->resop != OP_ILLEGAL)
4849 return (xdr_nfs4x_resop4(xdrs, objp));
4850
4851 return (xdr_nfs_resop4(xdrs, objp));
4852 }
4853 }
4854
4855 static bool_t
xdr_nfs_resop4_clnt(XDR * xdrs,nfs_resop4 * objp,nfs_argop4 * aobjp)4856 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp)
4857 {
4858 if (!xdr_int(xdrs, (int *)&objp->resop))
4859 return (FALSE);
4860 /*
4861 * These should be ordered by frequency of use
4862 */
4863 switch (objp->resop) {
4864 case OP_PUTFH:
4865 return (xdr_int(xdrs,
4866 (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4867 case OP_GETATTR:
4868 if (!xdr_int(xdrs,
4869 (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4870 return (FALSE);
4871 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4872 return (TRUE);
4873 return (xdr_ga_res(xdrs,
4874 (GETATTR4res *)&objp->nfs_resop4_u.opgetattr,
4875 &aobjp->nfs_argop4_u.opgetattr));
4876 case OP_GETFH:
4877 if (!xdr_int(xdrs,
4878 (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4879 return (FALSE);
4880 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4881 return (TRUE);
4882 return (xdr_bytes(xdrs,
4883 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4884 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4885 NFS4_FHSIZE));
4886 case OP_LOOKUP:
4887 return (xdr_int(xdrs,
4888 (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4889 case OP_NVERIFY:
4890 return (xdr_int(xdrs,
4891 (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4892 case OP_OPEN:
4893 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4894 case OP_CLOSE:
4895 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4896 case OP_ACCESS:
4897 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4898 case OP_READ:
4899 return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread,
4900 &aobjp->nfs_argop4_u.opread));
4901 case OP_WRITE:
4902 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4903 case OP_DELEGRETURN:
4904 return (xdr_int(xdrs,
4905 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4906 case OP_LOOKUPP:
4907 return (xdr_int(xdrs,
4908 (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4909 case OP_READDIR:
4910 return (xdr_READDIR4res_clnt(xdrs,
4911 &objp->nfs_resop4_u.opreaddirclnt,
4912 &aobjp->nfs_argop4_u.opreaddir));
4913 case OP_REMOVE:
4914 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4915
4916 case OP_COMMIT:
4917 if (!xdr_int(xdrs,
4918 (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4919 return (FALSE);
4920 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4921 return (TRUE);
4922 return (xdr_u_longlong_t(xdrs,
4923 (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4924 writeverf));
4925 case OP_CREATE:
4926 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4927 case OP_DELEGPURGE:
4928 return (xdr_int(xdrs,
4929 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4930 case OP_LINK:
4931 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4932 case OP_LOCK:
4933 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4934 case OP_LOCKT:
4935 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4936 case OP_LOCKU:
4937 if (!xdr_int(xdrs,
4938 (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4939 return (FALSE);
4940 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4941 return (TRUE);
4942 if (!xdr_u_int(xdrs,
4943 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4944 return (FALSE);
4945 return (xdr_opaque(xdrs,
4946 objp->nfs_resop4_u.oplocku.lock_stateid.other,
4947 NFS4_OTHER_SIZE));
4948 case OP_OPENATTR:
4949 return (xdr_int(xdrs,
4950 (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4951 case OP_OPEN_CONFIRM:
4952 return (xdr_OPEN_CONFIRM4res(xdrs,
4953 &objp->nfs_resop4_u.opopen_confirm));
4954 case OP_OPEN_DOWNGRADE:
4955 return (xdr_OPEN_DOWNGRADE4res(xdrs,
4956 &objp->nfs_resop4_u.opopen_downgrade));
4957 case OP_PUTPUBFH:
4958 return (xdr_int(xdrs,
4959 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4960 case OP_PUTROOTFH:
4961 return (xdr_int(xdrs,
4962 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4963 case OP_READLINK:
4964 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4965 case OP_RENAME:
4966 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4967 case OP_RENEW:
4968 return (xdr_int(xdrs,
4969 (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4970 case OP_RESTOREFH:
4971 return (xdr_int(xdrs,
4972 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4973 case OP_SAVEFH:
4974 return (xdr_int(xdrs,
4975 (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4976 case OP_SECINFO:
4977 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4978 status))
4979 return (FALSE);
4980 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4981 return (TRUE);
4982 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4983 SECINFO4resok_val,
4984 (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4985 SECINFO4resok_len,
4986 ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4));
4987 case OP_SETATTR:
4988 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4989 status))
4990 return (FALSE);
4991 return (xdr_bitmap4(xdrs,
4992 &objp->nfs_resop4_u.opsetattr.attrsset));
4993 case OP_SETCLIENTID:
4994 return (xdr_SETCLIENTID4res(xdrs,
4995 &objp->nfs_resop4_u.opsetclientid));
4996 case OP_SETCLIENTID_CONFIRM:
4997 return (xdr_int(xdrs,
4998 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4999 status));
5000 case OP_VERIFY:
5001 return (xdr_int(xdrs,
5002 (int32_t *)&objp->nfs_resop4_u.opverify.status));
5003 case OP_RELEASE_LOCKOWNER:
5004 return (xdr_int(xdrs,
5005 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
5006 case OP_ILLEGAL:
5007 return (xdr_int(xdrs,
5008 (int32_t *)&objp->nfs_resop4_u.opillegal.status));
5009 }
5010 return (FALSE);
5011 }
5012
5013 bool_t
xdr_COMPOUND4args_clnt(XDR * xdrs,COMPOUND4args_clnt * objp)5014 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp)
5015 {
5016 static int32_t twelve = 12;
5017 static int32_t minorversion = NFS4_MINORVERSION;
5018 uint32_t *ctagp;
5019 rpc_inline_t *ptr;
5020 rdma_chunkinfo_t rci;
5021 struct xdr_ops *xops = xdrrdma_xops();
5022
5023 /*
5024 * XDR_ENCODE only
5025 */
5026 if (xdrs->x_op == XDR_FREE)
5027 return (TRUE);
5028 if (xdrs->x_op == XDR_DECODE)
5029 return (FALSE);
5030
5031 ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag;
5032
5033 if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) {
5034 /*
5035 * Efficiently encode fixed length tags, could be longlongs
5036 * but 8 byte XDR alignment not assured
5037 */
5038 IXDR_PUT_U_INT32(ptr, 12);
5039 IXDR_PUT_U_INT32(ptr, ctagp[0]);
5040 IXDR_PUT_U_INT32(ptr, ctagp[1]);
5041 IXDR_PUT_U_INT32(ptr, ctagp[2]);
5042
5043 /*
5044 * Fixed minor version for now
5045 */
5046 IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION);
5047 } else {
5048 if (!XDR_PUTINT32(xdrs, &twelve))
5049 return (FALSE);
5050 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0]))
5051 return (FALSE);
5052 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1]))
5053 return (FALSE);
5054 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2]))
5055 return (FALSE);
5056 if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion))
5057 return (FALSE);
5058 }
5059 if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
5060 rci.rci_type = RCI_REPLY_CHUNK;
5061 rci.rci_len = MAXPATHLEN * 2;
5062 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
5063 }
5064
5065 return (xdr_array(xdrs, (char **)&objp->array,
5066 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5067 sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4));
5068 }
5069
5070 bool_t
xdr_COMPOUND4args_srv(XDR * xdrs,COMPOUND4args * objp)5071 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp)
5072 {
5073 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5074 (uint_t *)&objp->tag.utf8string_len,
5075 NFS4_MAX_UTF8STRING))
5076 return (FALSE);
5077 if (!xdr_u_int(xdrs, &objp->minorversion))
5078 return (FALSE);
5079 if (xdrs->x_op != XDR_FREE)
5080 return (xdr_array(xdrs, (char **)&objp->array,
5081 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5082 sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4));
5083
5084 return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len));
5085 }
5086
5087 bool_t
xdr_COMPOUND4res_clnt(XDR * xdrs,COMPOUND4res_clnt * objp)5088 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp)
5089 {
5090 uint32_t len;
5091 int32_t *ptr;
5092 nfs_argop4 *argop;
5093 nfs_resop4 *resop;
5094
5095 /*
5096 * No XDR_ENCODE
5097 */
5098 if (xdrs->x_op == XDR_ENCODE)
5099 return (FALSE);
5100
5101 if (xdrs->x_op != XDR_FREE) {
5102 if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) {
5103 objp->status = IXDR_GET_U_INT32(ptr);
5104 len = IXDR_GET_U_INT32(ptr);
5105 } else {
5106 if (!xdr_int(xdrs, (int32_t *)&objp->status))
5107 return (FALSE);
5108 if (!xdr_u_int(xdrs, (uint32_t *)&len))
5109 return (FALSE);
5110 }
5111 if (len > NFS4_MAX_UTF8STRING)
5112 return (FALSE);
5113 /*
5114 * Ignore the tag
5115 */
5116 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len))
5117 return (FALSE);
5118
5119 if (!xdr_int(xdrs, (int32_t *)&objp->array_len))
5120 return (FALSE);
5121
5122 if (objp->array_len > objp->argsp->array_len)
5123 return (FALSE);
5124
5125 if (objp->status == NFS4_OK &&
5126 objp->array_len != objp->argsp->array_len)
5127 return (FALSE);
5128
5129 /* Alloc the results array */
5130 argop = objp->argsp->array;
5131 len = objp->array_len * sizeof (nfs_resop4);
5132 objp->decode_len = 0;
5133 objp->array = resop = kmem_zalloc(len, KM_SLEEP);
5134
5135 for (len = 0; len < objp->array_len;
5136 len++, resop++, argop++, objp->decode_len++) {
5137 if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) {
5138 /*
5139 * Make sure to free anything that may
5140 * have been allocated along the way.
5141 */
5142 xdrs->x_op = XDR_FREE;
5143 (void) xdr_nfs_resop4_free(xdrs, &objp->array,
5144 objp->array_len,
5145 objp->decode_len);
5146 return (FALSE);
5147 }
5148 }
5149 return (TRUE);
5150 }
5151 return (xdr_nfs_resop4_free(xdrs, &objp->array,
5152 objp->array_len, objp->decode_len));
5153 }
5154
5155 bool_t
xdr_COMPOUND4res_srv(XDR * xdrs,COMPOUND4res * objp)5156 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp)
5157 {
5158 if (!xdr_int(xdrs, (int32_t *)&objp->status))
5159 return (FALSE);
5160 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5161 (uint_t *)&objp->tag.utf8string_len,
5162 NFS4_MAX_UTF8STRING))
5163 return (FALSE);
5164
5165 if (xdrs->x_op != XDR_FREE)
5166 return (xdr_array(xdrs, (char **)&objp->array,
5167 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5168 sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4));
5169
5170 return (xdr_snfs_resop4_free(xdrs, &objp->array,
5171 objp->array_len, objp->array_len));
5172 }
5173
5174 /*
5175 * NFS server side callback, initiating the callback request so it
5176 * is the RPC client. Must convert from server's internal filehandle
5177 * format to wire format.
5178 */
5179 static bool_t
xdr_snfs_cb_argop4(XDR * xdrs,nfs_cb_argop4 * objp)5180 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5181 {
5182 CB_GETATTR4args *gargs;
5183 CB_RECALL4args *rargs;
5184
5185 ASSERT(xdrs->x_op == XDR_ENCODE);
5186
5187 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop))
5188 return (FALSE);
5189
5190 switch (objp->argop) {
5191 case OP_CB_GETATTR:
5192 gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5193
5194 if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh))
5195 return (FALSE);
5196 return (xdr_bitmap4(xdrs, &gargs->attr_request));
5197 case OP_CB_RECALL:
5198 rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5199
5200 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid))
5201 return (FALSE);
5202 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5203 return (FALSE);
5204 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate))
5205 return (FALSE);
5206 return (xdr_encode_nfs_fh4(xdrs, &rargs->fh));
5207 case OP_CB_ILLEGAL:
5208 return (TRUE);
5209 }
5210 return (FALSE);
5211 }
5212
5213 /*
5214 * NFS client side callback, receiving the callback request so it
5215 * is the RPC server. Must treat the file handles as opaque.
5216 */
5217 static bool_t
xdr_cnfs_cb_argop4(XDR * xdrs,nfs_cb_argop4 * objp)5218 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5219 {
5220 CB_GETATTR4args *gargs;
5221 CB_RECALL4args *rargs;
5222
5223 ASSERT(xdrs->x_op != XDR_ENCODE);
5224
5225 if (!xdr_u_int(xdrs, &objp->argop))
5226 return (FALSE);
5227 switch (objp->argop) {
5228 case OP_CB_GETATTR:
5229 gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5230
5231 if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val,
5232 (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE))
5233 return (FALSE);
5234 return (xdr_bitmap4(xdrs, &gargs->attr_request));
5235 case OP_CB_RECALL:
5236 rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5237
5238 if (!xdr_u_int(xdrs, &rargs->stateid.seqid))
5239 return (FALSE);
5240 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5241 return (FALSE);
5242 if (!xdr_bool(xdrs, &rargs->truncate))
5243 return (FALSE);
5244 return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val,
5245 (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE));
5246 case OP_CB_ILLEGAL:
5247 return (TRUE);
5248 }
5249 return (FALSE);
5250 }
5251
5252 /*
5253 * The NFS client side callback, RPC server
5254 */
5255 bool_t
xdr_CB_COMPOUND4args_clnt(XDR * xdrs,CB_COMPOUND4args * objp)5256 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp)
5257 {
5258 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5259 (uint_t *)&objp->tag.utf8string_len,
5260 NFS4_MAX_UTF8STRING))
5261 return (FALSE);
5262 if (!xdr_u_int(xdrs, &objp->minorversion))
5263 return (FALSE);
5264 if (!xdr_u_int(xdrs, &objp->callback_ident))
5265 return (FALSE);
5266 return (xdr_array(xdrs, (char **)&objp->array,
5267 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5268 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4));
5269 }
5270
5271 /*
5272 * The NFS server side callback, RPC client
5273 */
5274 bool_t
xdr_CB_COMPOUND4args_srv(XDR * xdrs,CB_COMPOUND4args * objp)5275 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp)
5276 {
5277 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5278 (uint_t *)&objp->tag.utf8string_len,
5279 NFS4_MAX_UTF8STRING))
5280 return (FALSE);
5281 if (!xdr_u_int(xdrs, &objp->minorversion))
5282 return (FALSE);
5283 if (!xdr_u_int(xdrs, &objp->callback_ident))
5284 return (FALSE);
5285 return (xdr_array(xdrs, (char **)&objp->array,
5286 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5287 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4));
5288 }
5289
5290 bool_t
xdr_CB_COMPOUND4res(XDR * xdrs,CB_COMPOUND4res * objp)5291 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp)
5292 {
5293 if (!xdr_int(xdrs, (int32_t *)&objp->status))
5294 return (FALSE);
5295 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5296 (uint_t *)&objp->tag.utf8string_len,
5297 NFS4_MAX_UTF8STRING))
5298 return (FALSE);
5299 return (xdr_array(xdrs, (char **)&objp->array,
5300 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5301 sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4));
5302 }
5303