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 if (xdrs->x_op == XDR_DECODE) {
2964 if (!xdr_u_int(xdrs, &w))
2965 return (FALSE);
2966
2967 *share_access = w & OPEN4_SHARE_ACCESS_MASK;
2968 *deleg_want = w & OPEN4_SHARE_WANT_MASK;
2969 }
2970
2971 return (TRUE);
2972 }
2973
2974 static bool_t
xdr_OPEN4args(XDR * xdrs,OPEN4args * objp)2975 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2976 {
2977 if (xdrs->x_op != XDR_FREE) {
2978 if (!xdr_u_int(xdrs, &objp->seqid))
2979 return (FALSE);
2980 if (!xdr_share_access(xdrs, &objp->share_access,
2981 &objp->deleg_want))
2982 return (FALSE);
2983 if (!xdr_u_int(xdrs, &objp->share_deny))
2984 return (FALSE);
2985
2986 /* xdr_open_owner4 */
2987 if (!xdr_u_longlong_t(xdrs,
2988 (u_longlong_t *)&objp->owner.clientid))
2989 return (FALSE);
2990 if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2991 (uint_t *)&objp->owner.owner_len,
2992 NFS4_OPAQUE_LIMIT))
2993 return (FALSE);
2994
2995 /* xdr_openflag4 */
2996 if (!xdr_int(xdrs, (int *)&objp->opentype))
2997 return (FALSE);
2998 if (objp->opentype == OPEN4_CREATE) {
2999
3000 /* xdr_createhow4 */
3001 if (!xdr_int(xdrs, (int *)&objp->mode))
3002 return (FALSE);
3003 switch (objp->mode) {
3004 case UNCHECKED4:
3005 case GUARDED4:
3006 if (!xdr_fattr4(xdrs,
3007 &objp->createhow4_u.createattrs))
3008 return (FALSE);
3009 break;
3010 case EXCLUSIVE4:
3011 if (!xdr_u_longlong_t(xdrs,
3012 (u_longlong_t *)&objp->createhow4_u.
3013 createverf))
3014 return (FALSE);
3015 break;
3016 case EXCLUSIVE4_1:
3017 if (!xdr_creatverfattr(xdrs,
3018 &objp->createhow4_u.ch_createboth))
3019 return (FALSE);
3020 break;
3021 default:
3022 return (FALSE);
3023 }
3024 }
3025
3026 /* xdr_open_claim4 */
3027 if (!xdr_open_claim4(xdrs, &objp->claim))
3028 return (FALSE);
3029
3030 return (TRUE);
3031 }
3032
3033 /*
3034 * Optimized free case
3035 */
3036 if (objp->owner.owner_val != NULL)
3037 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
3038
3039 if (objp->opentype == OPEN4_CREATE) {
3040 switch (objp->mode) {
3041 case UNCHECKED4:
3042 case GUARDED4:
3043 (void) xdr_fattr4(xdrs,
3044 &objp->createhow4_u.createattrs);
3045 break;
3046 case EXCLUSIVE4:
3047 default:
3048 break;
3049 }
3050 }
3051
3052 (void) xdr_open_claim4(xdrs, &objp->claim);
3053 return (TRUE);
3054 }
3055
3056 static bool_t
xdr_OPEN4cargs(XDR * xdrs,OPEN4cargs * objp)3057 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3058 {
3059 int op;
3060 int len;
3061 rpc_inline_t *ptr;
3062
3063 ASSERT(xdrs->x_op == XDR_ENCODE);
3064
3065 /*
3066 * We must always define the client's open_owner to be
3067 * 4 byte aligned and sized.
3068 */
3069 ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3070 ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3071
3072 len = objp->owner.owner_len;
3073 if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3074 int i;
3075 int32_t *ip;
3076
3077 IXDR_PUT_U_INT32(ptr, OP_OPEN);
3078 IXDR_PUT_U_INT32(ptr, objp->seqid);
3079 IXDR_PUT_U_INT32(ptr, objp->share_access);
3080 IXDR_PUT_U_INT32(ptr, objp->share_deny);
3081
3082 /* xdr_open_owner4 */
3083 IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3084 IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3085 /* We know this is very short so don't bcopy */
3086 ip = (int32_t *)objp->owner.owner_val;
3087 len /= BYTES_PER_XDR_UNIT;
3088 for (i = 0; i < len; i++)
3089 *ptr++ = *ip++;
3090
3091 /* xdr_openflag4 */
3092 IXDR_PUT_U_INT32(ptr, objp->opentype);
3093 } else {
3094 op = OP_OPEN;
3095 if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3096 return (FALSE);
3097 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3098 return (FALSE);
3099 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3100 return (FALSE);
3101 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3102 return (FALSE);
3103
3104 /* xdr_open_owner4 */
3105 if (!xdr_u_longlong_t(xdrs,
3106 (u_longlong_t *)&objp->owner.clientid))
3107 return (FALSE);
3108 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3109 return (FALSE);
3110 if (!xdr_opaque(xdrs, objp->owner.owner_val,
3111 objp->owner.owner_len))
3112 return (FALSE);
3113
3114 /* xdr_openflag4 */
3115 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype))
3116 return (FALSE);
3117 }
3118
3119 if (objp->opentype == OPEN4_CREATE) {
3120 /* xdr_createhow4 */
3121 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode))
3122 return (FALSE);
3123 switch (objp->mode) {
3124 case UNCHECKED4:
3125 case GUARDED4:
3126 if (!xdr_fattr4(xdrs,
3127 &objp->createhow4_u.createattrs))
3128 return (FALSE);
3129 break;
3130 case EXCLUSIVE4:
3131 if (!xdr_u_longlong_t(xdrs,
3132 (u_longlong_t *)&objp->createhow4_u.
3133 createverf))
3134 return (FALSE);
3135 break;
3136 default:
3137 return (FALSE);
3138 }
3139 }
3140
3141 /* xdr_open_claim4 */
3142 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim))
3143 return (FALSE);
3144
3145 switch (objp->claim) {
3146 case CLAIM_NULL:
3147 len = strlen(objp->open_claim4_u.cfile);
3148 if (len > NFS4_MAX_UTF8STRING)
3149 return (FALSE);
3150 if (XDR_PUTINT32(xdrs, &len)) {
3151 return (xdr_opaque(xdrs,
3152 objp->open_claim4_u.cfile, len));
3153 }
3154 return (FALSE);
3155 case CLAIM_PREVIOUS:
3156 return (XDR_PUTINT32(xdrs,
3157 (int32_t *)&objp->open_claim4_u.delegate_type));
3158 case CLAIM_DELEGATE_CUR:
3159 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u.
3160 delegate_cur_info.delegate_stateid.seqid))
3161 return (FALSE);
3162 if (!xdr_opaque(xdrs, objp->open_claim4_u.
3163 delegate_cur_info.delegate_stateid.other,
3164 NFS4_OTHER_SIZE))
3165 return (FALSE);
3166 len = strlen(objp->open_claim4_u.delegate_cur_info.cfile);
3167 if (len > NFS4_MAX_UTF8STRING)
3168 return (FALSE);
3169 if (XDR_PUTINT32(xdrs, &len)) {
3170 return (xdr_opaque(xdrs,
3171 objp->open_claim4_u.delegate_cur_info.cfile,
3172 len));
3173 }
3174 return (FALSE);
3175 case CLAIM_DELEGATE_PREV:
3176 len = strlen(objp->open_claim4_u.cfile_delegate_prev);
3177 if (len > NFS4_MAX_UTF8STRING)
3178 return (FALSE);
3179 if (XDR_PUTINT32(xdrs, &len)) {
3180 return (xdr_opaque(xdrs,
3181 objp->open_claim4_u.cfile_delegate_prev, len));
3182 }
3183 return (FALSE);
3184 default:
3185 return (FALSE);
3186 }
3187 }
3188
3189 static bool_t
xdr_OPEN4res(XDR * xdrs,OPEN4res * objp)3190 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp)
3191 {
3192 if (xdrs->x_op != XDR_FREE) {
3193 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3194 return (FALSE);
3195 if (objp->status != NFS4_OK)
3196 return (TRUE);
3197 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3198 return (FALSE);
3199 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3200 return (FALSE);
3201 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3202 return (FALSE);
3203 if (!xdr_u_longlong_t(xdrs,
3204 (u_longlong_t *)&objp->cinfo.before))
3205 return (FALSE);
3206 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
3207 return (FALSE);
3208 if (!xdr_u_int(xdrs, &objp->rflags))
3209 return (FALSE);
3210 if (!xdr_bitmap4(xdrs, &objp->attrset))
3211 return (FALSE);
3212 if (!xdr_int(xdrs,
3213 (int *)&objp->delegation.delegation_type))
3214 return (FALSE);
3215 switch (objp->delegation.delegation_type) {
3216 case OPEN_DELEGATE_NONE:
3217 return (TRUE);
3218 case OPEN_DELEGATE_READ:
3219 if (!xdr_u_int(xdrs, &objp->delegation.
3220 open_delegation4_u.read.stateid.seqid))
3221 return (FALSE);
3222 if (!xdr_opaque(xdrs, objp->delegation.
3223 open_delegation4_u.read.stateid.other,
3224 NFS4_OTHER_SIZE))
3225 return (FALSE);
3226 if (!xdr_bool(xdrs, &objp->delegation.
3227 open_delegation4_u.read.recall))
3228 return (FALSE);
3229 return (xdr_nfsace4(xdrs, &objp->delegation.
3230 open_delegation4_u.read.permissions));
3231 case OPEN_DELEGATE_WRITE:
3232 if (!xdr_u_int(xdrs, &objp->delegation.
3233 open_delegation4_u.write.stateid.seqid))
3234 return (FALSE);
3235 if (!xdr_opaque(xdrs, objp->delegation.
3236 open_delegation4_u.write.stateid.other,
3237 NFS4_OTHER_SIZE))
3238 return (FALSE);
3239 if (!xdr_bool(xdrs, &objp->delegation.
3240 open_delegation4_u.write.recall))
3241 return (FALSE);
3242 if (!xdr_int(xdrs, (int *)&objp->delegation.
3243 open_delegation4_u.write.space_limit.
3244 limitby))
3245 return (FALSE);
3246 switch (objp->delegation.
3247 open_delegation4_u.write.space_limit.
3248 limitby) {
3249 case NFS_LIMIT_SIZE:
3250 if (!xdr_u_longlong_t(xdrs,
3251 (u_longlong_t *)&objp->delegation.
3252 open_delegation4_u.write.space_limit.
3253 nfs_space_limit4_u.filesize))
3254 return (FALSE);
3255 break;
3256 case NFS_LIMIT_BLOCKS:
3257 if (!xdr_u_int(xdrs,
3258 &objp->delegation.open_delegation4_u.write.
3259 space_limit.nfs_space_limit4_u.
3260 mod_blocks.num_blocks))
3261 return (FALSE);
3262 if (!xdr_u_int(xdrs, &objp->delegation.
3263 open_delegation4_u.write.space_limit.
3264 nfs_space_limit4_u.mod_blocks.
3265 bytes_per_block))
3266 return (FALSE);
3267 break;
3268 default:
3269 return (FALSE);
3270 }
3271 return (xdr_nfsace4(xdrs, &objp->delegation.
3272 open_delegation4_u.write.permissions));
3273 }
3274 return (FALSE);
3275 }
3276
3277 /*
3278 * Optimized free case
3279 */
3280 if (objp->status != NFS4_OK)
3281 return (TRUE);
3282
3283 switch (objp->delegation.delegation_type) {
3284 case OPEN_DELEGATE_NONE:
3285 return (TRUE);
3286 case OPEN_DELEGATE_READ:
3287 return (xdr_nfsace4(xdrs, &objp->delegation.
3288 open_delegation4_u.read.permissions));
3289 case OPEN_DELEGATE_WRITE:
3290 switch (objp->delegation.
3291 open_delegation4_u.write.space_limit.limitby) {
3292 case NFS_LIMIT_SIZE:
3293 case NFS_LIMIT_BLOCKS:
3294 break;
3295 default:
3296 return (FALSE);
3297 }
3298 return (xdr_nfsace4(xdrs, &objp->delegation.
3299 open_delegation4_u.write.permissions));
3300 }
3301 return (FALSE);
3302 }
3303
3304 static bool_t
xdr_OPEN_CONFIRM4res(XDR * xdrs,OPEN_CONFIRM4res * objp)3305 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp)
3306 {
3307 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3308 return (FALSE);
3309 if (objp->status != NFS4_OK)
3310 return (TRUE);
3311 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3312 return (FALSE);
3313 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3314 }
3315
3316 static bool_t
xdr_OPEN_DOWNGRADE4args(XDR * xdrs,OPEN_DOWNGRADE4args * objp)3317 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
3318 {
3319 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3320 return (FALSE);
3321 if (!xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE))
3322 return (FALSE);
3323 if (!xdr_u_int(xdrs, &objp->seqid))
3324 return (FALSE);
3325 if (!xdr_share_access(xdrs, &objp->share_access, &objp->deleg_want))
3326 return (FALSE);
3327 return (xdr_u_int(xdrs, &objp->share_deny));
3328 }
3329
3330 static bool_t
xdr_OPEN_DOWNGRADE4res(XDR * xdrs,OPEN_DOWNGRADE4res * objp)3331 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp)
3332 {
3333 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3334 return (FALSE);
3335 if (objp->status != NFS4_OK)
3336 return (TRUE);
3337 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3338 return (FALSE);
3339 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3340 }
3341
3342 static bool_t
xdr_READ4args(XDR * xdrs,READ4args * objp)3343 xdr_READ4args(XDR *xdrs, READ4args *objp)
3344 {
3345 rdma_chunkinfo_t rci;
3346 rdma_wlist_conn_info_t rwci;
3347 struct xdr_ops *xops = xdrrdma_xops();
3348
3349 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3350 return (FALSE);
3351 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3352 return (FALSE);
3353 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3354 return (FALSE);
3355 if (!xdr_u_int(xdrs, &objp->count))
3356 return (FALSE);
3357
3358 DTRACE_PROBE1(xdr__i__read4args_buf_len,
3359 int, objp->count);
3360
3361 objp->wlist = NULL;
3362
3363 if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
3364 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3365 rci.rci_len = objp->count;
3366 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3367 }
3368
3369 if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
3370 return (TRUE);
3371
3372 if (xdrs->x_op == XDR_ENCODE) {
3373 if (objp->res_uiop != NULL) {
3374 rci.rci_type = RCI_WRITE_UIO_CHUNK;
3375 rci.rci_a.rci_uiop = objp->res_uiop;
3376 rci.rci_len = objp->count;
3377 rci.rci_clpp = &objp->wlist;
3378 } else {
3379 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3380 rci.rci_a.rci_addr = objp->res_data_val_alt;
3381 rci.rci_len = objp->count;
3382 rci.rci_clpp = &objp->wlist;
3383 }
3384
3385 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
3386 }
3387
3388 /* XDR_DECODE case */
3389 (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
3390 objp->wlist = rwci.rwci_wlist;
3391 objp->conn = rwci.rwci_conn;
3392
3393 return (TRUE);
3394 }
3395
3396 static bool_t
xdr_READ4res(XDR * xdrs,READ4res * objp)3397 xdr_READ4res(XDR *xdrs, READ4res *objp)
3398 {
3399 mblk_t *mp;
3400
3401 if (xdrs->x_op == XDR_DECODE)
3402 return (FALSE);
3403
3404 if (xdrs->x_op == XDR_FREE) {
3405 /*
3406 * Optimized free case
3407 */
3408 if (objp->status != NFS4_OK)
3409 return (TRUE);
3410 if (objp->data_val != NULL)
3411 kmem_free(objp->data_val, objp->data_len);
3412 return (TRUE);
3413 }
3414
3415 /* on with ENCODE paths */
3416 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status))
3417 return (FALSE);
3418 if (objp->status != NFS4_OK)
3419 return (TRUE);
3420
3421 if (!XDR_PUTINT32(xdrs, &objp->eof))
3422 return (FALSE);
3423
3424 mp = objp->mblk;
3425 if (mp != NULL) {
3426 if (xdrs->x_ops == &xdrmblk_ops) {
3427 if (xdrmblk_putmblk(xdrs, mp, objp->data_len)) {
3428 objp->mblk = NULL;
3429 return (TRUE);
3430 } else {
3431 return (FALSE);
3432 }
3433 } else if (mp->b_cont != NULL) {
3434 /*
3435 * See xdr_READ3res() for an explanation of why we need
3436 * to do a pullup here.
3437 */
3438 if (pullupmsg(mp, -1) == 0)
3439 return (FALSE);
3440 objp->data_val = (caddr_t)mp->b_rptr;
3441 }
3442 } else {
3443 if (xdr_u_int(xdrs, &objp->data_len) == FALSE) {
3444 return (FALSE);
3445 }
3446 /*
3447 * If read data sent by wlist (RDMA_WRITE), don't do
3448 * xdr_bytes() below. RDMA_WRITE transfers the data.
3449 * Note: this is encode-only because the client code
3450 * uses xdr_READ4res_clnt to decode results.
3451 */
3452 if (objp->wlist) {
3453 if (objp->data_len != 0) {
3454 return (xdrrdma_send_read_data(
3455 xdrs, objp->data_len, objp->wlist));
3456 }
3457 return (TRUE);
3458 }
3459 }
3460
3461 return (xdr_bytes(xdrs, (char **)&objp->data_val,
3462 (uint_t *)&objp->data_len,
3463 objp->data_len));
3464 }
3465
3466 static bool_t
xdr_READ4res_clnt(XDR * xdrs,READ4res * objp,READ4args * aobjp)3467 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp)
3468 {
3469 mblk_t *mp;
3470 size_t n;
3471 int error;
3472 uint_t size = aobjp->res_maxsize;
3473 count4 ocount;
3474
3475 if (xdrs->x_op == XDR_ENCODE)
3476 return (FALSE);
3477
3478 if (xdrs->x_op == XDR_FREE) {
3479 /*
3480 * Optimized free case
3481 */
3482 if (objp->status != NFS4_OK)
3483 return (TRUE);
3484 if (objp->data_val != NULL)
3485 kmem_free(objp->data_val, objp->data_len);
3486 return (TRUE);
3487 }
3488
3489 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
3490 return (FALSE);
3491 if (objp->status != NFS4_OK)
3492 return (TRUE);
3493
3494 if (!XDR_GETINT32(xdrs, &objp->eof))
3495 return (FALSE);
3496
3497
3498 /*
3499 * This is a special case such that the caller is providing a
3500 * uio as a guide to eventual data location; this is used for
3501 * handling DIRECTIO reads.
3502 */
3503 if (aobjp->res_uiop != NULL) {
3504 struct uio *uiop = aobjp->res_uiop;
3505 int32_t *ptr;
3506
3507 if (xdrs->x_ops == &xdrmblk_ops) {
3508 if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len))
3509 return (FALSE);
3510
3511 if (objp->data_len == 0)
3512 return (TRUE);
3513
3514 if (objp->data_len > size)
3515 return (FALSE);
3516
3517 size = objp->data_len;
3518 do {
3519 n = MIN(size, mp->b_wptr - mp->b_rptr);
3520 if ((n = MIN(uiop->uio_resid, n)) != 0) {
3521
3522 error = uiomove((char *)mp->b_rptr, n,
3523 UIO_READ, uiop);
3524 if (error)
3525 return (FALSE);
3526 mp->b_rptr += n;
3527 size -= n;
3528 }
3529
3530 while (mp && (mp->b_rptr >= mp->b_wptr))
3531 mp = mp->b_cont;
3532 } while (mp && size > 0 && uiop->uio_resid > 0);
3533
3534 return (TRUE);
3535 }
3536
3537 if (xdrs->x_ops == &xdrrdma_ops) {
3538 struct clist *cl;
3539
3540 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3541
3542 objp->wlist = cl;
3543
3544 if (objp->wlist) {
3545 /* opaque count */
3546 if (!xdr_u_int(xdrs, &ocount)) {
3547 objp->wlist = NULL;
3548 return (FALSE);
3549 }
3550
3551 objp->wlist_len = clist_len(cl);
3552 objp->data_len = ocount;
3553
3554 if (objp->wlist_len !=
3555 roundup(
3556 objp->data_len, BYTES_PER_XDR_UNIT)) {
3557 DTRACE_PROBE2(
3558 xdr__e__read4resuio_clnt_fail,
3559 int, ocount,
3560 int, objp->data_len);
3561 objp->wlist = NULL;
3562 return (FALSE);
3563 }
3564
3565 uiop->uio_resid -= objp->data_len;
3566 uiop->uio_iov->iov_len -= objp->data_len;
3567 uiop->uio_iov->iov_base += objp->data_len;
3568 uiop->uio_loffset += objp->data_len;
3569
3570 objp->wlist = NULL;
3571 return (TRUE);
3572 }
3573 }
3574
3575 /*
3576 * This isn't an xdrmblk stream nor RDMA.
3577 * Handle the likely case that it can be
3578 * inlined (ex. xdrmem).
3579 */
3580 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len))
3581 return (FALSE);
3582
3583 if (objp->data_len == 0)
3584 return (TRUE);
3585
3586 if (objp->data_len > size)
3587 return (FALSE);
3588
3589 size = (int)objp->data_len;
3590 if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
3591 return (uiomove(ptr, size, UIO_READ, uiop) ?
3592 FALSE : TRUE);
3593
3594 /*
3595 * Handle some other (unlikely) stream type that will
3596 * need a copy.
3597 */
3598 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
3599 return (FALSE);
3600
3601 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
3602 kmem_free(ptr, size);
3603 return (FALSE);
3604 }
3605 error = uiomove(ptr, size, UIO_READ, uiop);
3606 kmem_free(ptr, size);
3607
3608 return (error ? FALSE : TRUE);
3609 }
3610
3611 /*
3612 * Check for the other special case of the caller providing
3613 * the target area for the data.
3614 */
3615 if (aobjp->res_data_val_alt == NULL)
3616 return (FALSE);
3617
3618 /*
3619 * If read data received via RDMA_WRITE, don't do xdr_bytes().
3620 * RDMA_WRITE already moved the data so decode length of
3621 * RDMA_WRITE.
3622 */
3623 if (xdrs->x_ops == &xdrrdma_ops) {
3624 struct clist *cl;
3625
3626 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3627
3628 objp->wlist = cl;
3629
3630 /*
3631 * Data transferred through inline if
3632 * objp->wlist == NULL
3633 */
3634 if (objp->wlist) {
3635 /* opaque count */
3636 if (!xdr_u_int(xdrs, &ocount)) {
3637 objp->wlist = NULL;
3638 return (FALSE);
3639 }
3640
3641 objp->wlist_len = clist_len(cl);
3642 objp->data_len = ocount;
3643
3644 if (objp->wlist_len !=
3645 roundup(
3646 objp->data_len, BYTES_PER_XDR_UNIT)) {
3647 DTRACE_PROBE2(
3648 xdr__e__read4res_clnt_fail,
3649 int, ocount,
3650 int, objp->data_len);
3651 objp->wlist = NULL;
3652 return (FALSE);
3653 }
3654
3655 objp->wlist = NULL;
3656 return (TRUE);
3657 }
3658 }
3659
3660 return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt,
3661 (uint_t *)&objp->data_len,
3662 aobjp->res_maxsize));
3663 }
3664
3665 static bool_t
xdr_READDIR4args(XDR * xdrs,READDIR4args * objp)3666 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp)
3667 {
3668 rdma_chunkinfo_t rci;
3669 struct xdr_ops *xops = xdrrdma_xops();
3670
3671 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
3672 xdrs->x_op == XDR_ENCODE) {
3673 rci.rci_type = RCI_REPLY_CHUNK;
3674 rci.rci_len = objp->maxcount;
3675 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3676 }
3677
3678 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie))
3679 return (FALSE);
3680 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
3681 return (FALSE);
3682 if (!xdr_u_int(xdrs, &objp->dircount))
3683 return (FALSE);
3684 if (!xdr_u_int(xdrs, &objp->maxcount))
3685 return (FALSE);
3686 return (xdr_bitmap4(xdrs, &objp->attr_request));
3687 }
3688
3689 bool_t
xdr_READDIR4res(XDR * xdrs,READDIR4res * objp)3690 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp)
3691 {
3692 mblk_t *mp = objp->mblk;
3693 bool_t ret_val;
3694 uint_t flags = 0;
3695
3696 ASSERT(xdrs->x_op == XDR_ENCODE);
3697
3698 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3699 return (FALSE);
3700 if (objp->status != NFS4_OK)
3701 return (TRUE);
3702 if (mp == NULL)
3703 return (FALSE);
3704
3705 if (xdrs->x_ops == &xdrmblk_ops) {
3706 if (xdrmblk_putmblk_raw(xdrs, mp)
3707 == TRUE) {
3708 /* mblk successfully inserted into outgoing chain */
3709 objp->mblk = NULL;
3710 return (TRUE);
3711 }
3712 }
3713
3714 ASSERT(mp->b_cont == NULL);
3715
3716 /*
3717 * If transport is RDMA, the pre-encoded m_blk needs to be moved
3718 * without being chunked.
3719 * Check if chunking is enabled for the xdr stream.
3720 * If it is enabled, disable it temporarily for this op,
3721 * then re-enable.
3722 */
3723 XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags);
3724
3725 if (!(flags & XDR_RDMA_CHUNK))
3726 return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len));
3727
3728 flags &= ~XDR_RDMA_CHUNK;
3729
3730 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3731
3732 ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len);
3733
3734 flags |= XDR_RDMA_CHUNK;
3735
3736 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3737
3738 return (ret_val);
3739 }
3740
3741 static bool_t
xdr_READLINK4res(XDR * xdrs,READLINK4res * objp)3742 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp)
3743 {
3744 if (xdrs->x_op != XDR_FREE) {
3745 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3746 return (FALSE);
3747 if (objp->status != NFS4_OK)
3748 return (TRUE);
3749 return (xdr_bytes(xdrs, (char **)&objp->link.linktext4_val,
3750 (uint_t *)&objp->link.linktext4_len,
3751 NFS4_MAX_UTF8STRING));
3752 }
3753
3754 /*
3755 * Optimized free case
3756 */
3757 if (objp->status != NFS4_OK)
3758 return (TRUE);
3759 if (objp->link.linktext4_val != NULL)
3760 kmem_free(objp->link.linktext4_val, objp->link.linktext4_len);
3761 return (TRUE);
3762 }
3763
3764 static bool_t
xdr_REMOVE4res(XDR * xdrs,REMOVE4res * objp)3765 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp)
3766 {
3767 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3768 return (FALSE);
3769 if (objp->status != NFS4_OK)
3770 return (TRUE);
3771 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3772 return (FALSE);
3773 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
3774 return (FALSE);
3775 return (xdr_u_longlong_t(xdrs,
3776 (u_longlong_t *)&objp->cinfo.after));
3777 }
3778
3779 static bool_t
xdr_RENAME4res(XDR * xdrs,RENAME4res * objp)3780 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp)
3781 {
3782 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3783 return (FALSE);
3784 if (objp->status != NFS4_OK)
3785 return (TRUE);
3786 if (!xdr_bool(xdrs, &objp->source_cinfo.atomic))
3787 return (FALSE);
3788 if (!xdr_u_longlong_t(xdrs,
3789 (u_longlong_t *)&objp->source_cinfo.before))
3790 return (FALSE);
3791 if (!xdr_u_longlong_t(xdrs,
3792 (u_longlong_t *)&objp->source_cinfo.after))
3793 return (FALSE);
3794 if (!xdr_bool(xdrs, &objp->target_cinfo.atomic))
3795 return (FALSE);
3796 if (!xdr_u_longlong_t(xdrs,
3797 (u_longlong_t *)&objp->target_cinfo.before))
3798 return (FALSE);
3799 return (xdr_u_longlong_t(xdrs,
3800 (u_longlong_t *)&objp->target_cinfo.after));
3801 }
3802
3803 static bool_t
xdr_secinfo4(XDR * xdrs,secinfo4 * objp)3804 xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
3805 {
3806 if (xdrs->x_op != XDR_FREE) {
3807 if (!xdr_u_int(xdrs, &objp->flavor))
3808 return (FALSE);
3809 if (objp->flavor != RPCSEC_GSS)
3810 return (TRUE);
3811 if (!xdr_bytes(xdrs,
3812 (char **)&objp->flavor_info.oid.sec_oid4_val,
3813 (uint_t *)&objp->flavor_info.oid.sec_oid4_len,
3814 NFS4_MAX_SECOID4))
3815 return (FALSE);
3816 if (!xdr_u_int(xdrs, &objp->flavor_info.qop))
3817 return (FALSE);
3818 return (xdr_int(xdrs, (int *)&objp->flavor_info.service));
3819 }
3820
3821 /*
3822 * Optimized free path
3823 */
3824 if (objp->flavor != RPCSEC_GSS)
3825 return (TRUE);
3826
3827 if (objp->flavor_info.oid.sec_oid4_val != NULL)
3828 kmem_free(objp->flavor_info.oid.sec_oid4_val,
3829 objp->flavor_info.oid.sec_oid4_len);
3830 return (TRUE);
3831 }
3832
3833 bool_t
xdr_SECINFO4res(XDR * xdrs,SECINFO4res * objp)3834 xdr_SECINFO4res(XDR *xdrs, SECINFO4res *objp)
3835 {
3836 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3837 return (FALSE);
3838 if (objp->status != NFS4_OK)
3839 return (TRUE);
3840 return (xdr_array(xdrs, (char **)&objp->SECINFO4resok_val,
3841 (uint_t *)&objp->SECINFO4resok_len, ~0, sizeof (secinfo4),
3842 (xdrproc_t)xdr_secinfo4));
3843 }
3844
3845 static bool_t
xdr_SETCLIENTID4args(XDR * xdrs,SETCLIENTID4args * objp)3846 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
3847 {
3848 if (xdrs->x_op != XDR_FREE) {
3849 if (!xdr_u_longlong_t(xdrs,
3850 (u_longlong_t *)&objp->client.verifier))
3851 return (FALSE);
3852 if (!xdr_bytes(xdrs, (char **)&objp->client.id_val,
3853 (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT))
3854 return (FALSE);
3855 if (!xdr_u_int(xdrs, &objp->callback.cb_program))
3856 return (FALSE);
3857 if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3858 NFS4_OPAQUE_LIMIT))
3859 return (FALSE);
3860 if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3861 NFS4_OPAQUE_LIMIT))
3862 return (FALSE);
3863 return (xdr_u_int(xdrs, &objp->callback_ident));
3864 }
3865
3866 /*
3867 * Optimized free case
3868 */
3869 if (objp->client.id_val != NULL)
3870 kmem_free(objp->client.id_val, objp->client.id_len);
3871 (void) xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3872 NFS4_OPAQUE_LIMIT);
3873 return (xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3874 NFS4_OPAQUE_LIMIT));
3875 }
3876
3877 static bool_t
xdr_SETCLIENTID4res(XDR * xdrs,SETCLIENTID4res * objp)3878 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp)
3879 {
3880 if (xdrs->x_op != XDR_FREE) {
3881 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3882 return (FALSE);
3883 switch (objp->status) {
3884 case NFS4_OK:
3885 if (!xdr_u_longlong_t(xdrs,
3886 (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4.
3887 clientid))
3888 return (FALSE);
3889 return (xdr_u_longlong_t(xdrs,
3890 (u_longlong_t *)&objp->SETCLIENTID4res_u.
3891 resok4.setclientid_confirm));
3892 case NFS4ERR_CLID_INUSE:
3893 if (!xdr_string(xdrs,
3894 &objp->SETCLIENTID4res_u.client_using.
3895 r_netid, NFS4_OPAQUE_LIMIT))
3896 return (FALSE);
3897 return (xdr_string(xdrs,
3898 &objp->SETCLIENTID4res_u.client_using.
3899 r_addr, NFS4_OPAQUE_LIMIT));
3900 }
3901 return (TRUE);
3902 }
3903
3904 /*
3905 * Optimized free case
3906 */
3907 if (objp->status != NFS4ERR_CLID_INUSE)
3908 return (TRUE);
3909
3910 if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid,
3911 NFS4_OPAQUE_LIMIT))
3912 return (FALSE);
3913 return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr,
3914 NFS4_OPAQUE_LIMIT));
3915 }
3916
3917 static bool_t
xdr_WRITE4args(XDR * xdrs,WRITE4args * objp)3918 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp)
3919 {
3920 if (xdrs->x_op != XDR_FREE) {
3921 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3922 return (FALSE);
3923 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3924 return (FALSE);
3925 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3926 return (FALSE);
3927 if (!xdr_int(xdrs, (int *)&objp->stable))
3928 return (FALSE);
3929 if (xdrs->x_op == XDR_DECODE) {
3930 if (xdrs->x_ops == &xdrmblk_ops) {
3931 objp->data_val = NULL;
3932 return (xdrmblk_getmblk(xdrs, &objp->mblk,
3933 &objp->data_len));
3934 }
3935 objp->mblk = NULL;
3936 if (xdrs->x_ops == &xdrrdmablk_ops) {
3937 int retval;
3938 retval = xdrrdma_getrdmablk(xdrs,
3939 &objp->rlist,
3940 &objp->data_len,
3941 &objp->conn, NFS4_DATA_LIMIT);
3942 if (retval == FALSE)
3943 return (FALSE);
3944 return (xdrrdma_read_from_client(objp->rlist,
3945 &objp->conn, objp->data_len));
3946 }
3947 }
3948 /* Else fall thru for the xdr_bytes(). */
3949 return (xdr_bytes(xdrs, (char **)&objp->data_val,
3950 (uint_t *)&objp->data_len, NFS4_DATA_LIMIT));
3951 }
3952 if (objp->rlist != NULL) {
3953 (void) xdrrdma_free_clist(objp->conn, objp->rlist);
3954 objp->rlist = NULL;
3955 objp->data_val = NULL;
3956
3957 return (TRUE);
3958 }
3959
3960 /*
3961 * Optimized free case
3962 */
3963 if (objp->data_val != NULL)
3964 kmem_free(objp->data_val, objp->data_len);
3965 return (TRUE);
3966 }
3967
3968 static bool_t
xdr_WRITE4res(XDR * xdrs,WRITE4res * objp)3969 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp)
3970 {
3971 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3972 return (FALSE);
3973 if (objp->status != NFS4_OK)
3974 return (TRUE);
3975 if (!xdr_u_int(xdrs, &objp->count))
3976 return (FALSE);
3977 if (!xdr_int(xdrs, (int *)&objp->committed))
3978 return (FALSE);
3979 return (xdr_u_longlong_t(xdrs,
3980 (u_longlong_t *)&objp->writeverf));
3981 }
3982
3983 static bool_t
xdr_snfs_argop4_free(XDR * xdrs,nfs_argop4 ** arrayp,int len)3984 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
3985 {
3986 int i;
3987 nfs_argop4 *array = *arrayp;
3988
3989 /*
3990 * Optimized XDR_FREE only args array
3991 */
3992 ASSERT(xdrs->x_op == XDR_FREE);
3993
3994 /*
3995 * Nothing to do?
3996 */
3997 if (array == NULL)
3998 return (TRUE);
3999
4000 for (i = 0; i < len; i++) {
4001 /* Freeing for nfs4.x */
4002 if (array[i].argop >= OP_BACKCHANNEL_CTL &&
4003 array[i].argop != OP_ILLEGAL) {
4004 xdr_nfs4x_argop4(xdrs, &array[i]);
4005 continue;
4006 }
4007
4008 /*
4009 * These should be ordered by frequency of use
4010 */
4011 switch (array[i].argop) {
4012 case OP_PUTFH: {
4013 nfs_fh4 *objp = &array[i].nfs_argop4_u.opputfh.object;
4014
4015 if (objp->nfs_fh4_val != NULL) {
4016 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
4017 }
4018 continue;
4019 }
4020 case OP_GETATTR:
4021 case OP_GETFH:
4022 continue;
4023 case OP_LOOKUP:
4024 if (array[i].nfs_argop4_u.oplookup.objname.
4025 utf8string_val != NULL) {
4026 kmem_free(array[i].nfs_argop4_u.oplookup.
4027 objname.utf8string_val,
4028 array[i].nfs_argop4_u.oplookup.
4029 objname.utf8string_len);
4030 }
4031 continue;
4032 case OP_OPEN:
4033 (void) xdr_OPEN4args(xdrs,
4034 &array[i].nfs_argop4_u.opopen);
4035 continue;
4036 case OP_CLOSE:
4037 case OP_ACCESS:
4038 case OP_READ:
4039 continue;
4040 case OP_WRITE:
4041 (void) xdr_WRITE4args(xdrs,
4042 &array[i].nfs_argop4_u.opwrite);
4043 continue;
4044 case OP_DELEGRETURN:
4045 case OP_LOOKUPP:
4046 case OP_READDIR:
4047 continue;
4048 case OP_REMOVE:
4049 if (array[i].nfs_argop4_u.opremove.target.
4050 utf8string_val != NULL) {
4051 kmem_free(array[i].nfs_argop4_u.opremove.target.
4052 utf8string_val,
4053 array[i].nfs_argop4_u.opremove.target.
4054 utf8string_len);
4055 }
4056 continue;
4057 case OP_COMMIT:
4058 continue;
4059 case OP_CREATE:
4060 (void) xdr_CREATE4args(xdrs,
4061 &array[i].nfs_argop4_u.opcreate);
4062 continue;
4063 case OP_DELEGPURGE:
4064 continue;
4065 case OP_LINK:
4066 if (array[i].nfs_argop4_u.oplink.newname.
4067 utf8string_val != NULL) {
4068 kmem_free(array[i].nfs_argop4_u.oplink.newname.
4069 utf8string_val,
4070 array[i].nfs_argop4_u.oplink.newname.
4071 utf8string_len);
4072 }
4073 continue;
4074 case OP_LOCK:
4075 (void) xdr_LOCK4args(xdrs,
4076 &array[i].nfs_argop4_u.oplock);
4077 continue;
4078 case OP_LOCKT:
4079 (void) xdr_LOCKT4args(xdrs,
4080 &array[i].nfs_argop4_u.oplockt);
4081 continue;
4082 case OP_LOCKU:
4083 continue;
4084 case OP_NVERIFY:
4085 (void) xdr_fattr4(xdrs,
4086 &array[i].nfs_argop4_u.opnverify.obj_attributes);
4087 continue;
4088 case OP_OPENATTR:
4089 case OP_OPEN_CONFIRM:
4090 case OP_OPEN_DOWNGRADE:
4091 case OP_PUTPUBFH:
4092 case OP_PUTROOTFH:
4093 case OP_READLINK:
4094 continue;
4095 case OP_RENAME:
4096 if (array[i].nfs_argop4_u.oprename.oldname.
4097 utf8string_val != NULL) {
4098 kmem_free(array[i].nfs_argop4_u.oprename.
4099 oldname.utf8string_val,
4100 array[i].nfs_argop4_u.oprename.
4101 oldname.utf8string_len);
4102 }
4103 if (array[i].nfs_argop4_u.oprename.newname.
4104 utf8string_val != NULL) {
4105 kmem_free(array[i].nfs_argop4_u.oprename.
4106 newname.utf8string_val,
4107 array[i].nfs_argop4_u.oprename.
4108 newname.utf8string_len);
4109 }
4110 continue;
4111 case OP_RENEW:
4112 case OP_RESTOREFH:
4113 case OP_SAVEFH:
4114 continue;
4115 case OP_SECINFO:
4116 if (array[i].nfs_argop4_u.opsecinfo.name.
4117 utf8string_val != NULL) {
4118 kmem_free(array[i].nfs_argop4_u.opsecinfo.name.
4119 utf8string_val,
4120 array[i].nfs_argop4_u.opsecinfo.name.
4121 utf8string_len);
4122 }
4123 continue;
4124 case OP_SETATTR:
4125 (void) xdr_fattr4(xdrs,
4126 &array[i].nfs_argop4_u.opsetattr.obj_attributes);
4127 continue;
4128 case OP_SETCLIENTID:
4129 (void) xdr_SETCLIENTID4args(xdrs,
4130 &array[i].nfs_argop4_u.opsetclientid);
4131 continue;
4132 case OP_SETCLIENTID_CONFIRM:
4133 continue;
4134 case OP_VERIFY:
4135 (void) xdr_fattr4(xdrs,
4136 &array[i].nfs_argop4_u.opverify.obj_attributes);
4137 continue;
4138 case OP_RELEASE_LOCKOWNER:
4139 if (array[i].nfs_argop4_u.oprelease_lockowner.
4140 lock_owner.owner_val != NULL) {
4141 kmem_free(array[i].nfs_argop4_u.
4142 oprelease_lockowner.lock_owner.owner_val,
4143 array[i].nfs_argop4_u.
4144 oprelease_lockowner.lock_owner.owner_len);
4145 }
4146 continue;
4147 case OP_ILLEGAL:
4148 continue;
4149 default:
4150 /*
4151 * An invalid op is a coding error, it should never
4152 * have been decoded.
4153 * Don't error because the caller cannot finish
4154 * freeing the residual memory of the array.
4155 */
4156 continue;
4157 }
4158 }
4159
4160 kmem_free(*arrayp, len * sizeof (nfs_argop4));
4161 *arrayp = NULL;
4162 return (TRUE);
4163 }
4164
4165 static bool_t
xdr_nfs_argop4(XDR * xdrs,nfs_argop4 * objp)4166 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4167 {
4168 rdma_chunkinfo_t rci;
4169 struct xdr_ops *xops = xdrrdma_xops();
4170
4171 /*
4172 * These should be ordered by frequency of use
4173 */
4174 switch (objp->argop) {
4175 case OP_PUTFH:
4176 return (xdr_bytes(xdrs,
4177 (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val,
4178 (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len,
4179 NFS4_FHSIZE));
4180 case OP_GETATTR:
4181 /*
4182 * ACLs can become relatively large ( > 8K) and the default
4183 * 8K reply chunk of RDMA may not suffice. Check for
4184 * get ACL bit and if it's RDMA, add a chunk equal the size
4185 * of the transfer size to the reply chunk list.
4186 */
4187 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4188 (xdrs->x_op == XDR_ENCODE) &&
4189 (objp->nfs_argop4_u.opgetattr.attr_request &
4190 FATTR4_ACL_MASK)) {
4191 rci.rci_type = RCI_REPLY_CHUNK;
4192 rci.rci_len = objp->nfs_argop4_u.opgetattr.mi->mi_tsize;
4193 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4194
4195 DTRACE_PROBE1(xdr__i__argop4__getattr, int,
4196 rci.rci_len);
4197 }
4198 return (xdr_bitmap4(xdrs,
4199 &objp->nfs_argop4_u.opgetattr.attr_request));
4200 case OP_GETFH:
4201 return (TRUE);
4202 case OP_LOOKUP:
4203 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup.
4204 objname.utf8string_val,
4205 (uint_t *)&objp->nfs_argop4_u.oplookup.
4206 objname.utf8string_len,
4207 NFS4_MAX_UTF8STRING));
4208 case OP_OPEN:
4209 return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen));
4210 case OP_CLOSE:
4211 return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose));
4212 case OP_ACCESS:
4213 return (xdr_u_int(xdrs,
4214 &objp->nfs_argop4_u.opaccess.access));
4215 case OP_READ:
4216 return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread));
4217 case OP_WRITE:
4218 return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite));
4219 case OP_DELEGRETURN:
4220 if (!xdr_u_int(xdrs,
4221 &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid))
4222 return (FALSE);
4223 return (xdr_opaque(xdrs,
4224 objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other,
4225 NFS4_OTHER_SIZE));
4226 case OP_LOOKUPP:
4227 return (TRUE);
4228 case OP_READDIR:
4229 return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir));
4230 case OP_REMOVE:
4231 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove.
4232 target.utf8string_val,
4233 (uint_t *)&objp->nfs_argop4_u.opremove.
4234 target.utf8string_len,
4235 NFS4_MAX_UTF8STRING));
4236 case OP_COMMIT:
4237 if (!xdr_u_longlong_t(xdrs,
4238 (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset))
4239 return (FALSE);
4240 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count));
4241 case OP_CREATE:
4242 return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate));
4243 case OP_DELEGPURGE:
4244 return (xdr_u_longlong_t(xdrs,
4245 (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid));
4246 case OP_LINK:
4247 return (xdr_bytes(xdrs,
4248 (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val,
4249 (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len,
4250 NFS4_MAX_UTF8STRING));
4251 case OP_LOCK:
4252 return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock));
4253 case OP_LOCKT:
4254 return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt));
4255 case OP_LOCKU:
4256 return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku));
4257 case OP_NVERIFY:
4258 return (xdr_fattr4(xdrs,
4259 &objp->nfs_argop4_u.opnverify.obj_attributes));
4260 case OP_OPENATTR:
4261 return (xdr_bool(xdrs,
4262 &objp->nfs_argop4_u.opopenattr.createdir));
4263 case OP_OPEN_CONFIRM:
4264 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4265 open_stateid.seqid))
4266 return (FALSE);
4267 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm.
4268 open_stateid.other, NFS4_OTHER_SIZE))
4269 return (FALSE);
4270 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4271 seqid));
4272 case OP_OPEN_DOWNGRADE:
4273 return (xdr_OPEN_DOWNGRADE4args(xdrs,
4274 &objp->nfs_argop4_u.opopen_downgrade));
4275 case OP_PUTPUBFH:
4276 return (TRUE);
4277 case OP_PUTROOTFH:
4278 return (TRUE);
4279 case OP_READLINK:
4280 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4281 xdrs->x_op == XDR_ENCODE) {
4282 rci.rci_type = RCI_REPLY_CHUNK;
4283 rci.rci_len = MAXPATHLEN;
4284 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4285 }
4286 return (TRUE);
4287 case OP_RENAME:
4288 if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4289 oldname.utf8string_val,
4290 (uint_t *)&objp->nfs_argop4_u.oprename.
4291 oldname.utf8string_len,
4292 NFS4_MAX_UTF8STRING))
4293 return (FALSE);
4294 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4295 newname.utf8string_val,
4296 (uint_t *)&objp->nfs_argop4_u.oprename.
4297 newname.utf8string_len,
4298 NFS4_MAX_UTF8STRING));
4299 case OP_RENEW:
4300 return (xdr_u_longlong_t(xdrs,
4301 (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid));
4302 case OP_RESTOREFH:
4303 return (TRUE);
4304 case OP_SAVEFH:
4305 return (TRUE);
4306 case OP_SECINFO:
4307 return (xdr_bytes(xdrs,
4308 (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val,
4309 (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len,
4310 NFS4_MAX_UTF8STRING));
4311 case OP_SETATTR:
4312 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr.
4313 stateid.seqid))
4314 return (FALSE);
4315 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr.
4316 stateid.other, NFS4_OTHER_SIZE))
4317 return (FALSE);
4318 return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr.
4319 obj_attributes));
4320 case OP_SETCLIENTID:
4321 return (xdr_SETCLIENTID4args(xdrs,
4322 &objp->nfs_argop4_u.opsetclientid));
4323 case OP_SETCLIENTID_CONFIRM:
4324 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u.
4325 opsetclientid_confirm.clientid))
4326 return (FALSE);
4327 return (xdr_u_longlong_t(xdrs,
4328 (u_longlong_t *)&objp->nfs_argop4_u.
4329 opsetclientid_confirm.setclientid_confirm));
4330 case OP_VERIFY:
4331 return (xdr_fattr4(xdrs,
4332 &objp->nfs_argop4_u.opverify.obj_attributes));
4333 case OP_RELEASE_LOCKOWNER:
4334 if (!xdr_u_longlong_t(xdrs,
4335 (u_longlong_t *)&objp->nfs_argop4_u.
4336 oprelease_lockowner.lock_owner.clientid))
4337 return (FALSE);
4338 return (xdr_bytes(xdrs,
4339 (char **)&objp->nfs_argop4_u.oprelease_lockowner.
4340 lock_owner.owner_val,
4341 (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner.
4342 lock_owner.owner_len, NFS4_OPAQUE_LIMIT));
4343 case OP_ILLEGAL:
4344 return (TRUE);
4345 }
4346 return (FALSE);
4347 }
4348
4349 static bool_t
xdr_cnfs_argop4_wrap(XDR * xdrs,nfs_argop4 * objp)4350 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp)
4351 {
4352 if (!xdr_int(xdrs, (int *)&objp->argop))
4353 return (FALSE);
4354
4355 return (xdr_nfs_argop4(xdrs, objp));
4356 }
4357
4358 static bool_t
xdr_snfs_argop4(XDR * xdrs,nfs_argop4 * objp)4359 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4360 {
4361 if (!xdr_int(xdrs, (int *)&objp->argop))
4362 return (FALSE);
4363
4364 switch (objp->argop) {
4365 case OP_PUTFH:
4366 return (xdr_decode_nfs_fh4(xdrs,
4367 &objp->nfs_argop4_u.opputfh.object));
4368 default:
4369 if (objp->argop >= OP_BACKCHANNEL_CTL &&
4370 objp->argop != OP_ILLEGAL)
4371 return (xdr_nfs4x_argop4(xdrs, objp));
4372
4373 return (xdr_nfs_argop4(xdrs, objp));
4374 }
4375 }
4376
4377 /*
4378 * Client side encode only arg op processing
4379 */
4380 static bool_t
xdr_cnfs_argop4(XDR * xdrs,nfs_argop4 * objp)4381 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4382 {
4383 int len;
4384 int op;
4385 nfs4_sharedfh_t *sfh;
4386 mntinfo4_t *mi;
4387 rpc_inline_t *ptr;
4388
4389 ASSERT(xdrs->x_op == XDR_ENCODE);
4390
4391 /*
4392 * Special case the private pseudo ops
4393 */
4394 if (!(objp->argop & SUNW_PRIVATE_OP))
4395 return (xdr_cnfs_argop4_wrap(xdrs, objp));
4396
4397 /*
4398 * These should be ordered by frequency of use
4399 */
4400 switch (objp->argop) {
4401 case OP_CPUTFH:
4402 /*
4403 * We are passed in the file handle as a nfs4_sharedfh_t *
4404 * We need to acquire the correct locks so we can copy it out.
4405 */
4406 sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh;
4407 mi = sfh->sfh_mi;
4408 (void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0);
4409
4410 len = sfh->sfh_fh.nfs_fh4_len;
4411 ASSERT(len <= NFS4_FHSIZE);
4412
4413 /*
4414 * First try and inline the copy
4415 * Must first be a multiple of BYTES_PER_XDR_UNIT
4416 */
4417 if (!(len % BYTES_PER_XDR_UNIT) &&
4418 (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) !=
4419 NULL) {
4420 IXDR_PUT_U_INT32(ptr, OP_PUTFH);
4421 IXDR_PUT_U_INT32(ptr, len);
4422 bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len);
4423 nfs_rw_exit(&mi->mi_fh_lock);
4424 return (TRUE);
4425 }
4426
4427 op = OP_PUTFH;
4428 if (!XDR_PUTINT32(xdrs, &op)) {
4429 nfs_rw_exit(&mi->mi_fh_lock);
4430 return (FALSE);
4431 }
4432 if (!XDR_PUTINT32(xdrs, &len)) {
4433 nfs_rw_exit(&mi->mi_fh_lock);
4434 return (FALSE);
4435 }
4436 if (!(len % BYTES_PER_XDR_UNIT)) {
4437 if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4438 nfs_rw_exit(&mi->mi_fh_lock);
4439 return (TRUE);
4440 }
4441 } else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4442 nfs_rw_exit(&mi->mi_fh_lock);
4443 return (TRUE);
4444 }
4445 nfs_rw_exit(&mi->mi_fh_lock);
4446 return (FALSE);
4447 case OP_CLOOKUP:
4448 len = strlen(objp->nfs_argop4_u.opclookup.cname);
4449 if (len > NFS4_MAX_UTF8STRING)
4450 return (FALSE);
4451 op = OP_LOOKUP;
4452 if (XDR_PUTINT32(xdrs, &op)) {
4453 if (XDR_PUTINT32(xdrs, &len)) {
4454 return (xdr_opaque(xdrs,
4455 objp->nfs_argop4_u.opclookup.cname,
4456 len));
4457 }
4458 }
4459 return (FALSE);
4460 case OP_COPEN:
4461 /* op processing inlined in xdr_OPEN4cargs */
4462 return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen));
4463 case OP_CREMOVE:
4464 len = strlen(objp->nfs_argop4_u.opcremove.ctarget);
4465 if (len > NFS4_MAX_UTF8STRING)
4466 return (FALSE);
4467 op = OP_REMOVE;
4468 if (XDR_PUTINT32(xdrs, &op)) {
4469 if (XDR_PUTINT32(xdrs, &len)) {
4470 return (xdr_opaque(xdrs,
4471 objp->nfs_argop4_u.opcremove.ctarget,
4472 len));
4473 }
4474 }
4475 return (FALSE);
4476 case OP_CCREATE:
4477 op = OP_CREATE;
4478 if (!XDR_PUTINT32(xdrs, &op))
4479 return (FALSE);
4480 return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate));
4481 case OP_CLINK:
4482 len = strlen(objp->nfs_argop4_u.opclink.cnewname);
4483 if (len > NFS4_MAX_UTF8STRING)
4484 return (FALSE);
4485 op = OP_LINK;
4486 if (XDR_PUTINT32(xdrs, &op)) {
4487 if (XDR_PUTINT32(xdrs, &len)) {
4488 return (xdr_opaque(xdrs,
4489 objp->nfs_argop4_u.opclink.cnewname,
4490 len));
4491 }
4492 }
4493 return (FALSE);
4494 case OP_CRENAME:
4495 len = strlen(objp->nfs_argop4_u.opcrename.coldname);
4496 if (len > NFS4_MAX_UTF8STRING)
4497 return (FALSE);
4498 op = OP_RENAME;
4499 if (!XDR_PUTINT32(xdrs, &op))
4500 return (FALSE);
4501 if (!XDR_PUTINT32(xdrs, &len))
4502 return (FALSE);
4503 if (!xdr_opaque(xdrs,
4504 objp->nfs_argop4_u.opcrename.coldname, len))
4505 return (FALSE);
4506 len = strlen(objp->nfs_argop4_u.opcrename.cnewname);
4507 if (len > NFS4_MAX_UTF8STRING)
4508 return (FALSE);
4509 if (XDR_PUTINT32(xdrs, &len)) {
4510 return (xdr_opaque(xdrs,
4511 objp->nfs_argop4_u.opcrename.cnewname, len));
4512 }
4513 return (FALSE);
4514 case OP_CSECINFO:
4515 len = strlen(objp->nfs_argop4_u.opcsecinfo.cname);
4516 if (len > NFS4_MAX_UTF8STRING)
4517 return (FALSE);
4518 op = OP_SECINFO;
4519 if (XDR_PUTINT32(xdrs, &op)) {
4520 if (XDR_PUTINT32(xdrs, &len)) {
4521 return (xdr_opaque(xdrs,
4522 objp->nfs_argop4_u.opcsecinfo.cname,
4523 len));
4524 }
4525 }
4526 return (FALSE);
4527 }
4528 return (FALSE);
4529 }
4530
4531 /*
4532 * Note that the len and decode_len will only be different in the case
4533 * of the client's use of this free function. If the server is
4534 * freeing results, then the len/decode_len will always match.
4535 */
4536 static bool_t
xdr_nfs_resop4_free(XDR * xdrs,nfs_resop4 ** arrayp,int len,int decode_len)4537 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4538 {
4539 int i;
4540 nfs_resop4 *array = *arrayp;
4541 nfs4_ga_res_t *gr;
4542
4543 /*
4544 * Optimized XDR_FREE only results array
4545 */
4546 ASSERT(xdrs->x_op == XDR_FREE);
4547
4548 if (array == NULL)
4549 return (TRUE);
4550
4551 for (i = 0; i < decode_len; i++) {
4552 /*
4553 * These should be ordered by frequency of use
4554 */
4555 switch (array[i].resop) {
4556 case OP_PUTFH:
4557 continue;
4558 case OP_GETATTR:
4559 if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK)
4560 continue;
4561
4562 gr = &array[i].nfs_resop4_u.opgetattr.ga_res;
4563 if (gr->n4g_ext_res) {
4564 if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK)
4565 (void) xdr_fattr4_fs_locations(xdrs,
4566 &gr->n4g_ext_res->n4g_fslocations);
4567 kmem_free(gr->n4g_ext_res,
4568 sizeof (struct nfs4_ga_ext_res));
4569 }
4570 continue;
4571 case OP_GETFH:
4572 if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK)
4573 continue;
4574 if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val !=
4575 NULL) {
4576 kmem_free(array[i].nfs_resop4_u.opgetfh.object.
4577 nfs_fh4_val,
4578 array[i].nfs_resop4_u.opgetfh.object.
4579 nfs_fh4_len);
4580 }
4581 continue;
4582 case OP_LOOKUP:
4583 continue;
4584 case OP_OPEN:
4585 (void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u.
4586 opopen);
4587 continue;
4588 case OP_CLOSE:
4589 case OP_ACCESS:
4590 continue;
4591 case OP_READ:
4592 (void) xdr_READ4res(xdrs,
4593 &array[i].nfs_resop4_u.opread);
4594 continue;
4595 case OP_WRITE:
4596 case OP_DELEGRETURN:
4597 case OP_LOOKUPP:
4598 case OP_READDIR:
4599 case OP_REMOVE:
4600 case OP_COMMIT:
4601 case OP_CREATE:
4602 case OP_DELEGPURGE:
4603 case OP_LINK:
4604 continue;
4605 case OP_LOCK:
4606 (void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u.
4607 oplock);
4608 continue;
4609 case OP_LOCKT:
4610 (void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u.
4611 oplockt);
4612 continue;
4613 case OP_LOCKU:
4614 case OP_NVERIFY:
4615 case OP_OPENATTR:
4616 case OP_OPEN_CONFIRM:
4617 case OP_OPEN_DOWNGRADE:
4618 case OP_PUTPUBFH:
4619 case OP_PUTROOTFH:
4620 case OP_RENAME:
4621 case OP_RENEW:
4622 case OP_RESTOREFH:
4623 case OP_SAVEFH:
4624 continue;
4625 case OP_READLINK:
4626 (void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u.
4627 opreadlink);
4628 continue;
4629 case OP_SECINFO:
4630 (void) xdr_array(xdrs,
4631 (char **)&array[i].nfs_resop4_u.opsecinfo.
4632 SECINFO4resok_val,
4633 (uint_t *)&array[i].nfs_resop4_u.opsecinfo.
4634 SECINFO4resok_len,
4635 NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4636 (xdrproc_t)xdr_secinfo4);
4637 continue;
4638 case OP_SETCLIENTID:
4639 (void) xdr_SETCLIENTID4res(xdrs,
4640 &array[i].nfs_resop4_u.opsetclientid);
4641 continue;
4642 case OP_SETATTR:
4643 case OP_SETCLIENTID_CONFIRM:
4644 case OP_VERIFY:
4645 case OP_RELEASE_LOCKOWNER:
4646 case OP_ILLEGAL:
4647 continue;
4648 default:
4649 /*
4650 * An invalid op is a coding error, it should never
4651 * have been decoded.
4652 * Don't error because the caller cannot finish
4653 * freeing the residual memory of the array.
4654 */
4655 continue;
4656 }
4657 }
4658
4659 kmem_free(*arrayp, len * sizeof (nfs_resop4));
4660 *arrayp = NULL;
4661 return (TRUE);
4662 }
4663
4664 static bool_t
xdr_snfs_resop4_free(XDR * xdrs,nfs_resop4 ** arrayp,int len,int decode_len)4665 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4666 {
4667 return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len));
4668 }
4669
4670 static bool_t
xdr_nfs_resop4(XDR * xdrs,nfs_resop4 * objp)4671 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4672 {
4673 /*
4674 * These should be ordered by frequency of use
4675 */
4676 switch (objp->resop) {
4677 case OP_PUTFH:
4678 return (xdr_int(xdrs,
4679 (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4680 case OP_GETATTR:
4681 if (!xdr_int(xdrs,
4682 (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4683 return (FALSE);
4684 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4685 return (TRUE);
4686 return (xdr_fattr4(xdrs,
4687 &objp->nfs_resop4_u.opgetattr.obj_attributes));
4688 case OP_GETFH:
4689 if (!xdr_int(xdrs,
4690 (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4691 return (FALSE);
4692 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4693 return (TRUE);
4694 return (xdr_bytes(xdrs,
4695 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4696 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4697 NFS4_FHSIZE));
4698 case OP_LOOKUP:
4699 return (xdr_int(xdrs,
4700 (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4701 case OP_OPEN:
4702 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4703 case OP_CLOSE:
4704 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4705 case OP_ACCESS:
4706 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4707 case OP_READ:
4708 return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread));
4709 case OP_WRITE:
4710 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4711 case OP_DELEGRETURN:
4712 return (xdr_int(xdrs,
4713 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4714 case OP_LOOKUPP:
4715 return (xdr_int(xdrs,
4716 (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4717 case OP_READDIR:
4718 return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir));
4719 case OP_REMOVE:
4720 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4721
4722 case OP_COMMIT:
4723 if (!xdr_int(xdrs,
4724 (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4725 return (FALSE);
4726 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4727 return (TRUE);
4728 return (xdr_u_longlong_t(xdrs,
4729 (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4730 writeverf));
4731 case OP_CREATE:
4732 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4733 case OP_DELEGPURGE:
4734 return (xdr_int(xdrs,
4735 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4736 case OP_LINK:
4737 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4738 case OP_LOCK:
4739 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4740 case OP_LOCKT:
4741 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4742 case OP_LOCKU:
4743 if (!xdr_int(xdrs,
4744 (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4745 return (FALSE);
4746 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4747 return (TRUE);
4748 if (!xdr_u_int(xdrs,
4749 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4750 return (FALSE);
4751 return (xdr_opaque(xdrs,
4752 objp->nfs_resop4_u.oplocku.lock_stateid.other,
4753 NFS4_OTHER_SIZE));
4754 case OP_NVERIFY:
4755 return (xdr_int(xdrs,
4756 (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4757 case OP_OPENATTR:
4758 return (xdr_int(xdrs,
4759 (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4760 case OP_OPEN_CONFIRM:
4761 return (xdr_OPEN_CONFIRM4res(xdrs,
4762 &objp->nfs_resop4_u.opopen_confirm));
4763 case OP_OPEN_DOWNGRADE:
4764 return (xdr_OPEN_DOWNGRADE4res(xdrs,
4765 &objp->nfs_resop4_u.opopen_downgrade));
4766 case OP_PUTPUBFH:
4767 return (xdr_int(xdrs,
4768 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4769 case OP_PUTROOTFH:
4770 return (xdr_int(xdrs,
4771 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4772 case OP_READLINK:
4773 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4774 case OP_RENAME:
4775 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4776 case OP_RENEW:
4777 return (xdr_int(xdrs,
4778 (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4779 case OP_RESTOREFH:
4780 return (xdr_int(xdrs,
4781 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4782 case OP_SAVEFH:
4783 return (xdr_int(xdrs,
4784 (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4785 case OP_SECINFO:
4786 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4787 status))
4788 return (FALSE);
4789 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4790 return (TRUE);
4791 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4792 SECINFO4resok_val,
4793 (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4794 SECINFO4resok_len,
4795 NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4796 (xdrproc_t)xdr_secinfo4));
4797 case OP_SETATTR:
4798 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4799 status))
4800 return (FALSE);
4801 return (xdr_bitmap4(xdrs,
4802 &objp->nfs_resop4_u.opsetattr.attrsset));
4803 case OP_SETCLIENTID:
4804 return (xdr_SETCLIENTID4res(xdrs,
4805 &objp->nfs_resop4_u.opsetclientid));
4806 case OP_SETCLIENTID_CONFIRM:
4807 return (xdr_int(xdrs,
4808 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4809 status));
4810 case OP_VERIFY:
4811 return (xdr_int(xdrs,
4812 (int32_t *)&objp->nfs_resop4_u.opverify.status));
4813 case OP_RELEASE_LOCKOWNER:
4814 return (xdr_int(xdrs,
4815 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4816 case OP_ILLEGAL:
4817 return (xdr_int(xdrs,
4818 (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4819 }
4820 return (FALSE);
4821 }
4822
4823 static bool_t
xdr_snfs_resop4(XDR * xdrs,nfs_resop4 * objp)4824 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4825 {
4826 if (!xdr_int(xdrs, (int *)&objp->resop))
4827 return (FALSE);
4828
4829 switch (objp->resop) {
4830 case OP_GETFH:
4831 if (!XDR_PUTINT32(xdrs,
4832 (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4833 return (FALSE);
4834 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4835 return (TRUE);
4836 return (xdr_encode_nfs_fh4(xdrs,
4837 &objp->nfs_resop4_u.opgetfh.object));
4838 default:
4839 if (objp->resop >= OP_BACKCHANNEL_CTL &&
4840 objp->resop != OP_ILLEGAL)
4841 return (xdr_nfs4x_resop4(xdrs, objp));
4842
4843 return (xdr_nfs_resop4(xdrs, objp));
4844 }
4845 }
4846
4847 static bool_t
xdr_nfs_resop4_clnt(XDR * xdrs,nfs_resop4 * objp,nfs_argop4 * aobjp)4848 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp)
4849 {
4850 if (!xdr_int(xdrs, (int *)&objp->resop))
4851 return (FALSE);
4852 /*
4853 * These should be ordered by frequency of use
4854 */
4855 switch (objp->resop) {
4856 case OP_PUTFH:
4857 return (xdr_int(xdrs,
4858 (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4859 case OP_GETATTR:
4860 if (!xdr_int(xdrs,
4861 (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4862 return (FALSE);
4863 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4864 return (TRUE);
4865 return (xdr_ga_res(xdrs,
4866 (GETATTR4res *)&objp->nfs_resop4_u.opgetattr,
4867 &aobjp->nfs_argop4_u.opgetattr));
4868 case OP_GETFH:
4869 if (!xdr_int(xdrs,
4870 (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4871 return (FALSE);
4872 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4873 return (TRUE);
4874 return (xdr_bytes(xdrs,
4875 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4876 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4877 NFS4_FHSIZE));
4878 case OP_LOOKUP:
4879 return (xdr_int(xdrs,
4880 (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4881 case OP_NVERIFY:
4882 return (xdr_int(xdrs,
4883 (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4884 case OP_OPEN:
4885 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4886 case OP_CLOSE:
4887 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4888 case OP_ACCESS:
4889 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4890 case OP_READ:
4891 return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread,
4892 &aobjp->nfs_argop4_u.opread));
4893 case OP_WRITE:
4894 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4895 case OP_DELEGRETURN:
4896 return (xdr_int(xdrs,
4897 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4898 case OP_LOOKUPP:
4899 return (xdr_int(xdrs,
4900 (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4901 case OP_READDIR:
4902 return (xdr_READDIR4res_clnt(xdrs,
4903 &objp->nfs_resop4_u.opreaddirclnt,
4904 &aobjp->nfs_argop4_u.opreaddir));
4905 case OP_REMOVE:
4906 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4907
4908 case OP_COMMIT:
4909 if (!xdr_int(xdrs,
4910 (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4911 return (FALSE);
4912 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4913 return (TRUE);
4914 return (xdr_u_longlong_t(xdrs,
4915 (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4916 writeverf));
4917 case OP_CREATE:
4918 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4919 case OP_DELEGPURGE:
4920 return (xdr_int(xdrs,
4921 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4922 case OP_LINK:
4923 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4924 case OP_LOCK:
4925 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4926 case OP_LOCKT:
4927 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4928 case OP_LOCKU:
4929 if (!xdr_int(xdrs,
4930 (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4931 return (FALSE);
4932 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4933 return (TRUE);
4934 if (!xdr_u_int(xdrs,
4935 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4936 return (FALSE);
4937 return (xdr_opaque(xdrs,
4938 objp->nfs_resop4_u.oplocku.lock_stateid.other,
4939 NFS4_OTHER_SIZE));
4940 case OP_OPENATTR:
4941 return (xdr_int(xdrs,
4942 (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4943 case OP_OPEN_CONFIRM:
4944 return (xdr_OPEN_CONFIRM4res(xdrs,
4945 &objp->nfs_resop4_u.opopen_confirm));
4946 case OP_OPEN_DOWNGRADE:
4947 return (xdr_OPEN_DOWNGRADE4res(xdrs,
4948 &objp->nfs_resop4_u.opopen_downgrade));
4949 case OP_PUTPUBFH:
4950 return (xdr_int(xdrs,
4951 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4952 case OP_PUTROOTFH:
4953 return (xdr_int(xdrs,
4954 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4955 case OP_READLINK:
4956 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4957 case OP_RENAME:
4958 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4959 case OP_RENEW:
4960 return (xdr_int(xdrs,
4961 (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4962 case OP_RESTOREFH:
4963 return (xdr_int(xdrs,
4964 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4965 case OP_SAVEFH:
4966 return (xdr_int(xdrs,
4967 (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4968 case OP_SECINFO:
4969 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4970 status))
4971 return (FALSE);
4972 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4973 return (TRUE);
4974 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4975 SECINFO4resok_val,
4976 (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4977 SECINFO4resok_len,
4978 ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4));
4979 case OP_SETATTR:
4980 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4981 status))
4982 return (FALSE);
4983 return (xdr_bitmap4(xdrs,
4984 &objp->nfs_resop4_u.opsetattr.attrsset));
4985 case OP_SETCLIENTID:
4986 return (xdr_SETCLIENTID4res(xdrs,
4987 &objp->nfs_resop4_u.opsetclientid));
4988 case OP_SETCLIENTID_CONFIRM:
4989 return (xdr_int(xdrs,
4990 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4991 status));
4992 case OP_VERIFY:
4993 return (xdr_int(xdrs,
4994 (int32_t *)&objp->nfs_resop4_u.opverify.status));
4995 case OP_RELEASE_LOCKOWNER:
4996 return (xdr_int(xdrs,
4997 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4998 case OP_ILLEGAL:
4999 return (xdr_int(xdrs,
5000 (int32_t *)&objp->nfs_resop4_u.opillegal.status));
5001 }
5002 return (FALSE);
5003 }
5004
5005 bool_t
xdr_COMPOUND4args_clnt(XDR * xdrs,COMPOUND4args_clnt * objp)5006 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp)
5007 {
5008 static int32_t twelve = 12;
5009 static int32_t minorversion = NFS4_MINORVERSION;
5010 uint32_t *ctagp;
5011 rpc_inline_t *ptr;
5012 rdma_chunkinfo_t rci;
5013 struct xdr_ops *xops = xdrrdma_xops();
5014
5015 /*
5016 * XDR_ENCODE only
5017 */
5018 if (xdrs->x_op == XDR_FREE)
5019 return (TRUE);
5020 if (xdrs->x_op == XDR_DECODE)
5021 return (FALSE);
5022
5023 ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag;
5024
5025 if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) {
5026 /*
5027 * Efficiently encode fixed length tags, could be longlongs
5028 * but 8 byte XDR alignment not assured
5029 */
5030 IXDR_PUT_U_INT32(ptr, 12);
5031 IXDR_PUT_U_INT32(ptr, ctagp[0]);
5032 IXDR_PUT_U_INT32(ptr, ctagp[1]);
5033 IXDR_PUT_U_INT32(ptr, ctagp[2]);
5034
5035 /*
5036 * Fixed minor version for now
5037 */
5038 IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION);
5039 } else {
5040 if (!XDR_PUTINT32(xdrs, &twelve))
5041 return (FALSE);
5042 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0]))
5043 return (FALSE);
5044 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1]))
5045 return (FALSE);
5046 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2]))
5047 return (FALSE);
5048 if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion))
5049 return (FALSE);
5050 }
5051 if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
5052 rci.rci_type = RCI_REPLY_CHUNK;
5053 rci.rci_len = MAXPATHLEN * 2;
5054 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
5055 }
5056
5057 return (xdr_array(xdrs, (char **)&objp->array,
5058 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5059 sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4));
5060 }
5061
5062 bool_t
xdr_COMPOUND4args_srv(XDR * xdrs,COMPOUND4args * objp)5063 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp)
5064 {
5065 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5066 (uint_t *)&objp->tag.utf8string_len,
5067 NFS4_MAX_UTF8STRING))
5068 return (FALSE);
5069 if (!xdr_u_int(xdrs, &objp->minorversion))
5070 return (FALSE);
5071 if (xdrs->x_op != XDR_FREE)
5072 return (xdr_array(xdrs, (char **)&objp->array,
5073 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5074 sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4));
5075
5076 return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len));
5077 }
5078
5079 bool_t
xdr_COMPOUND4res_clnt(XDR * xdrs,COMPOUND4res_clnt * objp)5080 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp)
5081 {
5082 uint32_t len;
5083 int32_t *ptr;
5084 nfs_argop4 *argop;
5085 nfs_resop4 *resop;
5086
5087 /*
5088 * No XDR_ENCODE
5089 */
5090 if (xdrs->x_op == XDR_ENCODE)
5091 return (FALSE);
5092
5093 if (xdrs->x_op != XDR_FREE) {
5094 if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) {
5095 objp->status = IXDR_GET_U_INT32(ptr);
5096 len = IXDR_GET_U_INT32(ptr);
5097 } else {
5098 if (!xdr_int(xdrs, (int32_t *)&objp->status))
5099 return (FALSE);
5100 if (!xdr_u_int(xdrs, (uint32_t *)&len))
5101 return (FALSE);
5102 }
5103 if (len > NFS4_MAX_UTF8STRING)
5104 return (FALSE);
5105 /*
5106 * Ignore the tag
5107 */
5108 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len))
5109 return (FALSE);
5110
5111 if (!xdr_int(xdrs, (int32_t *)&objp->array_len))
5112 return (FALSE);
5113
5114 if (objp->array_len > objp->argsp->array_len)
5115 return (FALSE);
5116
5117 if (objp->status == NFS4_OK &&
5118 objp->array_len != objp->argsp->array_len)
5119 return (FALSE);
5120
5121 /* Alloc the results array */
5122 argop = objp->argsp->array;
5123 len = objp->array_len * sizeof (nfs_resop4);
5124 objp->decode_len = 0;
5125 objp->array = resop = kmem_zalloc(len, KM_SLEEP);
5126
5127 for (len = 0; len < objp->array_len;
5128 len++, resop++, argop++, objp->decode_len++) {
5129 if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) {
5130 /*
5131 * Make sure to free anything that may
5132 * have been allocated along the way.
5133 */
5134 xdrs->x_op = XDR_FREE;
5135 (void) xdr_nfs_resop4_free(xdrs, &objp->array,
5136 objp->array_len,
5137 objp->decode_len);
5138 return (FALSE);
5139 }
5140 }
5141 return (TRUE);
5142 }
5143 return (xdr_nfs_resop4_free(xdrs, &objp->array,
5144 objp->array_len, objp->decode_len));
5145 }
5146
5147 bool_t
xdr_COMPOUND4res_srv(XDR * xdrs,COMPOUND4res * objp)5148 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp)
5149 {
5150 if (!xdr_int(xdrs, (int32_t *)&objp->status))
5151 return (FALSE);
5152 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5153 (uint_t *)&objp->tag.utf8string_len,
5154 NFS4_MAX_UTF8STRING))
5155 return (FALSE);
5156
5157 if (xdrs->x_op != XDR_FREE)
5158 return (xdr_array(xdrs, (char **)&objp->array,
5159 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5160 sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4));
5161
5162 return (xdr_snfs_resop4_free(xdrs, &objp->array,
5163 objp->array_len, objp->array_len));
5164 }
5165
5166 /*
5167 * NFS server side callback, initiating the callback request so it
5168 * is the RPC client. Must convert from server's internal filehandle
5169 * format to wire format.
5170 */
5171 static bool_t
xdr_snfs_cb_argop4(XDR * xdrs,nfs_cb_argop4 * objp)5172 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5173 {
5174 CB_GETATTR4args *gargs;
5175 CB_RECALL4args *rargs;
5176
5177 ASSERT(xdrs->x_op == XDR_ENCODE);
5178
5179 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop))
5180 return (FALSE);
5181
5182 switch (objp->argop) {
5183 case OP_CB_GETATTR:
5184 gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5185
5186 if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh))
5187 return (FALSE);
5188 return (xdr_bitmap4(xdrs, &gargs->attr_request));
5189 case OP_CB_RECALL:
5190 rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5191
5192 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid))
5193 return (FALSE);
5194 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5195 return (FALSE);
5196 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate))
5197 return (FALSE);
5198 return (xdr_encode_nfs_fh4(xdrs, &rargs->fh));
5199 case OP_CB_ILLEGAL:
5200 return (TRUE);
5201 }
5202 return (FALSE);
5203 }
5204
5205 /*
5206 * NFS client side callback, receiving the callback request so it
5207 * is the RPC server. Must treat the file handles as opaque.
5208 */
5209 static bool_t
xdr_cnfs_cb_argop4(XDR * xdrs,nfs_cb_argop4 * objp)5210 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5211 {
5212 CB_GETATTR4args *gargs;
5213 CB_RECALL4args *rargs;
5214
5215 ASSERT(xdrs->x_op != XDR_ENCODE);
5216
5217 if (!xdr_u_int(xdrs, &objp->argop))
5218 return (FALSE);
5219 switch (objp->argop) {
5220 case OP_CB_GETATTR:
5221 gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5222
5223 if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val,
5224 (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE))
5225 return (FALSE);
5226 return (xdr_bitmap4(xdrs, &gargs->attr_request));
5227 case OP_CB_RECALL:
5228 rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5229
5230 if (!xdr_u_int(xdrs, &rargs->stateid.seqid))
5231 return (FALSE);
5232 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5233 return (FALSE);
5234 if (!xdr_bool(xdrs, &rargs->truncate))
5235 return (FALSE);
5236 return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val,
5237 (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE));
5238 case OP_CB_ILLEGAL:
5239 return (TRUE);
5240 }
5241 return (FALSE);
5242 }
5243
5244 /*
5245 * The NFS client side callback, RPC server
5246 */
5247 bool_t
xdr_CB_COMPOUND4args_clnt(XDR * xdrs,CB_COMPOUND4args * objp)5248 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp)
5249 {
5250 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5251 (uint_t *)&objp->tag.utf8string_len,
5252 NFS4_MAX_UTF8STRING))
5253 return (FALSE);
5254 if (!xdr_u_int(xdrs, &objp->minorversion))
5255 return (FALSE);
5256 if (!xdr_u_int(xdrs, &objp->callback_ident))
5257 return (FALSE);
5258 return (xdr_array(xdrs, (char **)&objp->array,
5259 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5260 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4));
5261 }
5262
5263 /*
5264 * The NFS server side callback, RPC client
5265 */
5266 bool_t
xdr_CB_COMPOUND4args_srv(XDR * xdrs,CB_COMPOUND4args * objp)5267 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp)
5268 {
5269 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5270 (uint_t *)&objp->tag.utf8string_len,
5271 NFS4_MAX_UTF8STRING))
5272 return (FALSE);
5273 if (!xdr_u_int(xdrs, &objp->minorversion))
5274 return (FALSE);
5275 if (!xdr_u_int(xdrs, &objp->callback_ident))
5276 return (FALSE);
5277 return (xdr_array(xdrs, (char **)&objp->array,
5278 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5279 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4));
5280 }
5281
5282 bool_t
xdr_CB_COMPOUND4res(XDR * xdrs,CB_COMPOUND4res * objp)5283 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp)
5284 {
5285 if (!xdr_int(xdrs, (int32_t *)&objp->status))
5286 return (FALSE);
5287 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5288 (uint_t *)&objp->tag.utf8string_len,
5289 NFS4_MAX_UTF8STRING))
5290 return (FALSE);
5291 return (xdr_array(xdrs, (char **)&objp->array,
5292 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5293 sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4));
5294 }
5295