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