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