1 /*	$NetBSD: autofs_solaris_v2_v3.c,v 1.1.1.3 2015/01/17 16:34:16 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1999-2003 Ion Badulescu
5  * Copyright (c) 1997-2014 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.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Jan-Simon Pendry at Imperial College, London.
13  *
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. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *
39  * File: am-utils/conf/autofs/autofs_solaris_v2_v3.c
40  *
41  */
42 
43 /*
44  * Automounter filesystem
45  */
46 
47 #ifdef HAVE_CONFIG_H
48 # include <config.h>
49 #endif /* HAVE_CONFIG_H */
50 #include <am_defs.h>
51 #include <amd.h>
52 
53 /*
54  * MACROS:
55  */
56 #ifndef AUTOFS_NULL
57 # define AUTOFS_NULL	NULLPROC
58 #endif /* not AUTOFS_NULL */
59 
60 /*
61  * STRUCTURES:
62  */
63 
64 struct amd_rddirres {
65   enum autofs_res rd_status;
66   u_long rd_bufsize;
67   nfsdirlist rd_dl;
68 };
69 typedef struct amd_rddirres amd_rddirres;
70 
71 /*
72  * VARIABLES:
73  */
74 
75 SVCXPRT *autofs_xprt = NULL;
76 
77 /* forward declarations */
78 bool_t xdr_umntrequest(XDR *xdrs, umntrequest *objp);
79 bool_t xdr_umntres(XDR *xdrs, umntres *objp);
80 bool_t xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp);
81 bool_t xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp);
82 bool_t xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp);
83 bool_t xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp);
84 static bool_t xdr_amd_rddirres(XDR *xdrs, amd_rddirres *objp);
85 
86 /*
87  * These exist only in the AutoFS V2 protocol.
88  */
89 #ifdef AUTOFS_POSTUNMOUNT
90 bool_t xdr_postumntreq(XDR *xdrs, postumntreq *objp);
91 bool_t xdr_postumntres(XDR *xdrs, postumntres *objp);
92 bool_t xdr_postmountreq(XDR *xdrs, postmountreq *objp);
93 bool_t xdr_postmountres(XDR *xdrs, postmountres *objp);
94 #endif /* AUTOFS_POSTUMOUNT */
95 
96 /*
97  * AUTOFS XDR FUNCTIONS:
98  */
99 
100 bool_t
xdr_autofs_stat(XDR * xdrs,autofs_stat * objp)101 xdr_autofs_stat(XDR *xdrs, autofs_stat *objp)
102 {
103   if (!xdr_enum(xdrs, (enum_t *)objp))
104     return (FALSE);
105   return (TRUE);
106 }
107 
108 
109 bool_t
xdr_autofs_action(XDR * xdrs,autofs_action * objp)110 xdr_autofs_action(XDR *xdrs, autofs_action *objp)
111 {
112   if (!xdr_enum(xdrs, (enum_t *)objp))
113     return (FALSE);
114   return (TRUE);
115 }
116 
117 
118 bool_t
xdr_linka(XDR * xdrs,linka * objp)119 xdr_linka(XDR *xdrs, linka *objp)
120 {
121   if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
122     return (FALSE);
123   if (!xdr_string(xdrs, &objp->link, AUTOFS_MAXPATHLEN))
124     return (FALSE);
125   return (TRUE);
126 }
127 
128 
129 bool_t
xdr_autofs_netbuf(XDR * xdrs,struct netbuf * objp)130 xdr_autofs_netbuf(XDR *xdrs, struct netbuf *objp)
131 {
132   bool_t dummy;
133 
134   if (!xdr_u_long(xdrs, (u_long *) &objp->maxlen))
135     return (FALSE);
136   dummy = xdr_bytes(xdrs, (char **)&(objp->buf),
137 		    (u_int *)&(objp->len), objp->maxlen);
138   return (dummy);
139 }
140 
141 
142 bool_t
xdr_autofs_args(XDR * xdrs,autofs_args * objp)143 xdr_autofs_args(XDR *xdrs, autofs_args *objp)
144 {
145   if (!xdr_autofs_netbuf(xdrs, &objp->addr))
146     return (FALSE);
147   if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
148     return (FALSE);
149   if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
150     return (FALSE);
151   if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
152     return (FALSE);
153   if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
154     return (FALSE);
155   if (!xdr_string(xdrs, &objp->key, AUTOFS_MAXCOMPONENTLEN))
156     return (FALSE);
157   if (!xdr_int(xdrs, &objp->mount_to))
158     return (FALSE);
159   if (!xdr_int(xdrs, &objp->rpc_to))
160     return (FALSE);
161   if (!xdr_int(xdrs, &objp->direct))
162     return (FALSE);
163   return (TRUE);
164 }
165 
166 
167 bool_t
xdr_mounta(XDR * xdrs,struct mounta * objp)168 xdr_mounta(XDR *xdrs, struct mounta *objp)
169 {
170   if (!xdr_string(xdrs, &objp->spec, AUTOFS_MAXPATHLEN))
171     return (FALSE);
172   if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN))
173     return (FALSE);
174   if (!xdr_int(xdrs, &objp->flags))
175     return (FALSE);
176   if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
177     return (FALSE);
178   if (!xdr_pointer(xdrs, (char **)&objp->dataptr, sizeof(autofs_args),
179 		   (XDRPROC_T_TYPE) xdr_autofs_args))
180     return (FALSE);
181   if (!xdr_int(xdrs, &objp->datalen))
182     return (FALSE);
183   return (TRUE);
184 }
185 
186 
187 bool_t
xdr_action_list_entry(XDR * xdrs,action_list_entry * objp)188 xdr_action_list_entry(XDR *xdrs, action_list_entry *objp)
189 {
190   if (!xdr_autofs_action(xdrs, &objp->action))
191     return (FALSE);
192   switch (objp->action) {
193   case AUTOFS_MOUNT_RQ:
194     if (!xdr_mounta(xdrs, &objp->action_list_entry_u.mounta))
195       return (FALSE);
196     break;
197   case AUTOFS_LINK_RQ:
198     if (!xdr_linka(xdrs, &objp->action_list_entry_u.linka))
199       return (FALSE);
200     break;
201   default:
202     break;
203   }
204   return (TRUE);
205 }
206 
207 
208 bool_t
xdr_action_list(XDR * xdrs,action_list * objp)209 xdr_action_list(XDR *xdrs, action_list *objp)
210 {
211   if (!xdr_action_list_entry(xdrs, &objp->action))
212     return (FALSE);
213   if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(action_list),
214 		   (XDRPROC_T_TYPE) xdr_action_list))
215     return (FALSE);
216   return (TRUE);
217 }
218 
219 
220 bool_t
xdr_umntrequest(XDR * xdrs,umntrequest * objp)221 xdr_umntrequest(XDR *xdrs, umntrequest *objp)
222 {
223   if (amuDebug(D_XDRTRACE))
224     plog(XLOG_DEBUG, "xdr_umntrequest:");
225 
226   if (!xdr_bool_t(xdrs, &objp->isdirect))
227     return (FALSE);
228 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
229   if (!xdr_dev_t(xdrs, &objp->devid))
230     return (FALSE);
231   if (!xdr_dev_t(xdrs, &objp->rdevid))
232     return (FALSE);
233 #else  /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
234   if (!xdr_string(xdrs, &objp->mntresource, AUTOFS_MAXPATHLEN))
235     return (FALSE);
236   if (!xdr_string(xdrs, &objp->mntpnt, AUTOFS_MAXPATHLEN))
237     return (FALSE);
238   if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
239     return (FALSE);
240   if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN))
241     return (FALSE);
242 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
243   if (!xdr_pointer(xdrs, (char **) &objp->next, sizeof(umntrequest),
244 		   (XDRPROC_T_TYPE) xdr_umntrequest))
245     return (FALSE);
246 
247   return (TRUE);
248 }
249 
250 
251 bool_t
xdr_umntres(XDR * xdrs,umntres * objp)252 xdr_umntres(XDR *xdrs, umntres *objp)
253 {
254   if (amuDebug(D_XDRTRACE))
255     plog(XLOG_DEBUG, "xdr_mntres:");
256 
257   if (!xdr_int(xdrs, &objp->status))
258     return (FALSE);
259   return (TRUE);
260 }
261 
262 
263 /*
264  * These exist only in the AutoFS V2 protocol.
265  */
266 #ifdef AUTOFS_POSTUNMOUNT
267 bool_t
xdr_postumntreq(XDR * xdrs,postumntreq * objp)268 xdr_postumntreq(XDR *xdrs, postumntreq *objp)
269 {
270   if (!xdr_dev_t(xdrs, &objp->devid))
271     return (FALSE);
272   if (!xdr_dev_t(xdrs, &objp->rdevid))
273     return (FALSE);
274   if (!xdr_pointer(xdrs, (char **)&objp->next,
275 		   sizeof(struct postumntreq),
276 		   (XDRPROC_T_TYPE) xdr_postumntreq))
277     return (FALSE);
278   return (TRUE);
279 }
280 
281 
282 bool_t
xdr_postumntres(XDR * xdrs,postumntres * objp)283 xdr_postumntres(XDR *xdrs, postumntres *objp)
284 {
285   if (!xdr_int(xdrs, &objp->status))
286     return (FALSE);
287   return (TRUE);
288 }
289 
290 
291 bool_t
xdr_postmountreq(XDR * xdrs,postmountreq * objp)292 xdr_postmountreq(XDR *xdrs, postmountreq *objp)
293 {
294   if (!xdr_string(xdrs, &objp->special, AUTOFS_MAXPATHLEN))
295     return (FALSE);
296   if (!xdr_string(xdrs, &objp->mountp, AUTOFS_MAXPATHLEN))
297     return (FALSE);
298   if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN))
299     return (FALSE);
300   if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN))
301     return (FALSE);
302   if (!xdr_dev_t(xdrs, &objp->devid))
303     return (FALSE);
304   return (TRUE);
305 }
306 
307 
308 bool_t
xdr_postmountres(XDR * xdrs,postmountres * objp)309 xdr_postmountres(XDR *xdrs, postmountres *objp)
310 {
311   if (!xdr_int(xdrs, &objp->status))
312     return (FALSE);
313   return (TRUE);
314 }
315 #endif /* AUTOFS_POSTUNMOUNT */
316 
317 
318 bool_t
xdr_autofs_res(XDR * xdrs,autofs_res * objp)319 xdr_autofs_res(XDR *xdrs, autofs_res *objp)
320 {
321   if (!xdr_enum(xdrs, (enum_t *)objp))
322     return (FALSE);
323   return (TRUE);
324 }
325 
326 
327 bool_t
xdr_autofs_lookupargs(XDR * xdrs,autofs_lookupargs * objp)328 xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp)
329 {
330   if (amuDebug(D_XDRTRACE))
331     plog(XLOG_DEBUG, "xdr_autofs_lookupargs:");
332 
333   if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN))
334     return (FALSE);
335   if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN))
336     return (FALSE);
337   if (!xdr_string(xdrs, &objp->name, AUTOFS_MAXCOMPONENTLEN))
338     return (FALSE);
339   if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN))
340     return (FALSE);
341   if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN))
342     return (FALSE);
343   if (!xdr_bool_t(xdrs, &objp->isdirect))
344     return (FALSE);
345   return (TRUE);
346 }
347 
348 
349 bool_t
xdr_mount_result_type(XDR * xdrs,mount_result_type * objp)350 xdr_mount_result_type(XDR *xdrs, mount_result_type *objp)
351 {
352   if (!xdr_autofs_stat(xdrs, &objp->status))
353     return (FALSE);
354   switch (objp->status) {
355   case AUTOFS_ACTION:
356     if (!xdr_pointer(xdrs,
357 		     (char **)&objp->mount_result_type_u.list,
358 		     sizeof(action_list), (XDRPROC_T_TYPE) xdr_action_list))
359       return (FALSE);
360     break;
361   case AUTOFS_DONE:
362     if (!xdr_int(xdrs, &objp->mount_result_type_u.error))
363       return (FALSE);
364     break;
365   }
366   return (TRUE);
367 }
368 
369 
370 bool_t
xdr_autofs_mountres(XDR * xdrs,autofs_mountres * objp)371 xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp)
372 {
373   if (amuDebug(D_XDRTRACE))
374     plog(XLOG_DEBUG, "xdr_mntres:");
375 
376   if (!xdr_mount_result_type(xdrs, &objp->mr_type))
377     return (FALSE);
378   if (!xdr_int(xdrs, &objp->mr_verbose))
379     return (FALSE);
380 
381   return (TRUE);
382 }
383 
384 
385 bool_t
xdr_lookup_result_type(XDR * xdrs,lookup_result_type * objp)386 xdr_lookup_result_type(XDR *xdrs, lookup_result_type *objp)
387 {
388   if (!xdr_autofs_action(xdrs, &objp->action))
389     return (FALSE);
390   switch (objp->action) {
391   case AUTOFS_LINK_RQ:
392     if (!xdr_linka(xdrs, &objp->lookup_result_type_u.lt_linka))
393       return (FALSE);
394     break;
395   default:
396     break;
397   }
398   return (TRUE);
399 }
400 
401 
402 bool_t
xdr_autofs_lookupres(XDR * xdrs,autofs_lookupres * objp)403 xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp)
404 {
405   if (!xdr_autofs_res(xdrs, &objp->lu_res))
406     return (FALSE);
407   if (!xdr_lookup_result_type(xdrs, &objp->lu_type))
408     return (FALSE);
409   if (!xdr_int(xdrs, &objp->lu_verbose))
410     return (FALSE);
411   return (TRUE);
412 }
413 
414 
415 bool_t
xdr_autofs_rddirargs(XDR * xdrs,autofs_rddirargs * objp)416 xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp)
417 {
418   if (!xdr_string(xdrs, &objp->rda_map, AUTOFS_MAXPATHLEN))
419     return (FALSE);
420   if (!xdr_u_int(xdrs, (u_int *) &objp->rda_offset))
421     return (FALSE);
422   if (!xdr_u_int(xdrs, (u_int *) &objp->rda_count))
423     return (FALSE);
424   return (TRUE);
425 }
426 
427 
428 /*
429  * ENCODE ONLY
430  *
431  * Solaris automountd uses struct autofsrddir to pass the results.
432  * We use the traditional nfsreaddirres and do the conversion ourselves.
433  */
434 static bool_t
xdr_amd_putrddirres(XDR * xdrs,nfsdirlist * dp,ulong reqsize)435 xdr_amd_putrddirres(XDR *xdrs, nfsdirlist *dp, ulong reqsize)
436 {
437   nfsentry *ep;
438   char *name;
439   u_int namlen;
440   bool_t true = TRUE;
441   bool_t false = FALSE;
442   int entrysz;
443   int tofit;
444   int bufsize;
445   u_long ino, off;
446 
447   bufsize = 1 * BYTES_PER_XDR_UNIT;
448   for (ep = dp->dl_entries; ep; ep = ep->ne_nextentry) {
449     name = ep->ne_name;
450     namlen = strlen(name);
451     ino = (u_long) ep->ne_fileid;
452     off = (u_long) ep->ne_cookie + AUTOFS_DAEMONCOOKIE;
453     entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
454       roundup(namlen, BYTES_PER_XDR_UNIT);
455     tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
456     if (bufsize + tofit > reqsize) {
457       dp->dl_eof = FALSE;
458       break;
459     }
460     if (!xdr_bool(xdrs, &true) ||
461 	!xdr_u_long(xdrs, &ino) ||
462 	!xdr_bytes(xdrs, &name, &namlen, AUTOFS_MAXPATHLEN) ||
463 	!xdr_u_long(xdrs, &off)) {
464       return (FALSE);
465     }
466     bufsize += entrysz;
467   }
468   if (!xdr_bool(xdrs, &false)) {
469     return (FALSE);
470   }
471   if (!xdr_bool(xdrs, &dp->dl_eof)) {
472     return (FALSE);
473   }
474   return (TRUE);
475 }
476 
477 
478 static bool_t
xdr_amd_rddirres(XDR * xdrs,amd_rddirres * objp)479 xdr_amd_rddirres(XDR *xdrs, amd_rddirres *objp)
480 {
481   if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status))
482     return (FALSE);
483   if (objp->rd_status != AUTOFS_OK)
484     return (TRUE);
485   return (xdr_amd_putrddirres(xdrs, &objp->rd_dl, objp->rd_bufsize));
486 }
487 
488 
489 /*
490  * AUTOFS RPC methods
491  */
492 
493 static int
autofs_lookup_2_req(autofs_lookupargs * m,autofs_lookupres * res,struct authunix_parms * cred,SVCXPRT * transp)494 autofs_lookup_2_req(autofs_lookupargs *m,
495 		    autofs_lookupres *res,
496 		    struct authunix_parms *cred,
497 		    SVCXPRT *transp)
498 {
499   int err;
500   am_node *mp, *new_mp;
501   mntfs *mf;
502 
503   dlog("LOOKUP REQUEST: name=%s[%s] map=%s opts=%s path=%s direct=%d",
504        m->name, m->subdir, m->map, m->opts,
505        m->path, m->isdirect);
506 
507   /* find the effective uid/gid from RPC request */
508   xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) cred->aup_uid);
509   xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) cred->aup_gid);
510 
511   mp = find_ap(m->path);
512   if (!mp) {
513     plog(XLOG_ERROR, "map %s not found", m->path);
514     err = AUTOFS_NOENT;
515     goto out;
516   }
517 
518   mf = mp->am_al->al_mnt;
519   new_mp = mf->mf_ops->lookup_child(mp, m->name, &err, VLOOK_LOOKUP);
520   if (!new_mp) {
521     err = AUTOFS_NOENT;
522     goto out;
523   }
524 
525   if (err == 0) {
526     plog(XLOG_ERROR, "autofs requests to mount an already mounted node???");
527   } else {
528     free_map(new_mp);
529   }
530   err = AUTOFS_OK;
531   res->lu_type.action = AUTOFS_NONE;
532 
533  out:
534   res->lu_res = err;
535   res->lu_verbose = 1;
536 
537   dlog("LOOKUP REPLY: status=%d", res->lu_res);
538   return 0;
539 }
540 
541 
542 static void
autofs_lookup_2_free(autofs_lookupres * res)543 autofs_lookup_2_free(autofs_lookupres *res)
544 {
545   struct linka link;
546 
547   if ((res->lu_res == AUTOFS_OK) &&
548       (res->lu_type.action == AUTOFS_LINK_RQ)) {
549     /*
550      * Free link information
551      */
552     link = res->lu_type.lookup_result_type_u.lt_linka;
553     if (link.dir)
554       XFREE(link.dir);
555     if (link.link)
556       XFREE(link.link);
557   }
558 }
559 
560 
561 static int
autofs_mount_2_req(autofs_lookupargs * m,autofs_mountres * res,struct authunix_parms * cred,SVCXPRT * transp)562 autofs_mount_2_req(autofs_lookupargs *m,
563 		   autofs_mountres *res,
564 		   struct authunix_parms *cred,
565 		   SVCXPRT *transp)
566 {
567   int err = AUTOFS_OK;
568   am_node *mp, *new_mp;
569   mntfs *mf;
570 
571   dlog("MOUNT REQUEST: name=%s[%s] map=%s opts=%s path=%s direct=%d",
572        m->name, m->subdir, m->map, m->opts,
573        m->path, m->isdirect);
574 
575   /* find the effective uid/gid from RPC request */
576   xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) cred->aup_uid);
577   xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) cred->aup_gid);
578 
579   mp = find_ap(m->path);
580   if (!mp) {
581     plog(XLOG_ERROR, "map %s not found", m->path);
582     res->mr_type.status = AUTOFS_DONE;
583     res->mr_type.mount_result_type_u.error = AUTOFS_NOENT;
584     goto out;
585   }
586 
587   mf = mp->am_al->al_mnt;
588   new_mp = mf->mf_ops->lookup_child(mp, m->name + m->isdirect, &err, VLOOK_CREATE);
589   if (new_mp && err < 0) {
590     /* new_mp->am_transp = transp; */
591     new_mp = mf->mf_ops->mount_child(new_mp, &err);
592   }
593   if (new_mp == NULL) {
594     if (err < 0) {
595       /* we're working on it */
596       amd_stats.d_drops++;
597       return 1;
598     }
599     res->mr_type.status = AUTOFS_DONE;
600     res->mr_type.mount_result_type_u.error = AUTOFS_NOENT;
601     goto out;
602   }
603 
604   if (gopt.flags & CFM_AUTOFS_USE_LOFS ||
605       new_mp->am_al->al_mnt->mf_flags & MFF_ON_AUTOFS) {
606     res->mr_type.status = AUTOFS_DONE;
607     res->mr_type.mount_result_type_u.error = AUTOFS_OK;
608   } else {
609     struct action_list *list = malloc(sizeof(struct action_list));
610     char *target;
611     if (new_mp->am_link)
612       target = new_mp->am_link;
613     else
614       target = new_mp->am_al->al_mnt->mf_mount;
615     list->action.action = AUTOFS_LINK_RQ;
616     list->action.action_list_entry_u.linka.dir = xstrdup(new_mp->am_name);
617     list->action.action_list_entry_u.linka.link = xstrdup(target);
618     list->next = NULL;
619     res->mr_type.status = AUTOFS_ACTION;
620     res->mr_type.mount_result_type_u.list = list;
621   }
622 
623 out:
624   res->mr_verbose = 1;
625 
626   switch (res->mr_type.status) {
627   case AUTOFS_ACTION:
628     dlog("MOUNT REPLY: status=%d, AUTOFS_ACTION", err);
629     break;
630   case AUTOFS_DONE:
631     dlog("MOUNT REPLY: status=%d, AUTOFS_DONE", err);
632     break;
633   default:
634     dlog("MOUNT REPLY: status=%d, UNKNOWN(%d)", err, res->mr_type.status);
635   }
636 
637   if (err) {
638     if (m->isdirect) {
639       /* direct mount */
640       plog(XLOG_ERROR, "mount of %s failed", m->path);
641     } else {
642       /* indirect mount */
643       plog(XLOG_ERROR, "mount of %s/%s failed", m->path, m->name);
644     }
645   }
646   return 0;
647 }
648 
649 
650 static void
autofs_mount_2_free(struct autofs_mountres * res)651 autofs_mount_2_free(struct autofs_mountres *res)
652 {
653   if (res->mr_type.status == AUTOFS_ACTION &&
654       res->mr_type.mount_result_type_u.list != NULL) {
655     autofs_action action;
656     dlog("freeing action list");
657     action = res->mr_type.mount_result_type_u.list->action.action;
658     if (action == AUTOFS_LINK_RQ) {
659       /*
660        * Free link information
661        */
662       struct linka *link;
663       link = &(res->mr_type.mount_result_type_u.list->action.action_list_entry_u.linka);
664       if (link->dir)
665 	XFREE(link->dir);
666       if (link->link)
667 	XFREE(link->link);
668     } else if (action == AUTOFS_MOUNT_RQ) {
669       struct mounta *mnt;
670       mnt = &(res->mr_type.mount_result_type_u.list->action.action_list_entry_u.mounta);
671       if (mnt->spec)
672 	XFREE(mnt->spec);
673       if (mnt->dir)
674 	XFREE(mnt->dir);
675       if (mnt->fstype)
676 	XFREE(mnt->fstype);
677       if (mnt->dataptr)
678 	XFREE(mnt->dataptr);
679 #ifdef HAVE_MOUNTA_OPTPTR
680       if (mnt->optptr)
681 	XFREE(mnt->optptr);
682 #endif /* HAVE_MOUNTA_OPTPTR */
683     }
684     XFREE(res->mr_type.mount_result_type_u.list);
685   }
686 }
687 
688 
689 static int
autofs_unmount_2_req(umntrequest * ul,umntres * res,struct authunix_parms * cred,SVCXPRT * transp)690 autofs_unmount_2_req(umntrequest *ul,
691 		     umntres *res,
692 		     struct authunix_parms *cred,
693 		     SVCXPRT *transp)
694 {
695   int mapno, err;
696   am_node *mp = NULL;
697 
698 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
699   dlog("UNMOUNT REQUEST: dev=%lx rdev=%lx %s",
700        (u_long) ul->devid,
701        (u_long) ul->rdevid,
702        ul->isdirect ? "direct" : "indirect");
703 #else  /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
704   dlog("UNMOUNT REQUEST: mntresource='%s' mntpnt='%s' fstype='%s' mntopts='%s' %s",
705        ul->mntresource,
706        ul->mntpnt,
707        ul->fstype,
708        ul->mntopts,
709        ul->isdirect ? "direct" : "indirect");
710 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
711 
712   /* by default, and if not found, succeed */
713   res->status = 0;
714 
715 #ifdef HAVE_STRUCT_UMNTREQUEST_DEVID
716   for (mp = get_first_exported_ap(&mapno);
717        mp;
718        mp = get_next_exported_ap(&mapno)) {
719     if (mp->am_dev == ul->devid &&
720 	mp->am_rdev == ul->rdevid)
721       break;
722   }
723 #else  /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
724   mp = find_ap(ul->mntpnt);
725 #endif /* not HAVE_STRUCT_UMNTREQUEST_DEVID */
726 
727   if (mp) {
728     /* save RPC context */
729     if (!mp->am_transp && transp) {
730       mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
731       *(mp->am_transp) = *transp;
732     }
733 
734     mapno = mp->am_mapno;
735     err = unmount_mp(mp);
736 
737     if (err)
738       /* backgrounded, don't reply yet */
739       return 1;
740 
741     if (get_exported_ap(mapno))
742       /* unmounting failed, tell the kernel */
743       res->status = 1;
744   }
745 
746   dlog("UNMOUNT REPLY: status=%d", res->status);
747   return 0;
748 }
749 
750 
751 /*
752  * These exist only in the AutoFS V2 protocol.
753  */
754 #ifdef AUTOFS_POSTUNMOUNT
755 /* XXX not implemented */
756 static int
autofs_postunmount_2_req(postumntreq * req,postumntres * res,struct authunix_parms * cred,SVCXPRT * transp)757 autofs_postunmount_2_req(postumntreq *req,
758 			 postumntres *res,
759 			 struct authunix_parms *cred,
760 			 SVCXPRT *transp)
761 {
762   postumntreq *ul = req;
763 
764   dlog("POSTUNMOUNT REQUEST: dev=%lx rdev=%lx",
765        (u_long) ul->devid,
766        (u_long) ul->rdevid);
767 
768   /* succeed unconditionally */
769   res->status = 0;
770 
771   dlog("POSTUNMOUNT REPLY: status=%d", res->status);
772   return 0;
773 }
774 
775 
776 /* XXX not implemented */
777 static int
autofs_postmount_2_req(postmountreq * req,postmountres * res,struct authunix_parms * cred,SVCXPRT * transp)778 autofs_postmount_2_req(postmountreq *req,
779 		       postmountres *res,
780 		       struct authunix_parms *cred,
781 		       SVCXPRT *transp)
782 {
783   dlog("POSTMOUNT REQUEST: %s\tdev=%lx\tspecial=%s %s",
784        req->mountp, (u_long) req->devid, req->special, req->mntopts);
785 
786   /* succeed unconditionally */
787   res->status = 0;
788 
789   dlog("POSTMOUNT REPLY: status=%d", res->status);
790   return 0;
791 }
792 #endif /* AUTOFS_POSTUNMOUNT */
793 
794 
795 static int
autofs_readdir_2_req(struct autofs_rddirargs * req,struct amd_rddirres * res,struct authunix_parms * cred,SVCXPRT * transp)796 autofs_readdir_2_req(struct autofs_rddirargs *req,
797 		     struct amd_rddirres *res,
798 		     struct authunix_parms *cred,
799 		     SVCXPRT *transp)
800 {
801   am_node *mp;
802   int err;
803   static nfsentry e_res[MAX_READDIR_ENTRIES];
804 
805   dlog("READDIR REQUEST: %s @ %d",
806        req->rda_map, (int) req->rda_offset);
807 
808   mp = find_ap(req->rda_map);
809   if (!mp) {
810     plog(XLOG_ERROR, "map %s not found", req->rda_map);
811     res->rd_status = AUTOFS_NOENT;
812     goto out;
813   }
814 
815   mp->am_stats.s_readdir++;
816   req->rda_offset -= AUTOFS_DAEMONCOOKIE;
817   err = mp->am_al->al_mnt->mf_ops->readdir(mp, (char *)&req->rda_offset,
818 				    &res->rd_dl, e_res, req->rda_count);
819   if (err) {
820     res->rd_status = AUTOFS_ECOMM;
821     goto out;
822   }
823 
824   res->rd_status = AUTOFS_OK;
825   res->rd_bufsize = req->rda_count;
826 
827 out:
828   dlog("READDIR REPLY: status=%d", res->rd_status);
829   return 0;
830 }
831 
832 
833 /****************************************************************************/
834 /* autofs program dispatcher */
835 static void
autofs_program_2(struct svc_req * rqstp,SVCXPRT * transp)836 autofs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
837 {
838   union {
839     autofs_lookupargs autofs_mount_2_arg;
840     autofs_lookupargs autofs_lookup_2_arg;
841     umntrequest autofs_umount_2_arg;
842     autofs_rddirargs autofs_readdir_2_arg;
843 #ifdef AUTOFS_POSTUNMOUNT
844     postmountreq autofs_postmount_2_arg;
845     postumntreq autofs_postumnt_2_arg;
846 #endif /* AUTOFS_POSTUNMOUNT */
847   } argument;
848 
849   union {
850     autofs_mountres mount_res;
851     autofs_lookupres lookup_res;
852     umntres umount_res;
853     amd_rddirres readdir_res;
854 #ifdef AUTOFS_POSTUNMOUNT
855     postumntres postumnt_res;
856     postmountres postmnt_res;
857 #endif /* AUTOFS_POSTUNMOUNT */
858   } result;
859   int ret;
860 
861   bool_t (*xdr_argument)();
862   bool_t (*xdr_result)();
863   int (*local)();
864   void (*local_free)() = NULL;
865 
866   current_transp = transp;
867 
868   switch (rqstp->rq_proc) {
869 
870   case AUTOFS_NULL:
871     svc_sendreply(transp,
872 		  (XDRPROC_T_TYPE) xdr_void,
873 		  (SVC_IN_ARG_TYPE) NULL);
874     return;
875 
876   case AUTOFS_LOOKUP:
877     xdr_argument = xdr_autofs_lookupargs;
878     xdr_result = xdr_autofs_lookupres;
879     local = autofs_lookup_2_req;
880     local_free = autofs_lookup_2_free;
881     break;
882 
883   case AUTOFS_MOUNT:
884     xdr_argument = xdr_autofs_lookupargs;
885     xdr_result = xdr_autofs_mountres;
886     local = autofs_mount_2_req;
887     local_free = autofs_mount_2_free;
888     break;
889 
890   case AUTOFS_UNMOUNT:
891     xdr_argument = xdr_umntrequest;
892     xdr_result = xdr_umntres;
893     local = autofs_unmount_2_req;
894     break;
895 
896 /*
897  * These exist only in the AutoFS V2 protocol.
898  */
899 #ifdef AUTOFS_POSTUNMOUNT
900   case AUTOFS_POSTUNMOUNT:
901     xdr_argument = xdr_postumntreq;
902     xdr_result = xdr_postumntres;
903     local = autofs_postunmount_2_req;
904     break;
905 
906   case AUTOFS_POSTMOUNT:
907     xdr_argument = xdr_postmountreq;
908     xdr_result = xdr_postmountres;
909     local = autofs_postmount_2_req;
910     break;
911 #endif /* AUTOFS_POSTUNMOUNT */
912 
913   case AUTOFS_READDIR:
914     xdr_argument = xdr_autofs_rddirargs;
915     xdr_result = xdr_amd_rddirres;
916     local = autofs_readdir_2_req;
917     break;
918 
919   default:
920     svcerr_noproc(transp);
921     return;
922   }
923 
924   memset((char *) &argument, 0, sizeof(argument));
925   if (!svc_getargs(transp,
926 		   (XDRPROC_T_TYPE) xdr_argument,
927 		   (SVC_IN_ARG_TYPE) &argument)) {
928     plog(XLOG_ERROR, "AUTOFS xdr decode failed for %d %d %d",
929 	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
930     svcerr_decode(transp);
931     return;
932   }
933 
934   memset((char *)&result, 0, sizeof(result));
935   ret = (*local) (&argument, &result, rqstp->rq_clntcred, transp);
936 
937   current_transp = NULL;
938 
939   /* send reply only if the RPC method returned 0 */
940   if (!ret) {
941     if (!svc_sendreply(transp,
942 		       (XDRPROC_T_TYPE) xdr_result,
943 		       (SVC_IN_ARG_TYPE) &result)) {
944       svcerr_systemerr(transp);
945     }
946   }
947 
948   if (!svc_freeargs(transp,
949 		    (XDRPROC_T_TYPE) xdr_argument,
950 		    (SVC_IN_ARG_TYPE) &argument)) {
951     plog(XLOG_FATAL, "unable to free rpc arguments in autofs_program_2");
952   }
953 
954   if (local_free)
955     (*local_free)(&result);
956 }
957 
958 
959 int
autofs_get_fh(am_node * mp)960 autofs_get_fh(am_node *mp)
961 {
962   autofs_fh_t *fh;
963   char buf[MAXHOSTNAMELEN];
964   mntfs *mf = mp->am_al->al_mnt;
965   struct utsname utsname;
966 
967   plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path);
968   fh = ALLOC(autofs_fh_t);
969   memset((voidp) fh, 0, sizeof(autofs_fh_t)); /* Paranoid */
970 
971   /*
972    * SET MOUNT ARGS
973    */
974   if (uname(&utsname) < 0) {
975     xstrlcpy(buf, "localhost.autofs", sizeof(buf));
976   } else {
977     xstrlcpy(buf, utsname.nodename, sizeof(buf));
978     xstrlcat(buf, ".autofs", sizeof(buf));
979   }
980 #ifdef HAVE_AUTOFS_ARGS_T_ADDR
981   fh->addr.buf = xstrdup(buf);
982   fh->addr.len = fh->addr.maxlen = strlen(buf);
983 #endif /* HAVE_AUTOFS_ARGS_T_ADDR */
984 
985   fh->direct = ((mf->mf_ops->autofs_fs_flags & FS_DIRECT) == FS_DIRECT);
986   fh->rpc_to = 1;		/* XXX: arbitrary */
987   fh->mount_to = mp->am_timeo;
988   fh->path = mp->am_path;
989   fh->opts = "";		/* XXX: arbitrary */
990   fh->map = mp->am_path;	/* this is what we get back in readdir */
991   fh->subdir = "";
992   if (fh->direct)
993     fh->key = mp->am_name;
994   else
995     fh->key = "";
996 
997   mp->am_autofs_fh = fh;
998   return 0;
999 }
1000 
1001 
1002 void
autofs_mounted(am_node * mp)1003 autofs_mounted(am_node *mp)
1004 {
1005   /* We don't want any timeouts on autofs nodes */
1006   mp->am_autofs_ttl = NEVER;
1007 }
1008 
1009 
1010 void
autofs_release_fh(am_node * mp)1011 autofs_release_fh(am_node *mp)
1012 {
1013   autofs_fh_t *fh = mp->am_autofs_fh;
1014 #ifdef HAVE_AUTOFS_ARGS_T_ADDR
1015   XFREE(fh->addr.buf);
1016 #endif /* HAVE_AUTOFS_ARGS_T_ADDR */
1017   XFREE(fh);
1018   mp->am_autofs_fh = NULL;
1019 }
1020 
1021 
1022 void
autofs_get_mp(am_node * mp)1023 autofs_get_mp(am_node *mp)
1024 {
1025   /* nothing to do */
1026 }
1027 
1028 
1029 void
autofs_release_mp(am_node * mp)1030 autofs_release_mp(am_node *mp)
1031 {
1032   /* nothing to do */
1033 }
1034 
1035 
1036 void
autofs_add_fdset(fd_set * readfds)1037 autofs_add_fdset(fd_set *readfds)
1038 {
1039   /* nothing to do */
1040 }
1041 
1042 
1043 int
autofs_handle_fdset(fd_set * readfds,int nsel)1044 autofs_handle_fdset(fd_set *readfds, int nsel)
1045 {
1046   /* nothing to do */
1047   return nsel;
1048 }
1049 
1050 
1051 /*
1052  * Create the autofs service for amd
1053  */
1054 int
create_autofs_service(void)1055 create_autofs_service(void)
1056 {
1057   dlog("creating autofs service listener");
1058   return register_autofs_service(AUTOFS_CONFTYPE, autofs_program_2);
1059 }
1060 
1061 
1062 int
destroy_autofs_service(void)1063 destroy_autofs_service(void)
1064 {
1065   dlog("destroying autofs service listener");
1066   return unregister_autofs_service(AUTOFS_CONFTYPE);
1067 }
1068 
1069 
1070 int
autofs_mount_fs(am_node * mp,mntfs * mf)1071 autofs_mount_fs(am_node *mp, mntfs *mf)
1072 {
1073   int err = 0;
1074   char *target, *target2 = NULL;
1075   struct stat buf;
1076 
1077   /*
1078    * For sublinks, we could end up here with an already mounted f/s.
1079    * Don't do anything in that case.
1080    */
1081   if (!(mf->mf_flags & MFF_MOUNTED))
1082     err = mf->mf_ops->mount_fs(mp, mf);
1083 
1084   if (err || mf->mf_flags & MFF_ON_AUTOFS)
1085     /* Nothing else to do */
1086     return err;
1087 
1088   if (!(gopt.flags & CFM_AUTOFS_USE_LOFS))
1089     /* Symlinks will be requested in autofs_mount_succeeded */
1090     return 0;
1091 
1092   if (mp->am_link)
1093     target = mp->am_link;
1094   else
1095     target = mf->mf_mount;
1096 
1097   if (target[0] != '/')
1098     target2 = str3cat(NULL, mp->am_parent->am_path, "/", target);
1099   else
1100     target2 = xstrdup(target);
1101 
1102   plog(XLOG_INFO, "autofs: converting from link to lofs (%s -> %s)", mp->am_path, target2);
1103 
1104   /*
1105    * we need to stat() the destination, because the bind mount does not
1106    * follow symlinks and/or allow for non-existent destinations.
1107    * we fall back to symlinks if there are problems.
1108    *
1109    * we need to temporarily change pgrp, otherwise our stat() won't
1110    * trigger whatever cascading mounts are needed.
1111    *
1112    * WARNING: we will deadlock if this function is called from the master
1113    * amd process and it happens to trigger another auto mount. Therefore,
1114    * this function should be called only from a child amd process, or
1115    * at the very least it should not be called from the parent unless we
1116    * know for sure that it won't cause a recursive mount. We refuse to
1117    * cause the recursive mount anyway if called from the parent amd.
1118    */
1119   if (!foreground) {
1120     if ((err = stat(target2, &buf)))
1121       goto out;
1122   }
1123   if ((err = lstat(target2, &buf)))
1124     goto out;
1125 
1126   if ((err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1))) {
1127     errno = err;
1128     goto out;
1129   }
1130 
1131  out:
1132   if (target2)
1133     XFREE(target2);
1134 
1135   if (err)
1136     return errno;
1137   return 0;
1138 }
1139 
1140 
1141 int
autofs_umount_fs(am_node * mp,mntfs * mf)1142 autofs_umount_fs(am_node *mp, mntfs *mf)
1143 {
1144   int err = 0;
1145   if (!(mf->mf_flags & MFF_ON_AUTOFS) &&
1146       gopt.flags & CFM_AUTOFS_USE_LOFS) {
1147     err = UMOUNT_FS(mp->am_path, mnttab_file_name, 1);
1148     if (err)
1149       return err;
1150   }
1151 
1152   /*
1153    * Multiple sublinks could reference this f/s.
1154    * Don't actually unmount it unless we're holding the last reference.
1155    */
1156   if (mf->mf_refc == 1)
1157     err = mf->mf_ops->umount_fs(mp, mf);
1158   return err;
1159 }
1160 
1161 
1162 int
autofs_umount_succeeded(am_node * mp)1163 autofs_umount_succeeded(am_node *mp)
1164 {
1165   umntres res;
1166   SVCXPRT *transp = mp->am_transp;
1167 
1168   if (transp) {
1169     res.status = 0;
1170 
1171     if (!svc_sendreply(transp,
1172 		       (XDRPROC_T_TYPE) xdr_umntres,
1173 		       (SVC_IN_ARG_TYPE) &res))
1174       svcerr_systemerr(transp);
1175 
1176     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
1177     XFREE(transp);
1178     mp->am_transp = NULL;
1179   }
1180 
1181   plog(XLOG_INFO, "autofs: unmounting %s succeeded", mp->am_path);
1182   return 0;
1183 }
1184 
1185 
1186 int
autofs_umount_failed(am_node * mp)1187 autofs_umount_failed(am_node *mp)
1188 {
1189   umntres res;
1190   SVCXPRT *transp = mp->am_transp;
1191 
1192   if (transp) {
1193     res.status = 1;
1194 
1195     if (!svc_sendreply(transp,
1196 		       (XDRPROC_T_TYPE) xdr_umntres,
1197 		       (SVC_IN_ARG_TYPE) &res))
1198       svcerr_systemerr(transp);
1199 
1200     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
1201     XFREE(transp);
1202     mp->am_transp = NULL;
1203   }
1204 
1205   plog(XLOG_INFO, "autofs: unmounting %s failed", mp->am_path);
1206   return 0;
1207 }
1208 
1209 
1210 void
autofs_mount_succeeded(am_node * mp)1211 autofs_mount_succeeded(am_node *mp)
1212 {
1213   SVCXPRT *transp = mp->am_transp;
1214   struct stat stb;
1215 
1216   /*
1217    * Store dev and rdev -- but not for symlinks
1218    */
1219   if (gopt.flags & CFM_AUTOFS_USE_LOFS ||
1220       mp->am_al->al_mnt->mf_flags & MFF_ON_AUTOFS) {
1221     if (!lstat(mp->am_path, &stb)) {
1222       mp->am_dev = stb.st_dev;
1223       mp->am_rdev = stb.st_rdev;
1224     }
1225     /* don't expire the entries -- the kernel will do it for us */
1226     mp->am_flags |= AMF_NOTIMEOUT;
1227   }
1228 
1229   if (transp) {
1230     autofs_mountres res;
1231     res.mr_type.status = AUTOFS_DONE;
1232     res.mr_type.mount_result_type_u.error = AUTOFS_OK;
1233     res.mr_verbose = 1;
1234 
1235     if (!svc_sendreply(transp,
1236 		       (XDRPROC_T_TYPE) xdr_autofs_mountres,
1237 		       (SVC_IN_ARG_TYPE) &res))
1238       svcerr_systemerr(transp);
1239 
1240     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
1241     XFREE(transp);
1242     mp->am_transp = NULL;
1243   }
1244 
1245   plog(XLOG_INFO, "autofs: mounting %s succeeded", mp->am_path);
1246 }
1247 
1248 
1249 void
autofs_mount_failed(am_node * mp)1250 autofs_mount_failed(am_node *mp)
1251 {
1252   SVCXPRT *transp = mp->am_transp;
1253 
1254   if (transp) {
1255     autofs_mountres res;
1256     res.mr_type.status = AUTOFS_DONE;
1257     res.mr_type.mount_result_type_u.error = AUTOFS_NOENT;
1258     res.mr_verbose = 1;
1259 
1260     if (!svc_sendreply(transp,
1261 		       (XDRPROC_T_TYPE) xdr_autofs_mountres,
1262 		       (SVC_IN_ARG_TYPE) &res))
1263       svcerr_systemerr(transp);
1264 
1265     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
1266     XFREE(transp);
1267     mp->am_transp = NULL;
1268   }
1269 
1270   plog(XLOG_INFO, "autofs: mounting %s failed", mp->am_path);
1271 }
1272 
1273 
1274 void
autofs_get_opts(char * opts,size_t l,autofs_fh_t * fh)1275 autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh)
1276 {
1277   xsnprintf(opts, l, "%sdirect",
1278 	    fh->direct ? "" : "in");
1279 }
1280 
1281 
1282 int
autofs_compute_mount_flags(mntent_t * mntp)1283 autofs_compute_mount_flags(mntent_t *mntp)
1284 {
1285   /* Must use overlay mounts */
1286   return MNT2_GEN_OPT_OVERLAY;
1287 }
1288 
1289 
autofs_timeout_mp(am_node * mp)1290 void autofs_timeout_mp(am_node *mp)
1291 {
1292   /* We don't want any timeouts on autofs nodes */
1293   mp->am_autofs_ttl = NEVER;
1294 }
1295