1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/user.h>
36 #include <sys/vnode.h>
37 #include <sys/file.h>
38 #include <sys/dirent.h>
39 #include <sys/vfs.h>
40 #include <sys/stream.h>
41 #include <sys/strsubr.h>
42 #include <sys/debug.h>
43 #include <sys/t_lock.h>
44 #include <sys/sdt.h>
45
46 #include <rpc/types.h>
47 #include <rpc/xdr.h>
48
49 #include <nfs/nfs.h>
50
51 #include <vm/hat.h>
52 #include <vm/as.h>
53 #include <vm/seg.h>
54 #include <vm/seg_map.h>
55 #include <vm/seg_kmem.h>
56
57 static bool_t xdr_fastshorten(XDR *, uint_t);
58
59 /*
60 * These are the XDR routines used to serialize and deserialize
61 * the various structures passed as parameters accross the network
62 * between NFS clients and servers.
63 */
64
65 /*
66 * File access handle
67 * The fhandle struct is treated a opaque data on the wire
68 */
69 bool_t
70 xdr_fhandle(XDR *xdrs, fhandle_t *fh)
71 {
72 int32_t *ptr;
73 int32_t *fhp;
74
75 if (xdrs->x_op == XDR_FREE)
76 return (TRUE);
77
78 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
79 if (ptr != NULL) {
80 fhp = (int32_t *)fh;
81 if (xdrs->x_op == XDR_DECODE) {
82 *fhp++ = *ptr++;
83 *fhp++ = *ptr++;
84 *fhp++ = *ptr++;
85 *fhp++ = *ptr++;
86 *fhp++ = *ptr++;
87 *fhp++ = *ptr++;
88 *fhp++ = *ptr++;
89 *fhp = *ptr;
90 } else {
91 *ptr++ = *fhp++;
92 *ptr++ = *fhp++;
93 *ptr++ = *fhp++;
94 *ptr++ = *fhp++;
95 *ptr++ = *fhp++;
96 *ptr++ = *fhp++;
97 *ptr++ = *fhp++;
98 *ptr = *fhp;
99 }
100 return (TRUE);
101 }
102
103 return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE));
104 }
105
106 bool_t
107 xdr_fastfhandle(XDR *xdrs, fhandle_t **fh)
108 {
109 int32_t *ptr;
110
111 if (xdrs->x_op != XDR_DECODE)
112 return (FALSE);
113
114 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
115 if (ptr != NULL) {
116 *fh = (fhandle_t *)ptr;
117 return (TRUE);
118 }
119
120 return (FALSE);
121 }
122
123 /*
124 * Arguments to remote write and writecache
125 */
126 bool_t
127 xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa)
128 {
129 int32_t *ptr;
130 int32_t *fhp;
131
132 switch (xdrs->x_op) {
133 case XDR_DECODE:
134 wa->wa_args = &wa->wa_args_buf;
135 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
136 3 * BYTES_PER_XDR_UNIT);
137 if (ptr != NULL) {
138 fhp = (int32_t *)&wa->wa_fhandle;
139 *fhp++ = *ptr++;
140 *fhp++ = *ptr++;
141 *fhp++ = *ptr++;
142 *fhp++ = *ptr++;
143 *fhp++ = *ptr++;
144 *fhp++ = *ptr++;
145 *fhp++ = *ptr++;
146 *fhp = *ptr++;
147 wa->wa_begoff = IXDR_GET_U_INT32(ptr);
148 wa->wa_offset = IXDR_GET_U_INT32(ptr);
149 wa->wa_totcount = IXDR_GET_U_INT32(ptr);
150 wa->wa_mblk = NULL;
151 wa->wa_data = NULL;
152 wa->wa_rlist = NULL;
153 wa->wa_conn = NULL;
154 if (xdrs->x_ops == &xdrmblk_ops) {
155 return (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
156 &wa->wa_count));
157 } else {
158 if (xdrs->x_ops == &xdrrdmablk_ops) {
159 if (xdrrdma_getrdmablk(xdrs,
160 &wa->wa_rlist,
161 &wa->wa_count,
162 &wa->wa_conn,
163 NFS_MAXDATA) == TRUE)
164 return (xdrrdma_read_from_client(
165 wa->wa_rlist,
166 &wa->wa_conn,
167 wa->wa_count));
168
169 wa->wa_rlist = NULL;
170 wa->wa_conn = NULL;
171 }
172 }
173
174 /*
175 * It is just as efficient to xdr_bytes
176 * an array of unknown length as to inline copy it.
177 */
178 return (xdr_bytes(xdrs, &wa->wa_data,
179 &wa->wa_count, NFS_MAXDATA));
180 }
181 if (xdr_fhandle(xdrs, &wa->wa_fhandle) &&
182 xdr_u_int(xdrs, &wa->wa_begoff) &&
183 xdr_u_int(xdrs, &wa->wa_offset) &&
184 xdr_u_int(xdrs, &wa->wa_totcount)) {
185 /* deal with the variety of data transfer types */
186
187 wa->wa_mblk = NULL;
188 wa->wa_data = NULL;
189 wa->wa_rlist = NULL;
190 wa->wa_conn = NULL;
191
192 if (xdrs->x_ops == &xdrmblk_ops) {
193 if (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
194 &wa->wa_count) == TRUE)
195 return (TRUE);
196 } else {
197 if (xdrs->x_ops == &xdrrdmablk_ops) {
198 if (xdrrdma_getrdmablk(xdrs,
199 &wa->wa_rlist,
200 &wa->wa_count,
201 &wa->wa_conn,
202 NFS_MAXDATA) == TRUE)
203 return (xdrrdma_read_from_client(
204 wa->wa_rlist,
205 &wa->wa_conn,
206 wa->wa_count));
207
208 wa->wa_rlist = NULL;
209 wa->wa_conn = NULL;
210 }
211 }
212 return (xdr_bytes(xdrs, &wa->wa_data,
213 &wa->wa_count, NFS_MAXDATA));
214 }
215 return (FALSE);
216 case XDR_ENCODE:
217 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
218 3 * BYTES_PER_XDR_UNIT);
219 if (ptr != NULL) {
220 fhp = (int32_t *)&wa->wa_fhandle;
221 *ptr++ = *fhp++;
222 *ptr++ = *fhp++;
223 *ptr++ = *fhp++;
224 *ptr++ = *fhp++;
225 *ptr++ = *fhp++;
226 *ptr++ = *fhp++;
227 *ptr++ = *fhp++;
228 *ptr++ = *fhp;
229 IXDR_PUT_U_INT32(ptr, wa->wa_begoff);
230 IXDR_PUT_U_INT32(ptr, wa->wa_offset);
231 IXDR_PUT_U_INT32(ptr, wa->wa_totcount);
232 } else {
233 if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) &&
234 xdr_u_int(xdrs, &wa->wa_begoff) &&
235 xdr_u_int(xdrs, &wa->wa_offset) &&
236 xdr_u_int(xdrs, &wa->wa_totcount)))
237 return (FALSE);
238 }
239
240 return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count,
241 NFS_MAXDATA));
242 case XDR_FREE:
243 if (wa->wa_rlist) {
244 (void) xdrrdma_free_clist(wa->wa_conn, wa->wa_rlist);
245 wa->wa_rlist = NULL;
246 }
247
248 if (wa->wa_data != NULL) {
249 kmem_free(wa->wa_data, wa->wa_count);
250 wa->wa_data = NULL;
251 }
252 return (TRUE);
253 }
254 return (FALSE);
255 }
256
257
258 /*
259 * File attributes
260 */
261 bool_t
262 xdr_fattr(XDR *xdrs, struct nfsfattr *na)
263 {
264 int32_t *ptr;
265
266 if (xdrs->x_op == XDR_FREE)
267 return (TRUE);
268
269 ptr = XDR_INLINE(xdrs, 17 * BYTES_PER_XDR_UNIT);
270 if (ptr != NULL) {
271 if (xdrs->x_op == XDR_DECODE) {
272 na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
273 na->na_mode = IXDR_GET_U_INT32(ptr);
274 na->na_nlink = IXDR_GET_U_INT32(ptr);
275 na->na_uid = IXDR_GET_U_INT32(ptr);
276 na->na_gid = IXDR_GET_U_INT32(ptr);
277 na->na_size = IXDR_GET_U_INT32(ptr);
278 na->na_blocksize = IXDR_GET_U_INT32(ptr);
279 na->na_rdev = IXDR_GET_U_INT32(ptr);
280 na->na_blocks = IXDR_GET_U_INT32(ptr);
281 na->na_fsid = IXDR_GET_U_INT32(ptr);
282 na->na_nodeid = IXDR_GET_U_INT32(ptr);
283 na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
284 na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
285 na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
286 na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
287 na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
288 na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
289 } else {
290 IXDR_PUT_ENUM(ptr, na->na_type);
291 IXDR_PUT_U_INT32(ptr, na->na_mode);
292 IXDR_PUT_U_INT32(ptr, na->na_nlink);
293 IXDR_PUT_U_INT32(ptr, na->na_uid);
294 IXDR_PUT_U_INT32(ptr, na->na_gid);
295 IXDR_PUT_U_INT32(ptr, na->na_size);
296 IXDR_PUT_U_INT32(ptr, na->na_blocksize);
297 IXDR_PUT_U_INT32(ptr, na->na_rdev);
298 IXDR_PUT_U_INT32(ptr, na->na_blocks);
299 IXDR_PUT_U_INT32(ptr, na->na_fsid);
300 IXDR_PUT_U_INT32(ptr, na->na_nodeid);
301 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
302 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
303 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
304 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
305 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
306 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
307 }
308 return (TRUE);
309 }
310
311 if (xdr_enum(xdrs, (enum_t *)&na->na_type) &&
312 xdr_u_int(xdrs, &na->na_mode) &&
313 xdr_u_int(xdrs, &na->na_nlink) &&
314 xdr_u_int(xdrs, &na->na_uid) &&
315 xdr_u_int(xdrs, &na->na_gid) &&
316 xdr_u_int(xdrs, &na->na_size) &&
317 xdr_u_int(xdrs, &na->na_blocksize) &&
318 xdr_u_int(xdrs, &na->na_rdev) &&
319 xdr_u_int(xdrs, &na->na_blocks) &&
320 xdr_u_int(xdrs, &na->na_fsid) &&
321 xdr_u_int(xdrs, &na->na_nodeid) &&
322 xdr_nfs2_timeval(xdrs, &na->na_atime) &&
323 xdr_nfs2_timeval(xdrs, &na->na_mtime) &&
324 xdr_nfs2_timeval(xdrs, &na->na_ctime)) {
325 return (TRUE);
326 }
327 return (FALSE);
328 }
329
330 #ifdef _LITTLE_ENDIAN
331 bool_t
332 xdr_fastfattr(XDR *xdrs, struct nfsfattr *na)
333 {
334 if (xdrs->x_op == XDR_FREE)
335 return (TRUE);
336 if (xdrs->x_op == XDR_DECODE)
337 return (FALSE);
338
339 na->na_type = htonl(na->na_type);
340 na->na_mode = htonl(na->na_mode);
341 na->na_nlink = htonl(na->na_nlink);
342 na->na_uid = htonl(na->na_uid);
343 na->na_gid = htonl(na->na_gid);
344 na->na_size = htonl(na->na_size);
345 na->na_blocksize = htonl(na->na_blocksize);
346 na->na_rdev = htonl(na->na_rdev);
347 na->na_blocks = htonl(na->na_blocks);
348 na->na_fsid = htonl(na->na_fsid);
349 na->na_nodeid = htonl(na->na_nodeid);
350 na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
351 na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
352 na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
353 na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
354 na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
355 na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
356 return (TRUE);
357 }
358 #endif
359
360 bool_t
361 xdr_readlink(XDR *xdrs, fhandle_t *fh)
362 {
363 rdma_chunkinfo_t rci;
364 struct xdr_ops *xops = xdrrdma_xops();
365
366 if (xdr_fhandle(xdrs, fh)) {
367 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
368 xdrs->x_op == XDR_ENCODE) {
369 rci.rci_type = RCI_REPLY_CHUNK;
370 rci.rci_len = MAXPATHLEN;
371 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
372 }
373
374 return (TRUE);
375 }
376 return (FALSE);
377 }
378
379 /*
380 * Arguments to remote read
381 */
382 bool_t
383 xdr_readargs(XDR *xdrs, struct nfsreadargs *ra)
384 {
385 int32_t *ptr;
386 int32_t *fhp;
387 rdma_chunkinfo_t rci;
388 rdma_wlist_conn_info_t rwci;
389 struct xdr_ops *xops = xdrrdma_xops();
390
391 if (xdrs->x_op == XDR_FREE)
392 return (TRUE);
393
394 ptr = XDR_INLINE(xdrs,
395 RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT);
396 if (ptr != NULL) {
397 if (xdrs->x_op == XDR_DECODE) {
398 fhp = (int32_t *)&ra->ra_fhandle;
399 *fhp++ = *ptr++;
400 *fhp++ = *ptr++;
401 *fhp++ = *ptr++;
402 *fhp++ = *ptr++;
403 *fhp++ = *ptr++;
404 *fhp++ = *ptr++;
405 *fhp++ = *ptr++;
406 *fhp = *ptr++;
407 ra->ra_offset = IXDR_GET_INT32(ptr);
408 ra->ra_count = IXDR_GET_INT32(ptr);
409 ra->ra_totcount = IXDR_GET_INT32(ptr);
410 } else {
411 fhp = (int32_t *)&ra->ra_fhandle;
412 *ptr++ = *fhp++;
413 *ptr++ = *fhp++;
414 *ptr++ = *fhp++;
415 *ptr++ = *fhp++;
416 *ptr++ = *fhp++;
417 *ptr++ = *fhp++;
418 *ptr++ = *fhp++;
419 *ptr++ = *fhp;
420 IXDR_PUT_INT32(ptr, ra->ra_offset);
421 IXDR_PUT_INT32(ptr, ra->ra_count);
422 IXDR_PUT_INT32(ptr, ra->ra_totcount);
423 }
424 } else {
425 if (!xdr_fhandle(xdrs, &ra->ra_fhandle) ||
426 !xdr_u_int(xdrs, &ra->ra_offset) ||
427 !xdr_u_int(xdrs, &ra->ra_count) ||
428 !xdr_u_int(xdrs, &ra->ra_totcount)) {
429 return (FALSE);
430 }
431 }
432
433 if (ra->ra_count > NFS_MAXDATA)
434 return (FALSE);
435
436 ra->ra_wlist = NULL;
437 ra->ra_conn = NULL;
438
439 /* If this is xdrrdma_sizeof, record the expect response size */
440 if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
441 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
442 rci.rci_len = ra->ra_count;
443 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
444 }
445 /* Nothing special to do, return */
446 if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
447 return (TRUE);
448
449 if (xdrs->x_op == XDR_ENCODE) {
450 /* Place the target data location into the RDMA header */
451 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
452 rci.rci_a.rci_addr = ra->ra_data;
453 rci.rci_len = ra->ra_count;
454 rci.rci_clpp = &ra->ra_wlist;
455
456 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
457 }
458
459 /* XDR_DECODE case */
460 (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
461 ra->ra_wlist = rwci.rwci_wlist;
462 ra->ra_conn = rwci.rwci_conn;
463
464 return (TRUE);
465 }
466
467
468 /*
469 * Status OK portion of remote read reply
470 */
471 bool_t
472 xdr_rrok(XDR *xdrs, struct nfsrrok *rrok)
473 {
474 bool_t ret;
475 mblk_t *mp;
476 struct xdr_ops *xops = xdrrdma_xops();
477
478 if (xdr_fattr(xdrs, &rrok->rrok_attr) == FALSE)
479 return (FALSE);
480
481 /* deal with RDMA separately */
482 if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
483 if (xdrs->x_op == XDR_ENCODE &&
484 rrok->rrok_mp != NULL) {
485 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
486 &rrok->rrok_count, NFS_MAXDATA);
487 return (ret);
488 }
489
490 if (xdrs->x_op == XDR_ENCODE) {
491 if (xdr_u_int(xdrs, &rrok->rrok_count) == FALSE) {
492 return (FALSE);
493 }
494 /*
495 * If read data sent by wlist (RDMA_WRITE), don't do
496 * xdr_bytes() below. RDMA_WRITE transfers the data.
497 */
498 if (rrok->rrok_wlist) {
499 if (rrok->rrok_count != 0) {
500 return (xdrrdma_send_read_data(
501 xdrs, rrok->rrok_count,
502 rrok->rrok_wlist));
503 }
504 return (TRUE);
505 }
506 if (rrok->rrok_count == 0) {
507 return (TRUE);
508 }
509 } else {
510 struct clist *cl;
511 uint32_t count;
512
513 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
514
515 if (cl) {
516 if (!xdr_u_int(xdrs, &count))
517 return (FALSE);
518 if (count == 0) {
519 rrok->rrok_wlist_len = 0;
520 rrok->rrok_count = 0;
521 } else {
522 rrok->rrok_wlist_len = clist_len(cl);
523 if (rrok->rrok_wlist_len !=
524 roundup(count,
525 BYTES_PER_XDR_UNIT)) {
526 rrok->rrok_wlist_len = 0;
527 rrok->rrok_count = 0;
528 return (FALSE);
529 }
530 rrok->rrok_count = count;
531 }
532 return (TRUE);
533 }
534 }
535 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
536 &rrok->rrok_count, NFS_MAXDATA);
537
538 return (ret);
539 }
540
541 if (xdrs->x_op == XDR_ENCODE) {
542 int i, rndup;
543
544 mp = rrok->rrok_mp;
545 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
546 mp->b_wptr += rrok->rrok_count;
547 rndup = BYTES_PER_XDR_UNIT -
548 (rrok->rrok_count % BYTES_PER_XDR_UNIT);
549 if (rndup != BYTES_PER_XDR_UNIT)
550 for (i = 0; i < rndup; i++)
551 *mp->b_wptr++ = '\0';
552 if (xdrmblk_putmblk(xdrs, mp,
553 rrok->rrok_count) == TRUE) {
554 rrok->rrok_mp = NULL;
555 return (TRUE);
556 }
557 }
558
559 /*
560 * Fall thru for the xdr_bytes()
561 *
562 * Note: the mblk mp will be freed in rfs_rdfree
563 */
564 }
565
566 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
567 &rrok->rrok_count, NFS_MAXDATA);
568
569 return (ret);
570 }
571
572 static struct xdr_discrim rdres_discrim[2] = {
573 { NFS_OK, xdr_rrok },
574 { __dontcare__, NULL_xdrproc_t }
575 };
576
577 /*
578 * Reply from remote read
579 */
580 bool_t
581 xdr_rdresult(XDR *xdrs, struct nfsrdresult *rr)
582 {
583 return (xdr_union(xdrs, (enum_t *)&(rr->rr_status),
584 (caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void));
585 }
586
587 /*
588 * File attributes which can be set
589 */
590 bool_t
591 xdr_sattr(XDR *xdrs, struct nfssattr *sa)
592 {
593 if (xdr_u_int(xdrs, &sa->sa_mode) &&
594 xdr_u_int(xdrs, &sa->sa_uid) &&
595 xdr_u_int(xdrs, &sa->sa_gid) &&
596 xdr_u_int(xdrs, &sa->sa_size) &&
597 xdr_nfs2_timeval(xdrs, &sa->sa_atime) &&
598 xdr_nfs2_timeval(xdrs, &sa->sa_mtime)) {
599 return (TRUE);
600 }
601 return (FALSE);
602 }
603
604 static struct xdr_discrim attrstat_discrim[2] = {
605 { (int)NFS_OK, xdr_fattr },
606 { __dontcare__, NULL_xdrproc_t }
607 };
608
609 /*
610 * Reply status with file attributes
611 */
612 bool_t
613 xdr_attrstat(XDR *xdrs, struct nfsattrstat *ns)
614 {
615 return (xdr_union(xdrs, (enum_t *)&(ns->ns_status),
616 (caddr_t)&(ns->ns_attr), attrstat_discrim, xdr_void));
617 }
618
619 /*
620 * Fast reply status with file attributes
621 */
622 bool_t
623 xdr_fastattrstat(XDR *xdrs, struct nfsattrstat *ns)
624 {
625 #if defined(_LITTLE_ENDIAN)
626 /*
627 * we deal with the discriminator; it's an enum
628 */
629 if (!xdr_fastenum(xdrs, (enum_t *)&ns->ns_status))
630 return (FALSE);
631
632 if (ns->ns_status == NFS_OK)
633 return (xdr_fastfattr(xdrs, &ns->ns_attr));
634 #elif defined(_BIG_ENDIAN)
635 if (ns->ns_status == NFS_OK)
636 return (TRUE);
637 #endif
638 return (xdr_fastshorten(xdrs, sizeof (*ns)));
639 }
640
641 /*
642 * NFS_OK part of read sym link reply union
643 */
644 bool_t
645 xdr_srok(XDR *xdrs, struct nfssrok *srok)
646 {
647 /*
648 * It is just as efficient to xdr_bytes
649 * an array of unknown length as to inline copy it.
650 */
651 return (xdr_bytes(xdrs, &srok->srok_data, &srok->srok_count,
652 NFS_MAXPATHLEN));
653 }
654
655 static struct xdr_discrim rdlnres_discrim[2] = {
656 { (int)NFS_OK, xdr_srok },
657 { __dontcare__, NULL_xdrproc_t }
658 };
659
660 /*
661 * Result of reading symbolic link
662 */
663 bool_t
664 xdr_rdlnres(XDR *xdrs, struct nfsrdlnres *rl)
665 {
666 return (xdr_union(xdrs, (enum_t *)&(rl->rl_status),
667 (caddr_t)&(rl->rl_srok), rdlnres_discrim, xdr_void));
668 }
669
670 /*
671 * Arguments to readdir
672 */
673 bool_t
674 xdr_rddirargs(XDR *xdrs, struct nfsrddirargs *rda)
675 {
676 int32_t *ptr;
677 int32_t *fhp;
678 rdma_chunkinfo_t rci;
679 struct xdr_ops *xops = xdrrdma_xops();
680
681 if (xdrs->x_op == XDR_FREE)
682 return (TRUE);
683
684 ptr = XDR_INLINE(xdrs,
685 RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT);
686
687 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
688 xdrs->x_op == XDR_ENCODE) {
689 rci.rci_type = RCI_REPLY_CHUNK;
690 rci.rci_len = rda->rda_count;
691 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
692 }
693
694 if (ptr != NULL) {
695 if (xdrs->x_op == XDR_DECODE) {
696 fhp = (int32_t *)&rda->rda_fh;
697 *fhp++ = *ptr++;
698 *fhp++ = *ptr++;
699 *fhp++ = *ptr++;
700 *fhp++ = *ptr++;
701 *fhp++ = *ptr++;
702 *fhp++ = *ptr++;
703 *fhp++ = *ptr++;
704 *fhp = *ptr++;
705 rda->rda_offset = IXDR_GET_U_INT32(ptr);
706 rda->rda_count = IXDR_GET_U_INT32(ptr);
707 } else {
708 fhp = (int32_t *)&rda->rda_fh;
709 *ptr++ = *fhp++;
710 *ptr++ = *fhp++;
711 *ptr++ = *fhp++;
712 *ptr++ = *fhp++;
713 *ptr++ = *fhp++;
714 *ptr++ = *fhp++;
715 *ptr++ = *fhp++;
716 *ptr++ = *fhp;
717 IXDR_PUT_U_INT32(ptr, rda->rda_offset);
718 IXDR_PUT_U_INT32(ptr, rda->rda_count);
719 }
720 return (TRUE);
721 }
722
723 if (xdr_fhandle(xdrs, &rda->rda_fh) &&
724 xdr_u_int(xdrs, &rda->rda_offset) &&
725 xdr_u_int(xdrs, &rda->rda_count)) {
726 return (TRUE);
727 }
728 return (FALSE);
729 }
730
731
732 /*
733 * Directory read reply:
734 * union (enum status) {
735 * NFS_OK: entlist;
736 * boolean eof;
737 * default:
738 * }
739 *
740 * Directory entries
741 * struct direct {
742 * off_t d_off; * offset of next entry *
743 * u_int d_fileno; * inode number of entry *
744 * u_short d_reclen; * length of this record *
745 * u_short d_namlen; * length of string in d_name *
746 * char d_name[MAXNAMLEN + 1]; * name no longer than this *
747 * };
748 * are on the wire as:
749 * union entlist (boolean valid) {
750 * TRUE: struct otw_dirent;
751 * u_int nxtoffset;
752 * union entlist;
753 * FALSE:
754 * }
755 * where otw_dirent is:
756 * struct dirent {
757 * u_int de_fid;
758 * string de_name<NFS_MAXNAMELEN>;
759 * }
760 */
761
762 #ifdef nextdp
763 #undef nextdp
764 #endif
765 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
766 #ifdef roundup
767 #undef roundup
768 #endif
769 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
770
771 /*
772 * ENCODE ONLY
773 */
774 bool_t
775 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd)
776 {
777 bool_t true = TRUE;
778 bool_t false = FALSE;
779 struct nfsentry *entry;
780
781 if (xdrs->x_op != XDR_ENCODE)
782 return (FALSE);
783 if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
784 return (FALSE);
785 if (rd->rd_status != NFS_OK)
786 return (TRUE);
787
788 for (entry = rd->rd_entries; entry != NULL; entry = entry->nextentry) {
789 if (!xdr_bool(xdrs, &true) ||
790 !xdr_u_int(xdrs, &entry->fileid) ||
791 !xdr_string(xdrs, &entry->name, NFS_MAXNAMLEN) ||
792 !xdr_u_int(xdrs, &entry->cookie)) {
793 return (FALSE);
794 }
795 }
796 if (!xdr_bool(xdrs, &false))
797 return (FALSE);
798 if (!xdr_bool(xdrs, &rd->rd_eof))
799 return (FALSE);
800 return (TRUE);
801 }
802
803 /*
804 * DECODE ONLY
805 */
806 bool_t
807 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd)
808 {
809 struct dirent64 *dp;
810 uint_t namlen;
811 int size;
812 bool_t valid;
813 uint32_t offset;
814 uint_t fileid, this_reclen;
815
816 if (xdrs->x_op != XDR_DECODE)
817 return (FALSE);
818
819 if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
820 return (FALSE);
821 if (rd->rd_status != NFS_OK)
822 return (TRUE);
823
824 size = rd->rd_size;
825 dp = rd->rd_dirents;
826 offset = rd->rd_offset;
827 for (;;) {
828 if (!xdr_bool(xdrs, &valid))
829 return (FALSE);
830 if (!valid)
831 break;
832 if (!xdr_u_int(xdrs, &fileid) ||
833 !xdr_u_int(xdrs, &namlen))
834 return (FALSE);
835 this_reclen = DIRENT64_RECLEN(namlen);
836 if (this_reclen > size) {
837 rd->rd_eof = FALSE;
838 goto bufovflw;
839 }
840 if (!xdr_opaque(xdrs, dp->d_name, namlen)||
841 !xdr_u_int(xdrs, &offset)) {
842 return (FALSE);
843 }
844 bzero(&dp->d_name[namlen],
845 DIRENT64_NAMELEN(this_reclen) - namlen);
846 dp->d_ino = (ino64_t)fileid;
847 dp->d_reclen = this_reclen;
848 dp->d_off = (off64_t)offset;
849 size -= dp->d_reclen;
850 dp = nextdp(dp);
851 }
852 if (!xdr_bool(xdrs, &rd->rd_eof))
853 return (FALSE);
854 bufovflw:
855 rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_dirents));
856 rd->rd_offset = offset;
857 return (TRUE);
858 }
859
860 /*
861 * Arguments for directory operations
862 */
863 bool_t
864 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da)
865 {
866 int32_t *ptr;
867 int32_t *fhp;
868 uint32_t size;
869 uint32_t nodesize;
870 int i;
871 int rndup;
872 char *cptr;
873
874 if (xdrs->x_op == XDR_DECODE) {
875 da->da_fhandle = &da->da_fhandle_buf;
876 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
877 1 * BYTES_PER_XDR_UNIT);
878 if (ptr != NULL) {
879 fhp = (int32_t *)da->da_fhandle;
880 *fhp++ = *ptr++;
881 *fhp++ = *ptr++;
882 *fhp++ = *ptr++;
883 *fhp++ = *ptr++;
884 *fhp++ = *ptr++;
885 *fhp++ = *ptr++;
886 *fhp++ = *ptr++;
887 *fhp = *ptr++;
888 size = IXDR_GET_U_INT32(ptr);
889 if (size > NFS_MAXNAMLEN)
890 return (FALSE);
891 nodesize = size + 1;
892 if (nodesize == 0)
893 return (TRUE);
894 if (da->da_name == NULL) {
895 da->da_name = kmem_alloc(nodesize, KM_NOSLEEP);
896 if (da->da_name == NULL)
897 return (FALSE);
898 da->da_flags |= DA_FREENAME;
899 }
900 ptr = XDR_INLINE(xdrs, RNDUP(size));
901 if (ptr == NULL) {
902 if (!xdr_opaque(xdrs, da->da_name, size)) {
903 if (da->da_flags & DA_FREENAME) {
904 kmem_free(da->da_name,
905 nodesize);
906 da->da_name = NULL;
907 }
908 return (FALSE);
909 }
910 da->da_name[size] = '\0';
911 if (strlen(da->da_name) != size) {
912 if (da->da_flags & DA_FREENAME) {
913 kmem_free(da->da_name,
914 nodesize);
915 da->da_name = NULL;
916 }
917 return (FALSE);
918 }
919 return (TRUE);
920 }
921 bcopy(ptr, da->da_name, size);
922 da->da_name[size] = '\0';
923 if (strlen(da->da_name) != size) {
924 if (da->da_flags & DA_FREENAME) {
925 kmem_free(da->da_name, nodesize);
926 da->da_name = NULL;
927 }
928 return (FALSE);
929 }
930 return (TRUE);
931 }
932 if (da->da_name == NULL)
933 da->da_flags |= DA_FREENAME;
934 }
935
936 if (xdrs->x_op == XDR_ENCODE) {
937 size = (uint32_t)strlen(da->da_name);
938 if (size > NFS_MAXNAMLEN)
939 return (FALSE);
940 ptr = XDR_INLINE(xdrs, (int)(RNDUP(sizeof (fhandle_t)) +
941 1 * BYTES_PER_XDR_UNIT + RNDUP(size)));
942 if (ptr != NULL) {
943 fhp = (int32_t *)da->da_fhandle;
944 *ptr++ = *fhp++;
945 *ptr++ = *fhp++;
946 *ptr++ = *fhp++;
947 *ptr++ = *fhp++;
948 *ptr++ = *fhp++;
949 *ptr++ = *fhp++;
950 *ptr++ = *fhp++;
951 *ptr++ = *fhp;
952 IXDR_PUT_U_INT32(ptr, (uint32_t)size);
953 bcopy(da->da_name, ptr, size);
954 rndup = BYTES_PER_XDR_UNIT -
955 (size % BYTES_PER_XDR_UNIT);
956 if (rndup != BYTES_PER_XDR_UNIT) {
957 cptr = (char *)ptr + size;
958 for (i = 0; i < rndup; i++)
959 *cptr++ = '\0';
960 }
961 return (TRUE);
962 }
963 }
964
965 if (xdrs->x_op == XDR_FREE) {
966 if (da->da_name == NULL)
967 return (TRUE);
968 size = (uint32_t)strlen(da->da_name);
969 if (size > NFS_MAXNAMLEN)
970 return (FALSE);
971 if (da->da_flags & DA_FREENAME)
972 kmem_free(da->da_name, size + 1);
973 da->da_name = NULL;
974 return (TRUE);
975 }
976
977 if (xdr_fhandle(xdrs, da->da_fhandle) &&
978 xdr_string(xdrs, &da->da_name, NFS_MAXNAMLEN)) {
979 return (TRUE);
980 }
981 return (FALSE);
982 }
983
984 /*
985 * NFS_OK part of directory operation result
986 */
987 bool_t
988 xdr_drok(XDR *xdrs, struct nfsdrok *drok)
989 {
990 int32_t *ptr;
991 int32_t *fhp;
992 struct nfsfattr *na;
993
994 if (xdrs->x_op == XDR_FREE)
995 return (TRUE);
996
997 ptr = XDR_INLINE(xdrs,
998 RNDUP(sizeof (fhandle_t)) + 17 * BYTES_PER_XDR_UNIT);
999 if (ptr != NULL) {
1000 if (xdrs->x_op == XDR_DECODE) {
1001 fhp = (int32_t *)&drok->drok_fhandle;
1002 *fhp++ = *ptr++;
1003 *fhp++ = *ptr++;
1004 *fhp++ = *ptr++;
1005 *fhp++ = *ptr++;
1006 *fhp++ = *ptr++;
1007 *fhp++ = *ptr++;
1008 *fhp++ = *ptr++;
1009 *fhp = *ptr++;
1010 na = &drok->drok_attr;
1011 na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
1012 na->na_mode = IXDR_GET_U_INT32(ptr);
1013 na->na_nlink = IXDR_GET_U_INT32(ptr);
1014 na->na_uid = IXDR_GET_U_INT32(ptr);
1015 na->na_gid = IXDR_GET_U_INT32(ptr);
1016 na->na_size = IXDR_GET_U_INT32(ptr);
1017 na->na_blocksize = IXDR_GET_U_INT32(ptr);
1018 na->na_rdev = IXDR_GET_U_INT32(ptr);
1019 na->na_blocks = IXDR_GET_U_INT32(ptr);
1020 na->na_fsid = IXDR_GET_U_INT32(ptr);
1021 na->na_nodeid = IXDR_GET_U_INT32(ptr);
1022 na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
1023 na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
1024 na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
1025 na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
1026 na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
1027 na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
1028 } else {
1029 fhp = (int32_t *)&drok->drok_fhandle;
1030 *ptr++ = *fhp++;
1031 *ptr++ = *fhp++;
1032 *ptr++ = *fhp++;
1033 *ptr++ = *fhp++;
1034 *ptr++ = *fhp++;
1035 *ptr++ = *fhp++;
1036 *ptr++ = *fhp++;
1037 *ptr++ = *fhp;
1038 na = &drok->drok_attr;
1039 IXDR_PUT_ENUM(ptr, na->na_type);
1040 IXDR_PUT_U_INT32(ptr, na->na_mode);
1041 IXDR_PUT_U_INT32(ptr, na->na_nlink);
1042 IXDR_PUT_U_INT32(ptr, na->na_uid);
1043 IXDR_PUT_U_INT32(ptr, na->na_gid);
1044 IXDR_PUT_U_INT32(ptr, na->na_size);
1045 IXDR_PUT_U_INT32(ptr, na->na_blocksize);
1046 IXDR_PUT_U_INT32(ptr, na->na_rdev);
1047 IXDR_PUT_U_INT32(ptr, na->na_blocks);
1048 IXDR_PUT_U_INT32(ptr, na->na_fsid);
1049 IXDR_PUT_U_INT32(ptr, na->na_nodeid);
1050 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
1051 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
1052 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
1053 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
1054 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
1055 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
1056 }
1057 return (TRUE);
1058 }
1059
1060 if (xdr_fhandle(xdrs, &drok->drok_fhandle) &&
1061 xdr_fattr(xdrs, &drok->drok_attr)) {
1062 return (TRUE);
1063 }
1064 return (FALSE);
1065 }
1066
1067 #ifdef _LITTLE_ENDIAN
1068 bool_t
1069 xdr_fastdrok(XDR *xdrs, struct nfsdrok *drok)
1070 {
1071 struct nfsfattr *na;
1072
1073 if (xdrs->x_op == XDR_FREE)
1074 return (TRUE);
1075 if (xdrs->x_op == XDR_DECODE)
1076 return (FALSE);
1077
1078 na = &drok->drok_attr;
1079 na->na_type = (enum nfsftype)htonl(na->na_type);
1080 na->na_mode = (uint32_t)htonl(na->na_mode);
1081 na->na_nlink = (uint32_t)htonl(na->na_nlink);
1082 na->na_uid = (uint32_t)htonl(na->na_uid);
1083 na->na_gid = (uint32_t)htonl(na->na_gid);
1084 na->na_size = (uint32_t)htonl(na->na_size);
1085 na->na_blocksize = (uint32_t)htonl(na->na_blocksize);
1086 na->na_rdev = (uint32_t)htonl(na->na_rdev);
1087 na->na_blocks = (uint32_t)htonl(na->na_blocks);
1088 na->na_fsid = (uint32_t)htonl(na->na_fsid);
1089 na->na_nodeid = (uint32_t)htonl(na->na_nodeid);
1090 na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
1091 na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
1092 na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
1093 na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
1094 na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
1095 na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
1096 return (TRUE);
1097 }
1098 #endif
1099
1100 static struct xdr_discrim diropres_discrim[2] = {
1101 { NFS_OK, xdr_drok },
1102 { __dontcare__, NULL_xdrproc_t }
1103 };
1104
1105 /*
1106 * Results from directory operation
1107 */
1108 bool_t
1109 xdr_diropres(XDR *xdrs, struct nfsdiropres *dr)
1110 {
1111 return (xdr_union(xdrs, (enum_t *)&(dr->dr_status),
1112 (caddr_t)&(dr->dr_drok), diropres_discrim, xdr_void));
1113 }
1114
1115 /*
1116 * Results from directory operation
1117 */
1118 bool_t
1119 xdr_fastdiropres(XDR *xdrs, struct nfsdiropres *dr)
1120 {
1121 #if defined(_LITTLE_ENDIAN)
1122 /*
1123 * we deal with the discriminator; it's an enum
1124 */
1125 if (!xdr_fastenum(xdrs, (enum_t *)&dr->dr_status))
1126 return (FALSE);
1127
1128 if (dr->dr_status == NFS_OK)
1129 return (xdr_fastdrok(xdrs, &dr->dr_drok));
1130 #elif defined(_BIG_ENDIAN)
1131 if (dr->dr_status == NFS_OK)
1132 return (TRUE);
1133 #endif
1134 return (xdr_fastshorten(xdrs, sizeof (*dr)));
1135 }
1136
1137 /*
1138 * Time Structure, unsigned
1139 */
1140 bool_t
1141 xdr_nfs2_timeval(XDR *xdrs, struct nfs2_timeval *tv)
1142 {
1143 if (xdr_u_int(xdrs, &tv->tv_sec) &&
1144 xdr_u_int(xdrs, &tv->tv_usec))
1145 return (TRUE);
1146 return (FALSE);
1147 }
1148
1149 /*
1150 * arguments to setattr
1151 */
1152 bool_t
1153 xdr_saargs(XDR *xdrs, struct nfssaargs *argp)
1154 {
1155 int32_t *ptr;
1156 int32_t *arg;
1157 struct nfssattr *sa;
1158
1159 if (xdrs->x_op == XDR_FREE)
1160 return (TRUE);
1161
1162 ptr = XDR_INLINE(xdrs,
1163 RNDUP(sizeof (fhandle_t)) + 8 * BYTES_PER_XDR_UNIT);
1164 if (ptr != NULL) {
1165 if (xdrs->x_op == XDR_DECODE) {
1166 arg = (int32_t *)&argp->saa_fh;
1167 *arg++ = *ptr++;
1168 *arg++ = *ptr++;
1169 *arg++ = *ptr++;
1170 *arg++ = *ptr++;
1171 *arg++ = *ptr++;
1172 *arg++ = *ptr++;
1173 *arg++ = *ptr++;
1174 *arg = *ptr++;
1175 sa = &argp->saa_sa;
1176 sa->sa_mode = IXDR_GET_U_INT32(ptr);
1177 sa->sa_uid = IXDR_GET_U_INT32(ptr);
1178 sa->sa_gid = IXDR_GET_U_INT32(ptr);
1179 sa->sa_size = IXDR_GET_U_INT32(ptr);
1180 sa->sa_atime.tv_sec = IXDR_GET_U_INT32(ptr);
1181 sa->sa_atime.tv_usec = IXDR_GET_U_INT32(ptr);
1182 sa->sa_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
1183 sa->sa_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
1184 } else {
1185 arg = (int32_t *)&argp->saa_fh;
1186 *ptr++ = *arg++;
1187 *ptr++ = *arg++;
1188 *ptr++ = *arg++;
1189 *ptr++ = *arg++;
1190 *ptr++ = *arg++;
1191 *ptr++ = *arg++;
1192 *ptr++ = *arg++;
1193 *ptr++ = *arg;
1194 sa = &argp->saa_sa;
1195 IXDR_PUT_U_INT32(ptr, sa->sa_mode);
1196 IXDR_PUT_U_INT32(ptr, sa->sa_uid);
1197 IXDR_PUT_U_INT32(ptr, sa->sa_gid);
1198 IXDR_PUT_U_INT32(ptr, sa->sa_size);
1199 IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_sec);
1200 IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_usec);
1201 IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_sec);
1202 IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_usec);
1203 }
1204 return (TRUE);
1205 }
1206
1207 if (xdr_fhandle(xdrs, &argp->saa_fh) &&
1208 xdr_sattr(xdrs, &argp->saa_sa)) {
1209 return (TRUE);
1210 }
1211 return (FALSE);
1212 }
1213
1214
1215 /*
1216 * arguments to create and mkdir
1217 */
1218 bool_t
1219 xdr_creatargs(XDR *xdrs, struct nfscreatargs *argp)
1220 {
1221 argp->ca_sa = &argp->ca_sa_buf;
1222
1223 if (xdrs->x_op == XDR_DECODE)
1224 argp->ca_sa = &argp->ca_sa_buf;
1225 if (xdr_diropargs(xdrs, &argp->ca_da) &&
1226 xdr_sattr(xdrs, argp->ca_sa)) {
1227 return (TRUE);
1228 }
1229 return (FALSE);
1230 }
1231
1232 /*
1233 * arguments to link
1234 */
1235 bool_t
1236 xdr_linkargs(XDR *xdrs, struct nfslinkargs *argp)
1237 {
1238 if (xdrs->x_op == XDR_DECODE)
1239 argp->la_from = &argp->la_from_buf;
1240 if (xdr_fhandle(xdrs, argp->la_from) &&
1241 xdr_diropargs(xdrs, &argp->la_to)) {
1242 return (TRUE);
1243 }
1244 return (FALSE);
1245 }
1246
1247 /*
1248 * arguments to rename
1249 */
1250 bool_t
1251 xdr_rnmargs(XDR *xdrs, struct nfsrnmargs *argp)
1252 {
1253 if (xdr_diropargs(xdrs, &argp->rna_from) &&
1254 xdr_diropargs(xdrs, &argp->rna_to))
1255 return (TRUE);
1256 return (FALSE);
1257 }
1258
1259
1260 /*
1261 * arguments to symlink
1262 */
1263 bool_t
1264 xdr_slargs(XDR *xdrs, struct nfsslargs *argp)
1265 {
1266 if (xdrs->x_op == XDR_FREE) {
1267 if (!xdr_diropargs(xdrs, &argp->sla_from))
1268 return (FALSE);
1269 if ((argp->sla_tnm_flags & SLA_FREETNM) &&
1270 !xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN))
1271 return (FALSE);
1272 return (TRUE);
1273 }
1274
1275 if (xdrs->x_op == XDR_DECODE) {
1276 argp->sla_sa = &argp->sla_sa_buf;
1277 if (argp->sla_tnm == NULL)
1278 argp->sla_tnm_flags |= SLA_FREETNM;
1279 }
1280
1281 if (xdr_diropargs(xdrs, &argp->sla_from) &&
1282 xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN) &&
1283 xdr_sattr(xdrs, argp->sla_sa)) {
1284 return (TRUE);
1285 }
1286 return (FALSE);
1287 }
1288
1289
1290 /*
1291 * NFS_OK part of statfs operation
1292 */
1293 bool_t
1294 xdr_fsok(XDR *xdrs, struct nfsstatfsok *fsok)
1295 {
1296 int32_t *ptr;
1297
1298 if (xdrs->x_op == XDR_FREE)
1299 return (TRUE);
1300
1301 ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT);
1302 if (ptr != NULL) {
1303 if (xdrs->x_op == XDR_DECODE) {
1304 fsok->fsok_tsize = IXDR_GET_INT32(ptr);
1305 fsok->fsok_bsize = IXDR_GET_INT32(ptr);
1306 fsok->fsok_blocks = IXDR_GET_INT32(ptr);
1307 fsok->fsok_bfree = IXDR_GET_INT32(ptr);
1308 fsok->fsok_bavail = IXDR_GET_INT32(ptr);
1309 } else {
1310 IXDR_PUT_INT32(ptr, fsok->fsok_tsize);
1311 IXDR_PUT_INT32(ptr, fsok->fsok_bsize);
1312 IXDR_PUT_INT32(ptr, fsok->fsok_blocks);
1313 IXDR_PUT_INT32(ptr, fsok->fsok_bfree);
1314 IXDR_PUT_INT32(ptr, fsok->fsok_bavail);
1315 }
1316 return (TRUE);
1317 }
1318
1319 if (xdr_u_int(xdrs, &fsok->fsok_tsize) &&
1320 xdr_u_int(xdrs, &fsok->fsok_bsize) &&
1321 xdr_u_int(xdrs, &fsok->fsok_blocks) &&
1322 xdr_u_int(xdrs, &fsok->fsok_bfree) &&
1323 xdr_u_int(xdrs, &fsok->fsok_bavail)) {
1324 return (TRUE);
1325 }
1326 return (FALSE);
1327 }
1328
1329 #ifdef _LITTLE_ENDIAN
1330 bool_t
1331 xdr_fastfsok(XDR *xdrs, struct nfsstatfsok *fsok)
1332 {
1333
1334 if (xdrs->x_op == XDR_FREE)
1335 return (TRUE);
1336 if (xdrs->x_op == XDR_DECODE)
1337 return (FALSE);
1338
1339 fsok->fsok_tsize = htonl(fsok->fsok_tsize);
1340 fsok->fsok_bsize = htonl(fsok->fsok_bsize);
1341 fsok->fsok_blocks = htonl(fsok->fsok_blocks);
1342 fsok->fsok_bfree = htonl(fsok->fsok_bfree);
1343 fsok->fsok_bavail = htonl(fsok->fsok_bavail);
1344 return (TRUE);
1345 }
1346 #endif
1347
1348 static struct xdr_discrim statfs_discrim[2] = {
1349 { NFS_OK, xdr_fsok },
1350 { __dontcare__, NULL_xdrproc_t }
1351 };
1352
1353 /*
1354 * Results of statfs operation
1355 */
1356 bool_t
1357 xdr_statfs(XDR *xdrs, struct nfsstatfs *fs)
1358 {
1359 return (xdr_union(xdrs, (enum_t *)&(fs->fs_status),
1360 (caddr_t)&(fs->fs_fsok), statfs_discrim, xdr_void));
1361 }
1362
1363 /*
1364 * Results of statfs operation
1365 */
1366 bool_t
1367 xdr_faststatfs(XDR *xdrs, struct nfsstatfs *fs)
1368 {
1369 #if defined(_LITTLE_ENDIAN)
1370 /*
1371 * we deal with the discriminator; it's an enum
1372 */
1373 if (!xdr_fastenum(xdrs, (enum_t *)&fs->fs_status))
1374 return (FALSE);
1375
1376 if (fs->fs_status == NFS_OK)
1377 return (xdr_fastfsok(xdrs, &fs->fs_fsok));
1378 #elif defined(_BIG_ENDIAN)
1379 if (fs->fs_status == NFS_OK)
1380 return (TRUE);
1381 #endif
1382 return (xdr_fastshorten(xdrs, sizeof (*fs)));
1383 }
1384
1385 #ifdef _LITTLE_ENDIAN
1386 /*
1387 * XDR enumerations
1388 */
1389 #ifndef lint
1390 static enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */
1391 /* an enum */
1392 #endif
1393 bool_t
1394 xdr_fastenum(XDR *xdrs, enum_t *ep)
1395 {
1396 if (xdrs->x_op == XDR_FREE)
1397 return (TRUE);
1398 if (xdrs->x_op == XDR_DECODE)
1399 return (FALSE);
1400
1401 #ifndef lint
1402 /*
1403 * enums are treated as ints
1404 */
1405 if (sizeof (sizecheckvar) == sizeof (int32_t)) {
1406 *ep = (enum_t)htonl((int32_t)(*ep));
1407 } else if (sizeof (sizecheckvar) == sizeof (short)) {
1408 *ep = (enum_t)htons((short)(*ep));
1409 } else {
1410 return (FALSE);
1411 }
1412 return (TRUE);
1413 #else
1414 (void) (xdr_short(xdrs, (short *)ep));
1415 return (xdr_int(xdrs, (int *)ep));
1416 #endif
1417 }
1418 #endif
1419
1420 static bool_t
1421 xdr_fastshorten(XDR *xdrs, uint_t ressize)
1422 {
1423 uint_t curpos;
1424
1425 curpos = XDR_GETPOS(xdrs);
1426 ressize -= BYTES_PER_XDR_UNIT;
1427 curpos -= ressize;
1428 return (XDR_SETPOS(xdrs, curpos));
1429 }