xref: /titanic_50/usr/src/cmd/fs.d/autofs/autod_main.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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 /*
22*dd51520eSPavan 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>
48*dd51520eSPavan 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>
628548bf79Snr123932 #include <wait.h>
63*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h>
64*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h>
65*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h"
667c478bd9Sstevel@tonic-gate 
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();
838548bf79Snr123932 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 */
9639d3e169Sevanl 
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;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate int
main(argc,argv)1097c478bd9Sstevel@tonic-gate main(argc, argv)
1107c478bd9Sstevel@tonic-gate 	int argc;
1117c478bd9Sstevel@tonic-gate 	char *argv[];
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate {
1147c478bd9Sstevel@tonic-gate 	pid_t pid;
11539d3e169Sevanl 	int c, error;
1167c478bd9Sstevel@tonic-gate 	struct rlimit rlset;
117*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	char defval[6];
118*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	int ret = 0, bufsz;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) {
1217c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
1227c478bd9Sstevel@tonic-gate 		exit(1);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	/*
126*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	 * Read in the values from SMF first before we check
1277c478bd9Sstevel@tonic-gate 	 * commandline options so the options override the file.
1287c478bd9Sstevel@tonic-gate 	 */
129*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 6;
130*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = autofs_smf_get_prop("automountd_verbose", defval,
131*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    DEFAULT_INSTANCE, SCF_TYPE_BOOLEAN, AUTOMOUNTD, &bufsz);
132*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
1337c478bd9Sstevel@tonic-gate 		if (strncasecmp("true", defval, 4) == 0)
1347c478bd9Sstevel@tonic-gate 			verbose = TRUE;
1357c478bd9Sstevel@tonic-gate 		else
1367c478bd9Sstevel@tonic-gate 			verbose = FALSE;
1377c478bd9Sstevel@tonic-gate 	}
138*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 6;
139*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = autofs_smf_get_prop("nobrowse", defval, DEFAULT_INSTANCE,
140*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_BOOLEAN, AUTOMOUNTD, &bufsz);
141*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
1427c478bd9Sstevel@tonic-gate 		if (strncasecmp("true", defval, 4) == 0)
1437c478bd9Sstevel@tonic-gate 			automountd_nobrowse = TRUE;
1447c478bd9Sstevel@tonic-gate 		else
1457c478bd9Sstevel@tonic-gate 			automountd_nobrowse = FALSE;
1467c478bd9Sstevel@tonic-gate 	}
147*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	bufsz = 6;
148*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	ret = autofs_smf_get_prop("trace", defval, DEFAULT_INSTANCE,
149*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	    SCF_TYPE_INTEGER, AUTOMOUNTD, &bufsz);
150*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States 	if (ret == SA_OK) {
1517c478bd9Sstevel@tonic-gate 		errno = 0;
1527c478bd9Sstevel@tonic-gate 		trace = strtol(defval, (char **)NULL, 10);
1537c478bd9Sstevel@tonic-gate 		if (errno != 0)
1547c478bd9Sstevel@tonic-gate 			trace = 0;
1557c478bd9Sstevel@tonic-gate 	}
1566012a713Spetede 	put_automountd_env();
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "vnTD:")) != EOF) {
1597c478bd9Sstevel@tonic-gate 		switch (c) {
1607c478bd9Sstevel@tonic-gate 		case 'v':
1617c478bd9Sstevel@tonic-gate 			verbose++;
1627c478bd9Sstevel@tonic-gate 			break;
1637c478bd9Sstevel@tonic-gate 		case 'n':
1647c478bd9Sstevel@tonic-gate 			automountd_nobrowse++;
1657c478bd9Sstevel@tonic-gate 			break;
1667c478bd9Sstevel@tonic-gate 		case 'T':
1677c478bd9Sstevel@tonic-gate 			trace++;
1687c478bd9Sstevel@tonic-gate 			break;
1697c478bd9Sstevel@tonic-gate 		case 'D':
1707c478bd9Sstevel@tonic-gate 			(void) putenv(optarg);
1717c478bd9Sstevel@tonic-gate 			break;
1727c478bd9Sstevel@tonic-gate 		default:
1737c478bd9Sstevel@tonic-gate 			usage();
1747c478bd9Sstevel@tonic-gate 		}
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, self, sizeof (self)) == -1) {
1787c478bd9Sstevel@tonic-gate 		error = errno;
17939d3e169Sevanl 		(void) fprintf(stderr,
1807c478bd9Sstevel@tonic-gate 			"automountd: can't determine hostname, error: %d\n",
1817c478bd9Sstevel@tonic-gate 			error);
1827c478bd9Sstevel@tonic-gate 		exit(1);
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate #ifndef DEBUG
1867c478bd9Sstevel@tonic-gate 	pid = fork();
1877c478bd9Sstevel@tonic-gate 	if (pid < 0) {
1887c478bd9Sstevel@tonic-gate 		perror("cannot fork");
1897c478bd9Sstevel@tonic-gate 		exit(1);
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate 	if (pid)
1927c478bd9Sstevel@tonic-gate 		exit(0);
1937c478bd9Sstevel@tonic-gate #endif
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	(void) setsid();
1967c478bd9Sstevel@tonic-gate 	openlog("automountd", LOG_PID, LOG_DAEMON);
1977c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1987c478bd9Sstevel@tonic-gate 
1998548bf79Snr123932 	/*
2008548bf79Snr123932 	 * Create the door_servers to manage fork/exec requests for
2018548bf79Snr123932 	 * mounts and executable automount maps
2028548bf79Snr123932 	 */
2038548bf79Snr123932 	if ((did_fork_exec = door_create(automountd_do_fork_exec,
2048548bf79Snr123932 	    NULL, NULL)) == -1) {
2058548bf79Snr123932 		syslog(LOG_ERR, "door_create failed: %m, Exiting.");
2068548bf79Snr123932 		exit(errno);
2078548bf79Snr123932 	}
2088548bf79Snr123932 	if ((did_exec_map = door_create(automountd_do_exec_map,
2098548bf79Snr123932 	    NULL, NULL)) == -1) {
2108548bf79Snr123932 		syslog(LOG_ERR, "door_create failed: %m, Exiting.");
2118548bf79Snr123932 		if (door_revoke(did_fork_exec) == -1) {
2128548bf79Snr123932 			syslog(LOG_ERR, "failed to door_revoke(%d) %m",
2138548bf79Snr123932 			    did_fork_exec);
2148548bf79Snr123932 		}
2158548bf79Snr123932 		exit(errno);
2168548bf79Snr123932 	}
2178548bf79Snr123932 	/*
2188548bf79Snr123932 	 * Before we become multithreaded we fork allowing the parent
2198548bf79Snr123932 	 * to become a door server to handle all mount and unmount
2208548bf79Snr123932 	 * requests. This works around a potential hang in using
2218548bf79Snr123932 	 * fork1() within a multithreaded environment
2228548bf79Snr123932 	 */
2238548bf79Snr123932 
2248548bf79Snr123932 	pid = fork1();
2258548bf79Snr123932 	if (pid < 0) {
2268548bf79Snr123932 		syslog(LOG_ERR,
2278548bf79Snr123932 			"can't fork the automountd mount process %m");
2288548bf79Snr123932 		if (door_revoke(did_fork_exec) == -1) {
2298548bf79Snr123932 			syslog(LOG_ERR, "failed to door_revoke(%d) %m",
2308548bf79Snr123932 				did_fork_exec);
2318548bf79Snr123932 		}
2328548bf79Snr123932 		if (door_revoke(did_exec_map) == -1) {
2338548bf79Snr123932 			syslog(LOG_ERR, "failed to door_revoke(%d) %m",
2348548bf79Snr123932 				did_exec_map);
2358548bf79Snr123932 		}
2368548bf79Snr123932 		exit(1);
2378548bf79Snr123932 	} else if (pid > 0) {
2388548bf79Snr123932 		/* this is the door server process */
2398548bf79Snr123932 		automountd_wait_for_cleanup(pid);
2408548bf79Snr123932 	}
2418548bf79Snr123932 
2428548bf79Snr123932 
2437c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&cache_lock, USYNC_THREAD, NULL);
24439d3e169Sevanl 	(void) rwlock_init(&autofs_rddir_cache_lock, USYNC_THREAD, NULL);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/*
2477c478bd9Sstevel@tonic-gate 	 * initialize the name services, use NULL arguments to ensure
2487c478bd9Sstevel@tonic-gate 	 * we don't initialize the stack of files used in file service
2497c478bd9Sstevel@tonic-gate 	 */
2507c478bd9Sstevel@tonic-gate 	(void) ns_setup(NULL, NULL);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/*
2538f379ff8Sevanl 	 * we're using doors and its thread management now so we need to
2548f379ff8Sevanl 	 * make sure we have more than the default of 256 file descriptors
2558f379ff8Sevanl 	 * available.
2568f379ff8Sevanl 	 */
2578f379ff8Sevanl 	rlset.rlim_cur = RLIM_INFINITY;
2588f379ff8Sevanl 	rlset.rlim_max = RLIM_INFINITY;
2598f379ff8Sevanl 	if (setrlimit(RLIMIT_NOFILE, &rlset) == -1)
2608f379ff8Sevanl 		syslog(LOG_ERR, "setrlimit failed for %s: %s", AUTOMOUNTD,
2618f379ff8Sevanl 		    strerror(errno));
2628f379ff8Sevanl 
2638f379ff8Sevanl 	(void) enable_extended_FILE_stdio(-1, -1);
2648f379ff8Sevanl 
2658f379ff8Sevanl 	/*
2667c478bd9Sstevel@tonic-gate 	 * establish our lock on the lock file and write our pid to it.
2677c478bd9Sstevel@tonic-gate 	 * exit if some other process holds the lock, or if there's any
2687c478bd9Sstevel@tonic-gate 	 * error in writing/locking the file.
2697c478bd9Sstevel@tonic-gate 	 */
2707c478bd9Sstevel@tonic-gate 	pid = _enter_daemon_lock(AUTOMOUNTD);
2717c478bd9Sstevel@tonic-gate 	switch (pid) {
2727c478bd9Sstevel@tonic-gate 	case 0:
2737c478bd9Sstevel@tonic-gate 		break;
2747c478bd9Sstevel@tonic-gate 	case -1:
2758548bf79Snr123932 		syslog(LOG_ERR, "error locking for %s: %m", AUTOMOUNTD);
2767c478bd9Sstevel@tonic-gate 		exit(2);
2777c478bd9Sstevel@tonic-gate 	default:
2787c478bd9Sstevel@tonic-gate 		/* daemon was already running */
2797c478bd9Sstevel@tonic-gate 		exit(0);
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	/*
2837c478bd9Sstevel@tonic-gate 	 * If we coredump it'll be /core.
2847c478bd9Sstevel@tonic-gate 	 */
2857c478bd9Sstevel@tonic-gate 	if (chdir("/") < 0)
2867c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "chdir /: %m");
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	/*
2897c478bd9Sstevel@tonic-gate 	 * Create cache_cleanup thread
2907c478bd9Sstevel@tonic-gate 	 */
2917c478bd9Sstevel@tonic-gate 	if (thr_create(NULL, 0, (void *(*)(void *))cache_cleanup, NULL,
2927c478bd9Sstevel@tonic-gate 			THR_DETACHED | THR_DAEMON | THR_NEW_LWP, NULL)) {
2937c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "unable to create cache_cleanup thread");
2947c478bd9Sstevel@tonic-gate 		exit(1);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/* other initializations */
2987c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&portmap_cache_lock, USYNC_THREAD, NULL);
2997c478bd9Sstevel@tonic-gate 
30092373f0aSrica 	/*
30192373f0aSrica 	 * On a labeled system, allow read-down nfs mounts if privileged
30292373f0aSrica 	 * (PRIV_NET_MAC_AWARE) to do so.  Otherwise, ignore the error
30392373f0aSrica 	 * and "mount equal label only" behavior will result.
30492373f0aSrica 	 */
30545916cd2Sjpk 	if (is_system_labeled()) {
30692373f0aSrica 		(void) setpflags(NET_MAC_AWARE, 1);
30792373f0aSrica 		(void) setpflags(NET_MAC_AWARE_INHERIT, 1);
30845916cd2Sjpk 	}
30945916cd2Sjpk 
3107c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, warn_hup);
3117c478bd9Sstevel@tonic-gate 
31239d3e169Sevanl 	/* start services */
31339d3e169Sevanl 	return (start_autofs_svcs());
31439d3e169Sevanl 
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate  * The old automounter supported a SIGHUP
3197c478bd9Sstevel@tonic-gate  * to allow it to resynchronize internal
3207c478bd9Sstevel@tonic-gate  * state with the /etc/mnttab.
3217c478bd9Sstevel@tonic-gate  * This is no longer relevant, but we
3227c478bd9Sstevel@tonic-gate  * need to catch the signal and warn
3237c478bd9Sstevel@tonic-gate  * the user.
3247c478bd9Sstevel@tonic-gate  */
3257c478bd9Sstevel@tonic-gate /* ARGSUSED */
3267c478bd9Sstevel@tonic-gate static void
warn_hup(i)3277c478bd9Sstevel@tonic-gate warn_hup(i)
3287c478bd9Sstevel@tonic-gate 	int i;
3297c478bd9Sstevel@tonic-gate {
3307c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, "SIGHUP received: ignored");
3317c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, warn_hup);
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate static void
usage()3357c478bd9Sstevel@tonic-gate usage()
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage: automountd\n"
3387c478bd9Sstevel@tonic-gate 	    "\t[-T]\t\t(trace requests)\n"
3397c478bd9Sstevel@tonic-gate 	    "\t[-v]\t\t(verbose error msgs)\n"
3407c478bd9Sstevel@tonic-gate 	    "\t[-D n=s]\t(define env variable)\n");
3417c478bd9Sstevel@tonic-gate 	exit(1);
3427c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate static void
autofs_readdir_1_r(autofs_rddirargs * req,autofs_rddirres * res)34639d3e169Sevanl autofs_readdir_1_r(
34739d3e169Sevanl 	autofs_rddirargs *req,
3483bfb48feSsemery 	autofs_rddirres *res)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate 	if (trace > 0)
3517c478bd9Sstevel@tonic-gate 		trace_prt(1, "READDIR REQUEST	: %s @ %ld\n",
3527c478bd9Sstevel@tonic-gate 		    req->rda_map, req->rda_offset);
3537c478bd9Sstevel@tonic-gate 
3543bfb48feSsemery 	do_readdir(req, res);
3557c478bd9Sstevel@tonic-gate 	if (trace > 0)
356d6c8399bSrmesta 		trace_prt(1, "READDIR REPLY	: status=%d\n", res->rd_status);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate static void
autofs_readdir_1_free_r(struct autofs_rddirres * res)36039d3e169Sevanl autofs_readdir_1_free_r(struct autofs_rddirres *res)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate 	if (res->rd_status == AUTOFS_OK) {
3637c478bd9Sstevel@tonic-gate 		if (res->rd_rddir.rddir_entries)
3647c478bd9Sstevel@tonic-gate 			free(res->rd_rddir.rddir_entries);
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
36839d3e169Sevanl 
3697c478bd9Sstevel@tonic-gate /* ARGSUSED */
3707c478bd9Sstevel@tonic-gate static void
autofs_unmount_1_r(umntrequest * m,umntres * res)37139d3e169Sevanl autofs_unmount_1_r(
37239d3e169Sevanl 	umntrequest *m,
3733bfb48feSsemery 	umntres *res)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	struct umntrequest *ul;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	if (trace > 0) {
3787c478bd9Sstevel@tonic-gate 		char ctime_buf[CTIME_BUF_LEN];
3797c478bd9Sstevel@tonic-gate 		if (ctime_r(&timenow, ctime_buf, CTIME_BUF_LEN) == NULL)
3807c478bd9Sstevel@tonic-gate 			ctime_buf[0] = '\0';
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 		trace_prt(1, "UNMOUNT REQUEST: %s", ctime_buf);
3837c478bd9Sstevel@tonic-gate 		for (ul = m; ul; ul = ul->next)
3847c478bd9Sstevel@tonic-gate 			trace_prt(1, " resource=%s fstype=%s mntpnt=%s"
3857c478bd9Sstevel@tonic-gate 			    " mntopts=%s %s\n",
3867c478bd9Sstevel@tonic-gate 			    ul->mntresource,
3877c478bd9Sstevel@tonic-gate 			    ul->fstype,
3887c478bd9Sstevel@tonic-gate 			    ul->mntpnt,
3897c478bd9Sstevel@tonic-gate 			    ul->mntopts,
3907c478bd9Sstevel@tonic-gate 			    ul->isdirect ? "direct" : "indirect");
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
39339d3e169Sevanl 
3947c478bd9Sstevel@tonic-gate 	res->status = do_unmount1(m);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	if (trace > 0)
3977c478bd9Sstevel@tonic-gate 		trace_prt(1, "UNMOUNT REPLY: status=%d\n", res->status);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate static void
autofs_lookup_1_r(autofs_lookupargs * m,autofs_lookupres * res)40139d3e169Sevanl autofs_lookup_1_r(
40239d3e169Sevanl 	autofs_lookupargs *m,
4033bfb48feSsemery 	autofs_lookupres *res)
4047c478bd9Sstevel@tonic-gate {
40539d3e169Sevanl 	autofs_action_t action;
4067c478bd9Sstevel@tonic-gate 	struct	linka link;
4077c478bd9Sstevel@tonic-gate 	int status;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	if (trace > 0) {
4107c478bd9Sstevel@tonic-gate 		char ctime_buf[CTIME_BUF_LEN];
4117c478bd9Sstevel@tonic-gate 		if (ctime_r(&timenow, ctime_buf, CTIME_BUF_LEN) == NULL)
4127c478bd9Sstevel@tonic-gate 			ctime_buf[0] = '\0';
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 		trace_prt(1, "LOOKUP REQUEST: %s", ctime_buf);
4157c478bd9Sstevel@tonic-gate 		trace_prt(1, "  name=%s[%s] map=%s opts=%s path=%s direct=%d\n",
416d6c8399bSrmesta 		    m->name, m->subdir, m->map, m->opts, m->path, m->isdirect);
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 
41939d3e169Sevanl 	bzero(&link, sizeof (struct linka));
42039d3e169Sevanl 
4217c478bd9Sstevel@tonic-gate 	status = do_lookup1(m->map, m->name, m->subdir, m->opts, m->path,
4223bfb48feSsemery 	    (uint_t)m->isdirect, m->uid, &action, &link);
4237c478bd9Sstevel@tonic-gate 	if (status == 0) {
4247c478bd9Sstevel@tonic-gate 		/*
4257c478bd9Sstevel@tonic-gate 		 * Return action list to kernel.
4267c478bd9Sstevel@tonic-gate 		 */
4277c478bd9Sstevel@tonic-gate 		res->lu_res = AUTOFS_OK;
42839d3e169Sevanl 		if ((res->lu_type.action = action) == AUTOFS_LINK_RQ) {
4297c478bd9Sstevel@tonic-gate 			res->lu_type.lookup_result_type_u.lt_linka = link;
43039d3e169Sevanl 		}
4317c478bd9Sstevel@tonic-gate 	} else {
4327c478bd9Sstevel@tonic-gate 		/*
4337c478bd9Sstevel@tonic-gate 		 * Entry not found
4347c478bd9Sstevel@tonic-gate 		 */
4357c478bd9Sstevel@tonic-gate 		res->lu_res = AUTOFS_NOENT;
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate 	res->lu_verbose = verbose;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	if (trace > 0)
4407c478bd9Sstevel@tonic-gate 		trace_prt(1, "LOOKUP REPLY    : status=%d\n", res->lu_res);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate static void
autofs_mntinfo_1_r(autofs_lookupargs * m,autofs_mountres * res)44439d3e169Sevanl autofs_mntinfo_1_r(
44539d3e169Sevanl 	autofs_lookupargs *m,
4463bfb48feSsemery 	autofs_mountres *res)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate 	int status;
4497c478bd9Sstevel@tonic-gate 	action_list		*alp = NULL;
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	if (trace > 0) {
4527c478bd9Sstevel@tonic-gate 		char ctime_buf[CTIME_BUF_LEN];
4537c478bd9Sstevel@tonic-gate 		if (ctime_r(&timenow, ctime_buf, CTIME_BUF_LEN) == NULL)
4547c478bd9Sstevel@tonic-gate 			ctime_buf[0] = '\0';
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 		trace_prt(1, "MOUNT REQUEST:   %s", ctime_buf);
4577c478bd9Sstevel@tonic-gate 		trace_prt(1, "  name=%s[%s] map=%s opts=%s path=%s direct=%d\n",
458d6c8399bSrmesta 		    m->name, m->subdir, m->map, m->opts, m->path, m->isdirect);
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	status = do_mount1(m->map, m->name, m->subdir, m->opts, m->path,
4625e1e04ceSdm120769 	    (uint_t)m->isdirect, m->uid, &alp, DOMOUNT_USER);
4637c478bd9Sstevel@tonic-gate 	if (status != 0) {
4647c478bd9Sstevel@tonic-gate 		/*
4657c478bd9Sstevel@tonic-gate 		 * An error occurred, free action list if allocated.
4667c478bd9Sstevel@tonic-gate 		 */
4677c478bd9Sstevel@tonic-gate 		if (alp != NULL) {
4687c478bd9Sstevel@tonic-gate 			free_action_list(alp);
4697c478bd9Sstevel@tonic-gate 			alp = NULL;
4707c478bd9Sstevel@tonic-gate 		}
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 	if (alp != NULL) {
4735e1e04ceSdm120769 		/*
4745e1e04ceSdm120769 		 * Return action list to kernel.
4755e1e04ceSdm120769 		 */
4767c478bd9Sstevel@tonic-gate 		res->mr_type.status = AUTOFS_ACTION;
4777c478bd9Sstevel@tonic-gate 		res->mr_type.mount_result_type_u.list = alp;
4787c478bd9Sstevel@tonic-gate 	} else {
4797c478bd9Sstevel@tonic-gate 		/*
4807c478bd9Sstevel@tonic-gate 		 * No work to do left for the kernel
4817c478bd9Sstevel@tonic-gate 		 */
4827c478bd9Sstevel@tonic-gate 		res->mr_type.status = AUTOFS_DONE;
4837c478bd9Sstevel@tonic-gate 		res->mr_type.mount_result_type_u.error = status;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	if (trace > 0) {
4877c478bd9Sstevel@tonic-gate 		switch (res->mr_type.status) {
4887c478bd9Sstevel@tonic-gate 		case AUTOFS_ACTION:
4897c478bd9Sstevel@tonic-gate 			trace_prt(1,
4907c478bd9Sstevel@tonic-gate 			    "MOUNT REPLY    : status=%d, AUTOFS_ACTION\n",
4917c478bd9Sstevel@tonic-gate 			    status);
4927c478bd9Sstevel@tonic-gate 			break;
4937c478bd9Sstevel@tonic-gate 		case AUTOFS_DONE:
4947c478bd9Sstevel@tonic-gate 			trace_prt(1,
4957c478bd9Sstevel@tonic-gate 			    "MOUNT REPLY    : status=%d, AUTOFS_DONE\n",
4967c478bd9Sstevel@tonic-gate 			    status);
4977c478bd9Sstevel@tonic-gate 			break;
4987c478bd9Sstevel@tonic-gate 		default:
4997c478bd9Sstevel@tonic-gate 			trace_prt(1, "MOUNT REPLY    : status=%d, UNKNOWN\n",
5007c478bd9Sstevel@tonic-gate 			    status);
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if (status && verbose) {
5057c478bd9Sstevel@tonic-gate 		if (m->isdirect) {
5067c478bd9Sstevel@tonic-gate 			/* direct mount */
5077c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "mount of %s failed", m->path);
5087c478bd9Sstevel@tonic-gate 		} else {
5097c478bd9Sstevel@tonic-gate 			/* indirect mount */
5107c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
5117c478bd9Sstevel@tonic-gate 			    "mount of %s/%s failed", m->path, m->name);
5127c478bd9Sstevel@tonic-gate 		}
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate static void
autofs_mount_1_free_r(struct autofs_mountres * res)51739d3e169Sevanl autofs_mount_1_free_r(struct autofs_mountres *res)
5187c478bd9Sstevel@tonic-gate {
5197c478bd9Sstevel@tonic-gate 	if (res->mr_type.status == AUTOFS_ACTION) {
5207c478bd9Sstevel@tonic-gate 		if (trace > 2)
5217c478bd9Sstevel@tonic-gate 			trace_prt(1, "freeing action list\n");
5227c478bd9Sstevel@tonic-gate 		free_action_list(res->mr_type.mount_result_type_u.list);
5237c478bd9Sstevel@tonic-gate 	}
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate /*
527ace1a5f1Sdp  * Used for reporting messages from code shared with automount command.
528ace1a5f1Sdp  * Formats message into a buffer and calls syslog.
5297c478bd9Sstevel@tonic-gate  *
530ace1a5f1Sdp  * Print an error.  Works like printf (fmt string and variable args)
531ace1a5f1Sdp  * except that it will subsititute an error message for a "%m" string
532ace1a5f1Sdp  * (like syslog).
5337c478bd9Sstevel@tonic-gate  */
5347c478bd9Sstevel@tonic-gate void
pr_msg(const char * fmt,...)5357c478bd9Sstevel@tonic-gate pr_msg(const char *fmt, ...)
5367c478bd9Sstevel@tonic-gate {
5377c478bd9Sstevel@tonic-gate 	va_list ap;
5387c478bd9Sstevel@tonic-gate 	char fmtbuff[BUFSIZ], buff[BUFSIZ];
5397c478bd9Sstevel@tonic-gate 	const char *p1;
5407c478bd9Sstevel@tonic-gate 	char *p2;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	p2 = fmtbuff;
5437c478bd9Sstevel@tonic-gate 	fmt = gettext(fmt);
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	for (p1 = fmt; *p1; p1++) {
5467c478bd9Sstevel@tonic-gate 		if (*p1 == '%' && *(p1 + 1) == 'm') {
547ace1a5f1Sdp 			(void) strcpy(p2, strerror(errno));
5487c478bd9Sstevel@tonic-gate 			p2 += strlen(p2);
5497c478bd9Sstevel@tonic-gate 			p1++;
5507c478bd9Sstevel@tonic-gate 		} else {
5517c478bd9Sstevel@tonic-gate 			*p2++ = *p1;
5527c478bd9Sstevel@tonic-gate 		}
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 	if (p2 > fmtbuff && *(p2-1) != '\n')
5557c478bd9Sstevel@tonic-gate 		*p2++ = '\n';
5567c478bd9Sstevel@tonic-gate 	*p2 = '\0';
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
5597c478bd9Sstevel@tonic-gate 	(void) vsprintf(buff, fmtbuff, ap);
5607c478bd9Sstevel@tonic-gate 	va_end(ap);
5617c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, buff);
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate static void
free_action_list(action_list * alp)5657c478bd9Sstevel@tonic-gate free_action_list(action_list *alp)
5667c478bd9Sstevel@tonic-gate {
5677c478bd9Sstevel@tonic-gate 	action_list *p, *next = NULL;
5687c478bd9Sstevel@tonic-gate 	struct mounta *mp;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	for (p = alp; p != NULL; p = next) {
5717c478bd9Sstevel@tonic-gate 		switch (p->action.action) {
5727c478bd9Sstevel@tonic-gate 		case AUTOFS_MOUNT_RQ:
5737c478bd9Sstevel@tonic-gate 			mp = &(p->action.action_list_entry_u.mounta);
5747c478bd9Sstevel@tonic-gate 			/* LINTED pointer alignment */
57539d3e169Sevanl 			if (mp->fstype) {
57639d3e169Sevanl 				if (strcmp(mp->fstype, "autofs") == 0) {
57739d3e169Sevanl 					free_autofs_args((autofs_args *)
57839d3e169Sevanl 					    mp->dataptr);
579d6c8399bSrmesta 				} else if (strncmp(mp->fstype, "nfs", 3) == 0) {
58039d3e169Sevanl 					free_nfs_args((struct nfs_args *)
58139d3e169Sevanl 					    mp->dataptr);
58239d3e169Sevanl 				}
58339d3e169Sevanl 			}
5847c478bd9Sstevel@tonic-gate 			mp->dataptr = NULL;
5857c478bd9Sstevel@tonic-gate 			mp->datalen = 0;
5867c478bd9Sstevel@tonic-gate 			free_mounta(mp);
5877c478bd9Sstevel@tonic-gate 			break;
5887c478bd9Sstevel@tonic-gate 		case AUTOFS_LINK_RQ:
5897c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
5907c478bd9Sstevel@tonic-gate 			    "non AUTOFS_MOUNT_RQ requests not implemented\n");
5917c478bd9Sstevel@tonic-gate 			break;
5927c478bd9Sstevel@tonic-gate 		default:
5937c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
5947c478bd9Sstevel@tonic-gate 			    "non AUTOFS_MOUNT_RQ requests not implemented\n");
5957c478bd9Sstevel@tonic-gate 			break;
5967c478bd9Sstevel@tonic-gate 		}
5977c478bd9Sstevel@tonic-gate 		next = p->next;
5987c478bd9Sstevel@tonic-gate 		free(p);
5997c478bd9Sstevel@tonic-gate 	}
6007c478bd9Sstevel@tonic-gate }
60139d3e169Sevanl 
60239d3e169Sevanl static void
autofs_lookup_1_free_args(autofs_lookupargs * args)60339d3e169Sevanl autofs_lookup_1_free_args(autofs_lookupargs *args)
60439d3e169Sevanl {
60539d3e169Sevanl 	if (args->map)
60639d3e169Sevanl 		free(args->map);
60739d3e169Sevanl 	if (args->path)
60839d3e169Sevanl 		free(args->path);
60939d3e169Sevanl 	if (args->name)
61039d3e169Sevanl 		free(args->name);
61139d3e169Sevanl 	if (args->subdir)
61239d3e169Sevanl 		free(args->subdir);
61339d3e169Sevanl 	if (args->opts)
61439d3e169Sevanl 		free(args->opts);
61539d3e169Sevanl }
61639d3e169Sevanl 
61739d3e169Sevanl static void
autofs_unmount_1_free_args(umntrequest * args)61839d3e169Sevanl autofs_unmount_1_free_args(umntrequest *args)
61939d3e169Sevanl {
62039d3e169Sevanl 	if (args->mntresource)
62139d3e169Sevanl 		free(args->mntresource);
62239d3e169Sevanl 	if (args->mntpnt)
62339d3e169Sevanl 		free(args->mntpnt);
62439d3e169Sevanl 	if (args->fstype)
62539d3e169Sevanl 		free(args->fstype);
62639d3e169Sevanl 	if (args->mntopts)
62739d3e169Sevanl 		free(args->mntopts);
62839d3e169Sevanl 	if (args->next)
62939d3e169Sevanl 		autofs_unmount_1_free_args(args->next);
63039d3e169Sevanl }
63139d3e169Sevanl 
63239d3e169Sevanl static void
autofs_setdoor(int did)63339d3e169Sevanl autofs_setdoor(int did)
63439d3e169Sevanl {
63539d3e169Sevanl 
63639d3e169Sevanl 	if (did < 0) {
63739d3e169Sevanl 		did = 0;
63839d3e169Sevanl 	}
63939d3e169Sevanl 
64039d3e169Sevanl 	(void) _autofssys(AUTOFS_SETDOOR, &did);
64139d3e169Sevanl }
64239d3e169Sevanl 
64339d3e169Sevanl void *
autofs_get_buffer(size_t size)64439d3e169Sevanl autofs_get_buffer(size_t size)
64539d3e169Sevanl {
64639d3e169Sevanl 	autofs_tsd_t *tsd = NULL;
64739d3e169Sevanl 
64839d3e169Sevanl 	/*
64939d3e169Sevanl 	 * Make sure the buffer size is aligned
65039d3e169Sevanl 	 */
65139d3e169Sevanl 	(void) thr_getspecific(s_thr_key, (void **)&tsd);
65239d3e169Sevanl 	if (tsd == NULL) {
65339d3e169Sevanl 		tsd = (autofs_tsd_t *)malloc(sizeof (autofs_tsd_t));
65439d3e169Sevanl 		if (tsd == NULL) {
65539d3e169Sevanl 			return (NULL);
65639d3e169Sevanl 		}
65739d3e169Sevanl 		tsd->atsd_buf = malloc(size);
65839d3e169Sevanl 		if (tsd->atsd_buf != NULL)
65939d3e169Sevanl 			tsd->atsd_len = size;
66039d3e169Sevanl 		else
66139d3e169Sevanl 			tsd->atsd_len = 0;
66239d3e169Sevanl 		(void) thr_setspecific(s_thr_key, tsd);
66339d3e169Sevanl 	} else {
66439d3e169Sevanl 		if (tsd->atsd_buf && (tsd->atsd_len < size)) {
66539d3e169Sevanl 			free(tsd->atsd_buf);
66639d3e169Sevanl 			tsd->atsd_buf = malloc(size);
66739d3e169Sevanl 			if (tsd->atsd_buf != NULL)
66839d3e169Sevanl 				tsd->atsd_len = size;
66939d3e169Sevanl 			else {
67039d3e169Sevanl 				tsd->atsd_len = 0;
67139d3e169Sevanl 			}
67239d3e169Sevanl 		}
67339d3e169Sevanl 	}
67439d3e169Sevanl 	if (tsd->atsd_buf) {
67539d3e169Sevanl 		bzero(tsd->atsd_buf, size);
67639d3e169Sevanl 		return (tsd->atsd_buf);
67739d3e169Sevanl 	} else {
678d6c8399bSrmesta 		syslog(LOG_ERR,
679d6c8399bSrmesta 		    gettext("Can't Allocate tsd buffer, size %d"), size);
68039d3e169Sevanl 		return (NULL);
68139d3e169Sevanl 	}
68239d3e169Sevanl }
68339d3e169Sevanl 
68439d3e169Sevanl /*
68539d3e169Sevanl  * Each request will automatically spawn a new thread with this
68639d3e169Sevanl  * as its entry point.
68739d3e169Sevanl  */
68839d3e169Sevanl /* ARGUSED */
68939d3e169Sevanl static void
autofs_doorfunc(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)69039d3e169Sevanl autofs_doorfunc(
69139d3e169Sevanl 	void *cookie,
69239d3e169Sevanl 	char *argp,
69339d3e169Sevanl 	size_t arg_size,
69439d3e169Sevanl 	door_desc_t *dp,
69539d3e169Sevanl 	uint_t n_desc)
69639d3e169Sevanl {
69739d3e169Sevanl 	char			*res;
69839d3e169Sevanl 	int			 res_size;
699d6c8399bSrmesta 	int			 which;
700d6c8399bSrmesta 	int			 error = 0;
701d6c8399bSrmesta 	int			 srsz = 0;
70239d3e169Sevanl 	autofs_lookupargs	*xdrargs;
70339d3e169Sevanl 	autofs_lookupres	 lookup_res;
70439d3e169Sevanl 	autofs_rddirargs	*rddir_args;
70539d3e169Sevanl 	autofs_rddirres		 rddir_res;
70639d3e169Sevanl 	autofs_mountres		 mount_res;
70739d3e169Sevanl 	umntrequest		*umnt_args;
70839d3e169Sevanl 	umntres			 umount_res;
70939d3e169Sevanl 	autofs_door_res_t	*door_res;
71039d3e169Sevanl 	autofs_door_res_t	 failed_res;
71139d3e169Sevanl 
71239d3e169Sevanl 	if (arg_size < sizeof (autofs_door_args_t)) {
71339d3e169Sevanl 		failed_res.res_status = EINVAL;
71439d3e169Sevanl 		error = door_return((char *)&failed_res,
71539d3e169Sevanl 		    sizeof (autofs_door_res_t), NULL, 0);
71639d3e169Sevanl 		/*
71739d3e169Sevanl 		 * If we got here the door_return() failed.
71839d3e169Sevanl 		 */
719d6c8399bSrmesta 		syslog(LOG_ERR, "Bad argument, door_return failure %d", error);
72039d3e169Sevanl 		return;
72139d3e169Sevanl 	}
72239d3e169Sevanl 
72339d3e169Sevanl 	timenow = time((time_t *)NULL);
72439d3e169Sevanl 
72539d3e169Sevanl 	which = ((autofs_door_args_t *)argp)->cmd;
72639d3e169Sevanl 	switch (which) {
72739d3e169Sevanl 	case AUTOFS_LOOKUP:
72839d3e169Sevanl 		if (error = decode_args(xdr_autofs_lookupargs,
72939d3e169Sevanl 		    (autofs_door_args_t *)argp, (caddr_t *)&xdrargs,
73039d3e169Sevanl 		    sizeof (autofs_lookupargs))) {
731d6c8399bSrmesta 			syslog(LOG_ERR,
732d6c8399bSrmesta 			    "error allocating lookup arguments buffer");
73339d3e169Sevanl 			failed_res.res_status = error;
73439d3e169Sevanl 			failed_res.xdr_len = 0;
73539d3e169Sevanl 			res = (caddr_t)&failed_res;
7365e1e04ceSdm120769 			res_size = 0;
73739d3e169Sevanl 			break;
73839d3e169Sevanl 		}
73939d3e169Sevanl 		bzero(&lookup_res, sizeof (autofs_lookupres));
74039d3e169Sevanl 
7413bfb48feSsemery 		autofs_lookup_1_r(xdrargs, &lookup_res);
74239d3e169Sevanl 
74339d3e169Sevanl 		autofs_lookup_1_free_args(xdrargs);
74439d3e169Sevanl 		free(xdrargs);
7455e1e04ceSdm120769 
74639d3e169Sevanl 		if (!encode_res(xdr_autofs_lookupres, &door_res,
74739d3e169Sevanl 		    (caddr_t)&lookup_res, &res_size)) {
748d6c8399bSrmesta 			syslog(LOG_ERR,
749d6c8399bSrmesta 			    "error allocating lookup results buffer");
7505e1e04ceSdm120769 			failed_res.res_status = EINVAL;
75139d3e169Sevanl 			failed_res.xdr_len = 0;
75239d3e169Sevanl 			res = (caddr_t)&failed_res;
75339d3e169Sevanl 		} else {
75439d3e169Sevanl 			door_res->res_status = 0;
75539d3e169Sevanl 			res = (caddr_t)door_res;
75639d3e169Sevanl 		}
75739d3e169Sevanl 		break;
75839d3e169Sevanl 
75939d3e169Sevanl 	case AUTOFS_MNTINFO:
76039d3e169Sevanl 		if (error = decode_args(xdr_autofs_lookupargs,
76139d3e169Sevanl 		    (autofs_door_args_t *)argp, (caddr_t *)&xdrargs,
76239d3e169Sevanl 		    sizeof (autofs_lookupargs))) {
763d6c8399bSrmesta 			syslog(LOG_ERR,
764d6c8399bSrmesta 			    "error allocating lookup arguments buffer");
76539d3e169Sevanl 			failed_res.res_status = error;
76639d3e169Sevanl 			failed_res.xdr_len = 0;
76739d3e169Sevanl 			res = (caddr_t)&failed_res;
7685e1e04ceSdm120769 			res_size = 0;
76939d3e169Sevanl 			break;
77039d3e169Sevanl 		}
77139d3e169Sevanl 
7725e1e04ceSdm120769 		autofs_mntinfo_1_r((autofs_lookupargs *)xdrargs, &mount_res);
77339d3e169Sevanl 
77439d3e169Sevanl 		autofs_lookup_1_free_args(xdrargs);
77539d3e169Sevanl 		free(xdrargs);
77639d3e169Sevanl 
77739d3e169Sevanl 		/*
77839d3e169Sevanl 		 * Only reason we would get a NULL res is because
77939d3e169Sevanl 		 * we could not allocate a results buffer.  Use
7805e1e04ceSdm120769 		 * a local one to return the error EAGAIN as has
7815e1e04ceSdm120769 		 * always been done when memory allocations fail.
78239d3e169Sevanl 		 */
78339d3e169Sevanl 		if (!encode_res(xdr_autofs_mountres, &door_res,
78439d3e169Sevanl 		    (caddr_t)&mount_res, &res_size)) {
785d6c8399bSrmesta 			syslog(LOG_ERR,
786d6c8399bSrmesta 			    "error allocating mount results buffer");
7875e1e04ceSdm120769 			failed_res.res_status = EAGAIN;
78839d3e169Sevanl 			failed_res.xdr_len = 0;
78939d3e169Sevanl 			res = (caddr_t)&failed_res;
79039d3e169Sevanl 		} else {
79139d3e169Sevanl 			door_res->res_status = 0;
79239d3e169Sevanl 			res = (caddr_t)door_res;
79339d3e169Sevanl 		}
79439d3e169Sevanl 		autofs_mount_1_free_r(&mount_res);
79539d3e169Sevanl 		break;
79639d3e169Sevanl 
79739d3e169Sevanl 	case AUTOFS_UNMOUNT:
79839d3e169Sevanl 		if (error = decode_args(xdr_umntrequest,
79939d3e169Sevanl 		    (autofs_door_args_t *)argp,
80039d3e169Sevanl 		    (caddr_t *)&umnt_args, sizeof (umntrequest))) {
801d6c8399bSrmesta 			syslog(LOG_ERR,
802d6c8399bSrmesta 			    "error allocating unmount argument buffer");
80339d3e169Sevanl 			failed_res.res_status = error;
80439d3e169Sevanl 			failed_res.xdr_len = 0;
80539d3e169Sevanl 			res = (caddr_t)&failed_res;
80639d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
80739d3e169Sevanl 			break;
80839d3e169Sevanl 		}
80939d3e169Sevanl 
8103bfb48feSsemery 		autofs_unmount_1_r(umnt_args, &umount_res);
81139d3e169Sevanl 
81239d3e169Sevanl 		error = umount_res.status;
81339d3e169Sevanl 
81439d3e169Sevanl 		autofs_unmount_1_free_args(umnt_args);
81539d3e169Sevanl 		free(umnt_args);
8165e1e04ceSdm120769 
81739d3e169Sevanl 		if (!encode_res(xdr_umntres, &door_res, (caddr_t)&umount_res,
81839d3e169Sevanl 		    &res_size)) {
819d6c8399bSrmesta 			syslog(LOG_ERR,
820d6c8399bSrmesta 			    "error allocating unmount results buffer");
8215e1e04ceSdm120769 			failed_res.res_status = EINVAL;
82239d3e169Sevanl 			failed_res.xdr_len = 0;
82339d3e169Sevanl 			res = (caddr_t)&failed_res;
8245e1e04ceSdm120769 			res_size = sizeof (autofs_door_res_t);
82539d3e169Sevanl 		} else {
82639d3e169Sevanl 			door_res->res_status = 0;
82739d3e169Sevanl 			res = (caddr_t)door_res;
82839d3e169Sevanl 		}
82939d3e169Sevanl 		break;
83039d3e169Sevanl 
83139d3e169Sevanl 	case AUTOFS_READDIR:
83239d3e169Sevanl 		if (error = decode_args(xdr_autofs_rddirargs,
83339d3e169Sevanl 		    (autofs_door_args_t *)argp,
83439d3e169Sevanl 		    (caddr_t *)&rddir_args,
83539d3e169Sevanl 		    sizeof (autofs_rddirargs))) {
83639d3e169Sevanl 			syslog(LOG_ERR,
83739d3e169Sevanl 			    "error allocating readdir argument buffer");
83839d3e169Sevanl 			failed_res.res_status = error;
83939d3e169Sevanl 			failed_res.xdr_len = 0;
84039d3e169Sevanl 			res = (caddr_t)&failed_res;
84139d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
84239d3e169Sevanl 			break;
84339d3e169Sevanl 		}
84439d3e169Sevanl 
8453bfb48feSsemery 		autofs_readdir_1_r(rddir_args, &rddir_res);
84639d3e169Sevanl 
84739d3e169Sevanl 		free(rddir_args->rda_map);
84839d3e169Sevanl 		free(rddir_args);
8495e1e04ceSdm120769 
85039d3e169Sevanl 		if (!encode_res(xdr_autofs_rddirres, &door_res,
85139d3e169Sevanl 		    (caddr_t)&rddir_res, &res_size)) {
852d6c8399bSrmesta 			syslog(LOG_ERR,
853d6c8399bSrmesta 			    "error allocating readdir results buffer");
85439d3e169Sevanl 			failed_res.res_status = ENOMEM;
85539d3e169Sevanl 			failed_res.xdr_len = 0;
85639d3e169Sevanl 			res = (caddr_t)&failed_res;
8575e1e04ceSdm120769 			res_size = sizeof (autofs_door_res_t);
85839d3e169Sevanl 		} else {
85939d3e169Sevanl 			door_res->res_status = 0;
86039d3e169Sevanl 			res = (caddr_t)door_res;
86139d3e169Sevanl 		}
86239d3e169Sevanl 		autofs_readdir_1_free_r(&rddir_res);
86339d3e169Sevanl 		break;
86439d3e169Sevanl #ifdef MALLOC_DEBUG
86539d3e169Sevanl 	case AUTOFS_DUMP_DEBUG:
86639d3e169Sevanl 			check_leaks("/var/tmp/automountd.leak");
86739d3e169Sevanl 			error = door_return(NULL, 0, NULL, 0);
86839d3e169Sevanl 			/*
86939d3e169Sevanl 			 * If we got here, door_return() failed
87039d3e169Sevanl 			 */
87139d3e169Sevanl 			syslog(LOG_ERR, "dump debug door_return failure %d",
87239d3e169Sevanl 			    error);
87339d3e169Sevanl 			return;
87439d3e169Sevanl #endif
87539d3e169Sevanl 	case NULLPROC:
87639d3e169Sevanl 			res = NULL;
87739d3e169Sevanl 			res_size = 0;
87839d3e169Sevanl 			break;
87939d3e169Sevanl 	default:
88039d3e169Sevanl 			failed_res.res_status = EINVAL;
88139d3e169Sevanl 			res = (char *)&failed_res;
88239d3e169Sevanl 			res_size = sizeof (autofs_door_res_t);
88339d3e169Sevanl 			break;
88439d3e169Sevanl 	}
885d6c8399bSrmesta 
886d6c8399bSrmesta 	srsz = res_size;
887d6c8399bSrmesta 	errno = 0;
88839d3e169Sevanl 	error = door_return(res, res_size, NULL, 0);
889d6c8399bSrmesta 
890d6c8399bSrmesta 	if (errno == E2BIG) {
89139d3e169Sevanl 		/*
892d6c8399bSrmesta 		 * Failed due to encoded results being bigger than the
893d6c8399bSrmesta 		 * kernel expected bufsize. Passing actual results size
894d6c8399bSrmesta 		 * back down to kernel.
89539d3e169Sevanl 		 */
896d6c8399bSrmesta 		failed_res.res_status = EOVERFLOW;
897d6c8399bSrmesta 		failed_res.xdr_len = srsz;
898d6c8399bSrmesta 		res = (caddr_t)&failed_res;
899d6c8399bSrmesta 		res_size = sizeof (autofs_door_res_t);
900d6c8399bSrmesta 	} else {
901d6c8399bSrmesta 		syslog(LOG_ERR, "door_return failed %d, buffer %p, "
902d6c8399bSrmesta 		    "buffer size %d", error, (void *)res, res_size);
903d6c8399bSrmesta 		res = NULL;
904d6c8399bSrmesta 		res_size = 0;
905d6c8399bSrmesta 	}
906d6c8399bSrmesta 	(void) door_return(res, res_size, NULL, 0);
907d6c8399bSrmesta 	/* NOTREACHED */
90839d3e169Sevanl }
90939d3e169Sevanl 
91039d3e169Sevanl static int
start_autofs_svcs(void)91139d3e169Sevanl start_autofs_svcs(void)
91239d3e169Sevanl {
91339d3e169Sevanl 	int doorfd;
91439d3e169Sevanl #ifdef DEBUG
91539d3e169Sevanl 	int dfd;
91639d3e169Sevanl #endif
91739d3e169Sevanl 
91839d3e169Sevanl 	if ((doorfd = door_create(autofs_doorfunc, NULL,
91939d3e169Sevanl 	    DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
92039d3e169Sevanl 		syslog(LOG_ERR, gettext("Unable to create door\n"));
92139d3e169Sevanl 		return (1);
92239d3e169Sevanl 	}
92339d3e169Sevanl 
92439d3e169Sevanl #ifdef DEBUG
92539d3e169Sevanl 	/*
92639d3e169Sevanl 	 * Create a file system path for the door
92739d3e169Sevanl 	 */
92839d3e169Sevanl 	if ((dfd = open(AUTOFS_DOOR, O_RDWR|O_CREAT|O_TRUNC,
92939d3e169Sevanl 	    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
93039d3e169Sevanl 		syslog(LOG_ERR, "Unable to open %s: %m\n", AUTOFS_DOOR);
93139d3e169Sevanl 		(void) close(doorfd);
93239d3e169Sevanl 		return (1);
93339d3e169Sevanl 	}
93439d3e169Sevanl 
93539d3e169Sevanl 	/*
93639d3e169Sevanl 	 * stale associations clean up
93739d3e169Sevanl 	 */
93839d3e169Sevanl 	(void) fdetach(AUTOFS_DOOR);
93939d3e169Sevanl 
94039d3e169Sevanl 	/*
94139d3e169Sevanl 	 * Register in the namespace to the kernel to door_ki_open.
94239d3e169Sevanl 	 */
94339d3e169Sevanl 	if (fattach(doorfd, AUTOFS_DOOR) == -1) {
94439d3e169Sevanl 		syslog(LOG_ERR, "Unable to fattach door %m\n", AUTOFS_DOOR);
94539d3e169Sevanl 		(void) close(dfd);
94639d3e169Sevanl 		(void) close(doorfd);
94739d3e169Sevanl 		return (1);
94839d3e169Sevanl 	}
94939d3e169Sevanl #endif /* DEBUG */
95039d3e169Sevanl 
95139d3e169Sevanl 	/*
95239d3e169Sevanl 	 * Pass door name to kernel for door_ki_open
95339d3e169Sevanl 	 */
95439d3e169Sevanl 	autofs_setdoor(doorfd);
95539d3e169Sevanl 
95639d3e169Sevanl 	(void) thr_keycreate(&s_thr_key, NULL);
95739d3e169Sevanl 
95839d3e169Sevanl 	/*
95939d3e169Sevanl 	 * Wait for incoming calls
96039d3e169Sevanl 	 */
96139d3e169Sevanl 	/*CONSTCOND*/
96239d3e169Sevanl 	while (1)
96339d3e169Sevanl 		(void) pause();
96439d3e169Sevanl 
96539d3e169Sevanl 	/* NOTREACHED */
96639d3e169Sevanl 	syslog(LOG_ERR, gettext("Door server exited"));
96739d3e169Sevanl 	return (10);
96839d3e169Sevanl }
96939d3e169Sevanl 
97039d3e169Sevanl static int
decode_args(xdrproc_t xdrfunc,autofs_door_args_t * argp,caddr_t * xdrargs,int size)97139d3e169Sevanl decode_args(
97239d3e169Sevanl 	xdrproc_t xdrfunc,
97339d3e169Sevanl 	autofs_door_args_t *argp,
97439d3e169Sevanl 	caddr_t *xdrargs,
97539d3e169Sevanl 	int size)
97639d3e169Sevanl {
97739d3e169Sevanl 	XDR xdrs;
97839d3e169Sevanl 
97939d3e169Sevanl 	caddr_t tmpargs = (caddr_t)&((autofs_door_args_t *)argp)->xdr_arg;
98039d3e169Sevanl 	size_t arg_size = ((autofs_door_args_t *)argp)->xdr_len;
98139d3e169Sevanl 
98239d3e169Sevanl 	xdrmem_create(&xdrs, tmpargs, arg_size, XDR_DECODE);
98339d3e169Sevanl 
98439d3e169Sevanl 	*xdrargs = malloc(size);
98539d3e169Sevanl 	if (*xdrargs == NULL) {
986d6c8399bSrmesta 		syslog(LOG_ERR, "error allocating arguments buffer");
98739d3e169Sevanl 		return (ENOMEM);
98839d3e169Sevanl 	}
98939d3e169Sevanl 
99039d3e169Sevanl 	bzero(*xdrargs, size);
99139d3e169Sevanl 
99239d3e169Sevanl 	if (!(*xdrfunc)(&xdrs, *xdrargs)) {
99339d3e169Sevanl 		free(*xdrargs);
99439d3e169Sevanl 		*xdrargs = NULL;
99539d3e169Sevanl 		syslog(LOG_ERR, "error decoding arguments");
99639d3e169Sevanl 		return (EINVAL);
99739d3e169Sevanl 	}
99839d3e169Sevanl 
99939d3e169Sevanl 	return (0);
100039d3e169Sevanl }
100139d3e169Sevanl 
100239d3e169Sevanl 
100339d3e169Sevanl static bool_t
encode_res(xdrproc_t xdrfunc,autofs_door_res_t ** results,caddr_t resp,int * size)100439d3e169Sevanl encode_res(
100539d3e169Sevanl 	xdrproc_t xdrfunc,
100639d3e169Sevanl 	autofs_door_res_t **results,
100739d3e169Sevanl 	caddr_t resp,
100839d3e169Sevanl 	int *size)
100939d3e169Sevanl {
101039d3e169Sevanl 	XDR xdrs;
101139d3e169Sevanl 
101239d3e169Sevanl 	*size = xdr_sizeof((*xdrfunc), resp);
101339d3e169Sevanl 	*results = autofs_get_buffer(
101439d3e169Sevanl 	    sizeof (autofs_door_res_t) + *size);
101539d3e169Sevanl 	if (*results == NULL) {
10165e1e04ceSdm120769 		(*results)->res_status = ENOMEM;
101739d3e169Sevanl 		return (FALSE);
101839d3e169Sevanl 	}
101939d3e169Sevanl 	(*results)->xdr_len = *size;
102039d3e169Sevanl 	*size = sizeof (autofs_door_res_t) + (*results)->xdr_len;
102139d3e169Sevanl 	xdrmem_create(&xdrs, (caddr_t)((*results)->xdr_res),
1022d6c8399bSrmesta 	    (*results)->xdr_len, XDR_ENCODE);
10235e1e04ceSdm120769 	if (!(*xdrfunc)(&xdrs, resp)) {
10245e1e04ceSdm120769 		(*results)->res_status = EINVAL;
10255e1e04ceSdm120769 		syslog(LOG_ERR, "error encoding results");
102639d3e169Sevanl 		return (FALSE);
102739d3e169Sevanl 	}
102839d3e169Sevanl 	(*results)->res_status = 0;
102939d3e169Sevanl 	return (TRUE);
103039d3e169Sevanl }
10318548bf79Snr123932 
10328548bf79Snr123932 static void
automountd_wait_for_cleanup(pid_t pid)10338548bf79Snr123932 automountd_wait_for_cleanup(pid_t pid)
10348548bf79Snr123932 {
10358548bf79Snr123932 	int status;
10368548bf79Snr123932 	int child_exitval;
10378548bf79Snr123932 
10388548bf79Snr123932 	/*
10398548bf79Snr123932 	 * Wait for the main automountd process to exit so we cleanup
10408548bf79Snr123932 	 */
10418548bf79Snr123932 	(void) waitpid(pid, &status, 0);
10428548bf79Snr123932 
10438548bf79Snr123932 	child_exitval = WEXITSTATUS(status);
10448548bf79Snr123932 
10458548bf79Snr123932 	/*
10468548bf79Snr123932 	 * Shutdown the door server for mounting and unmounting
10478548bf79Snr123932 	 * filesystems
10488548bf79Snr123932 	 */
10498548bf79Snr123932 	if (door_revoke(did_fork_exec) == -1) {
1050d6c8399bSrmesta 		syslog(LOG_ERR, "failed to door_revoke(%d) %m", did_fork_exec);
10518548bf79Snr123932 	}
10528548bf79Snr123932 	if (door_revoke(did_exec_map) == -1) {
1053d6c8399bSrmesta 		syslog(LOG_ERR, "failed to door_revoke(%d) %m", did_exec_map);
10548548bf79Snr123932 	}
10558548bf79Snr123932 	exit(child_exitval);
10568548bf79Snr123932 }
1057