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