17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
27004388ebScasper #include <stdio_ext.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <unistd.h>
307c478bd9Sstevel@tonic-gate #include <signal.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <memory.h>
337c478bd9Sstevel@tonic-gate #include <stropts.h>
347c478bd9Sstevel@tonic-gate #include <netconfig.h>
357c478bd9Sstevel@tonic-gate #include <stdarg.h>
367c478bd9Sstevel@tonic-gate #include <sys/resource.h>
377c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
387c478bd9Sstevel@tonic-gate #include <syslog.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
407c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
417c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
427c478bd9Sstevel@tonic-gate #include <net/if.h>
437c478bd9Sstevel@tonic-gate #include <netdir.h>
447c478bd9Sstevel@tonic-gate #include <string.h>
457c478bd9Sstevel@tonic-gate #include <thread.h>
467c478bd9Sstevel@tonic-gate #include <locale.h>
4739d3e169Sevanl #include <door.h>
48dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <limits.h>
497c478bd9Sstevel@tonic-gate #include "automount.h"
507c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
517c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
527c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
537c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h>
547c478bd9Sstevel@tonic-gate #include <deflt.h>
557c478bd9Sstevel@tonic-gate #include <strings.h>
5645916cd2Sjpk #include <priv.h>
5745916cd2Sjpk #include <tsol/label.h>
5839d3e169Sevanl #include <sys/utsname.h>
5939d3e169Sevanl #include <sys/thread.h>
6039d3e169Sevanl #include <nfs/rnode.h>
6139d3e169Sevanl #include <nfs/nfs.h>
628548bf79Snr #include <wait.h>
63dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h>
64dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h>
65dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h"
6639d3e169Sevanl 
6739d3e169Sevanl static void autofs_doorfunc(void *, char *, size_t, door_desc_t *, uint_t);
6839d3e169Sevanl static void autofs_setdoor(int);
693bfb48feSsemery static void autofs_mntinfo_1_r(autofs_lookupargs *, autofs_mountres *);
707c478bd9Sstevel@tonic-gate static void autofs_mount_1_free_r(struct autofs_mountres *);
713bfb48feSsemery static void autofs_lookup_1_r(autofs_lookupargs *, autofs_lookupres *);
7239d3e169Sevanl static void autofs_lookup_1_free_args(autofs_lookupargs *);
733bfb48feSsemery static void autofs_unmount_1_r(umntrequest *, umntres *);
7439d3e169Sevanl static void autofs_unmount_1_free_args(umntrequest *);
753bfb48feSsemery static void autofs_readdir_1_r(autofs_rddirargs *, autofs_rddirres *);
767c478bd9Sstevel@tonic-gate static void autofs_readdir_1_free_r(struct autofs_rddirres *);
7739d3e169Sevanl static int decode_args(xdrproc_t, autofs_door_args_t *, caddr_t *, int);
7839d3e169Sevanl static bool_t encode_res(xdrproc_t, autofs_door_res_t **, caddr_t, int *);
797c478bd9Sstevel@tonic-gate static void usage();
807c478bd9Sstevel@tonic-gate static void warn_hup(int);
817c478bd9Sstevel@tonic-gate static void free_action_list();
8239d3e169Sevanl static int start_autofs_svcs();
838548bf79Snr static void automountd_wait_for_cleanup(pid_t);
847c478bd9Sstevel@tonic-gate 
8539d3e169Sevanl /*
8639d3e169Sevanl  * Private autofs system call
8739d3e169Sevanl  */
8839d3e169Sevanl extern int _autofssys(int, void *);
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate #define	CTIME_BUF_LEN 26
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #define	RESOURCE_FACTOR 8
9339d3e169Sevanl #ifdef DEBUG
9439d3e169Sevanl #define	AUTOFS_DOOR	"/var/run/autofs_door"
9539d3e169Sevanl #endif /* DEBUG */
967c478bd9Sstevel@tonic-gate 
9739d3e169Sevanl static thread_key_t	s_thr_key;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate struct autodir *dir_head;
1007c478bd9Sstevel@tonic-gate struct autodir *dir_tail;
1017c478bd9Sstevel@tonic-gate char self[64];
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate time_t timenow;
1047c478bd9Sstevel@tonic-gate int verbose = 0;
1057c478bd9Sstevel@tonic-gate int trace = 0;
1067c478bd9Sstevel@tonic-gate int automountd_nobrowse = 0;
107*bfbf29e2SToomas Soome int did_fork_exec;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate int
main(argc,argv)1107c478bd9Sstevel@tonic-gate main(argc, argv)
1117c478bd9Sstevel@tonic-gate 	int argc;
1127c478bd9Sstevel@tonic-gate 	char *argv[];
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	pid_t pid;
11639d3e169Sevanl 	int c, error;
1177c478bd9Sstevel@tonic-gate 	struct rlimit rlset;
118dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	char defval[6];
119dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	int ret = 0, bufsz;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) {
1227c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
1237c478bd9Sstevel@tonic-gate 		exit(1);
1247c478bd9Sstevel@tonic-gate 	}
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	/*
127dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	 * Read in the values from SMF first before we check
1287c478bd9Sstevel@tonic-gate 	 * commandline options so the options override the file.
1297c478bd9Sstevel@tonic-gate 	 */
130dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 6;
131dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = autofs_smf_get_prop("automountd_verbose", defval,
132dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    DEFAULT_INSTANCE, SCF_TYPE_BOOLEAN, AUTOMOUNTD, &bufsz);
133dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
134dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		if (strncasecmp("true", defval, 4) == 0)
135dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			verbose = TRUE;
136dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		else
137dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			verbose = FALSE;
138dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	}
139dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 6;
140dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = autofs_smf_get_prop("nobrowse", defval, DEFAULT_INSTANCE,
141dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_BOOLEAN, AUTOMOUNTD, &bufsz);
142dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
143dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		if (strncasecmp("true", defval, 4) == 0)
144dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			automountd_nobrowse = TRUE;
145dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		else
146dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			automountd_nobrowse = FALSE;
147dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	}
148dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 6;
149dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = autofs_smf_get_prop("trace", defval, DEFAULT_INSTANCE,
150dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_INTEGER, AUTOMOUNTD, &bufsz);
151dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
152dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		errno = 0;
153dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		trace = strtol(defval, (char **)NULL, 10);
154dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 		if (errno != 0)
155dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 			trace = 0;
1567c478bd9Sstevel@tonic-gate 	}
157dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	put_automountd_env();
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "vnTD:")) != EOF) {
1607c478bd9Sstevel@tonic-gate 		switch (c) {
1617c478bd9Sstevel@tonic-gate 		case 'v':
1627c478bd9Sstevel@tonic-gate 			verbose++;
1637c478bd9Sstevel@tonic-gate 			break;
1647c478bd9Sstevel@tonic-gate 		case 'n':
1657c478bd9Sstevel@tonic-gate 			automountd_nobrowse++;
1667c478bd9Sstevel@tonic-gate 			break;
1677c478bd9Sstevel@tonic-gate 		case 'T':
1687c478bd9Sstevel@tonic-gate 			trace++;
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 		case 'D':
1717c478bd9Sstevel@tonic-gate 			(void) putenv(optarg);
1727c478bd9Sstevel@tonic-gate 			break;
1737c478bd9Sstevel@tonic-gate 		default:
1747c478bd9Sstevel@tonic-gate 			usage();
1757c478bd9Sstevel@tonic-gate 		}
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, self, sizeof (self)) == -1) {
1797c478bd9Sstevel@tonic-gate 		error = errno;
18039d3e169Sevanl 		(void) fprintf(stderr,
1817c478bd9Sstevel@tonic-gate 			"automountd: can't determine hostname, error: %d\n",
1827c478bd9Sstevel@tonic-gate 			error);
1837c478bd9Sstevel@tonic-gate 		exit(1);
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate #ifndef DEBUG
1877c478bd9Sstevel@tonic-gate 	pid = fork();
1887c478bd9Sstevel@tonic-gate 	if (pid < 0) {
1897c478bd9Sstevel@tonic-gate 		perror("cannot fork");
1907c478bd9Sstevel@tonic-gate 		exit(1);
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 	if (pid)
1937c478bd9Sstevel@tonic-gate 		exit(0);
1947c478bd9Sstevel@tonic-gate #endif
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	(void) setsid();
1977c478bd9Sstevel@tonic-gate 	openlog("automountd", LOG_PID, LOG_DAEMON);
1987c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1997c478bd9Sstevel@tonic-gate 
2008548bf79Snr 	/*
2018548bf79Snr 	 * Create the door_servers to manage fork/exec requests for
2028548bf79Snr 	 * mounts and executable automount maps
2038548bf79Snr 	 */
2048548bf79Snr 	if ((did_fork_exec = door_create(automountd_do_fork_exec,
2058509e9caSToomas Soome 	    NULL, 0)) == -1) {
2068548bf79Snr 		syslog(LOG_ERR, "door_create failed: %m, Exiting.");
2078548bf79Snr 		exit(errno);
2088548bf79Snr 	}
2098548bf79Snr 	if ((did_exec_map = door_create(automountd_do_exec_map,
2108509e9caSToomas Soome 	    NULL, 0)) == -1) {
2118548bf79Snr 		syslog(LOG_ERR, "door_create failed: %m, Exiting.");
2128548bf79Snr 		if (door_revoke(did_fork_exec) == -1) {
2138548bf79Snr 			syslog(LOG_ERR, "failed to door_revoke(%d) %m",
2148548bf79Snr 			    did_fork_exec);
2158548bf79Snr 		}
2168548bf79Snr 		exit(errno);
2178548bf79Snr 	}
2188548bf79Snr 	/*
2198548bf79Snr 	 * Before we become multithreaded we fork allowing the parent
2208548bf79Snr 	 * to become a door server to handle all mount and unmount
2218548bf79Snr 	 * requests. This works around a potential hang in using
2228548bf79Snr 	 * fork1() within a multithreaded environment
2238548bf79Snr 	 */
2248548bf79Snr 
2258548bf79Snr 	pid = fork1();
2268548bf79Snr 	if (pid < 0) {
2278548bf79Snr 		syslog(LOG_ERR,
2288548bf79Snr 			"can't fork the automountd mount process %m");
2298548bf79Snr 		if (door_revoke(did_fork_exec) == -1) {
2308548bf79Snr 			syslog(LOG_ERR, "failed to door_revoke(%d) %m",
2318548bf79Snr 				did_fork_exec);
2328548bf79Snr 		}
2338548bf79Snr 		if (door_revoke(did_exec_map) == -1) {
2348548bf79Snr 			syslog(LOG_ERR, "failed to door_revoke(%d) %m",
2358548bf79Snr 				did_exec_map);
2368548bf79Snr 		}
2378548bf79Snr 		exit(1);
2388548bf79Snr 	} else if (pid > 0) {
2398548bf79Snr 		/* this is the door server process */
2408548bf79Snr 		automountd_wait_for_cleanup(pid);
2418548bf79Snr 	}
2428548bf79Snr 
2438548bf79Snr 
2447c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&cache_lock, USYNC_THREAD, NULL);
24539d3e169Sevanl 	(void) rwlock_init(&autofs_rddir_cache_lock, USYNC_THREAD, NULL);
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	/*
2487c478bd9Sstevel@tonic-gate 	 * initialize the name services, use NULL arguments to ensure
2497c478bd9Sstevel@tonic-gate 	 * we don't initialize the stack of files used in file service
2507c478bd9Sstevel@tonic-gate 	 */
2517c478bd9Sstevel@tonic-gate 	(void) ns_setup(NULL, NULL);
2527c478bd9Sstevel@tonic-gate 
2538f379ff8Sevanl 	/*
2548f379ff8Sevanl 	 * we're using doors and its thread management now so we need to
2558f379ff8Sevanl 	 * make sure we have more than the default of 256 file descriptors
2568f379ff8Sevanl 	 * available.
2578f379ff8Sevanl 	 */
2588f379ff8Sevanl 	rlset.rlim_cur = RLIM_INFINITY;
2598f379ff8Sevanl 	rlset.rlim_max = RLIM_INFINITY;
2608f379ff8Sevanl 	if (setrlimit(RLIMIT_NOFILE, &rlset) == -1)
2618f379ff8Sevanl 		syslog(LOG_ERR, "setrlimit failed for %s: %s", AUTOMOUNTD,
2628f379ff8Sevanl 		    strerror(errno));
2638f379ff8Sevanl 
2648f379ff8Sevanl 	(void) enable_extended_FILE_stdio(-1, -1);
2658f379ff8Sevanl 
2667c478bd9Sstevel@tonic-gate 	/*
2677c478bd9Sstevel@tonic-gate 	 * establish our lock on the lock file and write our pid to it.
2687c478bd9Sstevel@tonic-gate 	 * exit if some other process holds the lock, or if there's any
2697c478bd9Sstevel@tonic-gate 	 * error in writing/locking the file.
2707c478bd9Sstevel@tonic-gate 	 */
2717c478bd9Sstevel@tonic-gate 	pid = _enter_daemon_lock(AUTOMOUNTD);
2727c478bd9Sstevel@tonic-gate 	switch (pid) {
2737c478bd9Sstevel@tonic-gate 	case 0:
2747c478bd9Sstevel@tonic-gate 		break;
2757c478bd9Sstevel@tonic-gate 	case -1:
2768548bf79Snr 		syslog(LOG_ERR, "error locking for %s: %m", AUTOMOUNTD);
2777c478bd9Sstevel@tonic-gate 		exit(2);
2787c478bd9Sstevel@tonic-gate 	default:
2797c478bd9Sstevel@tonic-gate 		/* daemon was already running */
2807c478bd9Sstevel@tonic-gate 		exit(0);
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	/*
2847c478bd9Sstevel@tonic-gate 	 * If we coredump it'll be /core.
2857c478bd9Sstevel@tonic-gate 	 */
2867c478bd9Sstevel@tonic-gate 	if (chdir("/") < 0)
2877c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "chdir /: %m");
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/*
2907c478bd9Sstevel@tonic-gate 	 * Create cache_cleanup thread
2917c478bd9Sstevel@tonic-gate 	 */
2927c478bd9Sstevel@tonic-gate 	if (thr_create(NULL, 0, (void *(*)(void *))cache_cleanup, NULL,
2937c478bd9Sstevel@tonic-gate 			THR_DETACHED | THR_DAEMON | THR_NEW_LWP, NULL)) {
2947c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "unable to create cache_cleanup thread");
2957c478bd9Sstevel@tonic-gate 		exit(1);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	/* other initializations */
2997c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&portmap_cache_lock, USYNC_THREAD, NULL);
3007c478bd9Sstevel@tonic-gate 
30192373f0aSrica 	/*
30292373f0aSrica 	 * On a labeled system, allow read-down nfs mounts if privileged
30392373f0aSrica 	 * (PRIV_NET_MAC_AWARE) to do so.  Otherwise, ignore the error
30492373f0aSrica 	 * and "mount equal label only" behavior will result.
30592373f0aSrica 	 */
30645916cd2Sjpk 	if (is_system_labeled()) {
30792373f0aSrica 		(void) setpflags(NET_MAC_AWARE, 1);
30892373f0aSrica 		(void) setpflags(NET_MAC_AWARE_INHERIT, 1);
30945916cd2Sjpk 	}
31045916cd2Sjpk 
3117c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, warn_hup);
3127c478bd9Sstevel@tonic-gate 
31339d3e169Sevanl 	/* start services */
31439d3e169Sevanl 	return (start_autofs_svcs());
31539d3e169Sevanl 
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate /*
3197c478bd9Sstevel@tonic-gate  * The old automounter supported a SIGHUP
3207c478bd9Sstevel@tonic-gate  * to allow it to resynchronize internal
3217c478bd9Sstevel@tonic-gate  * state with the /etc/mnttab.
3227c478bd9Sstevel@tonic-gate  * This is no longer relevant, but we
3237c478bd9Sstevel@tonic-gate  * need to catch the signal and warn
3247c478bd9Sstevel@tonic-gate  * the user.
3257c478bd9Sstevel@tonic-gate  */
3267c478bd9Sstevel@tonic-gate /* ARGSUSED */
3277c478bd9Sstevel@tonic-gate static void
warn_hup(i)3287c478bd9Sstevel@tonic-gate warn_hup(i)
3297c478bd9Sstevel@tonic-gate 	int i;
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, "SIGHUP received: ignored");
3327c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, warn_hup);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate static void
usage()3367c478bd9Sstevel@tonic-gate usage()
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage: automountd\n"
339ace1a5f1Sdp 	    "\t[-T]\t\t(trace requests)\n"
340ace1a5f1Sdp 	    "\t[-v]\t\t(verbose error msgs)\n"
341ace1a5f1Sdp 	    "\t[-D n=s]\t(define env variable)\n");
3427c478bd9Sstevel@tonic-gate 	exit(1);
3437c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate static void
autofs_readdir_1_r(autofs_rddirargs * req,autofs_rddirres * res)34739d3e169Sevanl autofs_readdir_1_r(
34839d3e169Sevanl 	autofs_rddirargs *req,
3493bfb48feSsemery 	autofs_rddirres *res)
3507c478bd9Sstevel@tonic-gate {
3517c478bd9Sstevel@tonic-gate 	if (trace > 0)
3527c478bd9Sstevel@tonic-gate 		trace_prt(1, "READDIR REQUEST	: %s @ %ld\n",
353d6c8399bSrmesta 		    req->rda_map, req->rda_offset);
3547c478bd9Sstevel@tonic-gate 
3553bfb48feSsemery 	do_readdir(req, res);
3567c478bd9Sstevel@tonic-gate 	if (trace > 0)
357d6c8399bSrmesta 		trace_prt(1, "READDIR REPLY	: status=%d\n", res->rd_status);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate static void
autofs_readdir_1_free_r(struct autofs_rddirres * res)36139d3e169Sevanl autofs_readdir_1_free_r(struct autofs_rddirres *res)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate 	if (res->rd_status == AUTOFS_OK) {
3647c478bd9Sstevel@tonic-gate 		if (res->rd_rddir.rddir_entries)
3657c478bd9Sstevel@tonic-gate 			free(res->rd_rddir.rddir_entries);
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate 
36939d3e169Sevanl 
3707c478bd9Sstevel@tonic-gate /* ARGSUSED */
3717c478bd9Sstevel@tonic-gate static void
autofs_unmount_1_r(umntrequest * m,umntres * res)37239d3e169Sevanl autofs_unmount_1_r(
37339d3e169Sevanl 	umntrequest *m,
3743bfb48feSsemery 	umntres *res)
3757c478bd9Sstevel@tonic-gate {
3767c478bd9Sstevel@tonic-gate 	struct umntrequest *ul;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	if (trace > 0) {
3797c478bd9Sstevel@tonic-gate 		char ctime_buf[CTIME_BUF_LEN];
3807c478bd9Sstevel@tonic-gate 		if (ctime_r(&timenow, ctime_buf, CTIME_BUF_LEN) == NULL)
381d6c8399bSrmesta 			ctime_buf[0] = '\0';
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 		trace_prt(1, "UNMOUNT REQUEST: %s", ctime_buf);
3847c478bd9Sstevel@tonic-gate 		for (ul = m; ul; ul = ul->next)
3857c478bd9Sstevel@tonic-gate 			trace_prt(1, " resource=%s fstype=%s mntpnt=%s"
386d6c8399bSrmesta 			    " mntopts=%s %s\n",
387d6c8399bSrmesta 			    ul->mntresource,
388d6c8399bSrmesta 			    ul->fstype,
389d6c8399bSrmesta 			    ul->mntpnt,
390d6c8399bSrmesta 			    ul->mntopts,
391d6c8399bSrmesta 			    ul->isdirect ? "direct" : "indirect");
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 
39439d3e169Sevanl 
3957c478bd9Sstevel@tonic-gate 	res->status = do_unmount1(m);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if (trace > 0)
3987c478bd9Sstevel@tonic-gate 		trace_prt(1, "UNMOUNT REPLY: status=%d\n", res->status);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate static void
autofs_lookup_1_r(autofs_lookupargs * m,autofs_lookupres * res)40239d3e169Sevanl autofs_lookup_1_r(
40339d3e169Sevanl 	autofs_lookupargs *m,
4043bfb48feSsemery 	autofs_lookupres *res)
4057c478bd9Sstevel@tonic-gate {
40639d3e169Sevanl 	autofs_action_t action;
40739d3e169Sevanl 	struct	linka link;
4087c478bd9Sstevel@tonic-gate 	int status;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	if (trace > 0) {
4117c478bd9Sstevel@tonic-gate 		char ctime_buf[CTIME_BUF_LEN];
4127c478bd9Sstevel@tonic-gate 		if (ctime_r(&timenow, ctime_buf, CTIME_BUF_LEN) == NULL)
4137c478bd9Sstevel@tonic-gate 			ctime_buf[0] = '\0';
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 		trace_prt(1, "LOOKUP REQUEST: %s", ctime_buf);
4167c478bd9Sstevel@tonic-gate 		trace_prt(1, "  name=%s[%s] map=%s opts=%s path=%s direct=%d\n",
417d6c8399bSrmesta 		    m->name, m->subdir, m->map, m->opts, m->path, m->isdirect);
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 
42039d3e169Sevanl 	bzero(&link, sizeof (struct linka));
42139d3e169Sevanl 
4227c478bd9Sstevel@tonic-gate 	status = do_lookup1(m->map, m->name, m->subdir, m->opts, m->path,
423d6c8399bSrmesta 	    (uint_t)m->isdirect, m->uid, &action, &link);
4247c478bd9Sstevel@tonic-gate 	if (status == 0) {
4257c478bd9Sstevel@tonic-gate 		/*
4267c478bd9Sstevel@tonic-gate 		 * Return action list to kernel.
4277c478bd9Sstevel@tonic-gate 		 */
4287c478bd9Sstevel@tonic-gate 		res->lu_res = AUTOFS_OK;
42939d3e169Sevanl 		if ((res->lu_type.action = action) == AUTOFS_LINK_RQ) {
4307c478bd9Sstevel@tonic-gate 			res->lu_type.lookup_result_type_u.lt_linka = link;
43139d3e169Sevanl 		}
4327c478bd9Sstevel@tonic-gate 	} else {
4337c478bd9Sstevel@tonic-gate 		/*
4347c478bd9Sstevel@tonic-gate 		 * Entry not found
4357c478bd9Sstevel@tonic-gate 		 */
4367c478bd9Sstevel@tonic-gate 		res->lu_res = AUTOFS_NOENT;
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 	res->lu_verbose = verbose;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if (trace > 0)
4417c478bd9Sstevel@tonic-gate 		trace_prt(1, "LOOKUP REPLY    : status=%d\n", res->lu_res);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate static void
autofs_mntinfo_1_r(autofs_lookupargs * m,autofs_mountres * res)44539d3e169Sevanl autofs_mntinfo_1_r(
44639d3e169Sevanl 	autofs_lookupargs *m,
4473bfb48feSsemery 	autofs_mountres *res)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 	int status;
45039d3e169Sevanl 	action_list		*alp = NULL;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (trace > 0) {
4537c478bd9Sstevel@tonic-gate 		char ctime_buf[CTIME_BUF_LEN];
4547c478bd9Sstevel@tonic-gate 		if (ctime_r(&timenow, ctime_buf, CTIME_BUF_LEN) == NULL)
4557c478bd9Sstevel@tonic-gate 			ctime_buf[0] = '\0';
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		trace_prt(1, "MOUNT REQUEST:   %s", ctime_buf);
4587c478bd9Sstevel@tonic-gate 		trace_prt(1, "  name=%s[%s] map=%s opts=%s path=%s direct=%d\n",
459d6c8399bSrmesta 		    m->name, m->subdir, m->map, m->opts, m->path, m->isdirect);
4607c478bd9Sstevel@tonic-gate 	}
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	status = do_mount1(m->map, m->name, m->subdir, m->opts, m->path,
463d6c8399bSrmesta 	    (uint_t)m->isdirect, m->uid, &alp, DOMOUNT_USER);
4647c478bd9Sstevel@tonic-gate 	if (status != 0) {
4657c478bd9Sstevel@tonic-gate 		/*
4667c478bd9Sstevel@tonic-gate 		 * An error occurred, free action list if allocated.
4677c478bd9Sstevel@tonic-gate 		 */
4687c478bd9Sstevel@tonic-gate 		if (alp != NULL) {
4697c478bd9Sstevel@tonic-gate 			free_action_list(alp);
4707c478bd9Sstevel@tonic-gate 			alp = NULL;
4717c478bd9Sstevel@tonic-gate 		}
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate 	if (alp != NULL) {
4745e1e04ceSdm 		/*
4755e1e04ceSdm 		 * Return action list to kernel.
4765e1e04ceSdm 		 */
4777c478bd9Sstevel@tonic-gate 		res->mr_type.status = AUTOFS_ACTION;
4787c478bd9Sstevel@tonic-gate 		res->mr_type.mount_result_type_u.list = alp;
4797c478bd9Sstevel@tonic-gate 	} else {
4807c478bd9Sstevel@tonic-gate 		/*
4817c478bd9Sstevel@tonic-gate 		 * No work to do left for the kernel
4827c478bd9Sstevel@tonic-gate 		 */
4837c478bd9Sstevel@tonic-gate 		res->mr_type.status = AUTOFS_DONE;
4847c478bd9Sstevel@tonic-gate 		res->mr_type.mount_result_type_u.error = status;
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if (trace > 0) {
4887c478bd9Sstevel@tonic-gate 		switch (res->mr_type.status) {
4897c478bd9Sstevel@tonic-gate 		case AUTOFS_ACTION:
4907c478bd9Sstevel@tonic-gate 			trace_prt(1,
491d6c8399bSrmesta 			    "MOUNT REPLY    : status=%d, AUTOFS_ACTION\n",
492d6c8399bSrmesta 			    status);
4937c478bd9Sstevel@tonic-gate 			break;
4947c478bd9Sstevel@tonic-gate 		case AUTOFS_DONE:
4957c478bd9Sstevel@tonic-gate 			trace_prt(1,
496d6c8399bSrmesta 			    "MOUNT REPLY    : status=%d, AUTOFS_DONE\n",
497d6c8399bSrmesta 			    status);
4987c478bd9Sstevel@tonic-gate 			break;
4997c478bd9Sstevel@tonic-gate 		default:
5007c478bd9Sstevel@tonic-gate 			trace_prt(1, "MOUNT REPLY    : status=%d, UNKNOWN\n",
501d6c8399bSrmesta 			    status);
5027c478bd9Sstevel@tonic-gate 		}
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	if (status && verbose) {
5067c478bd9Sstevel@tonic-gate 		if (m->isdirect) {
5077c478bd9Sstevel@tonic-gate 			/* direct mount */
5087c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "mount of %s failed", m->path);
5097c478bd9Sstevel@tonic-gate 		} else {
5107c478bd9Sstevel@tonic-gate 			/* indirect mount */
5117c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
512d6c8399bSrmesta 			    "mount of %s/%s failed", m->path, m->name);
5137c478bd9Sstevel@tonic-gate 		}
5147c478bd9Sstevel@tonic-gate 	}
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate static void
autofs_mount_1_free_r(struct autofs_mountres * res)51839d3e169Sevanl autofs_mount_1_free_r(struct autofs_mountres *res)
5197c478bd9Sstevel@tonic-gate {
5207c478bd9Sstevel@tonic-gate 	if (res->mr_type.status == AUTOFS_ACTION) {
5217c478bd9Sstevel@tonic-gate 		if (trace > 2)
5227c478bd9Sstevel@tonic-gate 			trace_prt(1, "freeing action list\n");
5237c478bd9Sstevel@tonic-gate 		free_action_list(res->mr_type.mount_result_type_u.list);
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate /*
528ace1a5f1Sdp  * Used for reporting messages from code shared with automount command.
529ace1a5f1Sdp  * Formats message into a buffer and calls syslog.
5307c478bd9Sstevel@tonic-gate  *
531ace1a5f1Sdp  * Print an error.  Works like printf (fmt string and variable args)
532ace1a5f1Sdp  * except that it will subsititute an error message for a "%m" string
533ace1a5f1Sdp  * (like syslog).
5347c478bd9Sstevel@tonic-gate  */
5357c478bd9Sstevel@tonic-gate void
pr_msg(const char * fmt,...)5367c478bd9Sstevel@tonic-gate pr_msg(const char *fmt, ...)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	va_list ap;
5397c478bd9Sstevel@tonic-gate 	char fmtbuff[BUFSIZ], buff[BUFSIZ];
5407c478bd9Sstevel@tonic-gate 	const char *p1;
5417c478bd9Sstevel@tonic-gate 	char *p2;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	p2 = fmtbuff;
5447c478bd9Sstevel@tonic-gate 	fmt = gettext(fmt);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	for (p1 = fmt; *p1; p1++) {
547ace1a5f1Sdp 		if (*p1 == '%' && *(p1 + 1) == 'm') {
548ace1a5f1Sdp 			(void) strcpy(p2, strerror(errno));
549ace1a5f1Sdp 			p2 += strlen(p2);
5507c478bd9Sstevel@tonic-gate 			p1++;
5517c478bd9Sstevel@tonic-gate 		} else {
5527c478bd9Sstevel@tonic-gate 			*p2++ = *p1;
5537c478bd9Sstevel@tonic-gate 		}
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 	if (p2 > fmtbuff && *(p2-1) != '\n')
5567c478bd9Sstevel@tonic-gate 		*p2++ = '\n';
5577c478bd9Sstevel@tonic-gate 	*p2 = '\0';
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
5607c478bd9Sstevel@tonic-gate 	(void) vsprintf(buff, fmtbuff, ap);
5617c478bd9Sstevel@tonic-gate 	va_end(ap);
5627c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, buff);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate static void
free_action_list(action_list * alp)5667c478bd9Sstevel@tonic-gate free_action_list(action_list *alp)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	action_list *p, *next = NULL;
5697c478bd9Sstevel@tonic-gate 	struct mounta *mp;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	for (p = alp; p != NULL; p = next) {
5727c478bd9Sstevel@tonic-gate 		switch (p->action.action) {
5737c478bd9Sstevel@tonic-gate 		case AUTOFS_MOUNT_RQ:
5747c478bd9Sstevel@tonic-gate 			mp = &(p->action.action_list_entry_u.mounta);
5757c478bd9Sstevel@tonic-gate 			/* LINTED pointer alignment */
57639d3e169Sevanl 			if (mp->fstype) {
57739d3e169Sevanl 				if (strcmp(mp->fstype, "autofs") == 0) {
57839d3e169Sevanl 					free_autofs_args((autofs_args *)
579d6c8399bSrmesta 					    mp->dataptr);
580d6c8399bSrmesta 				} else if (strncmp(mp->fstype, "nfs", 3) == 0) {
58139d3e169Sevanl 					free_nfs_args((struct nfs_args *)
582d6c8399bSrmesta 					    mp->dataptr);
58339d3e169Sevanl 				}
58439d3e169Sevanl 			}
5857c478bd9Sstevel@tonic-gate 			mp->dataptr = NULL;
5867c478bd9Sstevel@tonic-gate 			mp->datalen = 0;
5877c478bd9Sstevel@tonic-gate 			free_mounta(mp);
5887c478bd9Sstevel@tonic-gate 			break;
5897c478bd9Sstevel@tonic-gate 		case AUTOFS_LINK_RQ:
5907c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
5917c478bd9Sstevel@tonic-gate 			    "non AUTOFS_MOUNT_RQ requests not implemented\n");
5927c478bd9Sstevel@tonic-gate 			break;
5937c478bd9Sstevel@tonic-gate 		default:
5947c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
5957c478bd9Sstevel@tonic-gate 			    "non AUTOFS_MOUNT_RQ requests not implemented\n");
5967c478bd9Sstevel@tonic-gate 			break;
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 		next = p->next;
5997c478bd9Sstevel@tonic-gate 		free(p);
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate }
60239d3e169Sevanl 
60339d3e169Sevanl static void
autofs_lookup_1_free_args(autofs_lookupargs * args)60439d3e169Sevanl autofs_lookup_1_free_args(autofs_lookupargs *args)
60539d3e169Sevanl {
60639d3e169Sevanl 	if (args->map)
60739d3e169Sevanl 		free(args->map);
60839d3e169Sevanl 	if (args->path)
60939d3e169Sevanl 		free(args->path);
61039d3e169Sevanl 	if (args->name)
61139d3e169Sevanl 		free(args->name);
61239d3e169Sevanl 	if (args->subdir)
61339d3e169Sevanl 		free(args->subdir);
61439d3e169Sevanl 	if (args->opts)
61539d3e169Sevanl 		free(args->opts);
61639d3e169Sevanl }
61739d3e169Sevanl 
61839d3e169Sevanl static void
autofs_unmount_1_free_args(umntrequest * args)61939d3e169Sevanl autofs_unmount_1_free_args(umntrequest *args)
62039d3e169Sevanl {
62139d3e169Sevanl 	if (args->mntresource)
62239d3e169Sevanl 		free(args->mntresource);
62339d3e169Sevanl 	if (args->mntpnt)
62439d3e169Sevanl 		free(args->mntpnt);
62539d3e169Sevanl 	if (args->fstype)
62639d3e169Sevanl 		free(args->fstype);
62739d3e169Sevanl 	if (args->mntopts)
62839d3e169Sevanl 		free(args->mntopts);
62939d3e169Sevanl 	if (args->next)
63039d3e169Sevanl 		autofs_unmount_1_free_args(args->next);
63139d3e169Sevanl }
63239d3e169Sevanl 
63339d3e169Sevanl static void
autofs_setdoor(int did)63439d3e169Sevanl autofs_setdoor(int did)
63539d3e169Sevanl {
63639d3e169Sevanl 
63739d3e169Sevanl 	if (did < 0) {
63839d3e169Sevanl 		did = 0;
63939d3e169Sevanl 	}
64039d3e169Sevanl 
64139d3e169Sevanl 	(void) _autofssys(AUTOFS_SETDOOR, &did);
64239d3e169Sevanl }
64339d3e169Sevanl 
64439d3e169Sevanl void *
autofs_get_buffer(size_t size)64539d3e169Sevanl autofs_get_buffer(size_t size)
64639d3e169Sevanl {
64739d3e169Sevanl 	autofs_tsd_t *tsd = NULL;
64839d3e169Sevanl 
64939d3e169Sevanl 	/*
65039d3e169Sevanl 	 * Make sure the buffer size is aligned
65139d3e169Sevanl 	 */
65239d3e169Sevanl 	(void) thr_getspecific(s_thr_key, (void **)&tsd);
65339d3e169Sevanl 	if (tsd == NULL) {
65439d3e169Sevanl 		tsd = (autofs_tsd_t *)malloc(sizeof (autofs_tsd_t));
65539d3e169Sevanl 		if (tsd == NULL) {
65639d3e169Sevanl 			return (NULL);
65739d3e169Sevanl 		}
65839d3e169Sevanl 		tsd->atsd_buf = malloc(size);
65939d3e169Sevanl 		if (tsd->atsd_buf != NULL)
66039d3e169Sevanl 			tsd->atsd_len = size;
66139d3e169Sevanl 		else
66239d3e169Sevanl 			tsd->atsd_len = 0;
66339d3e169Sevanl 		(void) thr_setspecific(s_thr_key, tsd);
66439d3e169Sevanl 	} else {
66539d3e169Sevanl 		if (tsd->atsd_buf && (tsd->atsd_len < size)) {
66639d3e169Sevanl 			free(tsd->atsd_buf);
66739d3e169Sevanl 			tsd->atsd_buf = malloc(size);
66839d3e169Sevanl 			if (tsd->atsd_buf != NULL)
66939d3e169Sevanl 				tsd->atsd_len = size;
67039d3e169Sevanl 			else {
67139d3e169Sevanl 				tsd->atsd_len = 0;
67239d3e169Sevanl 			}
67339d3e169Sevanl 		}
67439d3e169Sevanl 	}
67539d3e169Sevanl 	if (tsd->atsd_buf) {
67639d3e169Sevanl 		bzero(tsd->atsd_buf, size);
67739d3e169Sevanl 		return (tsd->atsd_buf);
67839d3e169Sevanl 	} else {
679d6c8399bSrmesta 		syslog(LOG_ERR,
680d6c8399bSrmesta 		    gettext("Can't Allocate tsd buffer, size %d"), size);
68139d3e169Sevanl 		return (NULL);
68239d3e169Sevanl 	}
68339d3e169Sevanl }
68439d3e169Sevanl 
68539d3e169Sevanl /*
68639d3e169Sevanl  * Each request will automatically spawn a new thread with this
68739d3e169Sevanl  * as its entry point.
68839d3e169Sevanl  */
68939d3e169Sevanl /* ARGUSED */
69039d3e169Sevanl static void
autofs_doorfunc(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)69139d3e169Sevanl autofs_doorfunc(
69239d3e169Sevanl 	void *cookie,
69339d3e169Sevanl 	char *argp,
69439d3e169Sevanl 	size_t arg_size,
69539d3e169Sevanl 	door_desc_t *dp,
69639d3e169Sevanl 	uint_t n_desc)
69739d3e169Sevanl {
69839d3e169Sevanl 	char			*res;
699d6c8399bSrmesta 	int			 res_size;
700d6c8399bSrmesta 	int			 which;
701d6c8399bSrmesta 	int			 error = 0;
702d6c8399bSrmesta 	int			 srsz = 0;
70339d3e169Sevanl 	autofs_lookupargs	*xdrargs;
704d6c8399bSrmesta 	autofs_lookupres	 lookup_res;
70539d3e169Sevanl 	autofs_rddirargs	*rddir_args;
706d6c8399bSrmesta 	autofs_rddirres		 rddir_res;
707d6c8399bSrmesta 	autofs_mountres		 mount_res;
70839d3e169Sevanl 	umntrequest		*umnt_args;
709d6c8399bSrmesta 	umntres			 umount_res;
71039d3e169Sevanl 	autofs_door_res_t	*door_res;
711d6c8399bSrmesta 	autofs_door_res_t	 failed_res;
71239d3e169Sevanl 
71339d3e169Sevanl 	if (arg_size < sizeof (autofs_door_args_t)) {
71439d3e169Sevanl 		failed_res.res_status = EINVAL;
71539d3e169Sevanl 		error = door_return((char *)&failed_res,
71639d3e169Sevanl 		    sizeof (autofs_door_res_t), NULL, 0);
71739d3e169Sevanl 		/*
71839d3e169Sevanl 		 * If we got here the door_return() failed.
71939d3e169Sevanl 		 */
720d6c8399bSrmesta 		syslog(LOG_ERR, "Bad argument, door_return failure %d", error);
72139d3e169Sevanl 		return;
72239d3e169Sevanl 	}
72339d3e169Sevanl 
72439d3e169Sevanl 	timenow = time((time_t *)NULL);
72539d3e169Sevanl 
72639d3e169Sevanl 	which = ((autofs_door_args_t *)argp)->cmd;
72739d3e169Sevanl 	switch (which) {
72839d3e169Sevanl 	case AUTOFS_LOOKUP:
72939d3e169Sevanl 		if (error = decode_args(xdr_autofs_lookupargs,
730d6c8399bSrmesta 		    (autofs_door_args_t *)argp, (caddr_t *)&xdrargs,
731d6c8399bSrmesta 		    sizeof (autofs_lookupargs))) {
732d6c8399bSrmesta 			syslog(LOG_ERR,
733d6c8399bSrmesta 			    "error allocating lookup arguments buffer");
73439d3e169Sevanl 			failed_res.res_status = error;
73539d3e169Sevanl 			failed_res.xdr_len = 0;
73639d3e169Sevanl 			res = (caddr_t)&failed_res;
7375e1e04ceSdm 			res_size = 0;
73839d3e169Sevanl 			break;
73939d3e169Sevanl 		}
74039d3e169Sevanl 		bzero(&lookup_res, sizeof (autofs_lookupres));
74139d3e169Sevanl 
7423bfb48feSsemery 		autofs_lookup_1_r(xdrargs, &lookup_res);
74339d3e169Sevanl 
74439d3e169Sevanl 		autofs_lookup_1_free_args(xdrargs);
74539d3e169Sevanl 		free(xdrargs);
7465e1e04ceSdm 
74739d3e169Sevanl 		if (!encode_res(xdr_autofs_lookupres, &door_res,
748d6c8399bSrmesta 		    (caddr_t)&lookup_res, &res_size)) {
749d6c8399bSrmesta 			syslog(LOG_ERR,
750d6c8399bSrmesta 			    "error allocating lookup results buffer");
7515e1e04ceSdm 			failed_res.res_status = EINVAL;
7525e1e04ceSdm 			failed_res.xdr_len = 0;
7535e1e04ceSdm 			res = (caddr_t)&failed_res;
75439d3e169Sevanl 		} else {
75539d3e169Sevanl 			door_res->res_status = 0;
75639d3e169Sevanl 			res = (caddr_t)door_res;
75739d3e169Sevanl 		}
75839d3e169Sevanl 		break;
75939d3e169Sevanl 
76039d3e169Sevanl 	case AUTOFS_MNTINFO:
76139d3e169Sevanl 		if (error = decode_args(xdr_autofs_lookupargs,
762d6c8399bSrmesta 		    (autofs_door_args_t *)argp, (caddr_t *)&xdrargs,
763d6c8399bSrmesta 		    sizeof (autofs_lookupargs))) {
764d6c8399bSrmesta 			syslog(LOG_ERR,
765d6c8399bSrmesta 			    "error allocating lookup arguments buffer");
76639d3e169Sevanl 			failed_res.res_status = error;
76739d3e169Sevanl 			failed_res.xdr_len = 0;
76839d3e169Sevanl 			res = (caddr_t)&failed_res;
7695e1e04ceSdm 			res_size = 0;
77039d3e169Sevanl 			break;
77139d3e169Sevanl 		}
77239d3e169Sevanl 
7735e1e04ceSdm 		autofs_mntinfo_1_r((autofs_lookupargs *)xdrargs, &mount_res);
77439d3e169Sevanl 
77539d3e169Sevanl 		autofs_lookup_1_free_args(xdrargs);
77639d3e169Sevanl 		free(xdrargs);
77739d3e169Sevanl 
77839d3e169Sevanl 		/*
77939d3e169Sevanl 		 * Only reason we would get a NULL res is because
78039d3e169Sevanl 		 * we could not allocate a results buffer.  Use
7815e1e04ceSdm 		 * a local one to return the error EAGAIN as has
7825e1e04ceSdm 		 * always been done when memory allocations fail.
78339d3e169Sevanl 		 */
78439d3e169Sevanl 		if (!encode_res(xdr_autofs_mountres, &door_res,
785d6c8399bSrmesta 		    (caddr_t)&mount_res, &res_size)) {
786d6c8399bSrmesta 			syslog(LOG_ERR,
787d6c8399bSrmesta 			    "error allocating mount results buffer");
7885e1e04ceSdm 			failed_res.res_status = EAGAIN;
7895e1e04ceSdm 			failed_res.xdr_len = 0;
7905e1e04ceSdm 			res = (caddr_t)&failed_res;
79139d3e169Sevanl 		} else {
79239d3e169Sevanl 			door_res->res_status = 0;
79339d3e169Sevanl 			res = (caddr_t)door_res;
79439d3e169Sevanl 		}
79539d3e169Sevanl 		autofs_mount_1_free_r(&mount_res);
79639d3e169Sevanl 		break;
79739d3e169Sevanl 
79839d3e169Sevanl 	case AUTOFS_UNMOUNT:
79939d3e169Sevanl 		if (error = decode_args(xdr_umntrequest,
800d6c8399bSrmesta 		    (autofs_door_args_t *)argp,
801d6c8399bSrmesta 		    (caddr_t *)&umnt_args, sizeof (umntrequest))) {
802d6c8399bSrmesta 			syslog(LOG_ERR,
803d6c8399bSrmesta 			    "error allocating unmount argument buffer");
80439d3e169Sevanl 			failed_res.res_status = error;
80539d3e169Sevanl 			failed_res.xdr_len = 0;
80639d3e169Sevanl 			res = (caddr_t)&failed_res;
80739d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
80839d3e169Sevanl 			break;
80939d3e169Sevanl 		}
81039d3e169Sevanl 
8113bfb48feSsemery 		autofs_unmount_1_r(umnt_args, &umount_res);
81239d3e169Sevanl 
81339d3e169Sevanl 		error = umount_res.status;
81439d3e169Sevanl 
81539d3e169Sevanl 		autofs_unmount_1_free_args(umnt_args);
81639d3e169Sevanl 		free(umnt_args);
8175e1e04ceSdm 
81839d3e169Sevanl 		if (!encode_res(xdr_umntres, &door_res, (caddr_t)&umount_res,
819d6c8399bSrmesta 		    &res_size)) {
820d6c8399bSrmesta 			syslog(LOG_ERR,
821d6c8399bSrmesta 			    "error allocating unmount results buffer");
8225e1e04ceSdm 			failed_res.res_status = EINVAL;
8235e1e04ceSdm 			failed_res.xdr_len = 0;
8245e1e04ceSdm 			res = (caddr_t)&failed_res;
82539d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
82639d3e169Sevanl 		} else {
82739d3e169Sevanl 			door_res->res_status = 0;
82839d3e169Sevanl 			res = (caddr_t)door_res;
82939d3e169Sevanl 		}
83039d3e169Sevanl 		break;
83139d3e169Sevanl 
83239d3e169Sevanl 	case AUTOFS_READDIR:
83339d3e169Sevanl 		if (error = decode_args(xdr_autofs_rddirargs,
834d6c8399bSrmesta 		    (autofs_door_args_t *)argp,
835d6c8399bSrmesta 		    (caddr_t *)&rddir_args,
836d6c8399bSrmesta 		    sizeof (autofs_rddirargs))) {
83739d3e169Sevanl 			syslog(LOG_ERR,
838d6c8399bSrmesta 			    "error allocating readdir argument buffer");
83939d3e169Sevanl 			failed_res.res_status = error;
84039d3e169Sevanl 			failed_res.xdr_len = 0;
84139d3e169Sevanl 			res = (caddr_t)&failed_res;
84239d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
84339d3e169Sevanl 			break;
84439d3e169Sevanl 		}
84539d3e169Sevanl 
8463bfb48feSsemery 		autofs_readdir_1_r(rddir_args, &rddir_res);
84739d3e169Sevanl 
84839d3e169Sevanl 		free(rddir_args->rda_map);
84939d3e169Sevanl 		free(rddir_args);
8505e1e04ceSdm 
85139d3e169Sevanl 		if (!encode_res(xdr_autofs_rddirres, &door_res,
85239d3e169Sevanl 		    (caddr_t)&rddir_res, &res_size)) {
853d6c8399bSrmesta 			syslog(LOG_ERR,
854d6c8399bSrmesta 			    "error allocating readdir results buffer");
8555e1e04ceSdm 			failed_res.res_status = ENOMEM;
8565e1e04ceSdm 			failed_res.xdr_len = 0;
8575e1e04ceSdm 			res = (caddr_t)&failed_res;
85839d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
85939d3e169Sevanl 		} else {
86039d3e169Sevanl 			door_res->res_status = 0;
86139d3e169Sevanl 			res = (caddr_t)door_res;
86239d3e169Sevanl 		}
86339d3e169Sevanl 		autofs_readdir_1_free_r(&rddir_res);
86439d3e169Sevanl 		break;
86539d3e169Sevanl #ifdef MALLOC_DEBUG
86639d3e169Sevanl 	case AUTOFS_DUMP_DEBUG:
86739d3e169Sevanl 			check_leaks("/var/tmp/automountd.leak");
86839d3e169Sevanl 			error = door_return(NULL, 0, NULL, 0);
86939d3e169Sevanl 			/*
87039d3e169Sevanl 			 * If we got here, door_return() failed
87139d3e169Sevanl 			 */
87239d3e169Sevanl 			syslog(LOG_ERR, "dump debug door_return failure %d",
873d6c8399bSrmesta 			    error);
87439d3e169Sevanl 			return;
87539d3e169Sevanl #endif
87639d3e169Sevanl 	case NULLPROC:
87739d3e169Sevanl 			res = NULL;
87839d3e169Sevanl 			res_size = 0;
87939d3e169Sevanl 			break;
88039d3e169Sevanl 	default:
88139d3e169Sevanl 			failed_res.res_status = EINVAL;
88239d3e169Sevanl 			res = (char *)&failed_res;
88339d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
88439d3e169Sevanl 			break;
88539d3e169Sevanl 	}
886d6c8399bSrmesta 
887d6c8399bSrmesta 	srsz = res_size;
888d6c8399bSrmesta 	errno = 0;
88939d3e169Sevanl 	error = door_return(res, res_size, NULL, 0);
890d6c8399bSrmesta 
891d6c8399bSrmesta 	if (errno == E2BIG) {
892d6c8399bSrmesta 		/*
893d6c8399bSrmesta 		 * Failed due to encoded results being bigger than the
894d6c8399bSrmesta 		 * kernel expected bufsize. Passing actual results size
895d6c8399bSrmesta 		 * back down to kernel.
896d6c8399bSrmesta 		 */
897d6c8399bSrmesta 		failed_res.res_status = EOVERFLOW;
898d6c8399bSrmesta 		failed_res.xdr_len = srsz;
899d6c8399bSrmesta 		res = (caddr_t)&failed_res;
900d6c8399bSrmesta 		res_size = sizeof (autofs_door_res_t);
901d6c8399bSrmesta 	} else {
902d6c8399bSrmesta 		syslog(LOG_ERR, "door_return failed %d, buffer %p, "
903d6c8399bSrmesta 		    "buffer size %d", error, (void *)res, res_size);
904d6c8399bSrmesta 		res = NULL;
905d6c8399bSrmesta 		res_size = 0;
906d6c8399bSrmesta 	}
907d6c8399bSrmesta 	(void) door_return(res, res_size, NULL, 0);
908d6c8399bSrmesta 	/* NOTREACHED */
90939d3e169Sevanl }
91039d3e169Sevanl 
91139d3e169Sevanl static int
start_autofs_svcs(void)91239d3e169Sevanl start_autofs_svcs(void)
91339d3e169Sevanl {
91439d3e169Sevanl 	int doorfd;
91539d3e169Sevanl #ifdef DEBUG
91639d3e169Sevanl 	int dfd;
91739d3e169Sevanl #endif
91839d3e169Sevanl 
91939d3e169Sevanl 	if ((doorfd = door_create(autofs_doorfunc, NULL,
92039d3e169Sevanl 	    DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
92139d3e169Sevanl 		syslog(LOG_ERR, gettext("Unable to create door\n"));
92239d3e169Sevanl 		return (1);
92339d3e169Sevanl 	}
92439d3e169Sevanl 
92539d3e169Sevanl #ifdef DEBUG
92639d3e169Sevanl 	/*
92739d3e169Sevanl 	 * Create a file system path for the door
92839d3e169Sevanl 	 */
92939d3e169Sevanl 	if ((dfd = open(AUTOFS_DOOR, O_RDWR|O_CREAT|O_TRUNC,
93039d3e169Sevanl 	    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
93139d3e169Sevanl 		syslog(LOG_ERR, "Unable to open %s: %m\n", AUTOFS_DOOR);
93239d3e169Sevanl 		(void) close(doorfd);
93339d3e169Sevanl 		return (1);
93439d3e169Sevanl 	}
93539d3e169Sevanl 
93639d3e169Sevanl 	/*
93739d3e169Sevanl 	 * stale associations clean up
93839d3e169Sevanl 	 */
93939d3e169Sevanl 	(void) fdetach(AUTOFS_DOOR);
94039d3e169Sevanl 
94139d3e169Sevanl 	/*
94239d3e169Sevanl 	 * Register in the namespace to the kernel to door_ki_open.
94339d3e169Sevanl 	 */
94439d3e169Sevanl 	if (fattach(doorfd, AUTOFS_DOOR) == -1) {
94539d3e169Sevanl 		syslog(LOG_ERR, "Unable to fattach door %m\n", AUTOFS_DOOR);
94639d3e169Sevanl 		(void) close(dfd);
94739d3e169Sevanl 		(void) close(doorfd);
94839d3e169Sevanl 		return (1);
94939d3e169Sevanl 	}
95039d3e169Sevanl #endif /* DEBUG */
95139d3e169Sevanl 
95239d3e169Sevanl 	/*
95339d3e169Sevanl 	 * Pass door name to kernel for door_ki_open
95439d3e169Sevanl 	 */
95539d3e169Sevanl 	autofs_setdoor(doorfd);
95639d3e169Sevanl 
95739d3e169Sevanl 	(void) thr_keycreate(&s_thr_key, NULL);
95839d3e169Sevanl 
95939d3e169Sevanl 	/*
96039d3e169Sevanl 	 * Wait for incoming calls
96139d3e169Sevanl 	 */
96239d3e169Sevanl 	/*CONSTCOND*/
96339d3e169Sevanl 	while (1)
96439d3e169Sevanl 		(void) pause();
96539d3e169Sevanl 
96639d3e169Sevanl 	/* NOTREACHED */
96739d3e169Sevanl 	syslog(LOG_ERR, gettext("Door server exited"));
96839d3e169Sevanl 	return (10);
96939d3e169Sevanl }
97039d3e169Sevanl 
97139d3e169Sevanl static int
decode_args(xdrproc_t xdrfunc,autofs_door_args_t * argp,caddr_t * xdrargs,int size)97239d3e169Sevanl decode_args(
97339d3e169Sevanl 	xdrproc_t xdrfunc,
97439d3e169Sevanl 	autofs_door_args_t *argp,
97539d3e169Sevanl 	caddr_t *xdrargs,
97639d3e169Sevanl 	int size)
97739d3e169Sevanl {
97839d3e169Sevanl 	XDR xdrs;
97939d3e169Sevanl 
98039d3e169Sevanl 	caddr_t tmpargs = (caddr_t)&((autofs_door_args_t *)argp)->xdr_arg;
98139d3e169Sevanl 	size_t arg_size = ((autofs_door_args_t *)argp)->xdr_len;
98239d3e169Sevanl 
98339d3e169Sevanl 	xdrmem_create(&xdrs, tmpargs, arg_size, XDR_DECODE);
98439d3e169Sevanl 
98539d3e169Sevanl 	*xdrargs = malloc(size);
98639d3e169Sevanl 	if (*xdrargs == NULL) {
987d6c8399bSrmesta 		syslog(LOG_ERR, "error allocating arguments buffer");
98839d3e169Sevanl 		return (ENOMEM);
98939d3e169Sevanl 	}
99039d3e169Sevanl 
99139d3e169Sevanl 	bzero(*xdrargs, size);
99239d3e169Sevanl 
99339d3e169Sevanl 	if (!(*xdrfunc)(&xdrs, *xdrargs)) {
99439d3e169Sevanl 		free(*xdrargs);
99539d3e169Sevanl 		*xdrargs = NULL;
99639d3e169Sevanl 		syslog(LOG_ERR, "error decoding arguments");
99739d3e169Sevanl 		return (EINVAL);
99839d3e169Sevanl 	}
99939d3e169Sevanl 
100039d3e169Sevanl 	return (0);
100139d3e169Sevanl }
100239d3e169Sevanl 
100339d3e169Sevanl 
100439d3e169Sevanl static bool_t
encode_res(xdrproc_t xdrfunc,autofs_door_res_t ** results,caddr_t resp,int * size)100539d3e169Sevanl encode_res(
100639d3e169Sevanl 	xdrproc_t xdrfunc,
100739d3e169Sevanl 	autofs_door_res_t **results,
100839d3e169Sevanl 	caddr_t resp,
100939d3e169Sevanl 	int *size)
101039d3e169Sevanl {
10115e1e04ceSdm 	XDR xdrs;
101239d3e169Sevanl 
101339d3e169Sevanl 	*size = xdr_sizeof((*xdrfunc), resp);
101439d3e169Sevanl 	*results = autofs_get_buffer(
101539d3e169Sevanl 	    sizeof (autofs_door_res_t) + *size);
101639d3e169Sevanl 	if (*results == NULL) {
10175e1e04ceSdm 		(*results)->res_status = ENOMEM;
101839d3e169Sevanl 		return (FALSE);
101939d3e169Sevanl 	}
102039d3e169Sevanl 	(*results)->xdr_len = *size;
102139d3e169Sevanl 	*size = sizeof (autofs_door_res_t) + (*results)->xdr_len;
102239d3e169Sevanl 	xdrmem_create(&xdrs, (caddr_t)((*results)->xdr_res),
1023d6c8399bSrmesta 	    (*results)->xdr_len, XDR_ENCODE);
10245e1e04ceSdm 	if (!(*xdrfunc)(&xdrs, resp)) {
10255e1e04ceSdm 		(*results)->res_status = EINVAL;
10265e1e04ceSdm 		syslog(LOG_ERR, "error encoding results");
102739d3e169Sevanl 		return (FALSE);
102839d3e169Sevanl 	}
102939d3e169Sevanl 	(*results)->res_status = 0;
103039d3e169Sevanl 	return (TRUE);
103139d3e169Sevanl }
10328548bf79Snr 
10338548bf79Snr static void
automountd_wait_for_cleanup(pid_t pid)10348548bf79Snr automountd_wait_for_cleanup(pid_t pid)
10358548bf79Snr {
10368548bf79Snr 	int status;
10378548bf79Snr 	int child_exitval;
10388548bf79Snr 
10398548bf79Snr 	/*
10408548bf79Snr 	 * Wait for the main automountd process to exit so we cleanup
10418548bf79Snr 	 */
10428548bf79Snr 	(void) waitpid(pid, &status, 0);
10438548bf79Snr 
10448548bf79Snr 	child_exitval = WEXITSTATUS(status);
10458548bf79Snr 
10468548bf79Snr 	/*
10478548bf79Snr 	 * Shutdown the door server for mounting and unmounting
10488548bf79Snr 	 * filesystems
10498548bf79Snr 	 */
10508548bf79Snr 	if (door_revoke(did_fork_exec) == -1) {
1051d6c8399bSrmesta 		syslog(LOG_ERR, "failed to door_revoke(%d) %m", did_fork_exec);
10528548bf79Snr 	}
10538548bf79Snr 	if (door_revoke(did_exec_map) == -1) {
1054d6c8399bSrmesta 		syslog(LOG_ERR, "failed to door_revoke(%d) %m", did_exec_map);
10558548bf79Snr 	}
10568548bf79Snr 	exit(child_exitval);
10578548bf79Snr }
1058