Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / external / bsd / am-utils / dist / conf / autofs / autofs_solaris_v2_v3.c
blobe6a149c1a1faceaba3b04c924fa04af441854f2b
1 /* $NetBSD$ */
3 /*
4 * Copyright (c) 1999-2003 Ion Badulescu
5 * Copyright (c) 1997-2009 Erez Zadok
6 * Copyright (c) 1990 Jan-Simon Pendry
7 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
8 * Copyright (c) 1990 The Regents of the University of California.
9 * All rights reserved.
11 * This code is derived from software contributed to Berkeley by
12 * Jan-Simon Pendry at Imperial College, London.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgment:
24 * This product includes software developed by the University of
25 * California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
43 * File: am-utils/conf/autofs/autofs_solaris_v2_v3.c
48 * Automounter filesystem
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif /* HAVE_CONFIG_H */
54 #include <am_defs.h>
55 #include <amd.h>
58 * MACROS:
60 #ifndef AUTOFS_NULL
61 # define AUTOFS_NULL NULLPROC
62 #endif /* not AUTOFS_NULL */
65 * STRUCTURES:
68 struct amd_rddirres {
69 enum autofs_res rd_status;
70 u_long rd_bufsize;
71 nfsdirlist rd_dl;
73 typedef struct amd_rddirres amd_rddirres;
76 * VARIABLES:
79 SVCXPRT *autofs_xprt = NULL;
81 /* forward declarations */
82 bool_t xdr_umntrequest(XDR *xdrs, umntrequest *objp);
83 bool_t xdr_umntres(XDR *xdrs, umntres *objp);
84 bool_t xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp);
85 bool_t xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp);
86 bool_t xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp);
87 bool_t xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp);
88 static bool_t xdr_amd_rddirres(XDR *xdrs, amd_rddirres *objp);
91 * These exist only in the AutoFS V2 protocol.
93 #ifdef AUTOFS_POSTUNMOUNT
94 bool_t xdr_postumntreq(XDR *xdrs, postumntreq *objp);
95 bool_t xdr_postumntres(XDR *xdrs, postumntres *objp);
96 bool_t xdr_postmountreq(XDR *xdrs, postmountreq *objp);
97 bool_t xdr_postmountres(XDR *xdrs, postmountres *objp);
98 #endif /* AUTOFS_POSTUMOUNT */
101 * AUTOFS XDR FUNCTIONS:
104 bool_t
105 xdr_autofs_stat(XDR *xdrs, autofs_stat *objp)
107 if (!xdr_enum(xdrs, (enum_t *)objp))
108 return (FALSE);
109 return (TRUE);
113 bool_t
114 xdr_autofs_action(XDR *xdrs, autofs_action *objp)
116 if (!xdr_enum(xdrs, (enum_t *)objp))
117 return (FALSE);
118 return (TRUE);
122 bool_t
123 xdr_linka(XDR *xdrs, linka *objp)
125 if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
126 return (FALSE);
127 if (!xdr_string(xdrs, &objp->link, AUTOFS_MAXPATHLEN))
128 return (FALSE);
129 return (TRUE);
133 bool_t
134 xdr_autofs_netbuf(XDR *xdrs, struct netbuf *objp)
136 bool_t dummy;
138 if (!xdr_u_long(xdrs, (u_long *) &objp->maxlen))
139 return (FALSE);
140 dummy = xdr_bytes(xdrs, (char **)&(objp->buf),
141 (u_int *)&(objp->len), objp->maxlen);
142 return (dummy);
146 bool_t
147 xdr_autofs_args(XDR *xdrs, autofs_args *objp)
149 if (!xdr_autofs_netbuf(xdrs, &objp->addr))
150 return (FALSE);
151 if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
152 return (FALSE);
153 if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
154 return (FALSE);
155 if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
156 return (FALSE);
157 if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
158 return (FALSE);
159 if (!xdr_string(xdrs, &objp->key, AUTOFS_MAXCOMPONENTLEN))
160 return (FALSE);
161 if (!xdr_int(xdrs, &objp->mount_to))
162 return (FALSE);
163 if (!xdr_int(xdrs, &objp->rpc_to))
164 return (FALSE);
165 if (!xdr_int(xdrs, &objp->direct))
166 return (FALSE);
167 return (TRUE);
171 bool_t
172 xdr_mounta(XDR *xdrs, struct mounta *objp)
174 if (!xdr_string(xdrs, &objp->spec, AUTOFS_MAXPATHLEN))
175 return (FALSE);
176 if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
177 return (FALSE);
178 if (!xdr_int(xdrs, &objp->flags))
179 return (FALSE);
180 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
181 return (FALSE);
182 if (!xdr_pointer(xdrs, (char **)&objp->dataptr, sizeof(autofs_args),
183 (XDRPROC_T_TYPE) xdr_autofs_args))
184 return (FALSE);
185 if (!xdr_int(xdrs, &objp->datalen))
186 return (FALSE);
187 return (TRUE);
191 bool_t
192 xdr_action_list_entry(XDR *xdrs, action_list_entry *objp)
194 if (!xdr_autofs_action(xdrs, &objp->action))
195 return (FALSE);
196 switch (objp->action) {
197 case AUTOFS_MOUNT_RQ:
198 if (!xdr_mounta(xdrs, &objp->action_list_entry_u.mounta))
199 return (FALSE);
200 break;
201 case AUTOFS_LINK_RQ:
202 if (!xdr_linka(xdrs, &objp->action_list_entry_u.linka))
203 return (FALSE);
204 break;
205 default:
206 break;
208 return (TRUE);
212 bool_t
213 xdr_action_list(XDR *xdrs, action_list *objp)
215 if (!xdr_action_list_entry(xdrs, &objp->action))
216 return (FALSE);
217 if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(action_list),
218 (XDRPROC_T_TYPE) xdr_action_list))
219 return (FALSE);
220 return (TRUE);
224 bool_t
225 xdr_umntrequest(XDR *xdrs, umntrequest *objp)
227 if (amuDebug(D_XDRTRACE))
228 plog(XLOG_DEBUG, "xdr_umntrequest:");
230 if (!xdr_bool_t(xdrs, &objp->isdirect))
231 return (FALSE);
232 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
233 if (!xdr_dev_t(xdrs, &objp->devid))
234 return (FALSE);
235 if (!xdr_dev_t(xdrs, &objp->rdevid))
236 return (FALSE);
237 #else /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
238 if (!xdr_string(xdrs, &objp->mntresource, AUTOFS_MAXPATHLEN))
239 return (FALSE);
240 if (!xdr_string(xdrs, &objp->mntpnt, AUTOFS_MAXPATHLEN))
241 return (FALSE);
242 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
243 return (FALSE);
244 if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN))
245 return (FALSE);
246 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
247 if (!xdr_pointer(xdrs, (char **) &objp->next, sizeof(umntrequest),
248 (XDRPROC_T_TYPE) xdr_umntrequest))
249 return (FALSE);
251 return (TRUE);
255 bool_t
256 xdr_umntres(XDR *xdrs, umntres *objp)
258 if (amuDebug(D_XDRTRACE))
259 plog(XLOG_DEBUG, "xdr_mntres:");
261 if (!xdr_int(xdrs, &objp->status))
262 return (FALSE);
263 return (TRUE);
268 * These exist only in the AutoFS V2 protocol.
270 #ifdef AUTOFS_POSTUNMOUNT
271 bool_t
272 xdr_postumntreq(XDR *xdrs, postumntreq *objp)
274 if (!xdr_dev_t(xdrs, &objp->devid))
275 return (FALSE);
276 if (!xdr_dev_t(xdrs, &objp->rdevid))
277 return (FALSE);
278 if (!xdr_pointer(xdrs, (char **)&objp->next,
279 sizeof(struct postumntreq),
280 (XDRPROC_T_TYPE) xdr_postumntreq))
281 return (FALSE);
282 return (TRUE);
286 bool_t
287 xdr_postumntres(XDR *xdrs, postumntres *objp)
289 if (!xdr_int(xdrs, &objp->status))
290 return (FALSE);
291 return (TRUE);
295 bool_t
296 xdr_postmountreq(XDR *xdrs, postmountreq *objp)
298 if (!xdr_string(xdrs, &objp->special, AUTOFS_MAXPATHLEN))
299 return (FALSE);
300 if (!xdr_string(xdrs, &objp->mountp, AUTOFS_MAXPATHLEN))
301 return (FALSE);
302 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
303 return (FALSE);
304 if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN))
305 return (FALSE);
306 if (!xdr_dev_t(xdrs, &objp->devid))
307 return (FALSE);
308 return (TRUE);
312 bool_t
313 xdr_postmountres(XDR *xdrs, postmountres *objp)
315 if (!xdr_int(xdrs, &objp->status))
316 return (FALSE);
317 return (TRUE);
319 #endif /* AUTOFS_POSTUNMOUNT */
322 bool_t
323 xdr_autofs_res(XDR *xdrs, autofs_res *objp)
325 if (!xdr_enum(xdrs, (enum_t *)objp))
326 return (FALSE);
327 return (TRUE);
331 bool_t
332 xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp)
334 if (amuDebug(D_XDRTRACE))
335 plog(XLOG_DEBUG, "xdr_autofs_lookupargs:");
337 if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
338 return (FALSE);
339 if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
340 return (FALSE);
341 if (!xdr_string(xdrs, &objp->name, AUTOFS_MAXCOMPONENTLEN))
342 return (FALSE);
343 if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
344 return (FALSE);
345 if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
346 return (FALSE);
347 if (!xdr_bool_t(xdrs, &objp->isdirect))
348 return (FALSE);
349 return (TRUE);
353 bool_t
354 xdr_mount_result_type(XDR *xdrs, mount_result_type *objp)
356 if (!xdr_autofs_stat(xdrs, &objp->status))
357 return (FALSE);
358 switch (objp->status) {
359 case AUTOFS_ACTION:
360 if (!xdr_pointer(xdrs,
361 (char **)&objp->mount_result_type_u.list,
362 sizeof(action_list), (XDRPROC_T_TYPE) xdr_action_list))
363 return (FALSE);
364 break;
365 case AUTOFS_DONE:
366 if (!xdr_int(xdrs, &objp->mount_result_type_u.error))
367 return (FALSE);
368 break;
370 return (TRUE);
374 bool_t
375 xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp)
377 if (amuDebug(D_XDRTRACE))
378 plog(XLOG_DEBUG, "xdr_mntres:");
380 if (!xdr_mount_result_type(xdrs, &objp->mr_type))
381 return (FALSE);
382 if (!xdr_int(xdrs, &objp->mr_verbose))
383 return (FALSE);
385 return (TRUE);
389 bool_t
390 xdr_lookup_result_type(XDR *xdrs, lookup_result_type *objp)
392 if (!xdr_autofs_action(xdrs, &objp->action))
393 return (FALSE);
394 switch (objp->action) {
395 case AUTOFS_LINK_RQ:
396 if (!xdr_linka(xdrs, &objp->lookup_result_type_u.lt_linka))
397 return (FALSE);
398 break;
399 default:
400 break;
402 return (TRUE);
406 bool_t
407 xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp)
409 if (!xdr_autofs_res(xdrs, &objp->lu_res))
410 return (FALSE);
411 if (!xdr_lookup_result_type(xdrs, &objp->lu_type))
412 return (FALSE);
413 if (!xdr_int(xdrs, &objp->lu_verbose))
414 return (FALSE);
415 return (TRUE);
419 bool_t
420 xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp)
422 if (!xdr_string(xdrs, &objp->rda_map, AUTOFS_MAXPATHLEN))
423 return (FALSE);
424 if (!xdr_u_int(xdrs, (u_int *) &objp->rda_offset))
425 return (FALSE);
426 if (!xdr_u_int(xdrs, (u_int *) &objp->rda_count))
427 return (FALSE);
428 return (TRUE);
433 * ENCODE ONLY
435 * Solaris automountd uses struct autofsrddir to pass the results.
436 * We use the traditional nfsreaddirres and do the conversion ourselves.
438 static bool_t
439 xdr_amd_putrddirres(XDR *xdrs, nfsdirlist *dp, ulong reqsize)
441 nfsentry *ep;
442 char *name;
443 u_int namlen;
444 bool_t true = TRUE;
445 bool_t false = FALSE;
446 int entrysz;
447 int tofit;
448 int bufsize;
449 u_long ino, off;
451 bufsize = 1 * BYTES_PER_XDR_UNIT;
452 for (ep = dp->dl_entries; ep; ep = ep->ne_nextentry) {
453 name = ep->ne_name;
454 namlen = strlen(name);
455 ino = (u_long) ep->ne_fileid;
456 off = (u_long) ep->ne_cookie + AUTOFS_DAEMONCOOKIE;
457 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
458 roundup(namlen, BYTES_PER_XDR_UNIT);
459 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
460 if (bufsize + tofit > reqsize) {
461 dp->dl_eof = FALSE;
462 break;
464 if (!xdr_bool(xdrs, &true) ||
465 !xdr_u_long(xdrs, &ino) ||
466 !xdr_bytes(xdrs, &name, &namlen, AUTOFS_MAXPATHLEN) ||
467 !xdr_u_long(xdrs, &off)) {
468 return (FALSE);
470 bufsize += entrysz;
472 if (!xdr_bool(xdrs, &false)) {
473 return (FALSE);
475 if (!xdr_bool(xdrs, &dp->dl_eof)) {
476 return (FALSE);
478 return (TRUE);
482 static bool_t
483 xdr_amd_rddirres(XDR *xdrs, amd_rddirres *objp)
485 if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status))
486 return (FALSE);
487 if (objp->rd_status != AUTOFS_OK)
488 return (TRUE);
489 return (xdr_amd_putrddirres(xdrs, &objp->rd_dl, objp->rd_bufsize));
494 * AUTOFS RPC methods
497 static int
498 autofs_lookup_2_req(autofs_lookupargs *m,
499 autofs_lookupres *res,
500 struct authunix_parms *cred,
501 SVCXPRT *transp)
503 int err;
504 am_node *mp, *new_mp;
505 mntfs *mf;
507 dlog("LOOKUP REQUEST: name=%s[%s] map=%s opts=%s path=%s direct=%d",
508 m->name, m->subdir, m->map, m->opts,
509 m->path, m->isdirect);
511 /* find the effective uid/gid from RPC request */
512 xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) cred->aup_uid);
513 xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) cred->aup_gid);
515 mp = find_ap(m->path);
516 if (!mp) {
517 plog(XLOG_ERROR, "map %s not found", m->path);
518 err = AUTOFS_NOENT;
519 goto out;
522 mf = mp->am_mnt;
523 new_mp = mf->mf_ops->lookup_child(mp, m->name, &err, VLOOK_LOOKUP);
524 if (!new_mp) {
525 err = AUTOFS_NOENT;
526 goto out;
529 if (err == 0) {
530 plog(XLOG_ERROR, "autofs requests to mount an already mounted node???");
531 } else {
532 free_map(new_mp);
534 err = AUTOFS_OK;
535 res->lu_type.action = AUTOFS_NONE;
537 out:
538 res->lu_res = err;
539 res->lu_verbose = 1;
541 dlog("LOOKUP REPLY: status=%d", res->lu_res);
542 return 0;
546 static void
547 autofs_lookup_2_free(autofs_lookupres *res)
549 struct linka link;
551 if ((res->lu_res == AUTOFS_OK) &&
552 (res->lu_type.action == AUTOFS_LINK_RQ)) {
554 * Free link information
556 link = res->lu_type.lookup_result_type_u.lt_linka;
557 if (link.dir)
558 XFREE(link.dir);
559 if (link.link)
560 XFREE(link.link);
565 static int
566 autofs_mount_2_req(autofs_lookupargs *m,
567 autofs_mountres *res,
568 struct authunix_parms *cred,
569 SVCXPRT *transp)
571 int err = AUTOFS_OK;
572 am_node *mp, *new_mp;
573 mntfs *mf;
575 dlog("MOUNT REQUEST: name=%s[%s] map=%s opts=%s path=%s direct=%d",
576 m->name, m->subdir, m->map, m->opts,
577 m->path, m->isdirect);
579 /* find the effective uid/gid from RPC request */
580 xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) cred->aup_uid);
581 xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) cred->aup_gid);
583 mp = find_ap(m->path);
584 if (!mp) {
585 plog(XLOG_ERROR, "map %s not found", m->path);
586 res->mr_type.status = AUTOFS_DONE;
587 res->mr_type.mount_result_type_u.error = AUTOFS_NOENT;
588 goto out;
591 mf = mp->am_mnt;
592 new_mp = mf->mf_ops->lookup_child(mp, m->name + m->isdirect, &err, VLOOK_CREATE);
593 if (new_mp && err < 0) {
594 /* new_mp->am_transp = transp; */
595 new_mp = mf->mf_ops->mount_child(new_mp, &err);
597 if (new_mp == NULL) {
598 if (err < 0) {
599 /* we're working on it */
600 amd_stats.d_drops++;
601 return 1;
603 res->mr_type.status = AUTOFS_DONE;
604 res->mr_type.mount_result_type_u.error = AUTOFS_NOENT;
605 goto out;
608 if (gopt.flags & CFM_AUTOFS_USE_LOFS ||
609 new_mp->am_mnt->mf_flags & MFF_ON_AUTOFS) {
610 res->mr_type.status = AUTOFS_DONE;
611 res->mr_type.mount_result_type_u.error = AUTOFS_OK;
612 } else {
613 struct action_list *list = malloc(sizeof(struct action_list));
614 char *target;
615 if (new_mp->am_link)
616 target = new_mp->am_link;
617 else
618 target = new_mp->am_mnt->mf_mount;
619 list->action.action = AUTOFS_LINK_RQ;
620 list->action.action_list_entry_u.linka.dir = strdup(new_mp->am_name);
621 list->action.action_list_entry_u.linka.link = strdup(target);
622 list->next = NULL;
623 res->mr_type.status = AUTOFS_ACTION;
624 res->mr_type.mount_result_type_u.list = list;
627 out:
628 res->mr_verbose = 1;
630 switch (res->mr_type.status) {
631 case AUTOFS_ACTION:
632 dlog("MOUNT REPLY: status=%d, AUTOFS_ACTION", err);
633 break;
634 case AUTOFS_DONE:
635 dlog("MOUNT REPLY: status=%d, AUTOFS_DONE", err);
636 break;
637 default:
638 dlog("MOUNT REPLY: status=%d, UNKNOWN(%d)", err, res->mr_type.status);
641 if (err) {
642 if (m->isdirect) {
643 /* direct mount */
644 plog(XLOG_ERROR, "mount of %s failed", m->path);
645 } else {
646 /* indirect mount */
647 plog(XLOG_ERROR, "mount of %s/%s failed", m->path, m->name);
650 return 0;
654 static void
655 autofs_mount_2_free(struct autofs_mountres *res)
657 if (res->mr_type.status == AUTOFS_ACTION &&
658 res->mr_type.mount_result_type_u.list != NULL) {
659 autofs_action action;
660 dlog("freeing action list");
661 action = res->mr_type.mount_result_type_u.list->action.action;
662 if (action == AUTOFS_LINK_RQ) {
664 * Free link information
666 struct linka *link;
667 link = &(res->mr_type.mount_result_type_u.list->action.action_list_entry_u.linka);
668 if (link->dir)
669 XFREE(link->dir);
670 if (link->link)
671 XFREE(link->link);
672 } else if (action == AUTOFS_MOUNT_RQ) {
673 struct mounta *mnt;
674 mnt = &(res->mr_type.mount_result_type_u.list->action.action_list_entry_u.mounta);
675 if (mnt->spec)
676 XFREE(mnt->spec);
677 if (mnt->dir)
678 XFREE(mnt->dir);
679 if (mnt->fstype)
680 XFREE(mnt->fstype);
681 if (mnt->dataptr)
682 XFREE(mnt->dataptr);
683 #ifdef HAVE_MOUNTA_OPTPTR
684 if (mnt->optptr)
685 XFREE(mnt->optptr);
686 #endif /* HAVE_MOUNTA_OPTPTR */
688 XFREE(res->mr_type.mount_result_type_u.list);
693 static int
694 autofs_unmount_2_req(umntrequest *ul,
695 umntres *res,
696 struct authunix_parms *cred,
697 SVCXPRT *transp)
699 int mapno, err;
700 am_node *mp = NULL;
702 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
703 dlog("UNMOUNT REQUEST: dev=%lx rdev=%lx %s",
704 (u_long) ul->devid,
705 (u_long) ul->rdevid,
706 ul->isdirect ? "direct" : "indirect");
707 #else /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
708 dlog("UNMOUNT REQUEST: mntresource='%s' mntpnt='%s' fstype='%s' mntopts='%s' %s",
709 ul->mntresource,
710 ul->mntpnt,
711 ul->fstype,
712 ul->mntopts,
713 ul->isdirect ? "direct" : "indirect");
714 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
716 /* by default, and if not found, succeed */
717 res->status = 0;
719 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
720 for (mp = get_first_exported_ap(&mapno);
722 mp = get_next_exported_ap(&mapno)) {
723 if (mp->am_dev == ul->devid &&
724 mp->am_rdev == ul->rdevid)
725 break;
727 #else /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
728 mp = find_ap(ul->mntpnt);
729 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
731 if (mp) {
732 /* save RPC context */
733 if (!mp->am_transp && transp) {
734 mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
735 *(mp->am_transp) = *transp;
738 mapno = mp->am_mapno;
739 err = unmount_mp(mp);
741 if (err)
742 /* backgrounded, don't reply yet */
743 return 1;
745 if (get_exported_ap(mapno))
746 /* unmounting failed, tell the kernel */
747 res->status = 1;
750 dlog("UNMOUNT REPLY: status=%d", res->status);
751 return 0;
756 * These exist only in the AutoFS V2 protocol.
758 #ifdef AUTOFS_POSTUNMOUNT
759 /* XXX not implemented */
760 static int
761 autofs_postunmount_2_req(postumntreq *req,
762 postumntres *res,
763 struct authunix_parms *cred,
764 SVCXPRT *transp)
766 postumntreq *ul = req;
768 dlog("POSTUNMOUNT REQUEST: dev=%lx rdev=%lx",
769 (u_long) ul->devid,
770 (u_long) ul->rdevid);
772 /* succeed unconditionally */
773 res->status = 0;
775 dlog("POSTUNMOUNT REPLY: status=%d", res->status);
776 return 0;
780 /* XXX not implemented */
781 static int
782 autofs_postmount_2_req(postmountreq *req,
783 postmountres *res,
784 struct authunix_parms *cred,
785 SVCXPRT *transp)
787 dlog("POSTMOUNT REQUEST: %s\tdev=%lx\tspecial=%s %s",
788 req->mountp, (u_long) req->devid, req->special, req->mntopts);
790 /* succeed unconditionally */
791 res->status = 0;
793 dlog("POSTMOUNT REPLY: status=%d", res->status);
794 return 0;
796 #endif /* AUTOFS_POSTUNMOUNT */
799 static int
800 autofs_readdir_2_req(struct autofs_rddirargs *req,
801 struct amd_rddirres *res,
802 struct authunix_parms *cred,
803 SVCXPRT *transp)
805 am_node *mp;
806 int err;
807 static nfsentry e_res[MAX_READDIR_ENTRIES];
809 dlog("READDIR REQUEST: %s @ %d",
810 req->rda_map, (int) req->rda_offset);
812 mp = find_ap(req->rda_map);
813 if (!mp) {
814 plog(XLOG_ERROR, "map %s not found", req->rda_map);
815 res->rd_status = AUTOFS_NOENT;
816 goto out;
819 mp->am_stats.s_readdir++;
820 req->rda_offset -= AUTOFS_DAEMONCOOKIE;
821 err = mp->am_mnt->mf_ops->readdir(mp, (char *)&req->rda_offset,
822 &res->rd_dl, e_res, req->rda_count);
823 if (err) {
824 res->rd_status = AUTOFS_ECOMM;
825 goto out;
828 res->rd_status = AUTOFS_OK;
829 res->rd_bufsize = req->rda_count;
831 out:
832 dlog("READDIR REPLY: status=%d", res->rd_status);
833 return 0;
837 /****************************************************************************/
838 /* autofs program dispatcher */
839 static void
840 autofs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
842 union {
843 autofs_lookupargs autofs_mount_2_arg;
844 autofs_lookupargs autofs_lookup_2_arg;
845 umntrequest autofs_umount_2_arg;
846 autofs_rddirargs autofs_readdir_2_arg;
847 #ifdef AUTOFS_POSTUNMOUNT
848 postmountreq autofs_postmount_2_arg;
849 postumntreq autofs_postumnt_2_arg;
850 #endif /* AUTOFS_POSTUNMOUNT */
851 } argument;
853 union {
854 autofs_mountres mount_res;
855 autofs_lookupres lookup_res;
856 umntres umount_res;
857 amd_rddirres readdir_res;
858 #ifdef AUTOFS_POSTUNMOUNT
859 postumntres postumnt_res;
860 postmountres postmnt_res;
861 #endif /* AUTOFS_POSTUNMOUNT */
862 } result;
863 int ret;
865 bool_t (*xdr_argument)();
866 bool_t (*xdr_result)();
867 int (*local)();
868 void (*local_free)() = NULL;
870 current_transp = transp;
872 switch (rqstp->rq_proc) {
874 case AUTOFS_NULL:
875 svc_sendreply(transp,
876 (XDRPROC_T_TYPE) xdr_void,
877 (SVC_IN_ARG_TYPE) NULL);
878 return;
880 case AUTOFS_LOOKUP:
881 xdr_argument = xdr_autofs_lookupargs;
882 xdr_result = xdr_autofs_lookupres;
883 local = autofs_lookup_2_req;
884 local_free = autofs_lookup_2_free;
885 break;
887 case AUTOFS_MOUNT:
888 xdr_argument = xdr_autofs_lookupargs;
889 xdr_result = xdr_autofs_mountres;
890 local = autofs_mount_2_req;
891 local_free = autofs_mount_2_free;
892 break;
894 case AUTOFS_UNMOUNT:
895 xdr_argument = xdr_umntrequest;
896 xdr_result = xdr_umntres;
897 local = autofs_unmount_2_req;
898 break;
901 * These exist only in the AutoFS V2 protocol.
903 #ifdef AUTOFS_POSTUNMOUNT
904 case AUTOFS_POSTUNMOUNT:
905 xdr_argument = xdr_postumntreq;
906 xdr_result = xdr_postumntres;
907 local = autofs_postunmount_2_req;
908 break;
910 case AUTOFS_POSTMOUNT:
911 xdr_argument = xdr_postmountreq;
912 xdr_result = xdr_postmountres;
913 local = autofs_postmount_2_req;
914 break;
915 #endif /* AUTOFS_POSTUNMOUNT */
917 case AUTOFS_READDIR:
918 xdr_argument = xdr_autofs_rddirargs;
919 xdr_result = xdr_amd_rddirres;
920 local = autofs_readdir_2_req;
921 break;
923 default:
924 svcerr_noproc(transp);
925 return;
928 memset((char *) &argument, 0, sizeof(argument));
929 if (!svc_getargs(transp,
930 (XDRPROC_T_TYPE) xdr_argument,
931 (SVC_IN_ARG_TYPE) &argument)) {
932 plog(XLOG_ERROR, "AUTOFS xdr decode failed for %d %d %d",
933 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
934 svcerr_decode(transp);
935 return;
938 memset((char *)&result, 0, sizeof(result));
939 ret = (*local) (&argument, &result, rqstp->rq_clntcred, transp);
941 current_transp = NULL;
943 /* send reply only if the RPC method returned 0 */
944 if (!ret) {
945 if (!svc_sendreply(transp,
946 (XDRPROC_T_TYPE) xdr_result,
947 (SVC_IN_ARG_TYPE) &result)) {
948 svcerr_systemerr(transp);
952 if (!svc_freeargs(transp,
953 (XDRPROC_T_TYPE) xdr_argument,
954 (SVC_IN_ARG_TYPE) &argument)) {
955 plog(XLOG_FATAL, "unable to free rpc arguments in autofs_program_2");
958 if (local_free)
959 (*local_free)(&result);
964 autofs_get_fh(am_node *mp)
966 autofs_fh_t *fh;
967 char buf[MAXHOSTNAMELEN];
968 mntfs *mf = mp->am_mnt;
969 struct utsname utsname;
971 plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path);
972 fh = ALLOC(autofs_fh_t);
973 memset((voidp) fh, 0, sizeof(autofs_fh_t)); /* Paranoid */
976 * SET MOUNT ARGS
978 if (uname(&utsname) < 0) {
979 xstrlcpy(buf, "localhost.autofs", sizeof(buf));
980 } else {
981 xstrlcpy(buf, utsname.nodename, sizeof(buf));
982 xstrlcat(buf, ".autofs", sizeof(buf));
984 #ifdef HAVE_AUTOFS_ARGS_T_ADDR
985 fh->addr.buf = strdup(buf);
986 fh->addr.len = fh->addr.maxlen = strlen(buf);
987 #endif /* HAVE_AUTOFS_ARGS_T_ADDR */
989 fh->direct = ((mf->mf_ops->autofs_fs_flags & FS_DIRECT) == FS_DIRECT);
990 fh->rpc_to = 1; /* XXX: arbitrary */
991 fh->mount_to = mp->am_timeo;
992 fh->path = mp->am_path;
993 fh->opts = ""; /* XXX: arbitrary */
994 fh->map = mp->am_path; /* this is what we get back in readdir */
995 fh->subdir = "";
996 if (fh->direct)
997 fh->key = mp->am_name;
998 else
999 fh->key = "";
1001 mp->am_autofs_fh = fh;
1002 return 0;
1006 void
1007 autofs_mounted(am_node *mp)
1009 /* We don't want any timeouts on autofs nodes */
1010 mp->am_autofs_ttl = NEVER;
1014 void
1015 autofs_release_fh(am_node *mp)
1017 autofs_fh_t *fh = mp->am_autofs_fh;
1018 #ifdef HAVE_AUTOFS_ARGS_T_ADDR
1019 XFREE(fh->addr.buf);
1020 #endif /* HAVE_AUTOFS_ARGS_T_ADDR */
1021 XFREE(fh);
1022 mp->am_autofs_fh = NULL;
1026 void
1027 autofs_get_mp(am_node *mp)
1029 /* nothing to do */
1033 void
1034 autofs_release_mp(am_node *mp)
1036 /* nothing to do */
1040 void
1041 autofs_add_fdset(fd_set *readfds)
1043 /* nothing to do */
1048 autofs_handle_fdset(fd_set *readfds, int nsel)
1050 /* nothing to do */
1051 return nsel;
1056 * Create the autofs service for amd
1059 create_autofs_service(void)
1061 dlog("creating autofs service listener");
1062 return register_autofs_service(AUTOFS_CONFTYPE, autofs_program_2);
1067 destroy_autofs_service(void)
1069 dlog("destroying autofs service listener");
1070 return unregister_autofs_service(AUTOFS_CONFTYPE);
1075 autofs_mount_fs(am_node *mp, mntfs *mf)
1077 int err = 0;
1078 char *target, *target2 = NULL;
1079 struct stat buf;
1082 * For sublinks, we could end up here with an already mounted f/s.
1083 * Don't do anything in that case.
1085 if (!(mf->mf_flags & MFF_MOUNTED))
1086 err = mf->mf_ops->mount_fs(mp, mf);
1088 if (err || mf->mf_flags & MFF_ON_AUTOFS)
1089 /* Nothing else to do */
1090 return err;
1092 if (!(gopt.flags & CFM_AUTOFS_USE_LOFS))
1093 /* Symlinks will be requested in autofs_mount_succeeded */
1094 return 0;
1096 if (mp->am_link)
1097 target = mp->am_link;
1098 else
1099 target = mf->mf_mount;
1101 if (target[0] != '/')
1102 target2 = str3cat(NULL, mp->am_parent->am_path, "/", target);
1103 else
1104 target2 = strdup(target);
1106 plog(XLOG_INFO, "autofs: converting from link to lofs (%s -> %s)", mp->am_path, target2);
1109 * we need to stat() the destination, because the bind mount does not
1110 * follow symlinks and/or allow for non-existent destinations.
1111 * we fall back to symlinks if there are problems.
1113 * we need to temporarily change pgrp, otherwise our stat() won't
1114 * trigger whatever cascading mounts are needed.
1116 * WARNING: we will deadlock if this function is called from the master
1117 * amd process and it happens to trigger another auto mount. Therefore,
1118 * this function should be called only from a child amd process, or
1119 * at the very least it should not be called from the parent unless we
1120 * know for sure that it won't cause a recursive mount. We refuse to
1121 * cause the recursive mount anyway if called from the parent amd.
1123 if (!foreground) {
1124 if ((err = stat(target2, &buf)))
1125 goto out;
1127 if ((err = lstat(target2, &buf)))
1128 goto out;
1130 if ((err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1))) {
1131 errno = err;
1132 goto out;
1135 out:
1136 if (target2)
1137 XFREE(target2);
1139 if (err)
1140 return errno;
1141 return 0;
1146 autofs_umount_fs(am_node *mp, mntfs *mf)
1148 int err = 0;
1149 if (!(mf->mf_flags & MFF_ON_AUTOFS) &&
1150 gopt.flags & CFM_AUTOFS_USE_LOFS) {
1151 err = UMOUNT_FS(mp->am_path, mnttab_file_name, 1);
1152 if (err)
1153 return err;
1157 * Multiple sublinks could reference this f/s.
1158 * Don't actually unmount it unless we're holding the last reference.
1160 if (mf->mf_refc == 1)
1161 err = mf->mf_ops->umount_fs(mp, mf);
1162 return err;
1167 autofs_umount_succeeded(am_node *mp)
1169 umntres res;
1170 SVCXPRT *transp = mp->am_transp;
1172 if (transp) {
1173 res.status = 0;
1175 if (!svc_sendreply(transp,
1176 (XDRPROC_T_TYPE) xdr_umntres,
1177 (SVC_IN_ARG_TYPE) &res))
1178 svcerr_systemerr(transp);
1180 dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
1181 XFREE(transp);
1182 mp->am_transp = NULL;
1185 plog(XLOG_INFO, "autofs: unmounting %s succeeded", mp->am_path);
1186 return 0;
1191 autofs_umount_failed(am_node *mp)
1193 umntres res;
1194 SVCXPRT *transp = mp->am_transp;
1196 if (transp) {
1197 res.status = 1;
1199 if (!svc_sendreply(transp,
1200 (XDRPROC_T_TYPE) xdr_umntres,
1201 (SVC_IN_ARG_TYPE) &res))
1202 svcerr_systemerr(transp);
1204 dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
1205 XFREE(transp);
1206 mp->am_transp = NULL;
1209 plog(XLOG_INFO, "autofs: unmounting %s failed", mp->am_path);
1210 return 0;
1214 void
1215 autofs_mount_succeeded(am_node *mp)
1217 SVCXPRT *transp = mp->am_transp;
1218 struct stat stb;
1221 * Store dev and rdev -- but not for symlinks
1223 if (gopt.flags & CFM_AUTOFS_USE_LOFS ||
1224 mp->am_mnt->mf_flags & MFF_ON_AUTOFS) {
1225 if (!lstat(mp->am_path, &stb)) {
1226 mp->am_dev = stb.st_dev;
1227 mp->am_rdev = stb.st_rdev;
1229 /* don't expire the entries -- the kernel will do it for us */
1230 mp->am_flags |= AMF_NOTIMEOUT;
1233 if (transp) {
1234 autofs_mountres res;
1235 res.mr_type.status = AUTOFS_DONE;
1236 res.mr_type.mount_result_type_u.error = AUTOFS_OK;
1237 res.mr_verbose = 1;
1239 if (!svc_sendreply(transp,
1240 (XDRPROC_T_TYPE) xdr_autofs_mountres,
1241 (SVC_IN_ARG_TYPE) &res))
1242 svcerr_systemerr(transp);
1244 dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
1245 XFREE(transp);
1246 mp->am_transp = NULL;
1249 plog(XLOG_INFO, "autofs: mounting %s succeeded", mp->am_path);
1253 void
1254 autofs_mount_failed(am_node *mp)
1256 SVCXPRT *transp = mp->am_transp;
1258 if (transp) {
1259 autofs_mountres res;
1260 res.mr_type.status = AUTOFS_DONE;
1261 res.mr_type.mount_result_type_u.error = AUTOFS_NOENT;
1262 res.mr_verbose = 1;
1264 if (!svc_sendreply(transp,
1265 (XDRPROC_T_TYPE) xdr_autofs_mountres,
1266 (SVC_IN_ARG_TYPE) &res))
1267 svcerr_systemerr(transp);
1269 dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
1270 XFREE(transp);
1271 mp->am_transp = NULL;
1274 plog(XLOG_INFO, "autofs: mounting %s failed", mp->am_path);
1278 void
1279 autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh)
1281 xsnprintf(opts, l, "%sdirect",
1282 fh->direct ? "" : "in");
1287 autofs_compute_mount_flags(mntent_t *mntp)
1289 /* Must use overlay mounts */
1290 return MNT2_GEN_OPT_OVERLAY;
1294 void autofs_timeout_mp(am_node *mp)
1296 /* We don't want any timeouts on autofs nodes */
1297 mp->am_autofs_ttl = NEVER;