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.
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
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
43 * File: am-utils/conf/autofs/autofs_solaris_v2_v3.c
48 * Automounter filesystem
53 #endif /* HAVE_CONFIG_H */
61 # define AUTOFS_NULL NULLPROC
62 #endif /* not AUTOFS_NULL */
69 enum autofs_res rd_status
;
73 typedef struct amd_rddirres amd_rddirres
;
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:
105 xdr_autofs_stat(XDR
*xdrs
, autofs_stat
*objp
)
107 if (!xdr_enum(xdrs
, (enum_t
*)objp
))
114 xdr_autofs_action(XDR
*xdrs
, autofs_action
*objp
)
116 if (!xdr_enum(xdrs
, (enum_t
*)objp
))
123 xdr_linka(XDR
*xdrs
, linka
*objp
)
125 if (!xdr_string(xdrs
, &objp
->dir
, AUTOFS_MAXPATHLEN
))
127 if (!xdr_string(xdrs
, &objp
->link
, AUTOFS_MAXPATHLEN
))
134 xdr_autofs_netbuf(XDR
*xdrs
, struct netbuf
*objp
)
138 if (!xdr_u_long(xdrs
, (u_long
*) &objp
->maxlen
))
140 dummy
= xdr_bytes(xdrs
, (char **)&(objp
->buf
),
141 (u_int
*)&(objp
->len
), objp
->maxlen
);
147 xdr_autofs_args(XDR
*xdrs
, autofs_args
*objp
)
149 if (!xdr_autofs_netbuf(xdrs
, &objp
->addr
))
151 if (!xdr_string(xdrs
, &objp
->path
, AUTOFS_MAXPATHLEN
))
153 if (!xdr_string(xdrs
, &objp
->opts
, AUTOFS_MAXOPTSLEN
))
155 if (!xdr_string(xdrs
, &objp
->map
, AUTOFS_MAXPATHLEN
))
157 if (!xdr_string(xdrs
, &objp
->subdir
, AUTOFS_MAXPATHLEN
))
159 if (!xdr_string(xdrs
, &objp
->key
, AUTOFS_MAXCOMPONENTLEN
))
161 if (!xdr_int(xdrs
, &objp
->mount_to
))
163 if (!xdr_int(xdrs
, &objp
->rpc_to
))
165 if (!xdr_int(xdrs
, &objp
->direct
))
172 xdr_mounta(XDR
*xdrs
, struct mounta
*objp
)
174 if (!xdr_string(xdrs
, &objp
->spec
, AUTOFS_MAXPATHLEN
))
176 if (!xdr_string(xdrs
, &objp
->dir
, AUTOFS_MAXPATHLEN
))
178 if (!xdr_int(xdrs
, &objp
->flags
))
180 if (!xdr_string(xdrs
, &objp
->fstype
, AUTOFS_MAXCOMPONENTLEN
))
182 if (!xdr_pointer(xdrs
, (char **)&objp
->dataptr
, sizeof(autofs_args
),
183 (XDRPROC_T_TYPE
) xdr_autofs_args
))
185 if (!xdr_int(xdrs
, &objp
->datalen
))
192 xdr_action_list_entry(XDR
*xdrs
, action_list_entry
*objp
)
194 if (!xdr_autofs_action(xdrs
, &objp
->action
))
196 switch (objp
->action
) {
197 case AUTOFS_MOUNT_RQ
:
198 if (!xdr_mounta(xdrs
, &objp
->action_list_entry_u
.mounta
))
202 if (!xdr_linka(xdrs
, &objp
->action_list_entry_u
.linka
))
213 xdr_action_list(XDR
*xdrs
, action_list
*objp
)
215 if (!xdr_action_list_entry(xdrs
, &objp
->action
))
217 if (!xdr_pointer(xdrs
, (char **)&objp
->next
, sizeof(action_list
),
218 (XDRPROC_T_TYPE
) xdr_action_list
))
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
))
232 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
233 if (!xdr_dev_t(xdrs
, &objp
->devid
))
235 if (!xdr_dev_t(xdrs
, &objp
->rdevid
))
237 #else /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
238 if (!xdr_string(xdrs
, &objp
->mntresource
, AUTOFS_MAXPATHLEN
))
240 if (!xdr_string(xdrs
, &objp
->mntpnt
, AUTOFS_MAXPATHLEN
))
242 if (!xdr_string(xdrs
, &objp
->fstype
, AUTOFS_MAXCOMPONENTLEN
))
244 if (!xdr_string(xdrs
, &objp
->mntopts
, AUTOFS_MAXOPTSLEN
))
246 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
247 if (!xdr_pointer(xdrs
, (char **) &objp
->next
, sizeof(umntrequest
),
248 (XDRPROC_T_TYPE
) xdr_umntrequest
))
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
))
268 * These exist only in the AutoFS V2 protocol.
270 #ifdef AUTOFS_POSTUNMOUNT
272 xdr_postumntreq(XDR
*xdrs
, postumntreq
*objp
)
274 if (!xdr_dev_t(xdrs
, &objp
->devid
))
276 if (!xdr_dev_t(xdrs
, &objp
->rdevid
))
278 if (!xdr_pointer(xdrs
, (char **)&objp
->next
,
279 sizeof(struct postumntreq
),
280 (XDRPROC_T_TYPE
) xdr_postumntreq
))
287 xdr_postumntres(XDR
*xdrs
, postumntres
*objp
)
289 if (!xdr_int(xdrs
, &objp
->status
))
296 xdr_postmountreq(XDR
*xdrs
, postmountreq
*objp
)
298 if (!xdr_string(xdrs
, &objp
->special
, AUTOFS_MAXPATHLEN
))
300 if (!xdr_string(xdrs
, &objp
->mountp
, AUTOFS_MAXPATHLEN
))
302 if (!xdr_string(xdrs
, &objp
->fstype
, AUTOFS_MAXCOMPONENTLEN
))
304 if (!xdr_string(xdrs
, &objp
->mntopts
, AUTOFS_MAXOPTSLEN
))
306 if (!xdr_dev_t(xdrs
, &objp
->devid
))
313 xdr_postmountres(XDR
*xdrs
, postmountres
*objp
)
315 if (!xdr_int(xdrs
, &objp
->status
))
319 #endif /* AUTOFS_POSTUNMOUNT */
323 xdr_autofs_res(XDR
*xdrs
, autofs_res
*objp
)
325 if (!xdr_enum(xdrs
, (enum_t
*)objp
))
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
))
339 if (!xdr_string(xdrs
, &objp
->path
, AUTOFS_MAXPATHLEN
))
341 if (!xdr_string(xdrs
, &objp
->name
, AUTOFS_MAXCOMPONENTLEN
))
343 if (!xdr_string(xdrs
, &objp
->subdir
, AUTOFS_MAXPATHLEN
))
345 if (!xdr_string(xdrs
, &objp
->opts
, AUTOFS_MAXOPTSLEN
))
347 if (!xdr_bool_t(xdrs
, &objp
->isdirect
))
354 xdr_mount_result_type(XDR
*xdrs
, mount_result_type
*objp
)
356 if (!xdr_autofs_stat(xdrs
, &objp
->status
))
358 switch (objp
->status
) {
360 if (!xdr_pointer(xdrs
,
361 (char **)&objp
->mount_result_type_u
.list
,
362 sizeof(action_list
), (XDRPROC_T_TYPE
) xdr_action_list
))
366 if (!xdr_int(xdrs
, &objp
->mount_result_type_u
.error
))
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
))
382 if (!xdr_int(xdrs
, &objp
->mr_verbose
))
390 xdr_lookup_result_type(XDR
*xdrs
, lookup_result_type
*objp
)
392 if (!xdr_autofs_action(xdrs
, &objp
->action
))
394 switch (objp
->action
) {
396 if (!xdr_linka(xdrs
, &objp
->lookup_result_type_u
.lt_linka
))
407 xdr_autofs_lookupres(XDR
*xdrs
, autofs_lookupres
*objp
)
409 if (!xdr_autofs_res(xdrs
, &objp
->lu_res
))
411 if (!xdr_lookup_result_type(xdrs
, &objp
->lu_type
))
413 if (!xdr_int(xdrs
, &objp
->lu_verbose
))
420 xdr_autofs_rddirargs(XDR
*xdrs
, autofs_rddirargs
*objp
)
422 if (!xdr_string(xdrs
, &objp
->rda_map
, AUTOFS_MAXPATHLEN
))
424 if (!xdr_u_int(xdrs
, (u_int
*) &objp
->rda_offset
))
426 if (!xdr_u_int(xdrs
, (u_int
*) &objp
->rda_count
))
435 * Solaris automountd uses struct autofsrddir to pass the results.
436 * We use the traditional nfsreaddirres and do the conversion ourselves.
439 xdr_amd_putrddirres(XDR
*xdrs
, nfsdirlist
*dp
, ulong reqsize
)
445 bool_t
false = FALSE
;
451 bufsize
= 1 * BYTES_PER_XDR_UNIT
;
452 for (ep
= dp
->dl_entries
; ep
; ep
= ep
->ne_nextentry
) {
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
) {
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
)) {
472 if (!xdr_bool(xdrs
, &false)) {
475 if (!xdr_bool(xdrs
, &dp
->dl_eof
)) {
483 xdr_amd_rddirres(XDR
*xdrs
, amd_rddirres
*objp
)
485 if (!xdr_enum(xdrs
, (enum_t
*)&objp
->rd_status
))
487 if (objp
->rd_status
!= AUTOFS_OK
)
489 return (xdr_amd_putrddirres(xdrs
, &objp
->rd_dl
, objp
->rd_bufsize
));
498 autofs_lookup_2_req(autofs_lookupargs
*m
,
499 autofs_lookupres
*res
,
500 struct authunix_parms
*cred
,
504 am_node
*mp
, *new_mp
;
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
);
517 plog(XLOG_ERROR
, "map %s not found", m
->path
);
523 new_mp
= mf
->mf_ops
->lookup_child(mp
, m
->name
, &err
, VLOOK_LOOKUP
);
530 plog(XLOG_ERROR
, "autofs requests to mount an already mounted node???");
535 res
->lu_type
.action
= AUTOFS_NONE
;
541 dlog("LOOKUP REPLY: status=%d", res
->lu_res
);
547 autofs_lookup_2_free(autofs_lookupres
*res
)
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
;
566 autofs_mount_2_req(autofs_lookupargs
*m
,
567 autofs_mountres
*res
,
568 struct authunix_parms
*cred
,
572 am_node
*mp
, *new_mp
;
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
);
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
;
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
) {
599 /* we're working on it */
603 res
->mr_type
.status
= AUTOFS_DONE
;
604 res
->mr_type
.mount_result_type_u
.error
= AUTOFS_NOENT
;
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
;
613 struct action_list
*list
= malloc(sizeof(struct action_list
));
616 target
= new_mp
->am_link
;
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
);
623 res
->mr_type
.status
= AUTOFS_ACTION
;
624 res
->mr_type
.mount_result_type_u
.list
= list
;
630 switch (res
->mr_type
.status
) {
632 dlog("MOUNT REPLY: status=%d, AUTOFS_ACTION", err
);
635 dlog("MOUNT REPLY: status=%d, AUTOFS_DONE", err
);
638 dlog("MOUNT REPLY: status=%d, UNKNOWN(%d)", err
, res
->mr_type
.status
);
644 plog(XLOG_ERROR
, "mount of %s failed", m
->path
);
647 plog(XLOG_ERROR
, "mount of %s/%s failed", m
->path
, m
->name
);
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
667 link
= &(res
->mr_type
.mount_result_type_u
.list
->action
.action_list_entry_u
.linka
);
672 } else if (action
== AUTOFS_MOUNT_RQ
) {
674 mnt
= &(res
->mr_type
.mount_result_type_u
.list
->action
.action_list_entry_u
.mounta
);
683 #ifdef HAVE_MOUNTA_OPTPTR
686 #endif /* HAVE_MOUNTA_OPTPTR */
688 XFREE(res
->mr_type
.mount_result_type_u
.list
);
694 autofs_unmount_2_req(umntrequest
*ul
,
696 struct authunix_parms
*cred
,
702 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
703 dlog("UNMOUNT REQUEST: dev=%lx rdev=%lx %s",
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",
713 ul
->isdirect
? "direct" : "indirect");
714 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
716 /* by default, and if not found, succeed */
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
)
727 #else /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
728 mp
= find_ap(ul
->mntpnt
);
729 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
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
);
742 /* backgrounded, don't reply yet */
745 if (get_exported_ap(mapno
))
746 /* unmounting failed, tell the kernel */
750 dlog("UNMOUNT REPLY: status=%d", res
->status
);
756 * These exist only in the AutoFS V2 protocol.
758 #ifdef AUTOFS_POSTUNMOUNT
759 /* XXX not implemented */
761 autofs_postunmount_2_req(postumntreq
*req
,
763 struct authunix_parms
*cred
,
766 postumntreq
*ul
= req
;
768 dlog("POSTUNMOUNT REQUEST: dev=%lx rdev=%lx",
770 (u_long
) ul
->rdevid
);
772 /* succeed unconditionally */
775 dlog("POSTUNMOUNT REPLY: status=%d", res
->status
);
780 /* XXX not implemented */
782 autofs_postmount_2_req(postmountreq
*req
,
784 struct authunix_parms
*cred
,
787 dlog("POSTMOUNT REQUEST: %s\tdev=%lx\tspecial=%s %s",
788 req
->mountp
, (u_long
) req
->devid
, req
->special
, req
->mntopts
);
790 /* succeed unconditionally */
793 dlog("POSTMOUNT REPLY: status=%d", res
->status
);
796 #endif /* AUTOFS_POSTUNMOUNT */
800 autofs_readdir_2_req(struct autofs_rddirargs
*req
,
801 struct amd_rddirres
*res
,
802 struct authunix_parms
*cred
,
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
);
814 plog(XLOG_ERROR
, "map %s not found", req
->rda_map
);
815 res
->rd_status
= AUTOFS_NOENT
;
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
);
824 res
->rd_status
= AUTOFS_ECOMM
;
828 res
->rd_status
= AUTOFS_OK
;
829 res
->rd_bufsize
= req
->rda_count
;
832 dlog("READDIR REPLY: status=%d", res
->rd_status
);
837 /****************************************************************************/
838 /* autofs program dispatcher */
840 autofs_program_2(struct svc_req
*rqstp
, SVCXPRT
*transp
)
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 */
854 autofs_mountres mount_res
;
855 autofs_lookupres lookup_res
;
857 amd_rddirres readdir_res
;
858 #ifdef AUTOFS_POSTUNMOUNT
859 postumntres postumnt_res
;
860 postmountres postmnt_res
;
861 #endif /* AUTOFS_POSTUNMOUNT */
865 bool_t (*xdr_argument
)();
866 bool_t (*xdr_result
)();
868 void (*local_free
)() = NULL
;
870 current_transp
= transp
;
872 switch (rqstp
->rq_proc
) {
875 svc_sendreply(transp
,
876 (XDRPROC_T_TYPE
) xdr_void
,
877 (SVC_IN_ARG_TYPE
) NULL
);
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
;
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
;
895 xdr_argument
= xdr_umntrequest
;
896 xdr_result
= xdr_umntres
;
897 local
= autofs_unmount_2_req
;
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
;
910 case AUTOFS_POSTMOUNT
:
911 xdr_argument
= xdr_postmountreq
;
912 xdr_result
= xdr_postmountres
;
913 local
= autofs_postmount_2_req
;
915 #endif /* AUTOFS_POSTUNMOUNT */
918 xdr_argument
= xdr_autofs_rddirargs
;
919 xdr_result
= xdr_amd_rddirres
;
920 local
= autofs_readdir_2_req
;
924 svcerr_noproc(transp
);
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
);
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 */
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");
959 (*local_free
)(&result
);
964 autofs_get_fh(am_node
*mp
)
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 */
978 if (uname(&utsname
) < 0) {
979 xstrlcpy(buf
, "localhost.autofs", sizeof(buf
));
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 */
997 fh
->key
= mp
->am_name
;
1001 mp
->am_autofs_fh
= fh
;
1007 autofs_mounted(am_node
*mp
)
1009 /* We don't want any timeouts on autofs nodes */
1010 mp
->am_autofs_ttl
= NEVER
;
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 */
1022 mp
->am_autofs_fh
= NULL
;
1027 autofs_get_mp(am_node
*mp
)
1034 autofs_release_mp(am_node
*mp
)
1041 autofs_add_fdset(fd_set
*readfds
)
1048 autofs_handle_fdset(fd_set
*readfds
, int 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
)
1078 char *target
, *target2
= NULL
;
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 */
1092 if (!(gopt
.flags
& CFM_AUTOFS_USE_LOFS
))
1093 /* Symlinks will be requested in autofs_mount_succeeded */
1097 target
= mp
->am_link
;
1099 target
= mf
->mf_mount
;
1101 if (target
[0] != '/')
1102 target2
= str3cat(NULL
, mp
->am_parent
->am_path
, "/", target
);
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.
1124 if ((err
= stat(target2
, &buf
)))
1127 if ((err
= lstat(target2
, &buf
)))
1130 if ((err
= mount_lofs(mp
->am_path
, target2
, mf
->mf_mopts
, 1))) {
1146 autofs_umount_fs(am_node
*mp
, mntfs
*mf
)
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);
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
);
1167 autofs_umount_succeeded(am_node
*mp
)
1170 SVCXPRT
*transp
= mp
->am_transp
;
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
);
1182 mp
->am_transp
= NULL
;
1185 plog(XLOG_INFO
, "autofs: unmounting %s succeeded", mp
->am_path
);
1191 autofs_umount_failed(am_node
*mp
)
1194 SVCXPRT
*transp
= mp
->am_transp
;
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
);
1206 mp
->am_transp
= NULL
;
1209 plog(XLOG_INFO
, "autofs: unmounting %s failed", mp
->am_path
);
1215 autofs_mount_succeeded(am_node
*mp
)
1217 SVCXPRT
*transp
= mp
->am_transp
;
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
;
1234 autofs_mountres res
;
1235 res
.mr_type
.status
= AUTOFS_DONE
;
1236 res
.mr_type
.mount_result_type_u
.error
= AUTOFS_OK
;
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
);
1246 mp
->am_transp
= NULL
;
1249 plog(XLOG_INFO
, "autofs: mounting %s succeeded", mp
->am_path
);
1254 autofs_mount_failed(am_node
*mp
)
1256 SVCXPRT
*transp
= mp
->am_transp
;
1259 autofs_mountres res
;
1260 res
.mr_type
.status
= AUTOFS_DONE
;
1261 res
.mr_type
.mount_result_type_u
.error
= AUTOFS_NOENT
;
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
);
1271 mp
->am_transp
= NULL
;
1274 plog(XLOG_INFO
, "autofs: mounting %s failed", mp
->am_path
);
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
;