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
xdr_umntrequest(XDR * xdrs,umntrequest * objp)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
xdr_umntres(XDR * xdrs,umntres * objp)90 xdr_umntres(XDR *xdrs, umntres *objp)
91 {
92 return (xdr_int(xdrs, &objp->status));
93 }
94
95 bool_t
xdr_autofs_stat(XDR * xdrs,autofs_stat * objp)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
xdr_autofs_action(XDR * xdrs,autofs_action * objp)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
xdr_linka(XDR * xdrs,linka * objp)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
xdr_autofs_args(XDR * xdrs,autofs_args * objp)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
xdr_action_list_entry(XDR * xdrs,action_list_entry * objp)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
xdr_action_list(XDR * xdrs,action_list * objp)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
xdr_autofs_netbuf(XDR * xdrs,struct netbuf * objp)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
xdr_mounta(XDR * xdrs,struct mounta * objp)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
xdr_autofs_res(XDR * xdrs,autofs_res * objp)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
xdr_autofs_lookupargs(XDR * xdrs,autofs_lookupargs * objp)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
xdr_mount_result_type(XDR * xdrs,mount_result_type * objp)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
xdr_autofs_mountres(XDR * xdrs,autofs_mountres * objp)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
xdr_lookup_result_type(XDR * xdrs,lookup_result_type * objp)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
xdr_autofs_lookupres(XDR * xdrs,autofs_lookupres * objp)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
xdr_autofs_rddirargs(XDR * xdrs,autofs_rddirargs * objp)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
xdr_autofs_putrddirres(XDR * xdrs,struct autofsrddir * rddir,uint_t reqsize)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
xdr_autofs_getrddirres(XDR * xdrs,struct autofsrddir * rddir)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
xdr_autofs_rddirres(XDR * xdrs,autofs_rddirres * objp)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