1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30 /*
31 * Copyright (c) 2013 by Delphix. All rights reserved.
32 */
33
34 /*
35 * A handcoded version based on the original rpcgen code.
36 *
37 * Note: All future NFS4 protocol changes should be added by hand
38 * to this file.
39 *
40 * CAUTION: All protocol changes must also be propagated to:
41 * usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c
42 */
43
44 #include <sys/types.h>
45 #include <sys/sunddi.h>
46 #include <sys/dnlc.h>
47 #include <nfs/nfs.h>
48 #include <nfs/nfs4_kprot.h>
49 #include <nfs/rnode4.h>
50 #include <nfs/nfs4.h>
51 #include <nfs/nfs4_clnt.h>
52 #include <sys/sdt.h>
53 #include <sys/mkdev.h>
54 #include <rpc/rpc_rdma.h>
55 #include <rpc/xdr.h>
56
57 #define xdr_dev_t xdr_u_int
58
59 extern bool_t xdr_netbuf(XDR *, struct netbuf *);
60 extern bool_t xdr_vector(XDR *, char *, const uint_t, const uint_t,
61 const xdrproc_t);
62 bool_t xdr_knetconfig(XDR *, struct knetconfig *);
63
64 bool_t
xdr_bitmap4(XDR * xdrs,bitmap4 * objp)65 xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
66 {
67 int32_t len, size;
68
69 if (xdrs->x_op == XDR_FREE)
70 return (TRUE);
71
72 /*
73 * Simplified bitmap4 processing, always encode from uint64_t
74 * to 2 uint32_t's, always decode first 2 uint32_t's into a
75 * uint64_t and ignore all of the rest.
76 */
77 if (xdrs->x_op == XDR_ENCODE) {
78 len = 2;
79
80 if (!XDR_PUTINT32(xdrs, &len))
81 return (FALSE);
82
83 #if defined(_LITTLE_ENDIAN)
84 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
85 BYTES_PER_XDR_UNIT)) == TRUE) {
86 return (XDR_PUTINT32(xdrs, (int32_t *)objp));
87 }
88 #elif defined(_BIG_ENDIAN)
89 if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) {
90 return (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
91 BYTES_PER_XDR_UNIT)));
92 }
93 #endif
94 return (FALSE);
95 }
96
97 if (!XDR_GETINT32(xdrs, &len))
98 return (FALSE);
99
100 /*
101 * Common fast DECODE cases
102 */
103 if (len == 2) {
104 #if defined(_LITTLE_ENDIAN)
105 if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
106 BYTES_PER_XDR_UNIT)) == TRUE) {
107 return (XDR_GETINT32(xdrs, (int32_t *)objp));
108 }
109 #elif defined(_BIG_ENDIAN)
110 if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) {
111 return (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
112 BYTES_PER_XDR_UNIT)));
113 }
114 #endif
115 return (FALSE);
116 }
117
118 *objp = 0;
119 if (len == 0)
120 return (TRUE);
121
122 /*
123 * The not so common DECODE cases, len == 1 || len > 2
124 */
125 #if defined(_LITTLE_ENDIAN)
126 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
127 return (FALSE);
128 if (--len == 0)
129 return (TRUE);
130 if (!XDR_GETINT32(xdrs, (int32_t *)objp))
131 return (FALSE);
132 #elif defined(_BIG_ENDIAN)
133 if (!XDR_GETINT32(xdrs, (int32_t *)objp))
134 return (FALSE);
135 if (--len == 0)
136 return (TRUE);
137 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
138 return (FALSE);
139 #else
140 return (FALSE);
141 #endif
142
143 if (--len == 0)
144 return (TRUE);
145
146 size = len * BYTES_PER_XDR_UNIT;
147 return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size));
148 }
149
150 /* Called by xdr_array, nfsid_map_xdr */
151 bool_t
xdr_utf8string(XDR * xdrs,utf8string * objp)152 xdr_utf8string(XDR *xdrs, utf8string *objp)
153 {
154 if (xdrs->x_op != XDR_FREE)
155 return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
156 (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
157
158 if (objp->utf8string_val != NULL) {
159 kmem_free(objp->utf8string_val, objp->utf8string_len);
160 objp->utf8string_val = NULL;
161 }
162 return (TRUE);
163 }
164
165 /*
166 * used by NFSv4 referrals to get info needed for NFSv4 referral mount.
167 */
168 bool_t
xdr_nfs_fsl_info(XDR * xdrs,struct nfs_fsl_info * objp)169 xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp)
170 {
171
172 if (!xdr_u_int(xdrs, &objp->netbuf_len))
173 return (FALSE);
174 if (!xdr_u_int(xdrs, &objp->netnm_len))
175 return (FALSE);
176 if (!xdr_u_int(xdrs, &objp->knconf_len))
177 return (FALSE);
178
179 #if defined(_LP64)
180 /*
181 * The object can come from a 32-bit binary; nfsmapid.
182 * To be safe we double the size of the knetconfig to
183 * allow some buffering for decoding.
184 */
185 if (xdrs->x_op == XDR_DECODE)
186 objp->knconf_len += sizeof (struct knetconfig);
187 #endif
188
189 if (!xdr_string(xdrs, &objp->netname, ~0))
190 return (FALSE);
191 if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len,
192 (xdrproc_t)xdr_netbuf))
193 return (FALSE);
194 if (!xdr_pointer(xdrs, (char **)&objp->knconf,
195 objp->knconf_len, (xdrproc_t)xdr_knetconfig))
196 return (FALSE);
197 return (TRUE);
198 }
199
200 bool_t
xdr_knetconfig(XDR * xdrs,struct knetconfig * objp)201 xdr_knetconfig(XDR *xdrs, struct knetconfig *objp)
202 {
203 rpc_inline_t *buf;
204 u_longlong_t dev64;
205 #if !defined(_LP64)
206 uint32_t major, minor;
207 #endif
208 int i;
209
210 if (!xdr_u_int(xdrs, &objp->knc_semantics))
211 return (FALSE);
212 if (xdrs->x_op == XDR_DECODE) {
213 objp->knc_protofmly = (((char *)objp) +
214 sizeof (struct knetconfig));
215 objp->knc_proto = objp->knc_protofmly + KNC_STRSIZE;
216 }
217 if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE))
218 return (FALSE);
219 if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE))
220 return (FALSE);
221
222 /*
223 * For interoperability between 32-bit daemon and 64-bit kernel,
224 * we always treat dev_t as 64-bit number and do the expanding
225 * or compression of dev_t as needed.
226 * We have to hand craft the conversion since there is no available
227 * function in ddi.c. Besides ddi.c is available only in the kernel
228 * and we want to keep both user and kernel of xdr_knetconfig() the
229 * same for consistency.
230 */
231 if (xdrs->x_op == XDR_ENCODE) {
232 #if defined(_LP64)
233 dev64 = objp->knc_rdev;
234 #else
235 major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32;
236 minor = objp->knc_rdev & MAXMIN32;
237 dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor;
238 #endif
239 if (!xdr_u_longlong_t(xdrs, &dev64))
240 return (FALSE);
241 }
242 if (xdrs->x_op == XDR_DECODE) {
243 #if defined(_LP64)
244 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev))
245 return (FALSE);
246 #else
247 if (!xdr_u_longlong_t(xdrs, &dev64))
248 return (FALSE);
249
250 major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32;
251 minor = dev64 & L_MAXMIN32;
252 objp->knc_rdev = (major << L_BITSMINOR32) | minor;
253 #endif
254 }
255
256 if (xdrs->x_op == XDR_ENCODE) {
257 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
258 if (buf == NULL) {
259 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
260 sizeof (uint_t), (xdrproc_t)xdr_u_int))
261 return (FALSE);
262 } else {
263 uint_t *genp;
264
265 for (i = 0, genp = objp->knc_unused;
266 i < 8; i++) {
267 #if defined(_LP64) || defined(_KERNEL)
268 IXDR_PUT_U_INT32(buf, *genp++);
269 #else
270 IXDR_PUT_U_LONG(buf, *genp++);
271 #endif
272 }
273 }
274 return (TRUE);
275 } else if (xdrs->x_op == XDR_DECODE) {
276 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
277 if (buf == NULL) {
278 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
279 sizeof (uint_t), (xdrproc_t)xdr_u_int))
280 return (FALSE);
281 } else {
282 uint_t *genp;
283
284 for (i = 0, genp = objp->knc_unused;
285 i < 8; i++) {
286 #if defined(_LP64) || defined(_KERNEL)
287 *genp++ = IXDR_GET_U_INT32(buf);
288 #else
289 *genp++ = IXDR_GET_U_LONG(buf);
290 #endif
291 }
292 }
293 return (TRUE);
294 }
295
296 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
297 sizeof (uint_t), (xdrproc_t)xdr_u_int))
298 return (FALSE);
299 return (TRUE);
300 }
301
302 /*
303 * XDR_INLINE decode a filehandle.
304 */
305 bool_t
xdr_inline_decode_nfs_fh4(uint32_t * ptr,nfs_fh4_fmt_t * fhp,uint32_t fhsize)306 xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *fhp, uint32_t fhsize)
307 {
308 uchar_t *bp = (uchar_t *)ptr;
309 uchar_t *cp;
310 uint32_t dsize;
311 uintptr_t resid;
312
313 /*
314 * Check to see if what the client sent us is bigger or smaller
315 * than what we can ever possibly send out. NFS_FHMAXDATA is
316 * unfortunately badly named as it is no longer the max and is
317 * really the min of what is sent over the wire.
318 */
319 if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
320 sizeof (ushort_t) + NFS_FHMAXDATA +
321 sizeof (ushort_t) + NFS_FHMAXDATA)) {
322 return (FALSE);
323 }
324
325 /*
326 * All internal parts of a filehandle are in native byte order.
327 *
328 * Decode what should be fh4_fsid, it is aligned.
329 */
330 fhp->fh4_fsid.val[0] = *(uint32_t *)bp;
331 bp += BYTES_PER_XDR_UNIT;
332 fhp->fh4_fsid.val[1] = *(uint32_t *)bp;
333 bp += BYTES_PER_XDR_UNIT;
334
335 /*
336 * Decode what should be fh4_len. fh4_len is two bytes, so we're
337 * unaligned now.
338 */
339 cp = (uchar_t *)&fhp->fh4_len;
340 *cp++ = *bp++;
341 *cp++ = *bp++;
342 fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
343
344 /*
345 * For backwards compatibility, the fid length may be less than
346 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
347 */
348 dsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
349
350 /*
351 * Make sure the client isn't sending us a bogus length for fh4_data.
352 */
353 if (fhsize < dsize)
354 return (FALSE);
355 bcopy(bp, fhp->fh4_data, dsize);
356 bp += dsize;
357 fhsize -= dsize;
358
359 if (fhsize < sizeof (ushort_t))
360 return (FALSE);
361 cp = (uchar_t *)&fhp->fh4_xlen;
362 *cp++ = *bp++;
363 *cp++ = *bp++;
364 fhsize -= sizeof (ushort_t);
365
366 dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
367
368 /*
369 * Make sure the client isn't sending us a bogus length for fh4_xdata.
370 */
371 if (fhsize < dsize)
372 return (FALSE);
373 bcopy(bp, fhp->fh4_xdata, dsize);
374 fhsize -= dsize;
375 bp += dsize;
376
377 /*
378 * We realign things on purpose, so skip any padding
379 */
380 resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
381 if (resid != 0) {
382 if (fhsize < (BYTES_PER_XDR_UNIT - resid))
383 return (FALSE);
384 bp += BYTES_PER_XDR_UNIT - resid;
385 fhsize -= BYTES_PER_XDR_UNIT - resid;
386 }
387
388 if (fhsize < BYTES_PER_XDR_UNIT)
389 return (FALSE);
390 fhp->fh4_flag = *(uint32_t *)bp;
391 bp += BYTES_PER_XDR_UNIT;
392 fhsize -= BYTES_PER_XDR_UNIT;
393
394 #ifdef VOLATILE_FH_TEST
395 if (fhsize < BYTES_PER_XDR_UNIT)
396 return (FALSE);
397 fhp->fh4_volatile_id = *(uint32_t *)bp;
398 bp += BYTES_PER_XDR_UNIT;
399 fhsize -= BYTES_PER_XDR_UNIT;
400 #endif
401 /*
402 * Make sure client didn't send extra bytes
403 */
404 if (fhsize != 0)
405 return (FALSE);
406 return (TRUE);
407 }
408
409 static bool_t
xdr_decode_nfs_fh4(XDR * xdrs,nfs_fh4 * objp)410 xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
411 {
412 uint32_t fhsize; /* filehandle size */
413 uint32_t bufsize;
414 rpc_inline_t *ptr;
415 uchar_t *bp;
416
417 ASSERT(xdrs->x_op == XDR_DECODE);
418
419 /*
420 * Retrieve the filehandle length.
421 */
422 if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
423 return (FALSE);
424
425 objp->nfs_fh4_val = NULL;
426 objp->nfs_fh4_len = 0;
427
428 /*
429 * Check to see if what the client sent us is bigger or smaller
430 * than what we can ever possibly send out. NFS_FHMAXDATA is
431 * unfortunately badly named as it is no longer the max and is
432 * really the min of what is sent over the wire.
433 */
434 if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
435 sizeof (ushort_t) + NFS_FHMAXDATA +
436 sizeof (ushort_t) + NFS_FHMAXDATA)) {
437 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
438 return (FALSE);
439 return (TRUE);
440 }
441
442 /*
443 * bring in fhsize plus any padding
444 */
445 bufsize = RNDUP(fhsize);
446 ptr = XDR_INLINE(xdrs, bufsize);
447 bp = (uchar_t *)ptr;
448 if (ptr == NULL) {
449 bp = kmem_alloc(bufsize, KM_SLEEP);
450 if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
451 kmem_free(bp, bufsize);
452 return (FALSE);
453 }
454 }
455
456 objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP);
457 objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t);
458
459 if (xdr_inline_decode_nfs_fh4((uint32_t *)bp,
460 (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) {
461 /*
462 * If in the process of decoding we find the file handle
463 * is not correctly formed, we need to continue decoding
464 * and trigger an NFS layer error. Set the nfs_fh4_len to
465 * zero so it gets caught as a bad length.
466 */
467 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
468 objp->nfs_fh4_val = NULL;
469 objp->nfs_fh4_len = 0;
470 }
471
472 if (ptr == NULL)
473 kmem_free(bp, bufsize);
474 return (TRUE);
475 }
476
477 /*
478 * XDR_INLINE encode a filehandle.
479 */
480 bool_t
xdr_inline_encode_nfs_fh4(uint32_t ** ptrp,uint32_t * ptr_redzone,nfs_fh4_fmt_t * fhp)481 xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone,
482 nfs_fh4_fmt_t *fhp)
483 {
484 uint32_t *ptr = *ptrp;
485 uchar_t *cp;
486 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */
487 uint32_t padword;
488
489 fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
490 xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
491
492 /*
493 * First get the initial and variable sized part of the filehandle.
494 */
495 otw_len = sizeof (fhp->fh4_fsid) +
496 sizeof (fhp->fh4_len) + fsize +
497 sizeof (fhp->fh4_xlen) + xsize;
498
499 /*
500 * Round out to a full word.
501 */
502 otw_len = RNDUP(otw_len);
503 padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */
504
505 /*
506 * Add in the fixed sized pieces.
507 */
508 otw_len += sizeof (fhp->fh4_flag);
509 #ifdef VOLATILE_FH_TEST
510 otw_len += sizeof (fhp->fh4_volatile_id);
511 #endif
512
513 /*
514 * Make sure we don't exceed our buffer.
515 */
516 if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
517 return (FALSE);
518
519 /*
520 * Zero out the padding.
521 */
522 ptr[padword] = 0;
523
524 IXDR_PUT_U_INT32(ptr, otw_len);
525
526 /*
527 * The rest of the filehandle is in native byteorder
528 */
529 /* fh4_fsid */
530 *ptr++ = (uint32_t)fhp->fh4_fsid.val[0];
531 *ptr++ = (uint32_t)fhp->fh4_fsid.val[1];
532
533 /*
534 * Since the next pieces are unaligned, we need to
535 * do bytewise copies.
536 */
537 cp = (uchar_t *)ptr;
538
539 /* fh4_len + fh4_data */
540 bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize);
541 cp += sizeof (fhp->fh4_len) + fsize;
542
543 /* fh4_xlen + fh4_xdata */
544 bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize);
545 cp += sizeof (fhp->fh4_xlen) + xsize;
546
547 /* do necessary rounding/padding */
548 cp = (uchar_t *)RNDUP((uintptr_t)cp);
549 ptr = (uint32_t *)cp;
550
551 /*
552 * With the above padding, we're word aligned again.
553 */
554 ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
555
556 /* fh4_flag */
557 *ptr++ = (uint32_t)fhp->fh4_flag;
558
559 #ifdef VOLATILE_FH_TEST
560 /* fh4_volatile_id */
561 *ptr++ = (uint32_t)fhp->fh4_volatile_id;
562 #endif
563 *ptrp = ptr;
564
565 return (TRUE);
566 }
567
568 static bool_t
xdr_encode_nfs_fh4(XDR * xdrs,nfs_fh4 * objp)569 xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
570 {
571 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */
572 bool_t ret;
573 rpc_inline_t *ptr;
574 rpc_inline_t *buf = NULL;
575 uint32_t *ptr_redzone;
576 nfs_fh4_fmt_t *fhp;
577
578 ASSERT(xdrs->x_op == XDR_ENCODE);
579
580 fhp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val;
581 fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
582 xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
583
584 /*
585 * First get the over the wire size, it is the 4 bytes
586 * for the length, plus the combined size of the
587 * file handle components.
588 */
589 otw_len = BYTES_PER_XDR_UNIT + sizeof (fhp->fh4_fsid) +
590 sizeof (fhp->fh4_len) + fsize +
591 sizeof (fhp->fh4_xlen) + xsize +
592 sizeof (fhp->fh4_flag);
593 #ifdef VOLATILE_FH_TEST
594 otw_len += sizeof (fhp->fh4_volatile_id);
595 #endif
596 /*
597 * Round out to a full word.
598 */
599 otw_len = RNDUP(otw_len);
600
601 /*
602 * Next try to inline the XDR stream, if that fails (rare)
603 * allocate a buffer to encode the file handle and then
604 * copy it using xdr_opaque and free the buffer.
605 */
606 ptr = XDR_INLINE(xdrs, otw_len);
607 if (ptr == NULL)
608 ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
609
610 ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
611 ret = xdr_inline_encode_nfs_fh4((uint32_t **)&ptr, ptr_redzone, fhp);
612
613 if (buf != NULL) {
614 if (ret == TRUE)
615 ret = xdr_opaque(xdrs, (char *)buf, otw_len);
616 kmem_free(buf, otw_len);
617 }
618 return (ret);
619 }
620
621 /*
622 * XDR a NFSv4 filehandle.
623 * Encoding interprets the contents (server).
624 * Decoding the contents are opaque (client).
625 */
626 bool_t
xdr_nfs_fh4(XDR * xdrs,nfs_fh4 * objp)627 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
628 {
629 switch (xdrs->x_op) {
630 case XDR_ENCODE:
631 return (xdr_encode_nfs_fh4(xdrs, objp));
632 case XDR_DECODE:
633 return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val,
634 (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE));
635 case XDR_FREE:
636 if (objp->nfs_fh4_val != NULL) {
637 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
638 objp->nfs_fh4_val = NULL;
639 }
640 return (TRUE);
641 }
642 return (FALSE);
643 }
644
645 /* Called by xdr_array */
646 static bool_t
xdr_fs_location4(XDR * xdrs,fs_location4 * objp)647 xdr_fs_location4(XDR *xdrs, fs_location4 *objp)
648 {
649 if (xdrs->x_op == XDR_DECODE) {
650 objp->server_val = NULL;
651 objp->rootpath.pathname4_val = NULL;
652 }
653 if (!xdr_array(xdrs, (char **)&objp->server_val,
654 (uint_t *)&objp->server_len, NFS4_MAX_UTF8STRING,
655 sizeof (utf8string), (xdrproc_t)xdr_utf8string))
656 return (FALSE);
657 return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val,
658 (uint_t *)&objp->rootpath.pathname4_len,
659 NFS4_MAX_PATHNAME4,
660 sizeof (utf8string), (xdrproc_t)xdr_utf8string));
661 }
662
663 /* Called by xdr_array */
664 static bool_t
xdr_nfsace4(XDR * xdrs,nfsace4 * objp)665 xdr_nfsace4(XDR *xdrs, nfsace4 *objp)
666 {
667 if (xdrs->x_op != XDR_FREE) {
668 if (!xdr_u_int(xdrs, &objp->type))
669 return (FALSE);
670 if (!xdr_u_int(xdrs, &objp->flag))
671 return (FALSE);
672 if (!xdr_u_int(xdrs, &objp->access_mask))
673 return (FALSE);
674
675 if (xdrs->x_op == XDR_DECODE) {
676 objp->who.utf8string_val = NULL;
677 objp->who.utf8string_len = 0;
678 }
679
680 return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val,
681 (uint_t *)&objp->who.utf8string_len,
682 NFS4_MAX_UTF8STRING));
683 }
684
685 /*
686 * Optimized free case
687 */
688 if (objp->who.utf8string_val != NULL) {
689 kmem_free(objp->who.utf8string_val, objp->who.utf8string_len);
690 objp->who.utf8string_val = NULL;
691 }
692 return (TRUE);
693 }
694
695 /*
696 * These functions are called out of nfs4_attr.c
697 */
698 bool_t
xdr_fattr4_fsid(XDR * xdrs,fattr4_fsid * objp)699 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp)
700 {
701 if (xdrs->x_op == XDR_FREE)
702 return (TRUE);
703
704 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major))
705 return (FALSE);
706 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor));
707 }
708
709
710 bool_t
xdr_fattr4_acl(XDR * xdrs,fattr4_acl * objp)711 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp)
712 {
713 return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val,
714 (uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT,
715 sizeof (nfsace4), (xdrproc_t)xdr_nfsace4));
716 }
717
718 bool_t
xdr_fattr4_fs_locations(XDR * xdrs,fattr4_fs_locations * objp)719 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp)
720 {
721 if (xdrs->x_op == XDR_DECODE) {
722 objp->fs_root.pathname4_len = 0;
723 objp->fs_root.pathname4_val = NULL;
724 objp->locations_val = NULL;
725 }
726 if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val,
727 (uint_t *)&objp->fs_root.pathname4_len,
728 NFS4_MAX_PATHNAME4,
729 sizeof (utf8string), (xdrproc_t)xdr_utf8string))
730 return (FALSE);
731 return (xdr_array(xdrs, (char **)&objp->locations_val,
732 (uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT,
733 sizeof (fs_location4), (xdrproc_t)xdr_fs_location4));
734 }
735
736 bool_t
xdr_fattr4_rawdev(XDR * xdrs,fattr4_rawdev * objp)737 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp)
738 {
739 if (xdrs->x_op == XDR_FREE)
740 return (TRUE);
741
742 if (!xdr_u_int(xdrs, &objp->specdata1))
743 return (FALSE);
744 return (xdr_u_int(xdrs, &objp->specdata2));
745 }
746
747 bool_t
xdr_nfstime4(XDR * xdrs,nfstime4 * objp)748 xdr_nfstime4(XDR *xdrs, nfstime4 *objp)
749 {
750 if (xdrs->x_op == XDR_FREE)
751 return (TRUE);
752
753 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds))
754 return (FALSE);
755 return (xdr_u_int(xdrs, &objp->nseconds));
756 }
757
758
759 /*
760 * structured used for calls into xdr_ga_fattr_res() as a means
761 * to do an immediate/short-term cache of owner/group strings
762 * for callers like the readdir processing. In the case of readdir,
763 * it is likely that the directory objects will be owned by the same
764 * owner/group and if so there is no need to call into the uid/gid
765 * mapping code. While the uid/gid interfaces have their own cache
766 * having one here will reduct pathlength further.
767 */
768 #define MAX_OG_NAME 100
769 typedef struct ug_cache
770 {
771 uid_t uid;
772 gid_t gid;
773 utf8string u_curr, u_last;
774 utf8string g_curr, g_last;
775 char u_buf1[MAX_OG_NAME];
776 char u_buf2[MAX_OG_NAME];
777 char g_buf1[MAX_OG_NAME];
778 char g_buf2[MAX_OG_NAME];
779 } ug_cache_t;
780
781 #define U_SWAP_CURR_LAST(ug) \
782 (ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len; \
783 if ((ug)->u_last.utf8string_val == (ug)->u_buf1) { \
784 (ug)->u_last.utf8string_val = (ug)->u_buf2; \
785 (ug)->u_curr.utf8string_val = (ug)->u_buf1; \
786 } else { \
787 (ug)->u_last.utf8string_val = (ug)->u_buf1; \
788 (ug)->u_curr.utf8string_val = (ug)->u_buf2; \
789 }
790
791 #define G_SWAP_CURR_LAST(ug) \
792 (ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len; \
793 if ((ug)->g_last.utf8string_val == (ug)->g_buf1) { \
794 (ug)->g_last.utf8string_val = (ug)->g_buf2; \
795 (ug)->g_curr.utf8string_val = (ug)->g_buf1; \
796 } else { \
797 (ug)->g_last.utf8string_val = (ug)->g_buf1; \
798 (ug)->g_curr.utf8string_val = (ug)->g_buf2; \
799 }
800
801 static ug_cache_t *
alloc_ugcache()802 alloc_ugcache()
803 {
804 ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP);
805
806 pug->uid = pug->gid = 0;
807 pug->u_curr.utf8string_len = 0;
808 pug->u_last.utf8string_len = 0;
809 pug->g_curr.utf8string_len = 0;
810 pug->g_last.utf8string_len = 0;
811 pug->u_curr.utf8string_val = pug->u_buf1;
812 pug->u_last.utf8string_val = pug->u_buf2;
813 pug->g_curr.utf8string_val = pug->g_buf1;
814 pug->g_last.utf8string_val = pug->g_buf2;
815
816 return (pug);
817 }
818
819 static void
xdr_ga_prefill_vattr(struct nfs4_ga_res * garp,struct mntinfo4 * mi)820 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi)
821 {
822 static vattr_t s_vattr = {
823 AT_ALL, /* va_mask */
824 VNON, /* va_type */
825 0777, /* va_mode */
826 UID_NOBODY, /* va_uid */
827 GID_NOBODY, /* va_gid */
828 0, /* va_fsid */
829 0, /* va_nodeid */
830 1, /* va_nlink */
831 0, /* va_size */
832 {0, 0}, /* va_atime */
833 {0, 0}, /* va_mtime */
834 {0, 0}, /* va_ctime */
835 0, /* va_rdev */
836 MAXBSIZE, /* va_blksize */
837 0, /* va_nblocks */
838 0 /* va_seq */
839 };
840
841
842 garp->n4g_va = s_vattr;
843 garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev;
844 hrt2ts(gethrtime(), &garp->n4g_va.va_atime);
845 garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime;
846 }
847
848 static void
xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res * gesp,struct mntinfo4 * mi)849 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi)
850 {
851 static statvfs64_t s_sb = {
852 MAXBSIZE, /* f_bsize */
853 DEV_BSIZE, /* f_frsize */
854 (fsfilcnt64_t)-1, /* f_blocks */
855 (fsfilcnt64_t)-1, /* f_bfree */
856 (fsfilcnt64_t)-1, /* f_bavail */
857 (fsfilcnt64_t)-1, /* f_files */
858 (fsfilcnt64_t)-1, /* f_ffree */
859 (fsfilcnt64_t)-1, /* f_favail */
860 0, /* f_fsid */
861 "\0", /* f_basetype */
862 0, /* f_flag */
863 MAXNAMELEN, /* f_namemax */
864 "\0", /* f_fstr */
865 };
866
867 gesp->n4g_sb = s_sb;
868 gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0];
869 }
870
871 static bool_t
xdr_ga_fattr_res(XDR * xdrs,struct nfs4_ga_res * garp,bitmap4 resbmap,bitmap4 argbmap,struct mntinfo4 * mi,ug_cache_t * pug)872 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap,
873 bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
874 {
875 int truefalse;
876 struct nfs4_ga_ext_res ges, *gesp;
877 vattr_t *vap = &garp->n4g_va;
878 vsecattr_t *vsap = &garp->n4g_vsa;
879
880 ASSERT(xdrs->x_op == XDR_DECODE);
881
882 if (garp->n4g_ext_res)
883 gesp = garp->n4g_ext_res;
884 else
885 gesp = ⩾
886
887 vap->va_mask = 0;
888
889 /* Check to see if the vattr should be pre-filled */
890 if (argbmap & NFS4_VATTR_MASK)
891 xdr_ga_prefill_vattr(garp, mi);
892
893 if (argbmap & NFS4_STATFS_ATTR_MASK)
894 xdr_ga_prefill_statvfs(gesp, mi);
895
896 if (resbmap &
897 (FATTR4_SUPPORTED_ATTRS_MASK |
898 FATTR4_TYPE_MASK |
899 FATTR4_FH_EXPIRE_TYPE_MASK |
900 FATTR4_CHANGE_MASK |
901 FATTR4_SIZE_MASK |
902 FATTR4_LINK_SUPPORT_MASK |
903 FATTR4_SYMLINK_SUPPORT_MASK |
904 FATTR4_NAMED_ATTR_MASK)) {
905
906 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
907 if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs))
908 return (FALSE);
909 }
910 if (resbmap & FATTR4_TYPE_MASK) {
911 if (!XDR_GETINT32(xdrs, (int *)&vap->va_type))
912 return (FALSE);
913
914 if ((nfs_ftype4)vap->va_type < NF4REG ||
915 (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
916 vap->va_type = VBAD;
917 else
918 vap->va_type = nf4_to_vt[vap->va_type];
919 if (vap->va_type == VBLK)
920 vap->va_blksize = DEV_BSIZE;
921
922 vap->va_mask |= AT_TYPE;
923 }
924 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
925 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet))
926 return (FALSE);
927 }
928 if (resbmap & FATTR4_CHANGE_MASK) {
929 if (!xdr_u_longlong_t(xdrs,
930 (u_longlong_t *)&garp->n4g_change))
931 return (FALSE);
932 garp->n4g_change_valid = 1;
933 }
934 if (resbmap & FATTR4_SIZE_MASK) {
935 if (!xdr_u_longlong_t(xdrs,
936 (u_longlong_t *)&vap->va_size))
937 return (FALSE);
938 if (!NFS4_SIZE_OK(vap->va_size)) {
939 garp->n4g_attrerr = EFBIG;
940 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
941 } else {
942 vap->va_mask |= AT_SIZE;
943 }
944 }
945 if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
946 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
947 return (FALSE);
948 gesp->n4g_pc4.pc4_link_support =
949 (truefalse ? TRUE : FALSE);
950 }
951 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
952 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
953 return (FALSE);
954 gesp->n4g_pc4.pc4_symlink_support =
955 (truefalse ? TRUE : FALSE);
956 }
957 if (resbmap & FATTR4_NAMED_ATTR_MASK) {
958 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
959 return (FALSE);
960 gesp->n4g_pc4.pc4_xattr_exists = TRUE;
961 gesp->n4g_pc4.pc4_xattr_exists =
962 (truefalse ? TRUE : FALSE);
963 }
964 }
965 if (resbmap &
966 (FATTR4_FSID_MASK |
967 FATTR4_UNIQUE_HANDLES_MASK |
968 FATTR4_LEASE_TIME_MASK |
969 FATTR4_RDATTR_ERROR_MASK)) {
970
971 if (resbmap & FATTR4_FSID_MASK) {
972 if ((!xdr_u_longlong_t(xdrs,
973 (u_longlong_t *)&garp->n4g_fsid.major)) ||
974 (!xdr_u_longlong_t(xdrs,
975 (u_longlong_t *)&garp->n4g_fsid.minor)))
976 return (FALSE);
977 garp->n4g_fsid_valid = 1;
978 }
979 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
980 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
981 return (FALSE);
982 gesp->n4g_pc4.pc4_unique_handles =
983 (truefalse ? TRUE : FALSE);
984 }
985 if (resbmap & FATTR4_LEASE_TIME_MASK) {
986 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime))
987 return (FALSE);
988 }
989 if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
990 if (!XDR_GETINT32(xdrs,
991 (int *)&gesp->n4g_rdattr_error))
992 return (FALSE);
993 }
994 }
995 if (resbmap &
996 (FATTR4_ACL_MASK |
997 FATTR4_ACLSUPPORT_MASK |
998 FATTR4_ARCHIVE_MASK |
999 FATTR4_CANSETTIME_MASK)) {
1000
1001 if (resbmap & FATTR4_ACL_MASK) {
1002 fattr4_acl acl;
1003
1004 acl.fattr4_acl_val = NULL;
1005 acl.fattr4_acl_len = 0;
1006
1007 if (!xdr_fattr4_acl(xdrs, &acl))
1008 return (FALSE);
1009
1010 vsap->vsa_aclcnt = acl.fattr4_acl_len;
1011 vsap->vsa_aclentp = acl.fattr4_acl_val;
1012 vsap->vsa_mask = VSA_ACE | VSA_ACECNT;
1013 vsap->vsa_aclentsz = vsap->vsa_aclcnt * sizeof (ace_t);
1014
1015 }
1016 if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1017 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport))
1018 return (FALSE);
1019 }
1020 if (resbmap & FATTR4_ARCHIVE_MASK) {
1021 ASSERT(0);
1022 }
1023 if (resbmap & FATTR4_CANSETTIME_MASK) {
1024 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1025 return (FALSE);
1026 gesp->n4g_pc4.pc4_cansettime =
1027 (truefalse ? TRUE : FALSE);
1028 }
1029 }
1030 if (resbmap &
1031 (FATTR4_CASE_INSENSITIVE_MASK |
1032 FATTR4_CASE_PRESERVING_MASK |
1033 FATTR4_CHOWN_RESTRICTED_MASK |
1034 FATTR4_FILEHANDLE_MASK |
1035 FATTR4_FILEID_MASK |
1036 FATTR4_FILES_AVAIL_MASK |
1037 FATTR4_FILES_FREE_MASK |
1038 FATTR4_FILES_TOTAL_MASK)) {
1039
1040 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1041 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1042 return (FALSE);
1043 gesp->n4g_pc4.pc4_case_insensitive =
1044 (truefalse ? TRUE : FALSE);
1045 }
1046 if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1047 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1048 return (FALSE);
1049 gesp->n4g_pc4.pc4_case_preserving =
1050 (truefalse ? TRUE : FALSE);
1051 }
1052 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1053 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1054 return (FALSE);
1055 gesp->n4g_pc4.pc4_chown_restricted =
1056 (truefalse ? TRUE : FALSE);
1057 }
1058 if (resbmap & FATTR4_FILEHANDLE_MASK) {
1059 gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1060 gesp->n4g_fh_u.nfs_fh4_alt.val =
1061 gesp->n4g_fh_u.nfs_fh4_alt.data;
1062 if (!xdr_bytes(xdrs,
1063 (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val,
1064 (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len,
1065 NFS4_FHSIZE))
1066 return (FALSE);
1067 }
1068 if (resbmap & FATTR4_FILEID_MASK) {
1069 if (!xdr_u_longlong_t(xdrs,
1070 (u_longlong_t *)&vap->va_nodeid))
1071 return (FALSE);
1072 vap->va_mask |= AT_NODEID;
1073 }
1074 if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1075 if (!xdr_u_longlong_t(xdrs,
1076 (u_longlong_t *)&gesp->n4g_sb.f_favail))
1077 return (FALSE);
1078 }
1079 if (resbmap & FATTR4_FILES_FREE_MASK) {
1080 if (!xdr_u_longlong_t(xdrs,
1081 (u_longlong_t *)&gesp->n4g_sb.f_ffree))
1082 return (FALSE);
1083 }
1084 if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1085 if (!xdr_u_longlong_t(xdrs,
1086 (u_longlong_t *)&gesp->n4g_sb.f_files))
1087 return (FALSE);
1088 }
1089 }
1090 if (resbmap &
1091 (FATTR4_FS_LOCATIONS_MASK |
1092 FATTR4_HIDDEN_MASK |
1093 FATTR4_HOMOGENEOUS_MASK)) {
1094
1095 if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1096 if (!xdr_fattr4_fs_locations(xdrs,
1097 &gesp->n4g_fslocations))
1098 return (FALSE);
1099 }
1100 if (resbmap & FATTR4_HIDDEN_MASK) {
1101 ASSERT(0);
1102 }
1103 if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1104 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1105 return (FALSE);
1106 gesp->n4g_pc4.pc4_homogeneous =
1107 (truefalse ? TRUE : FALSE);
1108 }
1109 }
1110 if (resbmap &
1111 (FATTR4_MAXFILESIZE_MASK |
1112 FATTR4_MAXLINK_MASK |
1113 FATTR4_MAXNAME_MASK |
1114 FATTR4_MAXREAD_MASK |
1115 FATTR4_MAXWRITE_MASK)) {
1116
1117 if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1118 if (!xdr_u_longlong_t(xdrs,
1119 (u_longlong_t *)&gesp->n4g_maxfilesize))
1120 return (FALSE);
1121 }
1122 if (resbmap & FATTR4_MAXLINK_MASK) {
1123 if (!XDR_GETINT32(xdrs,
1124 (int *)&gesp->n4g_pc4.pc4_link_max))
1125 return (FALSE);
1126 }
1127 if (resbmap & FATTR4_MAXNAME_MASK) {
1128 if (!XDR_GETINT32(xdrs,
1129 (int *)&gesp->n4g_pc4.pc4_name_max))
1130 return (FALSE);
1131 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1132 }
1133 if (resbmap & FATTR4_MAXREAD_MASK) {
1134 if (!xdr_u_longlong_t(xdrs,
1135 (u_longlong_t *)&gesp->n4g_maxread))
1136 return (FALSE);
1137 }
1138 if (resbmap & FATTR4_MAXWRITE_MASK) {
1139 if (!xdr_u_longlong_t(xdrs,
1140 (u_longlong_t *)&gesp->n4g_maxwrite))
1141 return (FALSE);
1142 }
1143 }
1144 if (resbmap &
1145 (FATTR4_MIMETYPE_MASK |
1146 FATTR4_MODE_MASK |
1147 FATTR4_NO_TRUNC_MASK |
1148 FATTR4_NUMLINKS_MASK)) {
1149
1150 if (resbmap & FATTR4_MIMETYPE_MASK) {
1151 ASSERT(0);
1152 }
1153 if (resbmap & FATTR4_MODE_MASK) {
1154 if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode))
1155 return (FALSE);
1156 vap->va_mask |= AT_MODE;
1157 }
1158 if (resbmap & FATTR4_NO_TRUNC_MASK) {
1159 if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1160 return (FALSE);
1161 gesp->n4g_pc4.pc4_no_trunc =
1162 (truefalse ? TRUE : FALSE);
1163 }
1164 if (resbmap & FATTR4_NUMLINKS_MASK) {
1165 if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink))
1166 return (FALSE);
1167 vap->va_mask |= AT_NLINK;
1168 }
1169 }
1170 if (resbmap &
1171 (FATTR4_OWNER_MASK |
1172 FATTR4_OWNER_GROUP_MASK |
1173 FATTR4_QUOTA_AVAIL_HARD_MASK |
1174 FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1175
1176 if (resbmap & FATTR4_OWNER_MASK) {
1177 uint_t *owner_length, ol;
1178 char *owner_val = NULL;
1179 char *owner_alloc = NULL;
1180 utf8string ov;
1181 int error;
1182
1183 /* get the OWNER_LENGTH */
1184 if (!xdr_u_int(xdrs, &ol))
1185 return (FALSE);
1186
1187 /* Manage the owner length location */
1188 if (pug && ol <= MAX_OG_NAME) {
1189 owner_length = &pug->u_curr.utf8string_len;
1190 *owner_length = ol;
1191 } else {
1192 owner_length = &ol;
1193 }
1194
1195 /* find memory to store the decode */
1196 if (*owner_length > MAX_OG_NAME || pug == NULL)
1197 owner_val = owner_alloc =
1198 kmem_alloc(*owner_length, KM_SLEEP);
1199 else
1200 owner_val = pug->u_curr.utf8string_val;
1201
1202 /* get the OWNER string */
1203 if (!xdr_opaque(xdrs, owner_val, *owner_length)) {
1204 if (owner_alloc)
1205 kmem_free(owner_alloc, *owner_length);
1206 return (FALSE);
1207 }
1208
1209 /* Optimize for matching if called for */
1210 if (pug &&
1211 *owner_length == pug->u_last.utf8string_len &&
1212 bcmp(owner_val, pug->u_last.utf8string_val,
1213 *owner_length) == 0) {
1214 vap->va_uid = pug->uid;
1215 vap->va_mask |= AT_UID;
1216 } else {
1217 uid_t uid;
1218
1219 ov.utf8string_len = *owner_length;
1220 ov.utf8string_val = owner_val;
1221 error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1222 /*
1223 * String was mapped, but to nobody because
1224 * we are nfsmapid, indicate it should not
1225 * be cached.
1226 */
1227 if (error == ENOTSUP) {
1228 error = 0;
1229 garp->n4g_attrwhy =
1230 NFS4_GETATTR_NOCACHE_OK;
1231 }
1232
1233 if (error) {
1234 garp->n4g_attrerr = error;
1235 garp->n4g_attrwhy =
1236 NFS4_GETATTR_ATUID_ERR;
1237 } else {
1238 vap->va_uid = uid;
1239 vap->va_mask |= AT_UID;
1240 if (pug && ol <= MAX_OG_NAME) {
1241 pug->uid = uid;
1242 U_SWAP_CURR_LAST(pug);
1243 }
1244 }
1245 if (owner_alloc)
1246 kmem_free(owner_alloc, *owner_length);
1247 }
1248 }
1249 if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1250 uint_t *group_length, gl;
1251 char *group_val = NULL;
1252 char *group_alloc = NULL;
1253 utf8string gv;
1254 int error;
1255
1256 /* get the OWNER_GROUP_LENGTH */
1257 if (!xdr_u_int(xdrs, &gl))
1258 return (FALSE);
1259
1260 /* Manage the group length location */
1261 if (pug && gl <= MAX_OG_NAME) {
1262 group_length = &pug->g_curr.utf8string_len;
1263 *group_length = gl;
1264 } else {
1265 group_length = ≷
1266 }
1267
1268 /* find memory to store the decode */
1269 if (*group_length > MAX_OG_NAME || pug == NULL)
1270 group_val = group_alloc =
1271 kmem_alloc(*group_length, KM_SLEEP);
1272 else
1273 group_val = pug->g_curr.utf8string_val;
1274
1275 /* get the OWNER_GROUP string */
1276 if (!xdr_opaque(xdrs, group_val, *group_length)) {
1277 if (group_alloc)
1278 kmem_free(group_alloc, *group_length);
1279 return (FALSE);
1280 }
1281
1282 /* Optimize for matching if called for */
1283 if (pug &&
1284 *group_length == pug->g_last.utf8string_len &&
1285 bcmp(group_val, pug->g_last.utf8string_val,
1286 *group_length) == 0) {
1287 vap->va_gid = pug->gid;
1288 vap->va_mask |= AT_GID;
1289 } else {
1290 uid_t gid;
1291
1292 gv.utf8string_len = *group_length;
1293 gv.utf8string_val = group_val;
1294 error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1295 /*
1296 * String was mapped, but to nobody because
1297 * we are nfsmapid, indicate it should not
1298 * be cached.
1299 */
1300 if (error == ENOTSUP) {
1301 error = 0;
1302 garp->n4g_attrwhy =
1303 NFS4_GETATTR_NOCACHE_OK;
1304 }
1305
1306 if (error) {
1307 garp->n4g_attrerr = error;
1308 garp->n4g_attrwhy =
1309 NFS4_GETATTR_ATGID_ERR;
1310 } else {
1311 vap->va_gid = gid;
1312 vap->va_mask |= AT_GID;
1313 if (pug && gl <= MAX_OG_NAME) {
1314 pug->gid = gid;
1315 G_SWAP_CURR_LAST(pug);
1316 }
1317 }
1318 if (group_alloc) {
1319 kmem_free(group_alloc, *group_length);
1320 }
1321 }
1322 }
1323 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1324 ASSERT(0);
1325 }
1326 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1327 ASSERT(0);
1328 }
1329 }
1330 if (resbmap &
1331 (FATTR4_QUOTA_USED_MASK |
1332 FATTR4_SPACE_AVAIL_MASK |
1333 FATTR4_SPACE_FREE_MASK |
1334 FATTR4_SPACE_TOTAL_MASK |
1335 FATTR4_SPACE_USED_MASK |
1336 FATTR4_SYSTEM_MASK)) {
1337
1338 if (resbmap & FATTR4_QUOTA_USED_MASK) {
1339 ASSERT(0);
1340 }
1341 if (resbmap & FATTR4_RAWDEV_MASK) {
1342 fattr4_rawdev rawdev;
1343 if (!xdr_fattr4_rawdev(xdrs, &rawdev))
1344 return (FALSE);
1345
1346 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1347 vap->va_rdev = makedevice(rawdev.specdata1,
1348 rawdev.specdata2);
1349 } else {
1350 vap->va_rdev = 0;
1351 }
1352 vap->va_mask |= AT_RDEV;
1353 }
1354 if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1355 if (!xdr_u_longlong_t(xdrs,
1356 (u_longlong_t *)&gesp->n4g_sb.f_bavail))
1357 return (FALSE);
1358 gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1359 }
1360 if (resbmap & FATTR4_SPACE_FREE_MASK) {
1361 if (!xdr_u_longlong_t(xdrs,
1362 (u_longlong_t *)&gesp->n4g_sb.f_bfree))
1363 return (FALSE);
1364 gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1365 }
1366 if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1367 if (!xdr_u_longlong_t(xdrs,
1368 (u_longlong_t *)&gesp->n4g_sb.f_blocks))
1369 return (FALSE);
1370 gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1371 }
1372 if (resbmap & FATTR4_SPACE_USED_MASK) {
1373 uint64_t space_used;
1374 if (!xdr_u_longlong_t(xdrs,
1375 (u_longlong_t *)&space_used))
1376 return (FALSE);
1377
1378 /* Compute space depending on device type */
1379 ASSERT((vap->va_mask & AT_TYPE));
1380 if (vap->va_type == VREG || vap->va_type == VDIR ||
1381 vap->va_type == VLNK) {
1382 vap->va_nblocks = (u_longlong_t)
1383 ((space_used + (offset4)DEV_BSIZE -
1384 (offset4)1) / (offset4)DEV_BSIZE);
1385 } else {
1386 vap->va_nblocks = 0;
1387 }
1388 vap->va_mask |= AT_NBLOCKS;
1389 }
1390 if (resbmap & FATTR4_SYSTEM_MASK) {
1391 ASSERT(0);
1392 }
1393 }
1394 if (resbmap &
1395 (FATTR4_TIME_ACCESS_MASK |
1396 FATTR4_TIME_ACCESS_SET_MASK |
1397 FATTR4_TIME_BACKUP_MASK |
1398 FATTR4_TIME_CREATE_MASK |
1399 FATTR4_TIME_DELTA_MASK |
1400 FATTR4_TIME_METADATA_MASK |
1401 FATTR4_TIME_MODIFY_MASK |
1402 FATTR4_TIME_MODIFY_SET_MASK |
1403 FATTR4_MOUNTED_ON_FILEID_MASK)) {
1404
1405 if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1406 nfstime4 atime;
1407 int error;
1408
1409 if (!xdr_longlong_t(xdrs,
1410 (longlong_t *)&atime.seconds))
1411 return (FALSE);
1412 if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds))
1413 return (FALSE);
1414 error = nfs4_time_ntov(&atime, &vap->va_atime);
1415 if (error) {
1416 garp->n4g_attrerr = error;
1417 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
1418 }
1419 vap->va_mask |= AT_ATIME;
1420 }
1421 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
1422 ASSERT(0);
1423 }
1424 if (resbmap & FATTR4_TIME_BACKUP_MASK) {
1425 ASSERT(0);
1426 }
1427 if (resbmap & FATTR4_TIME_CREATE_MASK) {
1428 ASSERT(0);
1429 }
1430 if (resbmap & FATTR4_TIME_DELTA_MASK) {
1431 if ((!xdr_u_longlong_t(xdrs,
1432 (u_longlong_t *)&gesp->n4g_delta.seconds)) ||
1433 (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds)))
1434 return (FALSE);
1435 }
1436 if (resbmap & FATTR4_TIME_METADATA_MASK) {
1437 nfstime4 mdt;
1438 int error;
1439
1440 if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds))
1441 return (FALSE);
1442 if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds))
1443 return (FALSE);
1444 error = nfs4_time_ntov(&mdt, &vap->va_ctime);
1445 if (error) {
1446 garp->n4g_attrerr = error;
1447 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
1448 }
1449 vap->va_mask |= AT_CTIME;
1450 }
1451 if (resbmap & FATTR4_TIME_MODIFY_MASK) {
1452 nfstime4 mtime;
1453 int error;
1454
1455 if (!xdr_longlong_t(xdrs,
1456 (longlong_t *)&mtime.seconds))
1457 return (FALSE);
1458 if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds))
1459 return (FALSE);
1460 error = nfs4_time_ntov(&mtime, &vap->va_mtime);
1461 if (error) {
1462 garp->n4g_attrerr = error;
1463 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
1464 }
1465 vap->va_mask |= AT_MTIME;
1466 }
1467 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
1468 ASSERT(0);
1469 }
1470 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
1471 if (!xdr_u_longlong_t(xdrs,
1472 (u_longlong_t *)&garp->n4g_mon_fid))
1473 return (FALSE);
1474 garp->n4g_mon_fid_valid = 1;
1475 }
1476 }
1477
1478 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
1479 /* copy only if not provided */
1480 if (garp->n4g_ext_res == NULL) {
1481 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
1482 bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
1483 }
1484 }
1485
1486 return (TRUE);
1487 }
1488
1489 /*
1490 * Inlined version of get_bitmap4 processing
1491 */
1492 bitmap4
xdr_get_bitmap4_inline(uint32_t ** iptr)1493 xdr_get_bitmap4_inline(uint32_t **iptr)
1494 {
1495 uint32_t resbmaplen;
1496 bitmap4 bm;
1497 uint32_t *ptr = *iptr;
1498
1499 /* bitmap LENGTH */
1500 resbmaplen = IXDR_GET_U_INT32(ptr);
1501
1502 /* Inline the bitmap and attrlen for common case of two word map */
1503 if (resbmaplen == 2) {
1504 IXDR_GET_HYPER(ptr, bm);
1505 *iptr = ptr;
1506 return (bm);
1507 }
1508
1509 #if defined(_LITTLE_ENDIAN)
1510 bm = IXDR_GET_U_INT32(ptr);
1511 if (--resbmaplen == 0) {
1512 *iptr = ptr;
1513 return (bm);
1514 }
1515 *((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr);
1516 if (--resbmaplen == 0) {
1517 *iptr = ptr;
1518 return (bm);
1519 }
1520 ptr += resbmaplen;
1521 *iptr = ptr;
1522 return (bm);
1523 #elif defined(_BIG_ENDIAN)
1524 *((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr);
1525 if (--resbmaplen == 0) {
1526 *iptr = ptr;
1527 return (bm);
1528 }
1529 bm |= IXDR_GET_U_INT32(ptr);
1530 if (--resbmaplen == 0) {
1531 *iptr = ptr;
1532 return (bm);
1533 }
1534 ptr += resbmaplen;
1535 *iptr = ptr;
1536 return (bm);
1537 #else
1538 ASSERT(0);
1539 ptr += resbmaplen;
1540 *iptr = ptr;
1541 return (0);
1542 #endif
1543 }
1544
1545 static bool_t
xdr_ga_fattr_res_inline(uint32_t * ptr,struct nfs4_ga_res * garp,bitmap4 resbmap,bitmap4 argbmap,struct mntinfo4 * mi,ug_cache_t * pug)1546 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp,
1547 bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
1548 {
1549 int truefalse;
1550 struct nfs4_ga_ext_res ges, *gesp;
1551 vattr_t *vap = &garp->n4g_va;
1552
1553 if (garp->n4g_ext_res)
1554 gesp = garp->n4g_ext_res;
1555 else
1556 gesp = ⩾
1557
1558 vap->va_mask = 0;
1559
1560 /* Check to see if the vattr should be pre-filled */
1561 if (argbmap & NFS4_VATTR_MASK)
1562 xdr_ga_prefill_vattr(garp, mi);
1563
1564 if (argbmap & NFS4_STATFS_ATTR_MASK)
1565 xdr_ga_prefill_statvfs(gesp, mi);
1566
1567 if (resbmap &
1568 (FATTR4_SUPPORTED_ATTRS_MASK |
1569 FATTR4_TYPE_MASK |
1570 FATTR4_FH_EXPIRE_TYPE_MASK |
1571 FATTR4_CHANGE_MASK |
1572 FATTR4_SIZE_MASK |
1573 FATTR4_LINK_SUPPORT_MASK |
1574 FATTR4_SYMLINK_SUPPORT_MASK |
1575 FATTR4_NAMED_ATTR_MASK)) {
1576
1577 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
1578 gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr);
1579 }
1580 if (resbmap & FATTR4_TYPE_MASK) {
1581 vap->va_type = IXDR_GET_U_INT32(ptr);
1582
1583 if ((nfs_ftype4)vap->va_type < NF4REG ||
1584 (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
1585 vap->va_type = VBAD;
1586 else
1587 vap->va_type = nf4_to_vt[vap->va_type];
1588 if (vap->va_type == VBLK)
1589 vap->va_blksize = DEV_BSIZE;
1590
1591 vap->va_mask |= AT_TYPE;
1592 }
1593 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
1594 gesp->n4g_fet = IXDR_GET_U_INT32(ptr);
1595 }
1596 if (resbmap & FATTR4_CHANGE_MASK) {
1597 IXDR_GET_U_HYPER(ptr, garp->n4g_change);
1598 garp->n4g_change_valid = 1;
1599 }
1600 if (resbmap & FATTR4_SIZE_MASK) {
1601 IXDR_GET_U_HYPER(ptr, vap->va_size);
1602
1603 if (!NFS4_SIZE_OK(vap->va_size)) {
1604 garp->n4g_attrerr = EFBIG;
1605 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1606 } else {
1607 vap->va_mask |= AT_SIZE;
1608 }
1609 }
1610 if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1611 truefalse = IXDR_GET_U_INT32(ptr);
1612 gesp->n4g_pc4.pc4_link_support =
1613 (truefalse ? TRUE : FALSE);
1614 }
1615 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1616 truefalse = IXDR_GET_U_INT32(ptr);
1617 gesp->n4g_pc4.pc4_symlink_support =
1618 (truefalse ? TRUE : FALSE);
1619 }
1620 if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1621 truefalse = IXDR_GET_U_INT32(ptr);
1622 gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1623 gesp->n4g_pc4.pc4_xattr_exists =
1624 (truefalse ? TRUE : FALSE);
1625 }
1626 }
1627 if (resbmap &
1628 (FATTR4_FSID_MASK |
1629 FATTR4_UNIQUE_HANDLES_MASK |
1630 FATTR4_LEASE_TIME_MASK |
1631 FATTR4_RDATTR_ERROR_MASK)) {
1632
1633 if (resbmap & FATTR4_FSID_MASK) {
1634 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major);
1635 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor);
1636 garp->n4g_fsid_valid = 1;
1637 }
1638 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1639 truefalse = IXDR_GET_U_INT32(ptr);
1640 gesp->n4g_pc4.pc4_unique_handles =
1641 (truefalse ? TRUE : FALSE);
1642 }
1643 if (resbmap & FATTR4_LEASE_TIME_MASK) {
1644 gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr);
1645 }
1646 if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1647 gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr);
1648 }
1649 }
1650 if (resbmap &
1651 (FATTR4_ACL_MASK |
1652 FATTR4_ACLSUPPORT_MASK |
1653 FATTR4_ARCHIVE_MASK |
1654 FATTR4_CANSETTIME_MASK)) {
1655
1656 if (resbmap & FATTR4_ACL_MASK) {
1657 ASSERT(0);
1658 }
1659 if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1660 gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr);
1661 }
1662 if (resbmap & FATTR4_ARCHIVE_MASK) {
1663 ASSERT(0);
1664 }
1665 if (resbmap & FATTR4_CANSETTIME_MASK) {
1666 truefalse = IXDR_GET_U_INT32(ptr);
1667 gesp->n4g_pc4.pc4_cansettime =
1668 (truefalse ? TRUE : FALSE);
1669 }
1670 }
1671 if (resbmap &
1672 (FATTR4_CASE_INSENSITIVE_MASK |
1673 FATTR4_CASE_PRESERVING_MASK |
1674 FATTR4_CHOWN_RESTRICTED_MASK |
1675 FATTR4_FILEHANDLE_MASK |
1676 FATTR4_FILEID_MASK |
1677 FATTR4_FILES_AVAIL_MASK |
1678 FATTR4_FILES_FREE_MASK |
1679 FATTR4_FILES_TOTAL_MASK)) {
1680
1681 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1682 truefalse = IXDR_GET_U_INT32(ptr);
1683 gesp->n4g_pc4.pc4_case_insensitive =
1684 (truefalse ? TRUE : FALSE);
1685 }
1686 if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1687 truefalse = IXDR_GET_U_INT32(ptr);
1688 gesp->n4g_pc4.pc4_case_preserving =
1689 (truefalse ? TRUE : FALSE);
1690 }
1691 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1692 truefalse = IXDR_GET_U_INT32(ptr);
1693 gesp->n4g_pc4.pc4_chown_restricted =
1694 (truefalse ? TRUE : FALSE);
1695 }
1696 if (resbmap & FATTR4_FILEHANDLE_MASK) {
1697 int len = IXDR_GET_U_INT32(ptr);
1698
1699 gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1700 gesp->n4g_fh_u.nfs_fh4_alt.val =
1701 gesp->n4g_fh_u.nfs_fh4_alt.data;
1702 gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len;
1703
1704 bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len);
1705
1706 ptr += RNDUP(len) / BYTES_PER_XDR_UNIT;
1707 }
1708 if (resbmap & FATTR4_FILEID_MASK) {
1709 IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
1710 vap->va_mask |= AT_NODEID;
1711 }
1712 if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1713 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail);
1714 }
1715 if (resbmap & FATTR4_FILES_FREE_MASK) {
1716 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree);
1717 }
1718 if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1719 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files);
1720 }
1721 }
1722 if (resbmap &
1723 (FATTR4_FS_LOCATIONS_MASK |
1724 FATTR4_HIDDEN_MASK |
1725 FATTR4_HOMOGENEOUS_MASK)) {
1726
1727 if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1728 ASSERT(0);
1729 }
1730 if (resbmap & FATTR4_HIDDEN_MASK) {
1731 ASSERT(0);
1732 }
1733 if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1734 truefalse = IXDR_GET_U_INT32(ptr);
1735 gesp->n4g_pc4.pc4_homogeneous =
1736 (truefalse ? TRUE : FALSE);
1737 }
1738 }
1739 if (resbmap &
1740 (FATTR4_MAXFILESIZE_MASK |
1741 FATTR4_MAXLINK_MASK |
1742 FATTR4_MAXNAME_MASK |
1743 FATTR4_MAXREAD_MASK |
1744 FATTR4_MAXWRITE_MASK)) {
1745
1746 if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1747 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize);
1748 }
1749 if (resbmap & FATTR4_MAXLINK_MASK) {
1750 gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr);
1751 }
1752 if (resbmap & FATTR4_MAXNAME_MASK) {
1753 gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr);
1754 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1755 }
1756 if (resbmap & FATTR4_MAXREAD_MASK) {
1757 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread);
1758 }
1759 if (resbmap & FATTR4_MAXWRITE_MASK) {
1760 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite);
1761 }
1762 }
1763 if (resbmap &
1764 (FATTR4_MIMETYPE_MASK |
1765 FATTR4_MODE_MASK |
1766 FATTR4_NO_TRUNC_MASK |
1767 FATTR4_NUMLINKS_MASK)) {
1768
1769 if (resbmap & FATTR4_MIMETYPE_MASK) {
1770 ASSERT(0);
1771 }
1772 if (resbmap & FATTR4_MODE_MASK) {
1773 vap->va_mode = IXDR_GET_U_INT32(ptr);
1774 vap->va_mask |= AT_MODE;
1775 }
1776 if (resbmap & FATTR4_NO_TRUNC_MASK) {
1777 truefalse = IXDR_GET_U_INT32(ptr);
1778 gesp->n4g_pc4.pc4_no_trunc =
1779 (truefalse ? TRUE : FALSE);
1780 }
1781 if (resbmap & FATTR4_NUMLINKS_MASK) {
1782 vap->va_nlink = IXDR_GET_U_INT32(ptr);
1783 vap->va_mask |= AT_NLINK;
1784 }
1785 }
1786 if (resbmap &
1787 (FATTR4_OWNER_MASK |
1788 FATTR4_OWNER_GROUP_MASK |
1789 FATTR4_QUOTA_AVAIL_HARD_MASK |
1790 FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1791
1792 if (resbmap & FATTR4_OWNER_MASK) {
1793 uint_t *owner_length, ol;
1794 char *owner_val = NULL;
1795 utf8string ov;
1796 int error;
1797
1798 /* get the OWNER_LENGTH */
1799 ol = IXDR_GET_U_INT32(ptr);
1800
1801 /* Manage the owner length location */
1802 if (pug && ol <= MAX_OG_NAME) {
1803 owner_length = &pug->u_curr.utf8string_len;
1804 *owner_length = ol;
1805 } else {
1806 owner_length = &ol;
1807 }
1808
1809 /* find memory to store the decode */
1810 if (*owner_length > MAX_OG_NAME || pug == NULL)
1811 owner_val = (char *)ptr;
1812 else
1813 owner_val = (char *)ptr;
1814
1815 /* Optimize for matching if called for */
1816 if (pug &&
1817 *owner_length == pug->u_last.utf8string_len &&
1818 bcmp(owner_val, pug->u_last.utf8string_val,
1819 *owner_length) == 0) {
1820 vap->va_uid = pug->uid;
1821 vap->va_mask |= AT_UID;
1822 } else {
1823 uid_t uid;
1824
1825 ov.utf8string_len = *owner_length;
1826 ov.utf8string_val = owner_val;
1827 error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1828 /*
1829 * String was mapped, but to nobody because
1830 * we are nfsmapid, indicate it should not
1831 * be cached.
1832 */
1833 if (error == ENOTSUP) {
1834 error = 0;
1835 garp->n4g_attrwhy =
1836 NFS4_GETATTR_NOCACHE_OK;
1837 }
1838
1839 if (error) {
1840 garp->n4g_attrerr = error;
1841 garp->n4g_attrwhy =
1842 NFS4_GETATTR_ATUID_ERR;
1843 } else {
1844 vap->va_uid = uid;
1845 vap->va_mask |= AT_UID;
1846 /* save the results for next time */
1847 if (pug && ol <= MAX_OG_NAME) {
1848 pug->uid = uid;
1849 pug->u_curr.utf8string_len =
1850 ov.utf8string_len;
1851 bcopy(owner_val,
1852 pug->u_curr.utf8string_val,
1853 ol);
1854 U_SWAP_CURR_LAST(pug);
1855 }
1856 }
1857 }
1858 ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT;
1859 }
1860 if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1861 uint_t *group_length, gl;
1862 char *group_val = NULL;
1863 utf8string gv;
1864 int error;
1865
1866 /* get the OWNER_GROUP_LENGTH */
1867 gl = IXDR_GET_U_INT32(ptr);
1868
1869 /* Manage the group length location */
1870 if (pug && gl <= MAX_OG_NAME) {
1871 group_length = &pug->g_curr.utf8string_len;
1872 *group_length = gl;
1873 } else {
1874 group_length = ≷
1875 }
1876
1877 /* find memory to store the decode */
1878 if (*group_length > MAX_OG_NAME || pug == NULL)
1879 group_val = (char *)ptr;
1880 else
1881 group_val = (char *)ptr;
1882
1883 /* Optimize for matching if called for */
1884 if (pug &&
1885 *group_length == pug->g_last.utf8string_len &&
1886 bcmp(group_val, pug->g_last.utf8string_val,
1887 *group_length) == 0) {
1888 vap->va_gid = pug->gid;
1889 vap->va_mask |= AT_GID;
1890 } else {
1891 uid_t gid;
1892
1893 gv.utf8string_len = *group_length;
1894 gv.utf8string_val = group_val;
1895 error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1896 /*
1897 * String was mapped, but to nobody because
1898 * we are nfsmapid, indicate it should not
1899 * be cached.
1900 */
1901 if (error == ENOTSUP) {
1902 error = 0;
1903 garp->n4g_attrwhy =
1904 NFS4_GETATTR_NOCACHE_OK;
1905 }
1906
1907 if (error) {
1908 garp->n4g_attrerr = error;
1909 garp->n4g_attrwhy =
1910 NFS4_GETATTR_ATGID_ERR;
1911 } else {
1912 vap->va_gid = gid;
1913 vap->va_mask |= AT_GID;
1914 if (pug && gl <= MAX_OG_NAME) {
1915 pug->gid = gid;
1916 pug->g_curr.utf8string_len =
1917 gv.utf8string_len;
1918 bcopy(group_val,
1919 pug->g_curr.utf8string_val,
1920 gl);
1921 G_SWAP_CURR_LAST(pug);
1922 }
1923 }
1924 }
1925 ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT;
1926 }
1927 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1928 ASSERT(0);
1929 }
1930 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1931 ASSERT(0);
1932 }
1933 }
1934 if (resbmap &
1935 (FATTR4_QUOTA_USED_MASK |
1936 FATTR4_SPACE_AVAIL_MASK |
1937 FATTR4_SPACE_FREE_MASK |
1938 FATTR4_SPACE_TOTAL_MASK |
1939 FATTR4_SPACE_USED_MASK |
1940 FATTR4_SYSTEM_MASK)) {
1941
1942 if (resbmap & FATTR4_QUOTA_USED_MASK) {
1943 ASSERT(0);
1944 }
1945 if (resbmap & FATTR4_RAWDEV_MASK) {
1946 fattr4_rawdev rawdev;
1947
1948 rawdev.specdata1 = IXDR_GET_U_INT32(ptr);
1949 rawdev.specdata2 = IXDR_GET_U_INT32(ptr);
1950
1951 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1952 vap->va_rdev = makedevice(rawdev.specdata1,
1953 rawdev.specdata2);
1954 } else {
1955 vap->va_rdev = 0;
1956 }
1957 vap->va_mask |= AT_RDEV;
1958 }
1959 if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1960 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail);
1961 gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1962 }
1963 if (resbmap & FATTR4_SPACE_FREE_MASK) {
1964 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree);
1965 gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1966 }
1967 if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1968 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks);
1969 gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1970 }
1971 if (resbmap & FATTR4_SPACE_USED_MASK) {
1972 uint64_t space_used;
1973 IXDR_GET_U_HYPER(ptr, space_used);
1974
1975 /* Compute space depending on device type */
1976 ASSERT((vap->va_mask & AT_TYPE));
1977 if (vap->va_type == VREG || vap->va_type == VDIR ||
1978 vap->va_type == VLNK) {
1979 vap->va_nblocks = (u_longlong_t)
1980 ((space_used + (offset4)DEV_BSIZE -
1981 (offset4)1) / (offset4)DEV_BSIZE);
1982 } else {
1983 vap->va_nblocks = 0;
1984 }
1985 vap->va_mask |= AT_NBLOCKS;
1986 }
1987 if (resbmap & FATTR4_SYSTEM_MASK) {
1988 ASSERT(0);
1989 }
1990 }
1991 if (resbmap &
1992 (FATTR4_TIME_ACCESS_MASK |
1993 FATTR4_TIME_ACCESS_SET_MASK |
1994 FATTR4_TIME_BACKUP_MASK |
1995 FATTR4_TIME_CREATE_MASK |
1996 FATTR4_TIME_DELTA_MASK |
1997 FATTR4_TIME_METADATA_MASK |
1998 FATTR4_TIME_MODIFY_MASK |
1999 FATTR4_TIME_MODIFY_SET_MASK |
2000 FATTR4_MOUNTED_ON_FILEID_MASK)) {
2001
2002 if (resbmap & FATTR4_TIME_ACCESS_MASK) {
2003 nfstime4 atime;
2004 int error;
2005
2006 IXDR_GET_U_HYPER(ptr, atime.seconds);
2007 atime.nseconds = IXDR_GET_U_INT32(ptr);
2008
2009 error = nfs4_time_ntov(&atime, &vap->va_atime);
2010 if (error) {
2011 garp->n4g_attrerr = error;
2012 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
2013 }
2014 vap->va_mask |= AT_ATIME;
2015 }
2016 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
2017 ASSERT(0);
2018 }
2019 if (resbmap & FATTR4_TIME_BACKUP_MASK) {
2020 ASSERT(0);
2021 }
2022 if (resbmap & FATTR4_TIME_CREATE_MASK) {
2023 ASSERT(0);
2024 }
2025 if (resbmap & FATTR4_TIME_DELTA_MASK) {
2026 IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds);
2027 gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr);
2028 }
2029 if (resbmap & FATTR4_TIME_METADATA_MASK) {
2030 nfstime4 mdt;
2031 int error;
2032
2033 IXDR_GET_U_HYPER(ptr, mdt.seconds);
2034 mdt.nseconds = IXDR_GET_U_INT32(ptr);
2035
2036 error = nfs4_time_ntov(&mdt, &vap->va_ctime);
2037 if (error) {
2038 garp->n4g_attrerr = error;
2039 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
2040 }
2041 vap->va_mask |= AT_CTIME;
2042 }
2043 if (resbmap & FATTR4_TIME_MODIFY_MASK) {
2044 nfstime4 mtime;
2045 int error;
2046
2047 IXDR_GET_U_HYPER(ptr, mtime.seconds);
2048 mtime.nseconds = IXDR_GET_U_INT32(ptr);
2049
2050 error = nfs4_time_ntov(&mtime, &vap->va_mtime);
2051 if (error) {
2052 garp->n4g_attrerr = error;
2053 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
2054 }
2055 vap->va_mask |= AT_MTIME;
2056 }
2057 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
2058 ASSERT(0);
2059 }
2060 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
2061 IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid);
2062 garp->n4g_mon_fid_valid = 1;
2063 }
2064 }
2065
2066 /*
2067 * FATTR4_ACL_MASK is not yet supported by this function, but
2068 * we check against it anyway, in case it ever is.
2069 */
2070 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
2071 /* copy only if not provided */
2072 if (garp->n4g_ext_res == NULL) {
2073 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
2074 bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
2075 }
2076 }
2077
2078 return (TRUE);
2079 }
2080
2081
2082 /*
2083 * "." and ".." buffers for filling in on read and readdir
2084 * calls. Intialize the first time and fill in on every
2085 * call to to readdir.
2086 */
2087 char *nfs4_dot_entries;
2088 char *nfs4_dot_dot_entry;
2089
2090 /*
2091 * Create the "." or ".." and pad the buffer once so they are
2092 * copied out as required into the user supplied buffer everytime.
2093 * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
2094 * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
2095 */
2096 void
nfs4_init_dot_entries()2097 nfs4_init_dot_entries()
2098 {
2099 struct dirent64 *odp;
2100
2101 /*
2102 * zalloc it so it zeros the buffer out. Need
2103 * to just do it once.
2104 */
2105 nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
2106 KM_SLEEP);
2107
2108 odp = (struct dirent64 *)nfs4_dot_entries;
2109 odp->d_off = 1; /* magic cookie for "." entry */
2110 odp->d_reclen = DIRENT64_RECLEN(1);
2111 odp->d_name[0] = '.';
2112 odp->d_name[1] = '\0';
2113
2114 nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1);
2115 odp = (struct dirent64 *)nfs4_dot_dot_entry;
2116
2117 odp->d_off = 2;
2118 odp->d_reclen = DIRENT64_RECLEN(2);
2119 odp->d_name[0] = '.';
2120 odp->d_name[1] = '.';
2121 odp->d_name[2] = '\0';
2122 }
2123
2124 void
nfs4_destroy_dot_entries()2125 nfs4_destroy_dot_entries()
2126 {
2127 if (nfs4_dot_entries)
2128 kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) +
2129 DIRENT64_RECLEN(2));
2130
2131 nfs4_dot_entries = nfs4_dot_dot_entry = NULL;
2132 }
2133
2134 bool_t
xdr_READDIR4res_clnt(XDR * xdrs,READDIR4res_clnt * objp,READDIR4args * aobjp)2135 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp)
2136 {
2137 bool_t more_data;
2138 rddir4_cache *rdc = aobjp->rdc;
2139 dirent64_t *dp = NULL;
2140 int entry_length = 0;
2141 int space_left = 0;
2142 bitmap4 resbmap;
2143 uint32_t attrlen;
2144 nfs4_ga_res_t gar;
2145 struct nfs4_ga_ext_res ges;
2146 uint64_t last_cookie = 0;
2147 int skip_to_end;
2148 ug_cache_t *pug = NULL;
2149
2150 ASSERT(xdrs->x_op == XDR_DECODE);
2151 ASSERT(rdc->entries == NULL);
2152 ASSERT(aobjp->dircount > 0);
2153
2154 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2155 return (FALSE);
2156 if (objp->status != NFS4_OK)
2157 return (TRUE);
2158
2159 gar.n4g_va.va_mask = 0;
2160 gar.n4g_change_valid = 0;
2161 gar.n4g_mon_fid_valid = 0;
2162 gar.n4g_fsid_valid = 0;
2163 gar.n4g_vsa.vsa_mask = 0;
2164 gar.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2165 ges.n4g_pc4.pc4_cache_valid = 0;
2166 ges.n4g_pc4.pc4_xattr_valid = 0;
2167 gar.n4g_ext_res = ⩾
2168
2169 /* READDIR4res_clnt_free needs to kmem_free this buffer */
2170 rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP);
2171
2172 dp = (dirent64_t *)rdc->entries;
2173 rdc->entlen = rdc->buflen = space_left = aobjp->dircount;
2174
2175 /* Fill in dot and dot-dot if needed */
2176 if (rdc->nfs4_cookie == (nfs_cookie4) 0 ||
2177 rdc->nfs4_cookie == (nfs_cookie4) 1) {
2178
2179 if (rdc->nfs4_cookie == (nfs_cookie4)0) {
2180 bcopy(nfs4_dot_entries, rdc->entries,
2181 DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2182 objp->dotp = dp;
2183 dp = (struct dirent64 *)(((char *)dp) +
2184 DIRENT64_RECLEN(1));
2185 objp->dotdotp = dp;
2186 dp = (struct dirent64 *)(((char *)dp) +
2187 DIRENT64_RECLEN(2));
2188 space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2189
2190 } else { /* for ".." entry */
2191 bcopy(nfs4_dot_dot_entry, rdc->entries,
2192 DIRENT64_RECLEN(2));
2193 objp->dotp = NULL;
2194 objp->dotdotp = dp;
2195 dp = (struct dirent64 *)(((char *)dp) +
2196 DIRENT64_RECLEN(2));
2197 space_left -= DIRENT64_RECLEN(2);
2198 }
2199 /* Magic NFSv4 number for entry after start */
2200 last_cookie = 2;
2201 }
2202
2203 /* Get the cookie VERIFIER */
2204 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
2205 goto noentries;
2206
2207 /* Get the do-we-have-a-next-entry BOOL */
2208 if (!xdr_bool(xdrs, &more_data))
2209 goto noentries;
2210
2211 if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK))
2212 pug = alloc_ugcache();
2213
2214 skip_to_end = 0;
2215 while (more_data) {
2216 uint_t namelen;
2217 uint64_t cookie;
2218
2219 /* Get the COOKIE */
2220 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie))
2221 goto noentries;
2222
2223 /* Get the LENGTH of the entry name */
2224 if (!xdr_u_int(xdrs, &namelen))
2225 goto noentries;
2226
2227 if (!skip_to_end) {
2228 /*
2229 * With the length of the directory entry name
2230 * in hand, figure out if there is room left
2231 * to encode it for the requestor. If not,
2232 * that is okay, but the rest of the readdir
2233 * operation result must be decoded in the
2234 * case there are following operations
2235 * in the compound request. Therefore, mark
2236 * the rest of the response as "skip" and
2237 * decode or skip the remaining data
2238 */
2239 entry_length = DIRENT64_RECLEN(namelen);
2240 if (space_left < entry_length)
2241 skip_to_end = 1;
2242 }
2243
2244 /* Get the NAME of the entry */
2245 if (!skip_to_end) {
2246 if (!xdr_opaque(xdrs, dp->d_name, namelen))
2247 goto noentries;
2248 bzero(&dp->d_name[namelen],
2249 DIRENT64_NAMELEN(entry_length) - namelen);
2250 dp->d_off = last_cookie = cookie;
2251 dp->d_reclen = entry_length;
2252 } else {
2253 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen))
2254 goto noentries;
2255 }
2256
2257 /* Get the attribute BITMAP */
2258 if (!xdr_bitmap4(xdrs, &resbmap))
2259 goto noentries;
2260 /* Get the LENGTH of the attributes */
2261 if (!xdr_u_int(xdrs, (uint_t *)&attrlen))
2262 goto noentries;
2263
2264 /* Get the ATTRIBUTES */
2265 if (!skip_to_end) {
2266 uint32_t *ptr;
2267
2268 if (!(resbmap & FATTR4_ACL_MASK) &&
2269 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen))
2270 != NULL) {
2271 if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap,
2272 aobjp->attr_request, aobjp->mi, pug))
2273 goto noentries;
2274 } else {
2275 if (!xdr_ga_fattr_res(xdrs, &gar, resbmap,
2276 aobjp->attr_request, aobjp->mi, pug))
2277 goto noentries;
2278 }
2279
2280 /* Fill in the d_ino per the server's fid values */
2281 /*
2282 * Important to note that the mounted on fileid
2283 * is returned in d_ino if supported. This is
2284 * expected, readdir returns the mounted on fileid
2285 * while stat() returns the fileid of the object
2286 * on "top" of the mount.
2287 */
2288 if (gar.n4g_mon_fid_valid)
2289 dp->d_ino = gar.n4g_mon_fid;
2290 else if (gar.n4g_va.va_mask & AT_NODEID)
2291 dp->d_ino = gar.n4g_va.va_nodeid;
2292 else
2293 dp->d_ino = 0;
2294
2295 /* See about creating an rnode for this entry */
2296 if ((resbmap &
2297 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) ==
2298 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) {
2299 nfs4_sharedfh_t *sfhp;
2300 vnode_t *vp;
2301
2302 sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh,
2303 aobjp->mi, NULL);
2304 vp = makenfs4node(sfhp, &gar,
2305 aobjp->dvp->v_vfsp,
2306 aobjp->t,
2307 aobjp->cr,
2308 aobjp->dvp,
2309 fn_get(VTOSV(aobjp->dvp)->sv_name,
2310 dp->d_name, sfhp));
2311 sfh4_rele(&sfhp);
2312 dnlc_update(aobjp->dvp, dp->d_name, vp);
2313 VN_RELE(vp);
2314 }
2315
2316 dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen);
2317
2318 space_left -= entry_length;
2319
2320 } else {
2321 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen))
2322 goto noentries;
2323 }
2324
2325 /* Get the do-we-have-a-next-entry BOOL */
2326 if (!xdr_bool(xdrs, &more_data))
2327 goto noentries;
2328 }
2329
2330 if (pug) {
2331 kmem_free(pug, sizeof (ug_cache_t));
2332 pug = NULL;
2333 }
2334
2335 /*
2336 * Finish up the rddir cache
2337 * If no entries were returned, free up buffer &
2338 * set ncookie to the starting cookie for this
2339 * readdir request so that the direof caching
2340 * will work properly.
2341 */
2342 ASSERT(rdc->entries);
2343 if (last_cookie == 0) {
2344 kmem_free(rdc->entries, rdc->entlen);
2345 rdc->entries = NULL;
2346 last_cookie = rdc->nfs4_cookie;
2347 }
2348
2349 rdc->actlen = rdc->entlen - space_left;
2350 rdc->nfs4_ncookie = last_cookie;
2351
2352 /* Get the EOF marker */
2353 if (!xdr_bool(xdrs, &objp->eof))
2354 goto noentries;
2355
2356 /*
2357 * If the server returns eof and there were no
2358 * skipped entries, set eof
2359 */
2360 rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE;
2361
2362 /*
2363 * If we encoded entries we are done
2364 */
2365 if (rdc->entries) {
2366 rdc->error = 0;
2367 return (TRUE);
2368 }
2369
2370 /*
2371 * If there were no entries and we skipped because
2372 * there was not enough space, return EINVAL
2373 */
2374 if (skip_to_end) {
2375 rdc->error = EINVAL;
2376 return (TRUE);
2377 }
2378
2379 /*
2380 * No entries, nothing skipped, and EOF, return OK.
2381 */
2382 if (objp->eof == TRUE) {
2383 rdc->error = 0;
2384 return (TRUE);
2385 }
2386
2387 /*
2388 * No entries, nothing skipped, and not EOF
2389 * probably a bad cookie, return ENOENT.
2390 */
2391 rdc->error = ENOENT;
2392 return (TRUE);
2393
2394 noentries:
2395 if (rdc->entries) {
2396 kmem_free(rdc->entries, rdc->entlen);
2397 rdc->entries = NULL;
2398 }
2399 if (pug)
2400 kmem_free(pug, sizeof (ug_cache_t));
2401 rdc->error = EIO;
2402 return (FALSE);
2403 }
2404
2405 /*
2406 * xdr_ga_res
2407 *
2408 * Returns: FALSE on raw data processing errors, TRUE otherwise.
2409 *
2410 * This function pre-processes the OP_GETATTR response, and then
2411 * calls common routines to process the GETATTR fattr4 results into
2412 * vnode attributes and other components that the client is interested
2413 * in. If an error other than an RPC error is encountered, the details
2414 * of the error are filled into objp, although the result of the
2415 * processing is set to TRUE.
2416 */
2417 static bool_t
xdr_ga_res(XDR * xdrs,GETATTR4res * objp,GETATTR4args * aobjp)2418 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp)
2419 {
2420 #ifdef INLINE
2421 uint32_t *ptr;
2422 #endif
2423 bitmap4 resbmap;
2424 uint32_t attrlen;
2425
2426 ASSERT(xdrs->x_op == XDR_DECODE);
2427
2428 /* Initialize objp attribute error values */
2429 objp->ga_res.n4g_attrerr =
2430 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2431
2432 if (!xdr_bitmap4(xdrs, &resbmap))
2433 return (FALSE);
2434
2435 /* save the response bitmap for the caller */
2436 objp->ga_res.n4g_resbmap = resbmap;
2437
2438 /* attrlen */
2439 if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen))
2440 return (FALSE);
2441
2442 /*
2443 * Handle case where request and response bitmaps don't match.
2444 */
2445 if (aobjp->attr_request && aobjp->attr_request != resbmap) {
2446 bitmap4 deltabmap;
2447
2448 /*
2449 * Return error for case where server sent extra attributes
2450 * because the "unknown" attributes may be anywhere in the
2451 * xdr stream and can't be properly processed.
2452 */
2453 deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap);
2454 if (deltabmap) {
2455 objp->ga_res.n4g_attrerr = EINVAL;
2456 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR;
2457 return (TRUE);
2458 }
2459
2460 /*
2461 * Return error for case where there is a mandatory
2462 * attribute missing in the server response. Note that
2463 * missing recommended attributes are evaluated in the
2464 * specific routines that decode the server response.
2465 */
2466 deltabmap = ((aobjp->attr_request ^ resbmap)
2467 & aobjp->attr_request);
2468 if ((deltabmap & FATTR4_MANDATTR_MASK)) {
2469 objp->ga_res.n4g_attrerr = EINVAL;
2470 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR;
2471 return (TRUE);
2472 }
2473 }
2474
2475 /* Check to see if the attrs can be inlined and go for it if so */
2476 #ifdef INLINE
2477 if (!(resbmap & FATTR4_ACL_MASK) &&
2478 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL)
2479 return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res,
2480 resbmap, aobjp->attr_request, aobjp->mi, NULL));
2481 else
2482 #endif
2483 return (xdr_ga_fattr_res(xdrs, &objp->ga_res,
2484 resbmap, aobjp->attr_request, aobjp->mi, NULL));
2485 }
2486
2487 #if defined(DEBUG) && !defined(lint)
2488 /*
2489 * We assume that an enum is a 32-bit value, check it once
2490 */
2491 static enum szchk { SZVAL } szchkvar;
2492 #endif
2493
2494 bool_t
xdr_settime4(XDR * xdrs,settime4 * objp)2495 xdr_settime4(XDR *xdrs, settime4 *objp)
2496 {
2497 #if defined(DEBUG) && !defined(lint)
2498 ASSERT(sizeof (szchkvar) == sizeof (int32_t));
2499 #endif
2500 if (xdrs->x_op == XDR_FREE)
2501 return (TRUE);
2502
2503 if (!xdr_int(xdrs, (int *)&objp->set_it))
2504 return (FALSE);
2505 if (objp->set_it != SET_TO_CLIENT_TIME4)
2506 return (TRUE);
2507 /* xdr_nfstime4 */
2508 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds))
2509 return (FALSE);
2510 return (xdr_u_int(xdrs, &objp->time.nseconds));
2511 }
2512
2513 static bool_t
xdr_fattr4(XDR * xdrs,fattr4 * objp)2514 xdr_fattr4(XDR *xdrs, fattr4 *objp)
2515 {
2516 if (xdrs->x_op != XDR_FREE) {
2517 if (!xdr_bitmap4(xdrs, &objp->attrmask))
2518 return (FALSE);
2519 return (xdr_bytes(xdrs, (char **)&objp->attrlist4,
2520 (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT));
2521 }
2522
2523 /*
2524 * Optimized free case
2525 */
2526 if (objp->attrlist4 != NULL)
2527 kmem_free(objp->attrlist4, objp->attrlist4_len);
2528 return (TRUE);
2529 }
2530
2531 static bool_t
xdr_ACCESS4res(XDR * xdrs,ACCESS4res * objp)2532 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp)
2533 {
2534 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2535 return (FALSE);
2536 if (objp->status != NFS4_OK)
2537 return (TRUE);
2538 if (!xdr_u_int(xdrs, &objp->supported))
2539 return (FALSE);
2540 return (xdr_u_int(xdrs, &objp->access));
2541 }
2542
2543 static bool_t
xdr_CLOSE4args(XDR * xdrs,CLOSE4args * objp)2544 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp)
2545 {
2546 if (!xdr_u_int(xdrs, &objp->seqid))
2547 return (FALSE);
2548 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2549 return (FALSE);
2550 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2551 }
2552
2553 static bool_t
xdr_CLOSE4res(XDR * xdrs,CLOSE4res * objp)2554 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp)
2555 {
2556 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2557 return (FALSE);
2558 if (objp->status != NFS4_OK)
2559 return (TRUE);
2560 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2561 return (FALSE);
2562 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2563 }
2564
2565 static bool_t
xdr_CREATE4args(XDR * xdrs,CREATE4args * objp)2566 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp)
2567 {
2568 if (xdrs->x_op != XDR_FREE) {
2569 if (!xdr_int(xdrs, (int32_t *)&objp->type))
2570 return (FALSE);
2571 switch (objp->type) {
2572 case NF4LNK:
2573 if (!xdr_bytes(xdrs,
2574 (char **)&objp->ftype4_u.linkdata.linktext4_val,
2575 (uint_t *)&objp->ftype4_u.linkdata.linktext4_len,
2576 NFS4_MAX_UTF8STRING))
2577 return (FALSE);
2578 break;
2579 case NF4BLK:
2580 case NF4CHR:
2581 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1))
2582 return (FALSE);
2583 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2))
2584 return (FALSE);
2585 break;
2586 case NF4SOCK:
2587 case NF4FIFO:
2588 case NF4DIR:
2589 default:
2590 break; /* server should return NFS4ERR_BADTYPE */
2591 }
2592 if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val,
2593 (uint_t *)&objp->objname.utf8string_len,
2594 NFS4_MAX_UTF8STRING))
2595 return (FALSE);
2596 return (xdr_fattr4(xdrs, &objp->createattrs));
2597 }
2598
2599 /*
2600 * Optimized free case
2601 */
2602 if (objp->type == NF4LNK) {
2603 if (objp->ftype4_u.linkdata.linktext4_val != NULL)
2604 kmem_free(objp->ftype4_u.linkdata.linktext4_val,
2605 objp->ftype4_u.linkdata.linktext4_len);
2606 }
2607 if (objp->objname.utf8string_val != NULL)
2608 kmem_free(objp->objname.utf8string_val,
2609 objp->objname.utf8string_len);
2610 return (xdr_fattr4(xdrs, &objp->createattrs));
2611 }
2612
2613 static bool_t
xdr_CREATE4cargs(XDR * xdrs,CREATE4cargs * objp)2614 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp)
2615 {
2616 int len;
2617
2618 ASSERT(xdrs->x_op == XDR_ENCODE);
2619
2620 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type))
2621 return (FALSE);
2622 switch (objp->type) {
2623 case NF4LNK:
2624 len = strlen(objp->ftype4_u.clinkdata);
2625 if (len > NFS4_MAX_UTF8STRING)
2626 return (FALSE);
2627 if (!XDR_PUTINT32(xdrs, &len))
2628 return (FALSE);
2629 if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len))
2630 return (FALSE);
2631 break;
2632 case NF4BLK:
2633 case NF4CHR:
2634 if (!XDR_PUTINT32(xdrs,
2635 (int32_t *)&objp->ftype4_u.devdata.specdata1))
2636 return (FALSE);
2637 if (!XDR_PUTINT32(xdrs,
2638 (int32_t *)&objp->ftype4_u.devdata.specdata2))
2639 return (FALSE);
2640 break;
2641 case NF4SOCK:
2642 case NF4FIFO:
2643 case NF4DIR:
2644 default:
2645 break; /* server should return NFS4ERR_BADTYPE */
2646 }
2647
2648 len = strlen(objp->cname);
2649 if (len > NFS4_MAX_UTF8STRING)
2650 return (FALSE);
2651 if (!XDR_PUTINT32(xdrs, &len))
2652 return (FALSE);
2653 if (!xdr_opaque(xdrs, objp->cname, len))
2654 return (FALSE);
2655
2656 return (xdr_fattr4(xdrs, &objp->createattrs));
2657 }
2658
2659 static bool_t
xdr_CREATE4res(XDR * xdrs,CREATE4res * objp)2660 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp)
2661 {
2662 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2663 return (FALSE);
2664 if (objp->status != NFS4_OK)
2665 return (TRUE);
2666 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2667 return (FALSE);
2668 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2669 return (FALSE);
2670 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
2671 return (FALSE);
2672 return (xdr_bitmap4(xdrs, &objp->attrset));
2673 }
2674
2675 static bool_t
xdr_LINK4res(XDR * xdrs,LINK4res * objp)2676 xdr_LINK4res(XDR *xdrs, LINK4res *objp)
2677 {
2678 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2679 return (FALSE);
2680 if (objp->status != NFS4_OK)
2681 return (TRUE);
2682 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2683 return (FALSE);
2684 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2685 return (FALSE);
2686 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after));
2687 }
2688
2689 static bool_t
xdr_LOCK4args(XDR * xdrs,LOCK4args * objp)2690 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp)
2691 {
2692 if (xdrs->x_op != XDR_FREE) {
2693 if (!xdr_int(xdrs, (int *)&objp->locktype))
2694 return (FALSE);
2695 if (!xdr_bool(xdrs, &objp->reclaim))
2696 return (FALSE);
2697 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2698 return (FALSE);
2699 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2700 return (FALSE);
2701 if (!xdr_bool(xdrs, &objp->locker.new_lock_owner))
2702 return (FALSE);
2703 if (objp->locker.new_lock_owner == TRUE) {
2704 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2705 open_seqid))
2706 return (FALSE);
2707 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2708 open_stateid.seqid))
2709 return (FALSE);
2710 if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner.
2711 open_stateid.other, NFS4_OTHER_SIZE))
2712 return (FALSE);
2713 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2714 lock_seqid))
2715 return (FALSE);
2716 if (!xdr_u_longlong_t(xdrs,
2717 (u_longlong_t *)&objp->locker.locker4_u.
2718 open_owner.lock_owner.clientid))
2719 return (FALSE);
2720 return (xdr_bytes(xdrs,
2721 (char **)&objp->locker.locker4_u.open_owner.
2722 lock_owner.owner_val,
2723 (uint_t *)&objp->locker.locker4_u.open_owner.
2724 lock_owner.owner_len,
2725 NFS4_OPAQUE_LIMIT));
2726 }
2727
2728 if (objp->locker.new_lock_owner != FALSE)
2729 return (FALSE);
2730
2731 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2732 lock_stateid.seqid))
2733 return (FALSE);
2734 if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner.
2735 lock_stateid.other, NFS4_OTHER_SIZE))
2736 return (FALSE);
2737 return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2738 lock_seqid));
2739 }
2740
2741 /*
2742 * Optimized free case
2743 */
2744 if (objp->locker.new_lock_owner == TRUE) {
2745 if (objp->locker.locker4_u.open_owner.lock_owner.owner_val !=
2746 NULL) {
2747 kmem_free(objp->locker.locker4_u.open_owner.lock_owner.
2748 owner_val,
2749 objp->locker.locker4_u.open_owner.lock_owner.
2750 owner_len);
2751 }
2752 }
2753
2754 return (TRUE);
2755 }
2756
2757 static bool_t
xdr_LOCK4res(XDR * xdrs,LOCK4res * objp)2758 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp)
2759 {
2760 if (xdrs->x_op != XDR_FREE) {
2761 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2762 return (FALSE);
2763 if (objp->status == NFS4_OK) {
2764 if (!xdr_u_int(xdrs,
2765 &objp->LOCK4res_u.lock_stateid.seqid))
2766 return (FALSE);
2767 return (xdr_opaque(xdrs,
2768 objp->LOCK4res_u.lock_stateid.other,
2769 NFS4_OTHER_SIZE));
2770 }
2771 if (objp->status != NFS4ERR_DENIED)
2772 return (TRUE);
2773
2774 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2775 denied.offset))
2776 return (FALSE);
2777 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2778 denied.length))
2779 return (FALSE);
2780 if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype))
2781 return (FALSE);
2782 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2783 denied.owner.clientid))
2784 return (FALSE);
2785 return (xdr_bytes(xdrs,
2786 (char **)&objp->LOCK4res_u.denied.owner.owner_val,
2787 (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len,
2788 NFS4_OPAQUE_LIMIT));
2789 }
2790
2791 /*
2792 * Optimized free case
2793 */
2794 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2795 return (TRUE);
2796
2797 if (objp->LOCK4res_u.denied.owner.owner_val != NULL)
2798 kmem_free(objp->LOCK4res_u.denied.owner.owner_val,
2799 objp->LOCK4res_u.denied.owner.owner_len);
2800 return (TRUE);
2801 }
2802
2803 static bool_t
xdr_LOCKT4args(XDR * xdrs,LOCKT4args * objp)2804 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp)
2805 {
2806 if (xdrs->x_op != XDR_FREE) {
2807 if (!xdr_int(xdrs, (int *)&objp->locktype))
2808 return (FALSE);
2809 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2810 return (FALSE);
2811 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2812 return (FALSE);
2813 if (!xdr_u_longlong_t(xdrs,
2814 (u_longlong_t *)&objp->owner.clientid))
2815 return (FALSE);
2816 return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2817 (uint_t *)&objp->owner.owner_len,
2818 NFS4_OPAQUE_LIMIT));
2819 }
2820
2821 /*
2822 * Optimized free case
2823 */
2824 if (objp->owner.owner_val != NULL)
2825 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2826 return (TRUE);
2827 }
2828
2829 static bool_t
xdr_LOCKT4res(XDR * xdrs,LOCKT4res * objp)2830 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp)
2831 {
2832 if (xdrs->x_op != XDR_FREE) {
2833 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2834 return (FALSE);
2835 if (objp->status == NFS4_OK)
2836 return (TRUE);
2837 if (objp->status != NFS4ERR_DENIED)
2838 return (TRUE);
2839 /* xdr_LOCK4denied */
2840 if (!xdr_u_longlong_t(xdrs,
2841 (u_longlong_t *)&objp->denied.offset))
2842 return (FALSE);
2843 if (!xdr_u_longlong_t(xdrs,
2844 (u_longlong_t *)&objp->denied.length))
2845 return (FALSE);
2846 if (!xdr_int(xdrs, (int *)&objp->denied.locktype))
2847 return (FALSE);
2848 if (!xdr_u_longlong_t(xdrs,
2849 (u_longlong_t *)&objp->denied.owner.clientid))
2850 return (FALSE);
2851 return (xdr_bytes(xdrs,
2852 (char **)&objp->denied.owner.owner_val,
2853 (uint_t *)&objp->denied.owner.owner_len,
2854 NFS4_OPAQUE_LIMIT));
2855 }
2856
2857 /*
2858 * Optimized free case
2859 */
2860 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2861 return (TRUE);
2862 if (objp->denied.owner.owner_val != NULL)
2863 kmem_free(objp->denied.owner.owner_val,
2864 objp->denied.owner.owner_len);
2865 return (TRUE);
2866 }
2867
2868 static bool_t
xdr_LOCKU4args(XDR * xdrs,LOCKU4args * objp)2869 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
2870 {
2871 if (!xdr_int(xdrs, (int *)&objp->locktype))
2872 return (FALSE);
2873 if (!xdr_u_int(xdrs, &objp->seqid))
2874 return (FALSE);
2875 if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid))
2876 return (FALSE);
2877 if (!xdr_opaque(xdrs, objp->lock_stateid.other, NFS4_OTHER_SIZE))
2878 return (FALSE);
2879 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2880 return (FALSE);
2881 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length));
2882 }
2883
2884 static bool_t
xdr_OPEN4args(XDR * xdrs,OPEN4args * objp)2885 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2886 {
2887 if (xdrs->x_op != XDR_FREE) {
2888 if (!xdr_u_int(xdrs, &objp->seqid))
2889 return (FALSE);
2890 if (!xdr_u_int(xdrs, &objp->share_access))
2891 return (FALSE);
2892 if (!xdr_u_int(xdrs, &objp->share_deny))
2893 return (FALSE);
2894
2895 /* xdr_open_owner4 */
2896 if (!xdr_u_longlong_t(xdrs,
2897 (u_longlong_t *)&objp->owner.clientid))
2898 return (FALSE);
2899 if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2900 (uint_t *)&objp->owner.owner_len,
2901 NFS4_OPAQUE_LIMIT))
2902 return (FALSE);
2903
2904 /* xdr_openflag4 */
2905 if (!xdr_int(xdrs, (int *)&objp->opentype))
2906 return (FALSE);
2907 if (objp->opentype == OPEN4_CREATE) {
2908
2909 /* xdr_createhow4 */
2910 if (!xdr_int(xdrs, (int *)&objp->mode))
2911 return (FALSE);
2912 switch (objp->mode) {
2913 case UNCHECKED4:
2914 case GUARDED4:
2915 if (!xdr_fattr4(xdrs,
2916 &objp->createhow4_u.createattrs))
2917 return (FALSE);
2918 break;
2919 case EXCLUSIVE4:
2920 if (!xdr_u_longlong_t(xdrs,
2921 (u_longlong_t *)&objp->createhow4_u.
2922 createverf))
2923 return (FALSE);
2924 break;
2925 default:
2926 return (FALSE);
2927 }
2928 }
2929
2930 /* xdr_open_claim4 */
2931 if (!xdr_int(xdrs, (int *)&objp->claim))
2932 return (FALSE);
2933
2934 switch (objp->claim) {
2935 case CLAIM_NULL:
2936 return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2937 file.utf8string_val,
2938 (uint_t *)&objp->open_claim4_u.file.
2939 utf8string_len,
2940 NFS4_MAX_UTF8STRING));
2941 case CLAIM_PREVIOUS:
2942 return (xdr_int(xdrs,
2943 (int *)&objp->open_claim4_u.delegate_type));
2944 case CLAIM_DELEGATE_CUR:
2945 if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u.
2946 delegate_cur_info.delegate_stateid.seqid))
2947 return (FALSE);
2948 if (!xdr_opaque(xdrs, objp->open_claim4_u.
2949 delegate_cur_info.delegate_stateid.other,
2950 NFS4_OTHER_SIZE))
2951 return (FALSE);
2952 return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2953 delegate_cur_info.file.utf8string_val,
2954 (uint_t *)&objp->open_claim4_u.
2955 delegate_cur_info.file.utf8string_len,
2956 NFS4_MAX_UTF8STRING));
2957 case CLAIM_DELEGATE_PREV:
2958 return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2959 file_delegate_prev.utf8string_val,
2960 (uint_t *)&objp->open_claim4_u.
2961 file_delegate_prev.utf8string_len,
2962 NFS4_MAX_UTF8STRING));
2963 default:
2964 return (FALSE);
2965 }
2966 }
2967
2968 /*
2969 * Optimized free case
2970 */
2971 if (objp->owner.owner_val != NULL)
2972 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2973
2974 if (objp->opentype == OPEN4_CREATE) {
2975 switch (objp->mode) {
2976 case UNCHECKED4:
2977 case GUARDED4:
2978 (void) xdr_fattr4(xdrs,
2979 &objp->createhow4_u.createattrs);
2980 break;
2981 case EXCLUSIVE4:
2982 default:
2983 break;
2984 }
2985 }
2986
2987 switch (objp->claim) {
2988 case CLAIM_NULL:
2989 if (objp->open_claim4_u.file.utf8string_val != NULL)
2990 kmem_free(objp->open_claim4_u.file.utf8string_val,
2991 objp->open_claim4_u.file.utf8string_len);
2992 return (TRUE);
2993 case CLAIM_PREVIOUS:
2994 return (TRUE);
2995 case CLAIM_DELEGATE_CUR:
2996 if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val !=
2997 NULL) {
2998 kmem_free(objp->open_claim4_u.delegate_cur_info.file.
2999 utf8string_val,
3000 objp->open_claim4_u.delegate_cur_info.file.
3001 utf8string_len);
3002 }
3003 return (TRUE);
3004 case CLAIM_DELEGATE_PREV:
3005 if (objp->open_claim4_u.file_delegate_prev.utf8string_val !=
3006 NULL) {
3007 kmem_free(objp->open_claim4_u.file_delegate_prev.
3008 utf8string_val,
3009 objp->open_claim4_u.file_delegate_prev.
3010 utf8string_len);
3011 }
3012 return (TRUE);
3013 default:
3014 return (TRUE);
3015 }
3016 }
3017
3018 static bool_t
xdr_OPEN4cargs(XDR * xdrs,OPEN4cargs * objp)3019 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3020 {
3021 int op;
3022 int len;
3023 rpc_inline_t *ptr;
3024
3025 ASSERT(xdrs->x_op == XDR_ENCODE);
3026
3027 /*
3028 * We must always define the client's open_owner to be
3029 * 4 byte aligned and sized.
3030 */
3031 ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3032 ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3033
3034 len = objp->owner.owner_len;
3035 if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3036 int i;
3037 int32_t *ip;
3038
3039 IXDR_PUT_U_INT32(ptr, OP_OPEN);
3040 IXDR_PUT_U_INT32(ptr, objp->seqid);
3041 IXDR_PUT_U_INT32(ptr, objp->share_access);
3042 IXDR_PUT_U_INT32(ptr, objp->share_deny);
3043
3044 /* xdr_open_owner4 */
3045 IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3046 IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3047 /* We know this is very short so don't bcopy */
3048 ip = (int32_t *)objp->owner.owner_val;
3049 len /= BYTES_PER_XDR_UNIT;
3050 for (i = 0; i < len; i++)
3051 *ptr++ = *ip++;
3052
3053 /* xdr_openflag4 */
3054 IXDR_PUT_U_INT32(ptr, objp->opentype);
3055 } else {
3056 op = OP_OPEN;
3057 if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3058 return (FALSE);
3059 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3060 return (FALSE);
3061 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3062 return (FALSE);
3063 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3064 return (FALSE);
3065
3066 /* xdr_open_owner4 */
3067 if (!xdr_u_longlong_t(xdrs,
3068 (u_longlong_t *)&objp->owner.clientid))
3069 return (FALSE);
3070 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3071