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