xref: /illumos-gate/usr/src/uts/common/fs/autofs/auto_xdr.c (revision 9a5d73e03cd3312ddb571a748c40a63c58bd66e5)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file can not be automatically generated by rpcgen from
28  * autofs_prot.x because of the xdr routines that provide readdir
29  * support, its own implementation of xdr_autofs_netbuf(). rpcgen will
30  * also generate xdr routines with recursion which should not be used
31  * in the kernel.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/kmem.h>
36 #include <sys/errno.h>
37 #include <sys/proc.h>
38 #include <sys/vfs.h>
39 #include <sys/vnode.h>
40 #include <sys/pathname.h>
41 #include <sys/cred.h>
42 #include <sys/mount.h>
43 #include <sys/cmn_err.h>
44 #include <sys/debug.h>
45 #include <sys/systm.h>
46 #include <rpc/types.h>
47 #include <rpc/xdr.h>
48 #include <rpc/auth.h>
49 #include <rpc/clnt.h>
50 #include <sys/ticotsord.h>
51 #include <sys/dirent.h>
52 #include <sys/sysmacros.h>
53 #include <fs/fs_subr.h>
54 #include <sys/fs/autofs.h>
55 
56 bool_t xdr_autofs_netbuf(XDR *, struct netbuf *);
57 bool_t xdr_mounta(XDR *, struct mounta *);
58 
59 bool_t
60 xdr_umntrequest(XDR *xdrs, umntrequest *objp)
61 {
62 	bool_t more_data;
63 
64 	ASSERT(xdrs->x_op == XDR_ENCODE);
65 
66 	for (; objp != NULL; objp = objp->next) {
67 		if (!xdr_bool_t(xdrs, &objp->isdirect))
68 			return (FALSE);
69 		if (!xdr_string(xdrs, &objp->mntresource, AUTOFS_MAXPATHLEN))
70 			return (FALSE);
71 		if (!xdr_string(xdrs, &objp->mntpnt, AUTOFS_MAXPATHLEN))
72 			return (FALSE);
73 		if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
74 			return (FALSE);
75 		if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN))
76 			return (FALSE);
77 
78 		if (objp->next != NULL)
79 			more_data = TRUE;
80 		else
81 			more_data = FALSE;
82 
83 		if (!xdr_bool(xdrs, &more_data))
84 			return (FALSE);
85 	}
86 	return (TRUE);
87 }
88 
89 bool_t
90 xdr_umntres(XDR *xdrs, umntres *objp)
91 {
92 	return (xdr_int(xdrs, &objp->status));
93 }
94 
95 bool_t
96 xdr_autofs_stat(XDR *xdrs, autofs_stat *objp)
97 {
98 	if (!xdr_enum(xdrs, (enum_t *)objp))
99 		return (FALSE);
100 	return (TRUE);
101 }
102 
103 bool_t
104 xdr_autofs_action(XDR *xdrs, autofs_action *objp)
105 {
106 	if (!xdr_enum(xdrs, (enum_t *)objp))
107 		return (FALSE);
108 	return (TRUE);
109 }
110 
111 bool_t
112 xdr_linka(XDR *xdrs, linka *objp)
113 {
114 	if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
115 		return (FALSE);
116 	if (!xdr_string(xdrs, &objp->link, AUTOFS_MAXPATHLEN))
117 		return (FALSE);
118 	return (TRUE);
119 }
120 
121 bool_t
122 xdr_autofs_args(XDR *xdrs, autofs_args *objp)
123 {
124 	if (!xdr_autofs_netbuf(xdrs, &objp->addr))
125 		return (FALSE);
126 	if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
127 		return (FALSE);
128 	if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
129 		return (FALSE);
130 	if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
131 		return (FALSE);
132 	if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
133 		return (FALSE);
134 	if (!xdr_string(xdrs, &objp->key, AUTOFS_MAXCOMPONENTLEN))
135 		return (FALSE);
136 	if (!xdr_int(xdrs, &objp->mount_to))
137 		return (FALSE);
138 	if (!xdr_int(xdrs, &objp->rpc_to))
139 		return (FALSE);
140 	if (!xdr_int(xdrs, &objp->direct))
141 		return (FALSE);
142 	return (TRUE);
143 }
144 
145 bool_t
146 xdr_action_list_entry(XDR *xdrs, action_list_entry *objp)
147 {
148 	if (!xdr_autofs_action(xdrs, &objp->action))
149 		return (FALSE);
150 	switch (objp->action) {
151 	case AUTOFS_MOUNT_RQ:
152 		if (!xdr_mounta(xdrs, &objp->action_list_entry_u.mounta))
153 			return (FALSE);
154 		break;
155 	case AUTOFS_LINK_RQ:
156 		if (!xdr_linka(xdrs, &objp->action_list_entry_u.linka))
157 			return (FALSE);
158 		break;
159 	default:
160 		break;
161 	}
162 	return (TRUE);
163 }
164 
165 bool_t
166 xdr_action_list(XDR *xdrs, action_list *objp)
167 {
168 	bool_t more_data = TRUE;
169 	bool_t status = TRUE;
170 	action_list *p, *last;
171 
172 	ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE));
173 
174 	more_data = (objp != NULL);
175 	p = objp;
176 
177 	if (xdrs->x_op == XDR_FREE) {
178 		while (p != NULL) {
179 			if (!xdr_action_list_entry(xdrs, &p->action))
180 				cmn_err(CE_WARN, "xdr_action_list: "
181 				    "action_list_entry free failed %p\n",
182 				    (void *)&p->action);
183 			last = p;
184 			p = p->next;
185 			kmem_free(last, sizeof (*last));
186 		}
187 		return (status);
188 	}
189 
190 	while (more_data) {
191 		if (!xdr_action_list_entry(xdrs, &p->action)) {
192 			status = FALSE;
193 			break;
194 		}
195 
196 		if (!xdr_bool(xdrs, &more_data)) {
197 			status = FALSE;
198 			break;
199 		}
200 
201 		if (more_data) {
202 			p->next = kmem_zalloc(sizeof (action_list), KM_SLEEP);
203 			p = p->next;
204 			if (p == NULL) {
205 				status = FALSE;
206 				break;
207 			}
208 		} else
209 			p->next = NULL;
210 	}
211 	return (status);
212 }
213 
214 bool_t
215 xdr_autofs_netbuf(XDR *xdrs, struct netbuf *objp)
216 {
217 	bool_t dummy;
218 
219 	if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen))
220 		return (FALSE);
221 	dummy = xdr_bytes(xdrs, (char **)&(objp->buf),
222 	    (uint_t *)&(objp->len), objp->maxlen);
223 	return (dummy);
224 }
225 
226 bool_t
227 xdr_mounta(XDR *xdrs, struct mounta *objp)
228 {
229 	if (!xdr_string(xdrs, &objp->spec, AUTOFS_MAXPATHLEN))
230 		return (FALSE);
231 	if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
232 		return (FALSE);
233 	if (!xdr_int(xdrs, &objp->flags))
234 		return (FALSE);
235 	if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
236 		return (FALSE);
237 	if (!xdr_pointer(xdrs, (char **)&objp->dataptr, sizeof (autofs_args),
238 	    (xdrproc_t)xdr_autofs_args))
239 		return (FALSE);
240 	/*
241 	 * The length is the original user-land length, not the
242 	 * length of the native kernel autofs_args structure provided
243 	 * after we decode the xdr buffer.  So passing the user's idea of
244 	 * the length is wrong and we need to stuff the length field with
245 	 * the length of the native structure.
246 	 */
247 	if (!xdr_int(xdrs, &objp->datalen))
248 		return (FALSE);
249 	if (xdrs->x_op == XDR_DECODE)
250 		objp->datalen = sizeof (struct autofs_args);
251 	if (!xdr_string(xdrs, &objp->optptr, AUTOFS_MAXOPTSLEN))
252 		return (FALSE);
253 	if (!xdr_int(xdrs, &objp->optlen))
254 		return (FALSE);
255 	ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE));
256 	return (TRUE);
257 }
258 
259 bool_t
260 xdr_autofs_res(XDR *xdrs, autofs_res *objp)
261 {
262 	if (!xdr_enum(xdrs, (enum_t *)objp))
263 		return (FALSE);
264 	return (TRUE);
265 }
266 
267 bool_t
268 xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp)
269 {
270 	if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
271 		return (FALSE);
272 	if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
273 		return (FALSE);
274 	if (!xdr_string(xdrs, &objp->name, AUTOFS_MAXCOMPONENTLEN))
275 		return (FALSE);
276 	if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
277 		return (FALSE);
278 	if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
279 		return (FALSE);
280 	if (!xdr_bool_t(xdrs, &objp->isdirect))
281 		return (FALSE);
282 	if (!xdr_u_int(xdrs, (uint_t *)&objp->uid))
283 		return (FALSE);
284 	return (TRUE);
285 }
286 
287 bool_t
288 xdr_mount_result_type(XDR *xdrs, mount_result_type *objp)
289 {
290 	if (!xdr_autofs_stat(xdrs, &objp->status))
291 		return (FALSE);
292 	switch (objp->status) {
293 	case AUTOFS_ACTION:
294 		if (!xdr_pointer(xdrs,
295 		    (char **)&objp->mount_result_type_u.list,
296 		    sizeof (action_list), (xdrproc_t)xdr_action_list))
297 			return (FALSE);
298 		break;
299 	case AUTOFS_DONE:
300 		if (!xdr_int(xdrs, &objp->mount_result_type_u.error))
301 			return (FALSE);
302 		break;
303 	}
304 	return (TRUE);
305 }
306 
307 bool_t
308 xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp)
309 {
310 	if (!xdr_mount_result_type(xdrs, &objp->mr_type))
311 		return (FALSE);
312 	if (!xdr_int(xdrs, &objp->mr_verbose))
313 		return (FALSE);
314 	return (TRUE);
315 }
316 
317 bool_t
318 xdr_lookup_result_type(XDR *xdrs, lookup_result_type *objp)
319 {
320 	if (!xdr_autofs_action(xdrs, &objp->action))
321 		return (FALSE);
322 	switch (objp->action) {
323 	case AUTOFS_LINK_RQ:
324 		if (!xdr_linka(xdrs, &objp->lookup_result_type_u.lt_linka))
325 			return (FALSE);
326 		break;
327 	default:
328 		break;
329 	}
330 	return (TRUE);
331 }
332 
333 bool_t
334 xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp)
335 {
336 	if (!xdr_autofs_res(xdrs, &objp->lu_res))
337 		return (FALSE);
338 	if (!xdr_lookup_result_type(xdrs, &objp->lu_type))
339 		return (FALSE);
340 	if (!xdr_int(xdrs, &objp->lu_verbose))
341 		return (FALSE);
342 	return (TRUE);
343 }
344 
345 bool_t
346 xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp)
347 {
348 	if (!xdr_string(xdrs, &objp->rda_map, AUTOFS_MAXPATHLEN))
349 		return (FALSE);
350 	if (!xdr_u_int(xdrs, &objp->rda_offset))
351 		return (FALSE);
352 	if (!xdr_u_int(xdrs, &objp->rda_count))
353 		return (FALSE);
354 	if (!xdr_u_int(xdrs, (uint_t *)&objp->uid))
355 		return (FALSE);
356 	return (TRUE);
357 }
358 
359 /*
360  * Directory read reply:
361  * union (enum autofs_res) {
362  *	AUTOFS_OK: entlist;
363  *		 boolean eof;
364  *	default:
365  * }
366  *
367  * Directory entries
368  *	struct  direct {
369  *		off_t   d_off;			* offset of next entry *
370  *		u_long  d_fileno;		* inode number of entry *
371  *		ushort_t d_reclen;		* length of this record *
372  *		ushort_t d_namlen;		* length of string in d_name *
373  *		char    d_name[MAXNAMLEN + 1];	* name no longer than this *
374  *	};
375  * are on the wire as:
376  * union entlist (boolean valid) {
377  * 	TRUE:	struct otw_dirent;
378  *		uint_t nxtoffset;
379  *		union entlist;
380  *	FALSE:
381  * }
382  * where otw_dirent is:
383  * 	struct dirent {
384  *		uint_t	de_fid;
385  *		string	de_name<AUTOFS_MAXPATHLEN>;
386  *	}
387  */
388 
389 #ifdef nextdp
390 #undef nextdp
391 #endif
392 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
393 
394 /*
395  * ENCODE ONLY
396  */
397 bool_t
398 xdr_autofs_putrddirres(XDR *xdrs, struct autofsrddir *rddir, uint_t reqsize)
399 {
400 	struct dirent64 *dp;
401 	char *name;
402 	int size;
403 	uint_t namlen;
404 	bool_t true = TRUE;
405 	bool_t false = FALSE;
406 	int entrysz;
407 	int tofit;
408 	int bufsize;
409 	uint_t ino, off;
410 
411 	bufsize = 1 * BYTES_PER_XDR_UNIT;
412 	for (size = rddir->rddir_size, dp = rddir->rddir_entries;
413 	    size > 0;
414 	    /* LINTED pointer alignment */
415 	    size -= dp->d_reclen, dp = nextdp(dp)) {
416 		if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */)
417 			return (FALSE);
418 		if (dp->d_ino == 0)
419 			continue;
420 		name = dp->d_name;
421 		namlen = (uint_t)strlen(name);
422 		ino = (uint_t)dp->d_ino;
423 		off = (uint_t)dp->d_off;
424 		entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
425 		    roundup(namlen, BYTES_PER_XDR_UNIT);
426 		tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
427 		if (bufsize + tofit > reqsize) {
428 			rddir->rddir_eof = FALSE;
429 			break;
430 		}
431 		if (!xdr_bool(xdrs, &true) ||
432 		    !xdr_u_int(xdrs, &ino) ||
433 		    !xdr_bytes(xdrs, &name, &namlen, AUTOFS_MAXPATHLEN) ||
434 		    !xdr_u_int(xdrs, &off)) {
435 			return (FALSE);
436 		}
437 		bufsize += entrysz;
438 	}
439 	if (!xdr_bool(xdrs, &false))
440 		return (FALSE);
441 	if (!xdr_bool(xdrs, &rddir->rddir_eof))
442 		return (FALSE);
443 	return (TRUE);
444 }
445 
446 
447 /*
448  * DECODE ONLY
449  */
450 bool_t
451 xdr_autofs_getrddirres(XDR *xdrs, struct autofsrddir *rddir)
452 {
453 	struct dirent64 *dp;
454 	uint_t namlen;
455 	int size;
456 	bool_t valid;
457 	uint_t offset;
458 	uint_t fileid;
459 
460 	offset = (uint_t)-1;
461 
462 	size = rddir->rddir_size;
463 	dp = rddir->rddir_entries;
464 	for (;;) {
465 		if (!xdr_bool(xdrs, &valid))
466 			return (FALSE);
467 		if (!valid)
468 			break;
469 		if (!xdr_u_int(xdrs, &fileid) ||
470 		    !xdr_u_int(xdrs, &namlen))
471 			return (FALSE);
472 		if (DIRENT64_RECLEN(namlen) > size) {
473 			rddir->rddir_eof = FALSE;
474 			goto bufovflw;
475 		}
476 		if (!xdr_opaque(xdrs, dp->d_name, namlen)||
477 		    !xdr_u_int(xdrs, &offset))
478 			return (FALSE);
479 		dp->d_ino = fileid;
480 		dp->d_reclen = (ushort_t)DIRENT64_RECLEN(namlen);
481 		bzero(&dp->d_name[namlen],
482 		    DIRENT64_NAMELEN(dp->d_reclen) - namlen);
483 		dp->d_off = offset;
484 		size -= dp->d_reclen;
485 		/* LINTED pointer alignment */
486 		dp = nextdp(dp);
487 	}
488 	if (!xdr_bool(xdrs, &rddir->rddir_eof))
489 		return (FALSE);
490 bufovflw:
491 	rddir->rddir_size = (uint_t)((char *)dp - (char *)rddir->rddir_entries);
492 	rddir->rddir_offset = offset;
493 	return (TRUE);
494 }
495 
496 bool_t
497 xdr_autofs_rddirres(XDR *xdrs, autofs_rddirres *objp)
498 {
499 	if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status))
500 		return (FALSE);
501 	if (objp->rd_status != AUTOFS_OK)
502 		return (TRUE);
503 	if (xdrs->x_op == XDR_ENCODE)
504 		return (xdr_autofs_putrddirres(xdrs,
505 		    (struct autofsrddir *)&objp->rd_rddir, objp->rd_bufsize));
506 	else if (xdrs->x_op == XDR_DECODE)
507 		return (xdr_autofs_getrddirres(xdrs,
508 		    (struct autofsrddir *)&objp->rd_rddir));
509 	return (FALSE);
510 }
511