xref: /illumos-gate/usr/src/uts/common/fs/autofs/auto_xdr.c (revision bcd524b5c10222cf2a1ef37ac7ea8bf1baa3a2ee)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * This file can not be automatically generated by rpcgen from
30  * autofs_prot.x because of the xdr routines that provide readdir
31  * support, its own implementation of xdr_autofs_netbuf(). rpcgen will
32  * also generate xdr routines with recursion which should not be used
33  * in the kernel.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/kmem.h>
38 #include <sys/errno.h>
39 #include <sys/proc.h>
40 #include <sys/vfs.h>
41 #include <sys/vnode.h>
42 #include <sys/pathname.h>
43 #include <sys/cred.h>
44 #include <sys/mount.h>
45 #include <sys/cmn_err.h>
46 #include <sys/debug.h>
47 #include <sys/systm.h>
48 #include <sys/utsname.h>
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51 #include <rpc/auth.h>
52 #include <rpc/clnt.h>
53 #include <sys/ticotsord.h>
54 #include <sys/dirent.h>
55 #include <sys/sysmacros.h>
56 #include <fs/fs_subr.h>
57 #include <sys/fs/autofs.h>
58 #include <sys/pathconf.h>
59 #include <rpc/auth.h>
60 #include <rpc/rpcsec_gss.h>
61 #include <nfs/mount.h>
62 #include <sys/thread.h>
63 #include <nfs/rnode.h>
64 
65 #define	FS_NFS2	2
66 #define	FS_NFS3	3
67 #define	FS_NFS4	4
68 #define	FS_AUTOFS	1
69 
70 #define	NFS4_FHSIZE 128
71 
72 bool_t xdr_autofs_netbuf(XDR *, struct netbuf *);
73 bool_t xdr_mounta(XDR *, struct mounta *);
74 
75 bool_t
76 xdr_nfs2_args(XDR *xdrs, struct nfs_args *objp);
77 
78 bool_t
79 xdr_nfs3_args(XDR *xdrs, struct nfs_args *objp);
80 
81 bool_t
82 xdr_nfs4_args(XDR *xdrs, struct nfs_args *objp);
83 
84 bool_t
85 xdr_umntrequest(XDR *xdrs, umntrequest *objp)
86 {
87 	bool_t more_data;
88 
89 	ASSERT(xdrs->x_op == XDR_ENCODE);
90 
91 	for (; objp != NULL; objp = objp->next) {
92 		if (!xdr_bool_t(xdrs, &objp->isdirect))
93 			return (FALSE);
94 		if (!xdr_string(xdrs, &objp->mntresource, AUTOFS_MAXPATHLEN))
95 			return (FALSE);
96 		if (!xdr_string(xdrs, &objp->mntpnt, AUTOFS_MAXPATHLEN))
97 			return (FALSE);
98 		if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
99 			return (FALSE);
100 		if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN))
101 			return (FALSE);
102 
103 		if (objp->next != NULL)
104 			more_data = TRUE;
105 		else
106 			more_data = FALSE;
107 
108 		if (!xdr_bool(xdrs, &more_data))
109 			return (FALSE);
110 	}
111 	return (TRUE);
112 }
113 
114 bool_t
115 xdr_umntres(XDR *xdrs, umntres *objp)
116 {
117 	return (xdr_int(xdrs, &objp->status));
118 }
119 
120 bool_t
121 xdr_autofs_stat(XDR *xdrs, autofs_stat *objp)
122 {
123 	if (!xdr_enum(xdrs, (enum_t *)objp))
124 		return (FALSE);
125 	return (TRUE);
126 }
127 
128 bool_t
129 xdr_autofs_action(XDR *xdrs, autofs_action *objp)
130 {
131 	if (!xdr_enum(xdrs, (enum_t *)objp))
132 		return (FALSE);
133 	return (TRUE);
134 }
135 
136 bool_t
137 xdr_linka(XDR *xdrs, linka *objp)
138 {
139 	if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
140 		return (FALSE);
141 	if (!xdr_string(xdrs, &objp->link, AUTOFS_MAXPATHLEN))
142 		return (FALSE);
143 	return (TRUE);
144 }
145 
146 
147 
148 bool_t
149 xdr_knetconfig(XDR *xdrs, struct knetconfig *objp)
150 {
151 
152 	rpc_inline_t *buf;
153 	char	*knstring;
154 	uint_t	d;
155 
156 	int i;
157 
158 	if (xdrs->x_op == XDR_DECODE) {
159 		if (!xdr_u_int(xdrs, &objp->knc_semantics))
160 			return (FALSE);
161 		/*
162 		 * The knc_protofmly and knc_proto strings will
163 		 * be freed as a size of KNC_STRSIZE, make sure the
164 		 * buffer allocated is also this size, and not just
165 		 * the string size.
166 		 */
167 		if (!xdr_string(xdrs, &objp->knc_protofmly, KNC_STRSIZE))
168 			return (FALSE);
169 		knstring = kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
170 		bcopy(objp->knc_protofmly, knstring,
171 			strlen(objp->knc_protofmly));
172 		kmem_free(objp->knc_protofmly, strlen(objp->knc_protofmly) + 1);
173 		objp->knc_protofmly = knstring;
174 
175 		if (!xdr_string(xdrs, &objp->knc_proto, KNC_STRSIZE))
176 			return (FALSE);
177 		knstring = kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
178 		bcopy(objp->knc_proto, knstring, strlen(objp->knc_proto));
179 		kmem_free(objp->knc_proto, strlen(objp->knc_proto) + 1);
180 		objp->knc_proto = knstring;
181 
182 		if (!xdr_u_int(xdrs, &d))
183 			return (FALSE);
184 		objp->knc_rdev = expldev(d);
185 
186 		buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
187 		if (buf == NULL) {
188 			if (!xdr_opaque(xdrs, (char *)&objp->knc_unused,
189 				sizeof (objp->knc_unused)))
190 				return (FALSE);
191 		} else {
192 			uint_t *genp;
193 
194 				for (i = 0, genp = objp->knc_unused; i < 8;
195 				    i++) {
196 					*genp++ = IXDR_GET_U_INT32(buf);
197 				}
198 		}
199 		return (TRUE);
200 	}
201 
202 	if (!xdr_u_int(xdrs, &objp->knc_semantics))
203 		return (FALSE);
204 	if (xdrs->x_op == XDR_FREE) {
205 		kmem_free(objp->knc_protofmly, KNC_STRSIZE);
206 		kmem_free(objp->knc_proto, KNC_STRSIZE);
207 	} else {
208 		if (!xdr_string(xdrs, &objp->knc_protofmly, KNC_STRSIZE))
209 			return (FALSE);
210 		if (!xdr_string(xdrs, &objp->knc_proto, KNC_STRSIZE))
211 			return (FALSE);
212 	}
213 	if (!xdr_u_int(xdrs, (uint_t *)&objp->knc_rdev))
214 		return (FALSE);
215 	if (!xdr_opaque(xdrs, (char *)&objp->knc_unused,
216 		sizeof (objp->knc_unused)))
217 		return (FALSE);
218 	return (TRUE);
219 }
220 
221 
222 bool_t
223 xdr_pathcnf(XDR *xdrs, struct pathcnf *objp)
224 {
225 
226 	rpc_inline_t *buf;
227 
228 	int i;
229 
230 
231 	if (xdrs->x_op == XDR_DECODE) {
232 		buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
233 		if (buf == NULL) {
234 			if (!xdr_int(xdrs, &objp->pc_link_max))
235 				return (FALSE);
236 			if (!xdr_short(xdrs, &objp->pc_max_canon))
237 				return (FALSE);
238 			if (!xdr_short(xdrs, &objp->pc_max_input))
239 				return (FALSE);
240 			if (!xdr_short(xdrs, &objp->pc_name_max))
241 				return (FALSE);
242 			if (!xdr_short(xdrs, &objp->pc_path_max))
243 				return (FALSE);
244 			if (!xdr_short(xdrs, &objp->pc_pipe_buf))
245 				return (FALSE);
246 		} else {
247 			objp->pc_link_max = IXDR_GET_INT32(buf);
248 			objp->pc_max_canon = IXDR_GET_SHORT(buf);
249 			objp->pc_max_input = IXDR_GET_SHORT(buf);
250 			objp->pc_name_max = IXDR_GET_SHORT(buf);
251 			objp->pc_path_max = IXDR_GET_SHORT(buf);
252 			objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
253 		}
254 		if (!xdr_char(xdrs, (char *)&objp->pc_vdisable))
255 			return (FALSE);
256 		if (!xdr_char(xdrs, &objp->pc_xxx))
257 			return (FALSE);
258 		buf = XDR_INLINE(xdrs, (_PC_N) * BYTES_PER_XDR_UNIT);
259 		if (buf == NULL) {
260 			if (!xdr_opaque(xdrs, (char *)objp->pc_mask,
261 				sizeof (objp->pc_mask)))
262 				return (FALSE);
263 		} else {
264 			{
265 				short *genp;
266 
267 				for (i = 0, genp = objp->pc_mask; i < _PC_N;
268 				    i++) {
269 					*genp++ = IXDR_GET_SHORT(buf);
270 				}
271 			}
272 
273 		}
274 		return (TRUE);
275 	}
276 
277 	if (!xdr_int(xdrs, &objp->pc_link_max))
278 		return (FALSE);
279 	if (!xdr_short(xdrs, &objp->pc_max_canon))
280 		return (FALSE);
281 	if (!xdr_short(xdrs, &objp->pc_max_input))
282 		return (FALSE);
283 	if (!xdr_short(xdrs, &objp->pc_name_max))
284 		return (FALSE);
285 	if (!xdr_short(xdrs, &objp->pc_path_max))
286 		return (FALSE);
287 	if (!xdr_short(xdrs, &objp->pc_pipe_buf))
288 		return (FALSE);
289 	if (!xdr_char(xdrs, (char *)&objp->pc_vdisable))
290 		return (FALSE);
291 	if (!xdr_char(xdrs, &objp->pc_xxx))
292 		return (FALSE);
293 	if (!xdr_opaque(xdrs, (char *)objp->pc_mask,
294 		sizeof (objp->pc_mask)))
295 		return (FALSE);
296 	return (TRUE);
297 }
298 
299 
300 bool_t
301 xdr_des_clnt_data(XDR *xdrs, dh_k4_clntdata_t *objp)
302 {
303 	if (!xdr_autofs_netbuf(xdrs, &objp->syncaddr))
304 		return (FALSE);
305 	if (!xdr_pointer(xdrs, (char **)&objp->knconf,
306 		sizeof (struct knetconfig), (xdrproc_t)xdr_knetconfig))
307 		return (FALSE);
308 	if (!xdr_string(xdrs, &objp->netname, SYS_NMLN))
309 		return (FALSE);
310 	if (!xdr_int(xdrs, &objp->netnamelen))
311 		return (FALSE);
312 	objp->netnamelen = strlen(objp->netname) + 1;
313 	return (TRUE);
314 }
315 
316 bool_t
317 xdr_gss_clnt_data(XDR *xdrs, struct gss_clnt_data *objp)
318 {
319 	if (!xdr_u_int(xdrs, &objp->mechanism.length))
320 		return (FALSE);
321 	if (!xdr_enum(xdrs, (enum_t *)&objp->service))
322 		return (FALSE);
323 	if (!xdr_opaque(xdrs, objp->mechanism.elements,
324 		objp->mechanism.length))
325 		return (FALSE);
326 	if (!xdr_opaque(xdrs, (char *)&objp->uname, MAX_NAME_LEN))
327 		return (FALSE);
328 	if (!xdr_opaque(xdrs, (char *)&objp->inst, MAX_NAME_LEN))
329 		return (FALSE);
330 	if (!xdr_opaque(xdrs, (char *)&objp->realm, MAX_NAME_LEN))
331 		return (FALSE);
332 	if (!xdr_u_int(xdrs, &objp->qop))
333 		return (FALSE);
334 	return (TRUE);
335 }
336 
337 bool_t
338 xdr_sec_data(XDR *xdrs, struct sec_data *objp)
339 {
340 	if (!xdr_u_int(xdrs, &objp->secmod))
341 		return (FALSE);
342 	if (!xdr_u_int(xdrs, &objp->rpcflavor))
343 		return (FALSE);
344 	if (!xdr_int(xdrs, &objp->flags))
345 		return (FALSE);
346 	if (!xdr_uid_t(xdrs, &objp->uid))
347 		return (FALSE);
348 
349 	switch (objp->rpcflavor) {
350 	case AUTH_NONE:
351 	case AUTH_UNIX:
352 	case AUTH_LOOPBACK:
353 		break;
354 	case AUTH_DES:
355 		if (!xdr_pointer(xdrs, (char **)&objp->data,
356 			sizeof (dh_k4_clntdata_t),
357 			(xdrproc_t)xdr_des_clnt_data))
358 			return (FALSE);
359 		break;
360 	case RPCSEC_GSS:
361 		if (!xdr_pointer(xdrs, (char **)&objp->data,
362 			sizeof (gss_clntdata_t),
363 			(xdrproc_t)xdr_gss_clnt_data))
364 			return (FALSE);
365 		break;
366 	default:
367 		return (FALSE);
368 	}
369 
370 	return (TRUE);
371 }
372 
373 bool_t
374 xdr_nfs2_fh(XDR *xdrs, nfs_fhandle *objp)
375 {
376 	objp->fh_len = NFS_FHSIZE;
377 	if (!xdr_opaque(xdrs, (char *)&objp->fh_buf, NFS_FHSIZE))
378 		return (B_FALSE);
379 	return (B_TRUE);
380 }
381 
382 bool_t
383 xdr_nfs3_fhandle(XDR *xdrs, nfs_fhandle *objp)
384 {
385 	if (!xdr_int(xdrs, &objp->fh_len))
386 		return (B_FALSE);
387 	if (!xdr_opaque(xdrs, (char *)&objp->fh_buf, objp->fh_len))
388 		return (B_FALSE);
389 	return (B_TRUE);
390 }
391 
392 bool_t
393 xdr_nfs(XDR *xdrs, struct nfs_args *objp, int nfsv)
394 {
395 
396 	rpc_inline_t *buf;
397 
398 	if (objp == NULL)
399 		return (TRUE);
400 
401 	if (xdrs->x_op == XDR_DECODE) {
402 		if (!xdr_pointer(xdrs, (char **)&objp->addr,
403 			sizeof (struct netbuf), (xdrproc_t)xdr_autofs_netbuf))
404 			return (FALSE);
405 		if (!xdr_pointer(xdrs, (char **)&objp->syncaddr,
406 			sizeof (struct netbuf), (xdrproc_t)xdr_autofs_netbuf))
407 			return (FALSE);
408 		if (!xdr_pointer(xdrs, (char **)&objp->knconf,
409 			sizeof (struct knetconfig), (xdrproc_t)xdr_knetconfig))
410 			return (FALSE);
411 		if (!xdr_string(xdrs, &objp->hostname, SYS_NMLN))
412 			return (FALSE);
413 		if (!xdr_string(xdrs, &objp->netname, SYS_NMLN))
414 			return (FALSE);
415 		if (nfsv == FS_NFS4) {
416 			if (!xdr_string(xdrs, &objp->fh, NFS4_FHSIZE))
417 				return (B_FALSE);
418 		} else if (nfsv == FS_NFS3) {
419 			if (!xdr_pointer(xdrs, (char **)&objp->fh,
420 				sizeof (nfs_fhandle),
421 				(xdrproc_t)xdr_nfs3_fhandle))
422 				return (B_FALSE);
423 		} else {
424 			if (!xdr_pointer(xdrs, (char **)&objp->fh,
425 				sizeof (nfs_fhandle),
426 				(xdrproc_t)xdr_nfs2_fh))
427 				return (B_FALSE);
428 		}
429 		buf = XDR_INLINE(xdrs, 9 * BYTES_PER_XDR_UNIT);
430 		if (buf == NULL) {
431 			if (!xdr_int(xdrs, &objp->flags))
432 				return (FALSE);
433 			if (!xdr_int(xdrs, &objp->wsize))
434 				return (FALSE);
435 			if (!xdr_int(xdrs, &objp->rsize))
436 				return (FALSE);
437 			if (!xdr_int(xdrs, &objp->timeo))
438 				return (FALSE);
439 			if (!xdr_int(xdrs, &objp->retrans))
440 				return (FALSE);
441 			if (!xdr_int(xdrs, &objp->acregmin))
442 				return (FALSE);
443 			if (!xdr_int(xdrs, &objp->acregmax))
444 				return (FALSE);
445 			if (!xdr_int(xdrs, &objp->acdirmin))
446 				return (FALSE);
447 			if (!xdr_int(xdrs, &objp->acdirmax))
448 				return (FALSE);
449 		} else {
450 			objp->flags = IXDR_GET_INT32(buf);
451 			objp->wsize = IXDR_GET_INT32(buf);
452 			objp->rsize = IXDR_GET_INT32(buf);
453 			objp->timeo = IXDR_GET_INT32(buf);
454 			objp->retrans = IXDR_GET_INT32(buf);
455 			objp->acregmin = IXDR_GET_INT32(buf);
456 			objp->acregmax = IXDR_GET_INT32(buf);
457 			objp->acdirmin = IXDR_GET_INT32(buf);
458 			objp->acdirmax = IXDR_GET_INT32(buf);
459 		}
460 		if (!xdr_pointer(xdrs, (char **)&objp->pathconf,
461 			sizeof (struct pathcnf), (xdrproc_t)xdr_pathcnf))
462 			return (FALSE);
463 		if (!xdr_int(xdrs, &objp->nfs_args_ext))
464 			return (FALSE);
465 		if (!xdr_pointer(xdrs,
466 			(char **)&objp->nfs_ext_u.nfs_extA.secdata,
467 			sizeof (struct sec_data), (xdrproc_t)xdr_sec_data))
468 			return (FALSE);
469 		if (objp->nfs_args_ext == NFS_ARGS_EXTB) {
470 			if (nfsv == FS_NFS4) {
471 				if (!xdr_pointer(xdrs,
472 					(char **)&objp->nfs_ext_u.nfs_extB.next,
473 					sizeof (struct nfs_args),
474 					(xdrproc_t)xdr_nfs4_args))
475 					return (FALSE);
476 			} else if (nfsv == FS_NFS3) {
477 				if (!xdr_pointer(xdrs,
478 					(char **)&objp->nfs_ext_u.nfs_extB.next,
479 					sizeof (struct nfs_args),
480 					(xdrproc_t)xdr_nfs3_args))
481 					return (FALSE);
482 			} else {
483 				if (!xdr_pointer(xdrs,
484 					(char **)&objp->nfs_ext_u.nfs_extB.next,
485 					sizeof (struct nfs_args),
486 					(xdrproc_t)xdr_nfs2_args))
487 					return (FALSE);
488 			}
489 		}
490 		return (TRUE);
491 	}
492 
493 	ASSERT(xdrs->x_op != XDR_DECODE);
494 	if (!xdr_pointer(xdrs, (char **)&objp->addr,
495 		sizeof (struct netbuf), (xdrproc_t)xdr_autofs_netbuf))
496 		return (FALSE);
497 	if (!xdr_pointer(xdrs, (char **)&objp->syncaddr,
498 		sizeof (struct netbuf), (xdrproc_t)xdr_autofs_netbuf))
499 		return (FALSE);
500 	if (!xdr_pointer(xdrs, (char **)&objp->knconf,
501 		sizeof (struct knetconfig), (xdrproc_t)xdr_knetconfig))
502 		return (FALSE);
503 	if (!xdr_string(xdrs, &objp->hostname, SYS_NMLN))
504 		return (FALSE);
505 	if (!xdr_string(xdrs, &objp->netname, SYS_NMLN))
506 		return (FALSE);
507 	if (nfsv == FS_NFS4) {
508 		if (!xdr_string(xdrs, &objp->fh, NFS4_FHSIZE))
509 			return (B_FALSE);
510 	} else if (nfsv == FS_NFS3) {
511 		if (!xdr_pointer(xdrs, (char **)&objp->fh,
512 			sizeof (nfs_fhandle),
513 			(xdrproc_t)xdr_nfs3_fhandle))
514 			return (B_FALSE);
515 	} else {
516 		if (!xdr_pointer(xdrs, (char **)&objp->fh,
517 			sizeof (nfs_fhandle),
518 			(xdrproc_t)xdr_nfs2_fh))
519 			return (B_FALSE);
520 	}
521 
522 	if (!xdr_int(xdrs, &objp->flags))
523 		return (FALSE);
524 	if (!xdr_int(xdrs, &objp->wsize))
525 		return (FALSE);
526 	if (!xdr_int(xdrs, &objp->rsize))
527 		return (FALSE);
528 	if (!xdr_int(xdrs, &objp->timeo))
529 		return (FALSE);
530 	if (!xdr_int(xdrs, &objp->retrans))
531 		return (FALSE);
532 	if (!xdr_int(xdrs, &objp->acregmin))
533 		return (FALSE);
534 	if (!xdr_int(xdrs, &objp->acregmax))
535 		return (FALSE);
536 	if (!xdr_int(xdrs, &objp->acdirmin))
537 		return (FALSE);
538 	if (!xdr_int(xdrs, &objp->acdirmax))
539 		return (FALSE);
540 	if (!xdr_pointer(xdrs, (char **)&objp->pathconf,
541 		sizeof (struct pathcnf), (xdrproc_t)xdr_pathcnf))
542 		return (FALSE);
543 	if (!xdr_int(xdrs, &objp->nfs_args_ext))
544 		return (FALSE);
545 	if (!xdr_pointer(xdrs, (char **)&objp->nfs_ext_u.nfs_extA.secdata,
546 		sizeof (struct sec_data), (xdrproc_t)xdr_sec_data))
547 		return (FALSE);
548 	if (objp->nfs_args_ext == NFS_ARGS_EXTB) {
549 		if (nfsv == FS_NFS4) {
550 			if (!xdr_pointer(xdrs,
551 				(char **)&objp->nfs_ext_u.nfs_extB.next,
552 				sizeof (struct nfs_args),
553 				(xdrproc_t)xdr_nfs4_args))
554 				return (FALSE);
555 		} else if (nfsv == FS_NFS3) {
556 			if (!xdr_pointer(xdrs,
557 				(char **)&objp->nfs_ext_u.nfs_extB.next,
558 				sizeof (struct nfs_args),
559 				(xdrproc_t)xdr_nfs3_args))
560 				return (FALSE);
561 		} else {
562 			if (!xdr_pointer(xdrs,
563 				(char **)&objp->nfs_ext_u.nfs_extB.next,
564 				sizeof (struct nfs_args),
565 				(xdrproc_t)xdr_nfs2_args))
566 				return (FALSE);
567 		}
568 	}
569 	return (TRUE);
570 }
571 
572 bool_t
573 xdr_nfs4_args(XDR *xdrs, struct nfs_args *objp)
574 {
575 	return (xdr_nfs(xdrs, objp, FS_NFS4));
576 }
577 
578 bool_t
579 xdr_nfs3_args(XDR *xdrs, struct nfs_args *objp)
580 {
581 	return (xdr_nfs(xdrs, objp, FS_NFS3));
582 }
583 
584 bool_t
585 xdr_nfs2_args(XDR *xdrs, struct nfs_args *objp)
586 {
587 	return (xdr_nfs(xdrs, objp, FS_NFS2));
588 }
589 
590 
591 
592 bool_t
593 xdr_autofs_args(XDR *xdrs, autofs_args *objp)
594 {
595 	if (!xdr_autofs_netbuf(xdrs, &objp->addr))
596 		return (FALSE);
597 	if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
598 		return (FALSE);
599 	if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
600 		return (FALSE);
601 	if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
602 		return (FALSE);
603 	if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
604 		return (FALSE);
605 	if (!xdr_string(xdrs, &objp->key, AUTOFS_MAXCOMPONENTLEN))
606 		return (FALSE);
607 	if (!xdr_int(xdrs, &objp->mount_to))
608 		return (FALSE);
609 	if (!xdr_int(xdrs, &objp->rpc_to))
610 		return (FALSE);
611 	if (!xdr_int(xdrs, &objp->direct))
612 		return (FALSE);
613 	return (TRUE);
614 }
615 
616 bool_t
617 xdr_action_list_entry(XDR *xdrs, action_list_entry *objp)
618 {
619 	if (!xdr_autofs_action(xdrs, &objp->action))
620 		return (FALSE);
621 	switch (objp->action) {
622 	case AUTOFS_MOUNT_RQ:
623 		if (!xdr_mounta(xdrs, &objp->action_list_entry_u.mounta))
624 			return (FALSE);
625 		break;
626 	case AUTOFS_LINK_RQ:
627 		if (!xdr_linka(xdrs, &objp->action_list_entry_u.linka))
628 			return (FALSE);
629 		break;
630 	default:
631 		break;
632 	}
633 	return (TRUE);
634 }
635 
636 bool_t
637 xdr_action_list(XDR *xdrs, action_list *objp)
638 {
639 	bool_t more_data = TRUE;
640 	bool_t status = TRUE;
641 	action_list *p, *last;
642 
643 	ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE));
644 
645 	more_data = (objp != NULL);
646 	p = objp;
647 
648 	if (xdrs->x_op == XDR_FREE) {
649 		while (p != NULL) {
650 			if (!xdr_action_list_entry(xdrs, &p->action))
651 				cmn_err(CE_WARN, "xdr_action_list: "
652 					"action_list_entry free failed %p\n",
653 					(void *)&p->action);
654 			last = p;
655 			p = p->next;
656 			/*
657 			 * Don't need this kmem_free the first action_list
658 			 * as xdr_reference using xdr_action_list will free
659 			 * it when called with the XDR_FREE op.
660 			 */
661 			if (last != objp)
662 				kmem_free(last, sizeof (*last));
663 		}
664 		return (status);
665 	}
666 
667 	while (more_data) {
668 		if (!xdr_action_list_entry(xdrs, &p->action)) {
669 			status = FALSE;
670 			break;
671 		}
672 
673 		if (!xdr_bool(xdrs, &more_data)) {
674 			status = FALSE;
675 			break;
676 		}
677 
678 		if (more_data) {
679 			p->next = kmem_zalloc(sizeof (action_list), KM_SLEEP);
680 			p = p->next;
681 			if (p == NULL) {
682 				status = FALSE;
683 				break;
684 			}
685 		} else
686 			p->next = NULL;
687 	}
688 	return (status);
689 }
690 
691 bool_t
692 xdr_autofs_netbuf(XDR *xdrs, struct netbuf *objp)
693 {
694 	bool_t dummy;
695 
696 	if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen))
697 		return (FALSE);
698 	dummy = xdr_bytes(xdrs, (char **)&(objp->buf),
699 	    (uint_t *)&(objp->len), objp->maxlen);
700 	return (dummy);
701 }
702 
703 bool_t
704 xdr_mounta(XDR *xdrs, struct mounta *objp)
705 {
706 	int	fstype = 0;
707 	if (!xdr_string(xdrs, &objp->spec, AUTOFS_MAXPATHLEN))
708 		return (FALSE);
709 	if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
710 		return (FALSE);
711 	if (!xdr_int(xdrs, &objp->flags))
712 		return (FALSE);
713 	/*
714 	 * For a free we must first determine the fstype before calling
715 	 * xdr_string on it, as the xdr_string will free it.  For a
716 	 * decode we must first call xdr_string to get the value to
717 	 * determine the fstype.
718 	 */
719 	if (xdrs->x_op == XDR_FREE) {
720 		if (strncmp(objp->fstype, "autofs", sizeof ("autofs")) == 0) {
721 			fstype = FS_AUTOFS;
722 		} else if (strncmp(objp->fstype, "nfs4",
723 				sizeof ("nfs4")) == 0) {
724 			fstype = FS_NFS4;
725 		} else if (strncmp(objp->fstype, "nfs3",
726 			sizeof ("nfs3")) == 0) {
727 			fstype = FS_NFS3;
728 		} else {
729 			fstype = FS_NFS2;
730 		}
731 	}
732 
733 	if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
734 		return (FALSE);
735 
736 	if (xdrs->x_op == XDR_DECODE) {
737 		if (strncmp(objp->fstype, "autofs", sizeof ("autofs")) == 0) {
738 			fstype = FS_AUTOFS;
739 		} else if (strncmp(objp->fstype, "nfs4",
740 			sizeof ("nfs4")) == 0) {
741 			fstype = FS_NFS4;
742 		} else if (strncmp(objp->fstype, "nfs3",
743 			sizeof ("nfs3")) == 0) {
744 			fstype = FS_NFS3;
745 		} else {
746 			fstype = FS_NFS2;
747 		}
748 	}
749 
750 	/*
751 	 * The length is the original user-land length, not the
752 	 * length of the native kernel autofs_args structure provided
753 	 * after we decode the xdr buffer.  So passing the user's idea of
754 	 * the length is wrong and we need to stuff the length field with
755 	 * the length of the native structure.
756 	 */
757 	if (fstype == FS_AUTOFS) {
758 		if (!xdr_pointer(xdrs, (char **)&objp->dataptr,
759 			sizeof (autofs_args),
760 			(xdrproc_t)xdr_autofs_args))
761 			return (FALSE);
762 		if (!xdr_int(xdrs, &objp->datalen))
763 			return (FALSE);
764 		if (xdrs->x_op == XDR_DECODE)
765 			objp->datalen = sizeof (struct autofs_args);
766 	} else if (fstype == FS_NFS4) {
767 		if (!xdr_pointer(xdrs, (char **)&objp->dataptr,
768 			sizeof (struct nfs_args),
769 			(xdrproc_t)xdr_nfs4_args))
770 			return (FALSE);
771 		if (!xdr_int(xdrs, &objp->datalen))
772 			return (FALSE);
773 		if (xdrs->x_op == XDR_DECODE)
774 			objp->datalen = sizeof (struct nfs_args);
775 	} else if (fstype == FS_NFS3) {
776 		if (!xdr_pointer(xdrs, (char **)&objp->dataptr,
777 			sizeof (struct nfs_args),
778 			(xdrproc_t)xdr_nfs3_args))
779 			return (FALSE);
780 		if (!xdr_int(xdrs, &objp->datalen))
781 			return (FALSE);
782 		if (xdrs->x_op == XDR_DECODE)
783 			objp->datalen = sizeof (struct nfs_args);
784 	} else if (fstype == FS_NFS2) {
785 		if (!xdr_pointer(xdrs, (char **)&objp->dataptr,
786 			sizeof (struct nfs_args),
787 			(xdrproc_t)xdr_nfs2_args))
788 			return (FALSE);
789 		if (!xdr_int(xdrs, &objp->datalen))
790 			return (FALSE);
791 		if (xdrs->x_op == XDR_DECODE)
792 			objp->datalen = sizeof (struct nfs_args);
793 	}
794 
795 	/*
796 	 * domount's call to vfs_buildoptionstr() can alter the contents
797 	 * of the options string, resulting in a shorter string
798 	 * length.  Thus, xdr_string can not be used to free this
799 	 * string as it may be freed using a different size than allocated.
800 	 */
801 	if (xdrs->x_op == XDR_DECODE) {
802 		if (!xdr_string(xdrs, &objp->optptr, AUTOFS_MAXOPTSLEN))
803 			return (FALSE);
804 	} else {
805 		ASSERT(xdrs->x_op == XDR_FREE);
806 		kmem_free(objp->optptr, objp->optlen);
807 	}
808 	if (!xdr_int(xdrs, &objp->optlen))
809 		return (FALSE);
810 	if (xdrs->x_op == XDR_DECODE)
811 		ASSERT((strlen(objp->optptr) + 1) == objp->optlen);
812 	return (TRUE);
813 }
814 
815 bool_t
816 xdr_autofs_res(XDR *xdrs, autofs_res *objp)
817 {
818 	if (!xdr_enum(xdrs, (enum_t *)objp))
819 		return (FALSE);
820 	return (TRUE);
821 }
822 
823 bool_t
824 xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp)
825 {
826 	if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
827 		return (FALSE);
828 	if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
829 		return (FALSE);
830 	if (!xdr_string(xdrs, &objp->name, AUTOFS_MAXCOMPONENTLEN))
831 		return (FALSE);
832 	if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
833 		return (FALSE);
834 	if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
835 		return (FALSE);
836 	if (!xdr_bool_t(xdrs, &objp->isdirect))
837 		return (FALSE);
838 	if (!xdr_u_int(xdrs, (uint_t *)&objp->uid))
839 		return (FALSE);
840 	return (TRUE);
841 }
842 
843 bool_t
844 xdr_mount_result_type(XDR *xdrs, mount_result_type *objp)
845 {
846 	if (!xdr_autofs_stat(xdrs, &objp->status))
847 		return (FALSE);
848 	switch (objp->status) {
849 	case AUTOFS_ACTION:
850 		if (!xdr_pointer(xdrs,
851 		    (char **)&objp->mount_result_type_u.list,
852 		    sizeof (action_list), (xdrproc_t)xdr_action_list))
853 			return (FALSE);
854 		break;
855 	case AUTOFS_DONE:
856 		if (!xdr_int(xdrs, &objp->mount_result_type_u.error))
857 			return (FALSE);
858 		break;
859 	}
860 	return (TRUE);
861 }
862 
863 bool_t
864 xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp)
865 {
866 	if (!xdr_mount_result_type(xdrs, &objp->mr_type))
867 		return (FALSE);
868 	if (!xdr_int(xdrs, &objp->mr_verbose))
869 		return (FALSE);
870 	return (TRUE);
871 }
872 
873 bool_t
874 xdr_lookup_result_type(XDR *xdrs, lookup_result_type *objp)
875 {
876 	if (!xdr_autofs_action(xdrs, &objp->action))
877 		return (FALSE);
878 	switch (objp->action) {
879 	case AUTOFS_LINK_RQ:
880 		if (!xdr_linka(xdrs, &objp->lookup_result_type_u.lt_linka))
881 			return (FALSE);
882 		break;
883 	default:
884 		break;
885 	}
886 	return (TRUE);
887 }
888 
889 bool_t
890 xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp)
891 {
892 	if (!xdr_autofs_res(xdrs, &objp->lu_res))
893 		return (FALSE);
894 	if (!xdr_lookup_result_type(xdrs, &objp->lu_type))
895 		return (FALSE);
896 	if (!xdr_int(xdrs, &objp->lu_verbose))
897 		return (FALSE);
898 	return (TRUE);
899 }
900 
901 bool_t
902 xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp)
903 {
904 	if (!xdr_string(xdrs, &objp->rda_map, AUTOFS_MAXPATHLEN))
905 		return (FALSE);
906 	if (!xdr_u_int(xdrs, &objp->rda_offset))
907 		return (FALSE);
908 	if (!xdr_u_int(xdrs, &objp->rda_count))
909 		return (FALSE);
910 	if (!xdr_u_int(xdrs, (uint_t *)&objp->uid))
911 		return (FALSE);
912 	return (TRUE);
913 }
914 
915 /*
916  * Directory read reply:
917  * union (enum autofs_res) {
918  *	AUTOFS_OK: entlist;
919  *		 boolean eof;
920  *	default:
921  * }
922  *
923  * Directory entries
924  *	struct  direct {
925  *		off_t   d_off;			* offset of next entry *
926  *		u_long  d_fileno;		* inode number of entry *
927  *		ushort_t d_reclen;		* length of this record *
928  *		ushort_t d_namlen;		* length of string in d_name *
929  *		char    d_name[MAXNAMLEN + 1];	* name no longer than this *
930  *	};
931  * are on the wire as:
932  * union entlist (boolean valid) {
933  * 	TRUE:	struct otw_dirent;
934  *		uint_t nxtoffset;
935  *		union entlist;
936  *	FALSE:
937  * }
938  * where otw_dirent is:
939  * 	struct dirent {
940  *		uint_t	de_fid;
941  *		string	de_name<AUTOFS_MAXPATHLEN>;
942  *	}
943  */
944 
945 #ifdef nextdp
946 #undef nextdp
947 #endif
948 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
949 
950 /*
951  * ENCODE ONLY
952  */
953 bool_t
954 xdr_autofs_putrddirres(XDR *xdrs, struct autofsrddir *rddir, uint_t reqsize)
955 {
956 	struct dirent64 *dp;
957 	char *name;
958 	int size;
959 	uint_t namlen;
960 	bool_t true = TRUE;
961 	bool_t false = FALSE;
962 	int entrysz;
963 	int tofit;
964 	int bufsize;
965 	uint_t ino, off;
966 
967 	bufsize = 1 * BYTES_PER_XDR_UNIT;
968 	for (size = rddir->rddir_size, dp = rddir->rddir_entries;
969 		size > 0;
970 		/* LINTED pointer alignment */
971 		size -= dp->d_reclen, dp = nextdp(dp)) {
972 		if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */)
973 			return (FALSE);
974 		if (dp->d_ino == 0)
975 			continue;
976 		name = dp->d_name;
977 		namlen = (uint_t)strlen(name);
978 		ino = (uint_t)dp->d_ino;
979 		off = (uint_t)dp->d_off;
980 		entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
981 		    roundup(namlen, BYTES_PER_XDR_UNIT);
982 		tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
983 		if (bufsize + tofit > reqsize) {
984 			rddir->rddir_eof = FALSE;
985 			break;
986 		}
987 		if (!xdr_bool(xdrs, &true) ||
988 		    !xdr_u_int(xdrs, &ino) ||
989 		    !xdr_bytes(xdrs, &name, &namlen, AUTOFS_MAXPATHLEN) ||
990 		    !xdr_u_int(xdrs, &off)) {
991 			return (FALSE);
992 		}
993 		bufsize += entrysz;
994 	}
995 	if (!xdr_bool(xdrs, &false))
996 		return (FALSE);
997 	if (!xdr_bool(xdrs, &rddir->rddir_eof))
998 		return (FALSE);
999 	return (TRUE);
1000 }
1001 
1002 
1003 /*
1004  * DECODE ONLY
1005  */
1006 bool_t
1007 xdr_autofs_getrddirres(XDR *xdrs, struct autofsrddir *rddir)
1008 {
1009 	struct dirent64 *dp;
1010 	uint_t namlen;
1011 	int size;
1012 	bool_t valid;
1013 	uint_t offset;
1014 	uint_t fileid;
1015 
1016 	offset = (uint_t)-1;
1017 
1018 	size = rddir->rddir_size;
1019 	dp = rddir->rddir_entries;
1020 	for (;;) {
1021 		if (!xdr_bool(xdrs, &valid))
1022 			return (FALSE);
1023 		if (!valid)
1024 			break;
1025 		if (!xdr_u_int(xdrs, &fileid) ||
1026 		    !xdr_u_int(xdrs, &namlen))
1027 			return (FALSE);
1028 		if (DIRENT64_RECLEN(namlen) > size) {
1029 			rddir->rddir_eof = FALSE;
1030 			goto bufovflw;
1031 		}
1032 		if (!xdr_opaque(xdrs, dp->d_name, namlen)||
1033 		    !xdr_u_int(xdrs, &offset))
1034 			return (FALSE);
1035 		dp->d_ino = fileid;
1036 		dp->d_reclen = (ushort_t)DIRENT64_RECLEN(namlen);
1037 		bzero(&dp->d_name[namlen],
1038 		    DIRENT64_NAMELEN(dp->d_reclen) - namlen);
1039 		dp->d_off = offset;
1040 		size -= dp->d_reclen;
1041 		/* LINTED pointer alignment */
1042 		dp = nextdp(dp);
1043 	}
1044 	if (!xdr_bool(xdrs, &rddir->rddir_eof))
1045 		return (FALSE);
1046 bufovflw:
1047 	rddir->rddir_size = (uint_t)((char *)dp - (char *)rddir->rddir_entries);
1048 	rddir->rddir_offset = offset;
1049 	return (TRUE);
1050 }
1051 
1052 bool_t
1053 xdr_autofs_rddirres(XDR *xdrs, autofs_rddirres *objp)
1054 {
1055 	if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status))
1056 		return (FALSE);
1057 	if (objp->rd_status != AUTOFS_OK)
1058 		return (TRUE);
1059 	if (xdrs->x_op == XDR_ENCODE)
1060 		return (xdr_autofs_putrddirres(xdrs,
1061 		    (struct autofsrddir *)&objp->rd_rddir, objp->rd_bufsize));
1062 	else if (xdrs->x_op == XDR_DECODE)
1063 		return (xdr_autofs_getrddirres(xdrs,
1064 		    (struct autofsrddir *)&objp->rd_rddir));
1065 	return (FALSE);
1066 }
1067