changeset 12926:e95332bf1454

6779186 need domain controller hot failover 6970986 Level II oplocks - smb_oplock_grant_t shouldn't be dynamically allocated 6971031 Unable add ACL on the share which has only the default owner tab by ZFS 6971899 OpenSSL not MT-safe and takes down smbd 6936762 libidmap should transparently handle interruption in connection to idmapd 6954902 mapping to unknown type does not use directory-based mapping information
author joyce mcintosh <Joyce.McIntosh@Sun.COM>
date Mon, 26 Jul 2010 15:02:13 -0700
parents fd395ba5d913
children d4c6a7489f84
files usr/src/cmd/idmap/idmap/idmap.c usr/src/cmd/idmap/idmap/namemaps.c usr/src/cmd/idmap/idmap/namemaps.h usr/src/cmd/idmap/idmapd/idmapd.h usr/src/cmd/smbsrv/smbd/server.xml usr/src/cmd/smbsrv/smbd/smbd.h usr/src/cmd/smbsrv/smbd/smbd_join.c usr/src/cmd/smbsrv/smbd/smbd_main.c usr/src/common/smbclnt/smbfs_ntacl.c usr/src/lib/libidmap/common/idmap.h usr/src/lib/libidmap/common/idmap_api.c usr/src/lib/libidmap/common/idmap_impl.h usr/src/lib/libidmap/common/idmap_priv.h usr/src/lib/libidmap/common/mapfile-vers usr/src/lib/libidmap/common/utils.c usr/src/lib/libsec/common/acltext.c usr/src/lib/libsec/common/aclutils.c usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/lib/nsswitch/ad/common/ad_common.h usr/src/lib/nsswitch/ad/common/getgrent.c usr/src/lib/nsswitch/ad/common/getpwnam.c usr/src/lib/nsswitch/ad/common/getspent.c usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c usr/src/lib/smbsrv/libsmb/common/smb_idmap.c usr/src/lib/smbsrv/libsmb/common/smb_sd.c usr/src/uts/common/fs/smbsrv/smb_ofile.c usr/src/uts/common/fs/smbsrv/smb_oplock.c usr/src/uts/common/smbsrv/smb_ktypes.h
diffstat 34 files changed, 597 insertions(+), 773 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/idmap/idmap/idmap.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/idmap/idmap/idmap.c	Mon Jul 26 15:02:13 2010 -0700
@@ -214,7 +214,6 @@
 static struct pos_sds *positions;
 
 /* Handles for idmap_api batch */
-static idmap_handle_t *handle = NULL;
 static idmap_udt_handle_t *udt = NULL;
 
 typedef struct {
@@ -472,61 +471,17 @@
 	return (0);
 }
 
-/* Initialization of the idmap api batch */
-static int
-init_batch()
-{
-	idmap_stat stat;
-
-	stat = idmap_init(&handle);
-	if (stat != IDMAP_SUCCESS) {
-		print_error(NULL,
-		    gettext("Connection not established (%s)\n"),
-		    idmap_stat2string(NULL, stat));
-		handle = NULL;
-		return (-1);
-	}
-
-	return (0);
-}
-
-/* Initialization of the libidmap API (idmap help doesn't run that) */
-static int
-init_command()
-{
-	if (batch_mode)
-		return (0);
-
-	return (init_batch());
-}
-
-/* Finalization of the libidmap API */
-static void
-fini_command()
-{
-	if (batch_mode)
-		return;
-
-	if (handle != NULL) {
-		(void) idmap_fini(handle);
-		handle = NULL;
-	}
-}
-
 /* Initialization of the commands which perform write operations  */
 static int
 init_udt_batch()
 {
 	idmap_stat stat;
 
-	if (init_batch())
-		return (-1);
-
-	stat = idmap_udt_create(handle, &udt);
+	stat = idmap_udt_create(&udt);
 	if (stat != IDMAP_SUCCESS) {
 		print_error(NULL,
 		    gettext("Error initiating transaction (%s)"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		return (-1);
 	}
 
@@ -577,7 +532,7 @@
 		if (stat1 != IDMAP_SUCCESS) {
 			print_error(NULL,
 			    gettext("Error diagnosing transaction (%s)\n"),
-			    idmap_stat2string(handle, stat1));
+			    idmap_stat2string(stat1));
 			goto out;
 		}
 
@@ -589,7 +544,7 @@
 
 		print_error(reported_pos,
 		    gettext("Error commiting transaction (%s)\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 	}
 
 out:
@@ -668,10 +623,6 @@
 {
 	idmap_stat stat;
 
-	if (!batch_mode)
-		if (init_batch() < 0)
-			return (-1);
-
 	if (namemaps.handle != NULL && (
 	    strcmp_null(user, namemaps.user) != 0 ||
 	    strcmp_null(passwd, namemaps.passwd) != 0 ||
@@ -682,13 +633,13 @@
 	}
 
 	if (namemaps.handle == NULL) {
-		stat = idmap_init_namemaps(handle, &namemaps.handle, user,
+		stat = idmap_init_namemaps(&namemaps.handle, user,
 		    passwd, auth, windomain, direction);
 		if (stat != IDMAP_SUCCESS) {
 			print_error(pos,
 			    gettext("Error: could not perform directory-based "
 			    "name mapping operation (%s)"),
-			    idmap_stat2string(handle, stat));
+			    idmap_stat2string(stat));
 			namemaps_free();
 			return (-1);
 		}
@@ -1597,9 +1548,6 @@
 	int		flag = 0;
 	idmap_info	info;
 
-	if (init_command())
-		return (-1);
-
 	ph = print_mapping_init(f[n_FLAG] != NULL ? MAPPING_NAME : MAPPING_ID,
 	    stdout);
 	if (ph == NULL)
@@ -1608,11 +1556,11 @@
 	if (f[v_FLAG] != NULL)
 		flag = IDMAP_REQ_FLG_MAPPING_INFO;
 
-	stat = idmap_iter_mappings(handle, &ihandle, flag);
+	stat = idmap_iter_mappings(&ihandle, flag);
 	if (stat < 0) {
 		print_error(pos,
 		    gettext("Iteration handle not obtained (%s)\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		rc = -1;
 		goto cleanup;
 	}
@@ -1646,7 +1594,7 @@
 	if (stat < 0 && stat != IDMAP_ERR_NOTFOUND) {
 		print_error(pos,
 		    gettext("Error during iteration (%s)\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		rc = -1;
 		goto cleanup;
 	}
@@ -1655,7 +1603,6 @@
 
 cleanup:
 	(void) print_mapping_fini(ph);
-	fini_command();
 	return (rc);
 }
 
@@ -2167,7 +2114,7 @@
 		print_error(pos,
 		    is_user ? gettext("Unable to flush users (%s).\n")
 		    : gettext("Unable to flush groups (%s).\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		return (-1);
 	}
 
@@ -2257,7 +2204,7 @@
 			if (stat < 0) {
 				print_error(&pos2,
 				    gettext("Transaction error (%s)\n"),
-				    idmap_stat2string(handle, stat));
+				    idmap_stat2string(stat));
 				rc = -1;
 			}
 
@@ -2299,11 +2246,11 @@
 	boolean_t is_wuser;
 	print_handle_t *ph;
 
-	stat = idmap_iter_namerules(handle, NULL, 0, 0, NULL, NULL, &ihandle);
+	stat = idmap_iter_namerules(NULL, 0, 0, NULL, NULL, &ihandle);
 	if (stat < 0) {
 		print_error(NULL,
 		    gettext("Iteration handle not obtained (%s)\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		idmap_iter_destroy(ihandle);
 		return (-1);
 	}
@@ -2337,7 +2284,7 @@
 	if (stat < 0 && stat !=  IDMAP_ERR_NOTFOUND) {
 		print_error(NULL,
 		    gettext("Error during iteration (%s)\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		idmap_iter_destroy(ihandle);
 		return (-1);
 	}
@@ -2370,16 +2317,9 @@
 		}
 	}
 
-	if (init_command() < 0) {
-		rc = -1;
-		goto cleanup;
-	}
-
 	/* List the requested types: */
 	rc = list_name_mappings(format, fi);
 
-	fini_command();
-
 cleanup:
 	if (fi != NULL && fi != stdout)
 		(void) fclose(fi);
@@ -2393,14 +2333,9 @@
 {
 	int rc;
 
-	if (init_command()) {
-		return (-1);
-	}
-
 	/* List the requested types: */
 	rc = list_name_mappings(DEFAULT_FORMAT, stdout);
 
-	fini_command();
 	return (rc);
 }
 
@@ -2707,7 +2642,7 @@
 	if (stat != IDMAP_SUCCESS) {
 		print_error(pos,
 		    gettext("Mapping not created (%s)\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		rc = -1;
 	}
 
@@ -2814,7 +2749,7 @@
 		if (stat != IDMAP_SUCCESS) {
 			print_error(pos,
 			    gettext("Mapping not deleted (%s)\n"),
-			    idmap_stat2string(handle, stat));
+			    idmap_stat2string(stat));
 			rc = -1;
 			break;
 		}
@@ -2849,18 +2784,14 @@
 	else
 		op = IDMAP_FLUSH_EXPIRE;
 
-	if (init_command())
-		return (-1);
-
-	stat = idmap_flush(handle, op);
+	stat = idmap_flush(op);
 	if (stat != IDMAP_SUCCESS) {
 		print_error(pos,
 		    gettext("%s\n"),
-		    idmap_stat2string(handle, stat));
+		    idmap_stat2string(stat));
 		rc = -1;
 	}
 
-	fini_command();
 	return (rc);
 }
 
@@ -2968,9 +2899,6 @@
 	if (f[V_FLAG] != NULL)
 		flag |= IDMAP_REQ_FLG_TRACE;
 
-	if (init_command())
-		return (-1);
-
 	nm = name_mapping_init();
 	if (nm == NULL)
 		goto cleanup;
@@ -3032,7 +2960,7 @@
 	    type_from  == TYPE_GSID || type_from  == TYPE_USID ||
 	    type_to  == TYPE_GSID || type_to  == TYPE_USID) {
 		if (type_from & IS_WIN) {
-			map_stat = idmap_get_w2u_mapping(handle,
+			map_stat = idmap_get_w2u_mapping(
 			    nm->sidprefix,
 			    &nm->rid,
 			    nm->winname,
@@ -3044,7 +2972,7 @@
 			    &nm->direction,
 			    &info);
 		} else {
-			map_stat = idmap_get_u2w_mapping(handle,
+			map_stat = idmap_get_u2w_mapping(
 			    &nm->pid,
 			    nm->unixname,
 			    flag,
@@ -3067,12 +2995,12 @@
 
 
 		/* Create an in-memory structure for all the batch: */
-		stat = idmap_get_create(handle, &ghandle);
+		stat = idmap_get_create(&ghandle);
 		if (stat != IDMAP_SUCCESS) {
 			print_error(pos,
 			    gettext("Unable to create handle for communicating"
 			    " with idmapd(1M) (%s)\n"),
-			    idmap_stat2string(handle, stat));
+			    idmap_stat2string(stat));
 			idmap_get_destroy(ghandle);
 			goto cleanup;
 		}
@@ -3129,7 +3057,7 @@
 		if (stat < 0) {
 			print_error(pos,
 			    gettext("Request for %.3s not sent (%s)\n"),
-			    argv[0], idmap_stat2string(handle, stat));
+			    argv[0], idmap_stat2string(stat));
 			idmap_get_destroy(ghandle);
 			goto cleanup;
 		}
@@ -3140,7 +3068,7 @@
 			print_error(pos,
 			    gettext("Mappings not obtained because of"
 			    " RPC problem (%s)\n"),
-			    idmap_stat2string(handle, stat));
+			    idmap_stat2string(stat));
 			idmap_get_destroy(ghandle);
 			goto cleanup;
 		}
@@ -3193,7 +3121,7 @@
 errormsg:
 	if (map_stat < 0) {
 		print_error(pos, gettext("Error:\t%s\n"),
-		    idmap_stat2string(handle, map_stat));
+		    idmap_stat2string(map_stat));
 		print_error_info(&info);
 	} else {
 		print_info(&info);
@@ -3203,7 +3131,6 @@
 cleanup:
 	if (nm != NULL)
 		name_mapping_fini(nm);
-	fini_command();
 	return (stat < 0 || map_stat < 0 ? -1 : 0);
 }
 
@@ -3342,7 +3269,7 @@
 	if (stat != IDMAP_SUCCESS) {
 		print_error(pos,
 		    gettext("Failed to set namemap (%s).\n"),
-		    idmap_stat2string(NULL, stat));
+		    idmap_stat2string(stat));
 	}
 
 	if (passwd != NULL) {
@@ -3425,7 +3352,7 @@
 	if (stat != IDMAP_SUCCESS) {
 		print_error(pos,
 		    gettext("Failed to unset namemap (%s).\n"),
-		    idmap_stat2string(NULL, stat));
+		    idmap_stat2string(stat));
 	}
 
 cleanup:
@@ -3498,7 +3425,7 @@
 	if (stat != IDMAP_SUCCESS) {
 		print_error(pos,
 		    gettext("Failed to get namemap info (%s).\n"),
-		    idmap_stat2string(NULL, stat));
+		    idmap_stat2string(stat));
 		goto cleanup;
 	}
 
@@ -3617,8 +3544,6 @@
 		fini_nm_command();
 	}
 
-	fini_command();
-
 	(void) engine_fini();
 	return (rc == 0 ? 0 : 1);
 }
--- a/usr/src/cmd/idmap/idmap/namemaps.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/idmap/idmap/namemaps.c	Mon Jul 26 15:02:13 2010 -0700
@@ -351,7 +351,7 @@
 
 
 idmap_stat
-idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh,
+idmap_init_namemaps(idmap_nm_handle_t **adh,
     char *user, char *passwd, char *auth, char *windomain,
     int direction)
 {
@@ -362,40 +362,40 @@
 	if (p == NULL)
 		return (IDMAP_ERR_MEMORY);
 
-	rc = idmap_get_prop_str(handle, PROP_DEFAULT_DOMAIN,
+	rc = idmap_get_prop_str(PROP_DEFAULT_DOMAIN,
 	    &p->default_domain);
 	if (rc != IDMAP_SUCCESS) {
 		namemap_log(
 		    gettext("Error obtaining default domain from idmapd (%s)"),
-		    idmap_stat2string(NULL, rc));
+		    idmap_stat2string(rc));
 		goto cleanup;
 	}
 
-	rc = idmap_get_prop_str(handle, PROP_AD_UNIXUSER_ATTR,
+	rc = idmap_get_prop_str(PROP_AD_UNIXUSER_ATTR,
 	    &p->ad_unixuser_attr);
 	if (rc != IDMAP_SUCCESS) {
 		namemap_log(
 		    gettext("Error obtaining AD unixuser attribute (%s)"),
-		    idmap_stat2string(NULL, rc));
+		    idmap_stat2string(rc));
 		goto cleanup;
 	}
 
-	rc = idmap_get_prop_str(handle, PROP_AD_UNIXGROUP_ATTR,
+	rc = idmap_get_prop_str(PROP_AD_UNIXGROUP_ATTR,
 	    &p->ad_unixgroup_attr);
 	if (rc != IDMAP_SUCCESS) {
 		namemap_log(
 		    gettext("Error obtaining AD unixgroup attribute (%s)"),
-		    idmap_stat2string(NULL, rc));
+		    idmap_stat2string(rc));
 		goto cleanup;
 	}
 
 
-	rc = idmap_get_prop_str(handle, PROP_NLDAP_WINNAME_ATTR,
+	rc = idmap_get_prop_str(PROP_NLDAP_WINNAME_ATTR,
 	    &p->nldap_winname_attr);
 	if (rc != IDMAP_SUCCESS) {
 		namemap_log(
 		    gettext("Error obtaining AD unixgroup attribute (%s)"),
-		    idmap_stat2string(NULL, rc));
+		    idmap_stat2string(rc));
 		goto cleanup;
 	}
 
--- a/usr/src/cmd/idmap/idmap/namemaps.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/idmap/idmap/namemaps.h	Mon Jul 26 15:02:13 2010 -0700
@@ -52,7 +52,7 @@
 
 extern void idmap_fini_namemaps(idmap_nm_handle_t *);
 
-extern idmap_stat idmap_init_namemaps(idmap_handle_t *, idmap_nm_handle_t **,
+extern idmap_stat idmap_init_namemaps(idmap_nm_handle_t **,
     char *, char *, char *, char *, int);
 
 #ifdef __cplusplus
--- a/usr/src/cmd/idmap/idmapd/idmapd.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/idmap/idmapd/idmapd.h	Mon Jul 26 15:02:13 2010 -0700
@@ -142,25 +142,28 @@
 } lookup_state_t;
 
 #define	NLDAP_OR_MIXED(nm) \
-	(nm == IDMAP_NM_NLDAP || nm == IDMAP_NM_MIXED)
+	((nm) == IDMAP_NM_NLDAP || (nm) == IDMAP_NM_MIXED)
 #define	AD_OR_MIXED(nm) \
-	(nm == IDMAP_NM_AD || nm == IDMAP_NM_MIXED)
+	((nm) == IDMAP_NM_AD || (nm) == IDMAP_NM_MIXED)
+
+#define	PID_UID_OR_UNKNOWN(pidtype) \
+	((pidtype) == IDMAP_UID || (pidtype) == IDMAP_POSIXID)
+#define	PID_GID_OR_UNKNOWN(pidtype) \
+	((pidtype) == IDMAP_GID || (pidtype) == IDMAP_POSIXID)
 
 #define	NLDAP_OR_MIXED_MODE(pidtype, ls) \
-	((pidtype == IDMAP_UID && NLDAP_OR_MIXED(ls->nm_siduid)) || \
-	(pidtype == IDMAP_GID && NLDAP_OR_MIXED(ls->nm_sidgid)))
+	(NLDAP_MODE(pidtype, ls) || MIXED_MODE(pidtype, ls))
 #define	AD_OR_MIXED_MODE(pidtype, ls)\
-	((pidtype == IDMAP_UID && AD_OR_MIXED(ls->nm_siduid)) || \
-	(pidtype == IDMAP_GID && AD_OR_MIXED(ls->nm_sidgid)))
+	(AD_MODE(pidtype, ls) || MIXED_MODE(pidtype, ls))
 #define	NLDAP_MODE(pidtype, ls) \
-	((pidtype == IDMAP_UID && ls->nm_siduid == IDMAP_NM_NLDAP) || \
-	(pidtype == IDMAP_GID && ls->nm_sidgid == IDMAP_NM_NLDAP))
+	((PID_UID_OR_UNKNOWN(pidtype) && (ls)->nm_siduid == IDMAP_NM_NLDAP) || \
+	(PID_GID_OR_UNKNOWN(pidtype) && (ls)->nm_sidgid == IDMAP_NM_NLDAP))
 #define	AD_MODE(pidtype, ls) \
-	((pidtype == IDMAP_UID && ls->nm_siduid == IDMAP_NM_AD) || \
-	(pidtype == IDMAP_GID && ls->nm_sidgid == IDMAP_NM_AD))
+	((PID_UID_OR_UNKNOWN(pidtype) && (ls)->nm_siduid == IDMAP_NM_AD) || \
+	(PID_GID_OR_UNKNOWN(pidtype) && (ls)->nm_sidgid == IDMAP_NM_AD))
 #define	MIXED_MODE(pidtype, ls) \
-	((pidtype == IDMAP_UID && ls->nm_siduid == IDMAP_NM_MIXED) || \
-	(pidtype == IDMAP_GID && ls->nm_sidgid == IDMAP_NM_MIXED))
+	((PID_UID_OR_UNKNOWN(pidtype) && (ls)->nm_siduid == IDMAP_NM_MIXED) || \
+	(PID_GID_OR_UNKNOWN(pidtype) && (ls)->nm_sidgid == IDMAP_NM_MIXED))
 
 
 typedef struct list_cb_data {
--- a/usr/src/cmd/smbsrv/smbd/server.xml	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/smbsrv/smbd/server.xml	Mon Jul 26 15:02:13 2010 -0700
@@ -64,7 +64,7 @@
 	<!-- Must have idmap service started -->
 	<dependency name='idmap'
 	    grouping='require_all'
-	    restart_on='restart'
+	    restart_on='none'
 	    type='service'>
 		<service_fmri value='svc:/system/idmap:default'/>
 	</dependency>
--- a/usr/src/cmd/smbsrv/smbd/smbd.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/smbsrv/smbd/smbd.h	Mon Jul 26 15:02:13 2010 -0700
@@ -45,14 +45,14 @@
 int smbd_nicmon_start(const char *);
 void smbd_nicmon_stop(void);
 int smbd_nicmon_refresh(void);
-boolean_t smbd_set_netlogon_cred(void);
-int smbd_locate_dc_start(void);
+int smbd_dc_monitor_init(void);
 smb_token_t *smbd_user_auth_logon(smb_logon_t *);
 void smbd_user_nonauth_logon(uint32_t);
 void smbd_user_auth_logoff(uint32_t);
 uint32_t smbd_join(smb_joininfo_t *);
 void smbd_set_secmode(int);
 boolean_t smbd_online(void);
+void smbd_online_wait(const char *);
 
 int smbd_vss_get_count(const char *, uint32_t *);
 void smbd_vss_get_snapshots(const char *, uint32_t, uint32_t *,
@@ -75,6 +75,10 @@
 	int		s_door_srv;
 	int		s_door_opipe;
 	int		s_secmode;	/* Current security mode */
+	pthread_t	s_refresh_tid;
+	pthread_t	s_localtime_tid;
+	pthread_t	s_spool_tid;
+	pthread_t	s_dc_monitor_tid;
 	boolean_t	s_nbt_listener_running;
 	boolean_t	s_tcp_listener_running;
 	pthread_t	s_nbt_listener_id;
--- a/usr/src/cmd/smbsrv/smbd/smbd_join.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c	Mon Jul 26 15:02:13 2010 -0700
@@ -37,19 +37,128 @@
 #include <smbsrv/smbinfo.h>
 #include "smbd.h"
 
+#define	SMBD_DC_MONITOR_ATTEMPTS		3
+#define	SMBD_DC_MONITOR_RETRY_INTERVAL		3	/* seconds */
+#define	SMBD_DC_MONITOR_INTERVAL		60	/* seconds */
 
-/*
- * This is a short-lived thread that triggers the initial DC discovery
- * at startup.
- */
-static pthread_t smb_locate_dc_thr;
+extern smbd_t smbd;
 
-static void *smbd_locate_dc_thread(void *);
+static void *smbd_dc_monitor(void *);
+static void smbd_dc_update(void);
+static boolean_t smbd_set_netlogon_cred(void);
 static int smbd_get_kpasswd_srv(char *, size_t);
 static uint32_t smbd_join_workgroup(smb_joininfo_t *);
 static uint32_t smbd_join_domain(smb_joininfo_t *);
 
 /*
+ * Launch the DC discovery and monitor thread.
+ */
+int
+smbd_dc_monitor_init(void)
+{
+	pthread_attr_t	attr;
+	int		rc;
+
+	smb_ads_init();
+
+	if (smbd.s_secmode != SMB_SECMODE_DOMAIN)
+		return (0);
+
+	(void) pthread_attr_init(&attr);
+	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	rc = pthread_create(&smbd.s_dc_monitor_tid, &attr, smbd_dc_monitor,
+	    NULL);
+	(void) pthread_attr_destroy(&attr);
+	return (rc);
+}
+
+/*ARGSUSED*/
+static void *
+smbd_dc_monitor(void *arg)
+{
+	boolean_t	ds_not_responding = B_FALSE;
+	int		i;
+
+	smbd_dc_update();
+	smbd_online_wait("smbd_dc_monitor");
+
+	while (smbd_online()) {
+		(void) sleep(SMBD_DC_MONITOR_INTERVAL);
+
+		for (i = 0; i < SMBD_DC_MONITOR_ATTEMPTS; ++i) {
+			if (dssetup_check_service() == 0) {
+				ds_not_responding = B_FALSE;
+				break;
+			}
+
+			ds_not_responding = B_TRUE;
+			(void) sleep(SMBD_DC_MONITOR_RETRY_INTERVAL);
+		}
+
+		if (ds_not_responding) {
+			smb_log(smbd.s_loghd, LOG_NOTICE,
+			    "smbd_dc_monitor: domain service not responding");
+
+			smb_ads_refresh();
+			smbd_dc_update();
+		}
+	}
+
+	smbd.s_dc_monitor_tid = 0;
+	return (NULL);
+}
+
+/*
+ * Locate a domain controller in the current resource domain and Update
+ * the Netlogon credential chain.
+ *
+ * The domain configuration will be updated upon successful DC discovery.
+ */
+static void
+smbd_dc_update(void)
+{
+	char		domain[MAXHOSTNAMELEN];
+	smb_domainex_t	info;
+	smb_domain_t	*primary;
+
+
+	if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) {
+		(void) smb_getdomainname(domain, MAXHOSTNAMELEN);
+		(void) smb_strupr(domain);
+	}
+
+	if (!smb_locate_dc(domain, "", &info)) {
+		smb_log(smbd.s_loghd, LOG_NOTICE,
+		    "smbd_dc_update: %s: locate failed", domain);
+	} else {
+		primary = &info.d_primary;
+
+		smb_config_setdomaininfo(primary->di_nbname,
+		    primary->di_fqname,
+		    primary->di_sid,
+		    primary->di_u.di_dns.ddi_forest,
+		    primary->di_u.di_dns.ddi_guid);
+
+		smb_log(smbd.s_loghd, LOG_NOTICE,
+		    "smbd_dc_update: %s: located %s", domain, info.d_dc);
+	}
+
+	if (smbd_set_netlogon_cred()) {
+		/*
+		 * Restart required because the domain changed
+		 * or the credential chain setup failed.
+		 */
+		smb_log(smbd.s_loghd, LOG_NOTICE,
+		    "smbd_dc_update: %s: smb/server restart required");
+
+		if (smb_smf_restart_service() != 0)
+			smb_log(smbd.s_loghd, LOG_ERR,
+			    "restart failed: run 'svcs -xv smb/server'"
+			    " for more information");
+	}
+}
+
+/*
  * smbd_join
  *
  * Joins the specified domain/workgroup.
@@ -91,7 +200,7 @@
  * If joining a new domain, the domain_name property must be set after a
  * successful credential chain setup.
  */
-boolean_t
+static boolean_t
 smbd_set_netlogon_cred(void)
 {
 	char kpasswd_srv[MAXHOSTNAMELEN];
@@ -103,9 +212,6 @@
 	smb_domainex_t dxi;
 	smb_domain_t *di;
 
-	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
-		return (B_FALSE);
-
 	if (smb_match_netlogon_seqnum())
 		return (B_FALSE);
 
@@ -158,7 +264,7 @@
 
 	smb_ipc_commit();
 	if (mlsvc_netlogon(dxi.d_dc, di->di_nbname)) {
-		syslog(LOG_ERR,
+		syslog(LOG_NOTICE,
 		    "failed to establish NETLOGON credential chain");
 		return (B_TRUE);
 	} else {
@@ -175,64 +281,6 @@
 }
 
 /*
- * smbd_locate_dc_start()
- *
- * Initialization of the thread that triggers the initial DC discovery
- * when SMB daemon starts up.
- * Returns 0 on success, an error number if thread creation fails.
- */
-int
-smbd_locate_dc_start(void)
-{
-	pthread_attr_t tattr;
-	int rc;
-
-	(void) pthread_attr_init(&tattr);
-	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-	rc = pthread_create(&smb_locate_dc_thr, &tattr, smbd_locate_dc_thread,
-	    NULL);
-	(void) pthread_attr_destroy(&tattr);
-	return (rc);
-}
-
-/*
- * smbd_locate_dc_thread()
- *
- * If necessary, set up Netlogon credential chain and locate a
- * domain controller in the given resource domain.
- *
- * The domain configuration will be updated upon a successful DC discovery.
- */
-/*ARGSUSED*/
-static void *
-smbd_locate_dc_thread(void *arg)
-{
-	char domain[MAXHOSTNAMELEN];
-	smb_domainex_t new_domain;
-	smb_domain_t *di;
-
-	if (!smb_match_netlogon_seqnum()) {
-		(void) smbd_set_netlogon_cred();
-	} else {
-		if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) {
-			(void) smb_getdomainname(domain, MAXHOSTNAMELEN);
-			(void) smb_strupr(domain);
-		}
-
-		if (smb_locate_dc(domain, "", &new_domain)) {
-			di = &new_domain.d_primary;
-			smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
-			    di->di_sid,
-			    di->di_u.di_dns.ddi_forest,
-			    di->di_u.di_dns.ddi_guid);
-		}
-	}
-
-	return (NULL);
-}
-
-
-/*
  * Retrieve the kpasswd server from krb5.conf.
  *
  * Initialization of the locate dc thread.
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c	Mon Jul 26 15:02:13 2010 -0700
@@ -58,6 +58,7 @@
 #include <smbsrv/libmlsvc.h>
 #include "smbd.h"
 
+#define	SMBD_ONLINE_WAIT_INTERVAL	10
 #define	SMB_CUPS_DOCNAME "generic_doc"
 #define	DRV_DEVICE_PATH	"/devices/pseudo/smbsrv@0:smbsrv"
 #define	SMB_DBDIR "/var/smb"
@@ -89,16 +90,15 @@
 static int smbd_localtime_init(void);
 static void *smbd_localtime_monitor(void *arg);
 
-static pthread_t localtime_thr;
+static int smbd_spool_init(void);
+static void *smbd_spool_monitor(void *arg);
 
 static int smbd_spool_init(void);
 static void *smbd_spool_monitor(void *arg);
-static pthread_t smbd_spool_thr;
 
 static int smbd_refresh_init(void);
 static void smbd_refresh_fini(void);
 static void *smbd_refresh_monitor(void *);
-static void smbd_refresh_dc(void);
 
 static void *smbd_nbt_receiver(void *);
 static void *smbd_nbt_listener(void *);
@@ -112,7 +112,6 @@
 
 static void smbd_fatal_error(const char *);
 
-static pthread_t refresh_thr;
 static pthread_cond_t refresh_cond;
 static pthread_mutex_t refresh_mutex;
 
@@ -516,17 +515,16 @@
 		}
 	}
 
-	smb_ads_init();
+	if (smbd_dc_monitor_init() != 0)
+		smbd_report("DC monitor initialization failed %s",
+		    strerror(errno));
+
 	if (mlsvc_init() != 0) {
 		smbd_report("msrpc initialization failed");
 		(void) mutex_unlock(&smbd_service_mutex);
 		return (-1);
 	}
 
-	if (smbd.s_secmode == SMB_SECMODE_DOMAIN)
-		if (smbd_locate_dc_start() != 0)
-			smbd_report("dc discovery failed %s", strerror(errno));
-
 	smbd.s_door_srv = smbd_door_start();
 	smbd.s_door_opipe = smbd_opipe_start();
 	if (smbd.s_door_srv < 0 || smbd.s_door_opipe < 0) {
@@ -623,7 +621,6 @@
 	smb_pwd_fini();
 	smb_domain_fini();
 	mlsvc_fini();
-	smb_ads_fini();
 	smb_netbios_stop();
 
 	smbd.s_initialized = B_FALSE;
@@ -654,7 +651,8 @@
 
 	(void) pthread_attr_init(&tattr);
 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-	rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0);
+	rc = pthread_create(&smbd.s_refresh_tid, &tattr, smbd_refresh_monitor,
+	    NULL);
 	(void) pthread_attr_destroy(&tattr);
 
 	return (rc);
@@ -668,8 +666,8 @@
 static void
 smbd_refresh_fini()
 {
-	if (pthread_self() != refresh_thr) {
-		(void) pthread_cancel(refresh_thr);
+	if (pthread_self() != smbd.s_refresh_tid) {
+		(void) pthread_cancel(smbd.s_refresh_tid);
 		(void) pthread_cond_destroy(&refresh_cond);
 		(void) pthread_mutex_destroy(&refresh_mutex);
 	}
@@ -722,28 +720,10 @@
 			smbd_report("NIC monitor refresh failed");
 		smb_netbios_name_reconfig();
 		smb_browser_reconfig();
-		smbd_refresh_dc();
 		dyndns_update_zones();
 
 		(void) mutex_unlock(&smbd_service_mutex);
 
-		if (smbd_set_netlogon_cred()) {
-			/*
-			 * Restart required because the domain changed
-			 * or the credential chain setup failed.
-			 */
-			if (smb_smf_restart_service() != 0) {
-				syslog(LOG_ERR,
-				    "unable to restart smb/server. "
-				    "Run 'svcs -xv smb/server' for more "
-				    "information.");
-				smbd_service_fini();
-				/*NOTREACHED*/
-			}
-
-			break;
-		}
-
 		if (!smbd.s_kbound) {
 			if ((error = smbd_kernel_bind()) == 0)
 				(void) smb_shr_load();
@@ -763,23 +743,6 @@
 	return (NULL);
 }
 
-/*
- * Update DC information on a refresh.
- */
-static void
-smbd_refresh_dc(void)
-{
-	char fqdomain[MAXHOSTNAMELEN];
-	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
-		return;
-
-	if (smb_getfqdomainname(fqdomain, MAXHOSTNAMELEN))
-		return;
-
-	if (!smb_locate_dc(fqdomain, "", NULL))
-		smbd_report("DC refresh failed");
-}
-
 void
 smbd_set_secmode(int secmode)
 {
@@ -808,6 +771,26 @@
 }
 
 /*
+ * Wait until the service is online.  Provided for threads that
+ * should wait until the service has been fully initialized before
+ * they start performing operations.
+ */
+void
+smbd_online_wait(const char *text)
+{
+	while (!smbd_online()) {
+		if (text != NULL)
+			smb_log(smbd.s_loghd, LOG_DEBUG,
+			    "%s: waiting for online", text);
+
+		(void) sleep(SMBD_ONLINE_WAIT_INTERVAL);
+	}
+
+	if (text != NULL)
+		smb_log(smbd.s_loghd, LOG_DEBUG, "%s: online", text);
+}
+
+/*
  * If the door has already been opened by another process (non-zero pid
  * in target), we assume that another smbd is already running.  If there
  * is a race here, it will be caught later when smbsrv is opened because
@@ -911,7 +894,8 @@
 
 	(void) pthread_attr_init(&tattr);
 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-	rc = pthread_create(&smbd_spool_thr, &tattr, smbd_spool_monitor, 0);
+	rc = pthread_create(&smbd.s_spool_tid, &tattr, smbd_spool_monitor,
+	    NULL);
 	(void) pthread_attr_destroy(&tattr);
 
 	return (rc);
@@ -936,6 +920,8 @@
 	smb_inaddr_t ipaddr;
 	int error_retry_cnt = 5;
 
+	smbd_online_wait("smbd_spool_monitor");
+
 	while (!smbd.s_shutting_down && (error_retry_cnt > 0)) {
 		errno = 0;
 
@@ -968,7 +954,8 @@
 
 	(void) pthread_attr_init(&tattr);
 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-	rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0);
+	rc = pthread_create(&smbd.s_localtime_tid, &tattr,
+	    smbd_localtime_monitor, NULL);
 	(void) pthread_attr_destroy(&tattr);
 	return (rc);
 }
@@ -992,6 +979,8 @@
 	int timeout;
 	int error;
 
+	smbd_online_wait("smbd_localtime_monitor");
+
 	for (;;) {
 		gmtoff = smbd_gmtoff();
 
--- a/usr/src/common/smbclnt/smbfs_ntacl.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/common/smbclnt/smbfs_ntacl.c	Mon Jul 26 15:02:13 2010 -0700
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -902,9 +901,6 @@
 	gid_t own_gid = (gid_t)-1;
 	i_ntacl_t *ntacl;
 	i_ntace_t **ntacep;
-#ifndef	_KERNEL
-	idmap_handle_t *idmap_h = NULL;
-#endif /* _KERNEL */
 	idmap_get_handle_t *idmap_gh = NULL;
 	idmap_stat	idms;
 
@@ -961,12 +957,7 @@
 #ifdef	_KERNEL
 	idmap_gh = kidmap_get_create(curproc->p_zone);
 #else /* _KERNEL */
-	idms = idmap_init(&idmap_h);
-	if (idms != IDMAP_SUCCESS) {
-		error = ENOTACTIVE;
-		goto errout;
-	}
-	idms = idmap_get_create(idmap_h, &idmap_gh);
+	idms = idmap_get_create(&idmap_gh);
 	if (idms != IDMAP_SUCCESS) {
 		error = ENOTACTIVE;
 		goto errout;
@@ -1147,8 +1138,6 @@
 #else /* _KERNEL */
 	if (idmap_gh != NULL)
 		idmap_get_destroy(idmap_gh);
-	if (idmap_h != NULL)
-		(void) idmap_fini(idmap_h);
 #endif /* _KERNEL */
 
 	return (error);
@@ -1440,9 +1429,6 @@
 	i_ntsd_t *sd = NULL;
 	i_ntacl_t *acl = NULL;
 	i_ntace_t **acep = NULL;
-#ifndef	_KERNEL
-	idmap_handle_t *idmap_h = NULL;
-#endif /* _KERNEL */
 	idmap_get_handle_t *idmap_gh = NULL;
 	idmap_stat	idms;
 
@@ -1499,12 +1485,7 @@
 #ifdef	_KERNEL
 	idmap_gh = kidmap_get_create(curproc->p_zone);
 #else /* _KERNEL */
-	idms = idmap_init(&idmap_h);
-	if (idms != IDMAP_SUCCESS) {
-		error = ENOTACTIVE;
-		goto errout;
-	}
-	idms = idmap_get_create(idmap_h, &idmap_gh);
+	idms = idmap_get_create(&idmap_gh);
 	if (idms != IDMAP_SUCCESS) {
 		error = ENOTACTIVE;
 		goto errout;
@@ -1719,8 +1700,6 @@
 #else /* _KERNEL */
 	if (idmap_gh != NULL)
 		idmap_get_destroy(idmap_gh);
-	if (idmap_h != NULL)
-		(void) idmap_fini(idmap_h);
 #endif /* _KERNEL */
 
 	return (error);
--- a/usr/src/lib/libidmap/common/idmap.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libidmap/common/idmap.h	Mon Jul 26 15:02:13 2010 -0700
@@ -46,9 +46,6 @@
 
 typedef uint32_t	idmap_rid_t;
 
-/* Opaque client handle */
-typedef struct idmap_handle idmap_handle_t;
-
 /* Opaque "get-mapping" handle */
 typedef struct idmap_get_handle idmap_get_handle_t;
 
@@ -58,14 +55,9 @@
 /*
  * Setup API
  */
-/* Create/Init handle for userland clients */
-extern idmap_stat idmap_init(idmap_handle_t **);
-
-/* Finalize/close handle */
-extern idmap_stat idmap_fini(idmap_handle_t *);
 
 /* Status code to string */
-extern const char *idmap_stat2string(idmap_handle_t *, idmap_stat);
+extern const char *idmap_stat2string(idmap_stat);
 
 /* Free memory allocated by the API */
 extern void idmap_free(void *);
@@ -83,7 +75,7 @@
  * API to batch SID to UID/GID mapping requests
  */
 /* Create handle */
-extern idmap_stat idmap_get_create(idmap_handle_t *, idmap_get_handle_t **);
+extern idmap_stat idmap_get_create(idmap_get_handle_t **);
 
 /* Given SID, get UID */
 extern idmap_stat idmap_get_uidbysid(idmap_get_handle_t *, char *,
--- a/usr/src/lib/libidmap/common/idmap_api.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libidmap/common/idmap_api.c	Mon Jul 26 15:02:13 2010 -0700
@@ -38,7 +38,6 @@
 #include <sys/stat.h>
 #include <dlfcn.h>
 #include <libintl.h>
-#include <ucontext.h>
 #include <syslog.h>
 #include <assert.h>
 #include "idmap_impl.h"
@@ -49,11 +48,7 @@
 static int idmap_stat2errno(idmap_stat);
 static idmap_stat	idmap_strdupnull(char **, const char *);
 
-#define	__ITER_CREATE(itera, argu, handl, ityp)\
-	if (handl == NULL) {\
-		errno = EINVAL;\
-		return (IDMAP_ERR_ARG);\
-	}\
+#define	__ITER_CREATE(itera, argu, ityp)\
 	itera = calloc(1, sizeof (*itera));\
 	if (itera == NULL) {\
 		errno = ENOMEM;\
@@ -65,7 +60,6 @@
 		errno = ENOMEM;\
 		return (IDMAP_ERR_MEMORY);\
 	}\
-	itera->ih = handl;\
 	itera->type = ityp;\
 	itera->retcode = IDMAP_NEXT;\
 	itera->limit = 1024;\
@@ -105,136 +99,30 @@
 }
 
 
-#define	MIN_STACK_NEEDS	65536
-
-/*
- * Create and Initialize idmap client handle for rpc/doors
- *
- * Output:
- * handle - idmap handle
- */
-idmap_stat
-idmap_init(idmap_handle_t **handle)
+static idmap_stat
+idmap_get_prop(idmap_prop_type pr, idmap_prop_res *res)
 {
-	CLIENT			*clnt = NULL;
-	struct idmap_handle	*hptr;
-	uint_t			sendsz = 0;
-	stack_t			st;
-
-	*handle = NULL;
-	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
-	if (hptr == NULL)
-		return (IDMAP_ERR_MEMORY);
-
-	/*
-	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
-	 * the call args buffer and once for the call result buffer), so
-	 * we want to pick a sendsz that will be large enough, but not
-	 * too large.
-	 */
-	if (stack_getbounds(&st) == 0) {
-		/*
-		 * Estimate how much stack space is left;
-		 * st.ss_sp is the top of stack.
-		 */
-		if ((char *)&sendsz < (char *)st.ss_sp)
-			/* stack grows up */
-			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
-		else
-			/* stack grows down */
-			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
-
-		if (sendsz <= MIN_STACK_NEEDS) {
-			sendsz = 0;	/* RPC call may fail */
-		} else {
-			/* Leave 64Kb (just a guess) for our needs */
-			sendsz -= MIN_STACK_NEEDS;
-
-			/* Divide the stack space left by two */
-			sendsz = RNDUP(sendsz / 2);
-
-			/* Limit sendsz to 256KB */
-			if (sendsz > IDMAP_MAX_DOOR_RPC)
-				sendsz = IDMAP_MAX_DOOR_RPC;
-		}
-	}
-
-	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
-	if (clnt == NULL) {
-		free(hptr);
-		return (IDMAP_ERR_RPC);
-	}
-	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
-	hptr->privhandle = clnt;
-	*handle = hptr;
-	return (IDMAP_SUCCESS);
-}
-
-
-/*
- * Finalize idmap handle
- *
- * Input:
- * handle - idmap handle
- */
-idmap_stat
-idmap_fini(idmap_handle_t *handle)
-{
-	CLIENT			*clnt;
-	struct idmap_handle	*hptr;
-
-	if (handle == NULL)
-		return (IDMAP_SUCCESS);
-
-	hptr = (struct idmap_handle *)handle;
-
-	switch (hptr->type) {
-	case _IDMAP_HANDLE_RPC_DOORS:
-		clnt = (CLIENT *)hptr->privhandle;
-		if (clnt) {
-			if (clnt->cl_auth)
-				auth_destroy(clnt->cl_auth);
-			clnt_destroy(clnt);
-		}
-		break;
-	default:
-		break;
-	}
-	free(hptr);
-	return (IDMAP_SUCCESS);
-}
-
-
-static idmap_stat
-idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
-{
-	CLIENT			*clnt;
-	enum clnt_stat		clntstat;
-
+	idmap_stat retcode;
 
 	(void) memset(res, 0, sizeof (*res));
-	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
 
-	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
+	retcode = _idmap_clnt_call(IDMAP_GET_PROP,
 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
-
-	if (clntstat != RPC_SUCCESS) {
-		return (_idmap_rpc2stat(clnt));
-	}
+	if (retcode != IDMAP_SUCCESS)
+		return (retcode);
 
 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
 }
 
 
 idmap_stat
-idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
-    idmap_ad_disc_ds_t *dc)
+idmap_get_prop_ds(idmap_prop_type pr, idmap_ad_disc_ds_t *dc)
 {
 	idmap_prop_res res;
 	idmap_stat rc = IDMAP_SUCCESS;
 
-	rc = idmap_get_prop(handle, pr, &res);
+	rc = idmap_get_prop(pr, &res);
 	if (rc < 0)
 		return (rc);
 
@@ -254,12 +142,12 @@
  * otherwise IDMAP_SUCCESS is returned.
  */
 idmap_stat
-idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
+idmap_get_prop_str(idmap_prop_type pr, char **str)
 {
 	idmap_prop_res res;
 	idmap_stat rc = IDMAP_SUCCESS;
 
-	rc = idmap_get_prop(handle, pr, &res);
+	rc = idmap_get_prop(pr, &res);
 	if (rc < 0)
 		return (rc);
 
@@ -274,11 +162,11 @@
  * udthandle - update handle
  */
 idmap_stat
-idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
+idmap_udt_create(idmap_udt_handle_t **udthandle)
 {
 	idmap_udt_handle_t	*tmp;
 
-	if (handle == NULL || udthandle == NULL) {
+	if (udthandle == NULL) {
 		errno = EINVAL;
 		return (IDMAP_ERR_ARG);
 	}
@@ -287,7 +175,6 @@
 		return (IDMAP_ERR_MEMORY);
 	}
 
-	tmp->ih = handle;
 	*udthandle = tmp;
 	return (IDMAP_SUCCESS);
 }
@@ -306,8 +193,6 @@
 idmap_stat
 idmap_udt_commit(idmap_udt_handle_t *udthandle)
 {
-	CLIENT			*clnt;
-	enum clnt_stat		clntstat;
 	idmap_update_res	res;
 	idmap_stat		retcode;
 
@@ -318,16 +203,12 @@
 
 	(void) memset(&res, 0, sizeof (res));
 
-	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
-	clntstat = clnt_call(clnt, IDMAP_UPDATE,
+	retcode = _idmap_clnt_call(IDMAP_UPDATE,
 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
 	    TIMEOUT);
-
-	if (clntstat != RPC_SUCCESS) {
-		retcode = _idmap_rpc2stat(clnt);
+	if (retcode != IDMAP_SUCCESS)
 		goto out;
-	}
 
 	retcode = udthandle->commit_stat = res.retcode;
 	udthandle->error_index = res.error_index;
@@ -692,7 +573,7 @@
  * iter - iterator
  */
 idmap_stat
-idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
+idmap_iter_namerules(const char *windomain,
 		boolean_t is_user, boolean_t is_wuser, const char *winname,
 		const char *unixname, idmap_iter_t **iter)
 {
@@ -702,7 +583,7 @@
 	idmap_namerule			*rule;
 	idmap_retcode			retcode;
 
-	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
+	__ITER_CREATE(tmpiter, arg, IDMAP_LIST_NAMERULES);
 
 	rule = &arg->rule;
 	rule->is_user = is_user;
@@ -847,12 +728,12 @@
  * iter - iterator
  */
 idmap_stat
-idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
+idmap_iter_mappings(idmap_iter_t **iter, int flag)
 {
 	idmap_iter_t			*tmpiter;
 	idmap_list_mappings_1_argument	*arg = NULL;
 
-	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
+	__ITER_CREATE(tmpiter, arg, IDMAP_LIST_MAPPINGS);
 
 	arg->flag = flag;
 	*iter = tmpiter;
@@ -1055,23 +936,16 @@
  * gh - "get mapping" handle
  */
 idmap_stat
-idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
+idmap_get_create(idmap_get_handle_t **gh)
 {
 	idmap_get_handle_t	*tmp;
 
-	/* sanity checks */
-	if (handle == NULL || gh == NULL) {
-		errno = EINVAL;
-		return (IDMAP_ERR_ARG);
-	}
-
 	/* allocate the handle */
 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
 		errno = ENOMEM;
 		return (IDMAP_ERR_MEMORY);
 	}
 
-	tmp->ih = handle;
 	*gh = tmp;
 	return (IDMAP_SUCCESS);
 }
@@ -1557,8 +1431,6 @@
 idmap_stat
 idmap_get_mappings(idmap_get_handle_t *gh)
 {
-	CLIENT		*clnt;
-	enum clnt_stat	clntstat;
 	idmap_retcode	retcode;
 	idmap_ids_res	res;
 	idmap_id	*res_id;
@@ -1570,17 +1442,15 @@
 		errno = EINVAL;
 		return (IDMAP_ERR_ARG);
 	}
-	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
 
 	(void) memset(&res, 0, sizeof (idmap_ids_res));
-	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
+	retcode = _idmap_clnt_call(IDMAP_GET_MAPPED_IDS,
 	    (xdrproc_t)xdr_idmap_mapping_batch,
 	    (caddr_t)&gh->batch,
 	    (xdrproc_t)xdr_idmap_ids_res,
 	    (caddr_t)&res,
 	    TIMEOUT);
-	if (clntstat != RPC_SUCCESS) {
-		retcode = _idmap_rpc2stat(clnt);
+	if (retcode != IDMAP_SUCCESS) {
 		goto out;
 	}
 	if (res.retcode != IDMAP_SUCCESS) {
@@ -1726,25 +1596,16 @@
  * Get windows to unix mapping
  */
 idmap_stat
-idmap_get_w2u_mapping(idmap_handle_t *handle,
+idmap_get_w2u_mapping(
 		const char *sidprefix, idmap_rid_t *rid,
 		const char *winname, const char *windomain,
 		int flag, int *is_user, int *is_wuser,
 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
 {
-	CLIENT			*clnt;
-	enum clnt_stat		clntstat;
 	idmap_mapping		request, *mapping;
 	idmap_mappings_res	result;
 	idmap_retcode		retcode, rc;
 
-	if (handle == NULL) {
-		errno = EINVAL;
-		return (IDMAP_ERR_ARG);
-	}
-
-	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
-
 	(void) memset(&request, 0, sizeof (request));
 	(void) memset(&result, 0, sizeof (result));
 
@@ -1789,13 +1650,13 @@
 	else
 		request.id1.idtype = IDMAP_SID;
 
-	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
+	retcode = _idmap_clnt_call(IDMAP_GET_MAPPED_ID_BY_NAME,
 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
 	    TIMEOUT);
 
-	if (clntstat != RPC_SUCCESS)
-		return (_idmap_rpc2stat(clnt));
+	if (retcode != IDMAP_SUCCESS)
+		return (retcode);
 
 	retcode = result.retcode;
 
@@ -1849,26 +1710,17 @@
  * Get unix to windows mapping
  */
 idmap_stat
-idmap_get_u2w_mapping(idmap_handle_t *handle,
+idmap_get_u2w_mapping(
 		uid_t *pid, const char *unixname,
 		int flag, int is_user, int *is_wuser,
 		char **sidprefix, idmap_rid_t *rid,
 		char **winname, char **windomain,
 		int *direction, idmap_info *info)
 {
-	CLIENT			*clnt;
-	enum clnt_stat		clntstat;
 	idmap_mapping		request, *mapping;
 	idmap_mappings_res	result;
 	idmap_retcode		retcode, rc;
 
-	if (handle == NULL) {
-		errno = EINVAL;
-		return (IDMAP_ERR_ARG);
-	}
-
-	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
-
 	if (sidprefix)
 		*sidprefix = NULL;
 	if (winname)
@@ -1905,13 +1757,13 @@
 	else if (*is_wuser == 1)
 		request.id2.idtype = IDMAP_USID;
 
-	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
+	retcode = _idmap_clnt_call(IDMAP_GET_MAPPED_ID_BY_NAME,
 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
 	    TIMEOUT);
 
-	if (clntstat != RPC_SUCCESS)
-		return (_idmap_rpc2stat(clnt));
+	if (retcode != IDMAP_SUCCESS)
+		return (retcode);
 
 	retcode = result.retcode;
 
@@ -2060,9 +1912,8 @@
  * Return Value:
  * human-readable localized description of idmap_stat
  */
-/* ARGSUSED */
 const char *
-idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
+idmap_stat2string(idmap_stat status)
 {
 	int i;
 
@@ -2258,7 +2109,6 @@
 idmap_getuidbywinname(const char *name, const char *domain, int flag,
 	uid_t *uid)
 {
-	idmap_handle_t	*ih;
 	idmap_retcode	rc;
 	int		is_user = 1;
 	int		is_wuser = -1;
@@ -2273,11 +2123,8 @@
 			return (rc);
 	}
 	/* Get mapping */
-	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
-		return (rc);
-	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
+	rc = idmap_get_w2u_mapping(NULL, NULL, name, domain, flag,
 	    &is_user, &is_wuser, uid, NULL, &direction, NULL);
-	(void) idmap_fini(ih);
 
 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
 		/* If we have not got the domain don't store UID to winname */
@@ -2297,7 +2144,6 @@
 idmap_getgidbywinname(const char *name, const char *domain, int flag,
 	gid_t *gid)
 {
-	idmap_handle_t	*ih;
 	idmap_retcode	rc;
 	int		is_user = 0;
 	int		is_wuser = -1;
@@ -2313,11 +2159,8 @@
 	}
 
 	/* Get mapping */
-	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
-		return (rc);
-	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
+	rc = idmap_get_w2u_mapping(NULL, NULL, name, domain, flag,
 	    &is_user, &is_wuser, gid, NULL, &direction, NULL);
-	(void) idmap_fini(ih);
 
 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
 		/* If we have not got the domain don't store GID to winname */
@@ -2337,7 +2180,6 @@
 idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name,
 	char **domain)
 {
-	idmap_handle_t	*ih;
 	idmap_retcode	rc;
 	int		len;
 	char		*winname, *windomain;
@@ -2360,11 +2202,8 @@
 	}
 
 	/* Get mapping */
-	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
-		return (rc);
-	rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL,
+	rc = idmap_get_u2w_mapping(&pid, NULL, flag, is_user, NULL,
 	    NULL, NULL, &winname, &windomain, &direction, NULL);
-	(void) idmap_fini(ih);
 
 	/* Return on error */
 	if (rc != IDMAP_SUCCESS)
@@ -2429,23 +2268,17 @@
 }
 
 idmap_stat
-idmap_flush(idmap_handle_t *handle, idmap_flush_op op)
+idmap_flush(idmap_flush_op op)
 {
-	CLIENT			*clnt;
-	enum clnt_stat		clntstat;
-	idmap_retcode		res;
-
-	res = IDMAP_SUCCESS;
-	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
+	idmap_retcode		rc1, rc2;
 
-	clntstat = clnt_call(clnt, IDMAP_FLUSH,
+	rc1 = _idmap_clnt_call(IDMAP_FLUSH,
 	    (xdrproc_t)xdr_idmap_flush_op, (caddr_t)&op,
-	    (xdrproc_t)xdr_idmap_retcode, (caddr_t)&res, TIMEOUT);
+	    (xdrproc_t)xdr_idmap_retcode, (caddr_t)&rc2, TIMEOUT);
 
-	if (clntstat != RPC_SUCCESS) {
-		return (_idmap_rpc2stat(clnt));
-	}
-	return (res);
+	if (rc1 != IDMAP_SUCCESS)
+		return (rc1);
+	return (rc2);
 }
 
 
--- a/usr/src/lib/libidmap/common/idmap_impl.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libidmap/common/idmap_impl.h	Mon Jul 26 15:02:13 2010 -0700
@@ -43,25 +43,7 @@
 extern "C" {
 #endif
 
-#define	_IDMAP_HANDLE_RPC_DOORS		1
-
-#define	_IDMAP_GET_CLIENT_HANDLE(h, clnt) \
-		if (h == NULL) \
-			return (IDMAP_ERR_CLIENT_HANDLE);\
-		if (h->type != _IDMAP_HANDLE_RPC_DOORS) \
-			return (IDMAP_ERR_NOTSUPPORTED);\
-		clnt = (CLIENT *)h->privhandle;\
-		if (clnt == NULL)\
-			return (IDMAP_ERR_RPC_HANDLE);
-
-struct idmap_handle {
-	int	type;
-	void	*privhandle;
-	/* locks */
-};
-
 struct idmap_udt_handle {
-	struct idmap_handle	*ih;
 	idmap_update_batch	batch;
 	uint64_t		next;
 	int64_t			error_index;
@@ -90,7 +72,6 @@
 } idmap_get_res_t;
 
 struct idmap_get_handle {
-	struct idmap_handle	*ih;
 	idmap_mapping_batch	batch;
 	idmap_get_res_t		*retlist;
 	uint64_t		next;
@@ -104,7 +85,6 @@
 	gh->next = 0;
 
 struct idmap_iter {
-	struct idmap_handle	*ih;
 	int			type;
 	uint64_t		limit;
 	void			*arg;
@@ -122,11 +102,15 @@
 
 typedef idmap_retcode	_idmap_stat;
 
+extern idmap_stat	_idmap_clnt_call(const rpcproc_t,
+				const xdrproc_t, const caddr_t,
+				const xdrproc_t, caddr_t out,
+				const struct timeval);
+
 extern idmap_retcode	_udt_extend_batch(idmap_udt_handle_t *);
 extern idmap_retcode	_get_ids_extend_batch(idmap_get_handle_t *);
 extern idmap_stat	_iter_get_next_list(int, idmap_iter_t *, void *,
 				uchar_t **, size_t, xdrproc_t, xdrproc_t);
-extern idmap_stat	_idmap_rpc2stat(CLIENT *);
 
 extern idmap_logger_t logger;
 
--- a/usr/src/lib/libidmap/common/idmap_priv.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libidmap/common/idmap_priv.h	Mon Jul 26 15:02:13 2010 -0700
@@ -68,8 +68,7 @@
  */
 
 /* Create handle for updates */
-extern idmap_stat idmap_udt_create(idmap_handle_t *,
-	idmap_udt_handle_t **);
+extern idmap_stat idmap_udt_create(idmap_udt_handle_t **);
 
 /* Commit */
 extern idmap_stat idmap_udt_commit(idmap_udt_handle_t *);
@@ -100,15 +99,14 @@
 extern idmap_stat idmap_udt_flush_namerules(idmap_udt_handle_t *);
 
 /* Flush caches */
-extern idmap_stat idmap_flush(idmap_handle_t *, idmap_flush_op);
+extern idmap_stat idmap_flush(idmap_flush_op);
 
 /*
  * Iterator API
  */
 
 /* Create a iterator to get SID to UID/GID mappings */
-extern idmap_stat idmap_iter_mappings(idmap_handle_t *,	idmap_iter_t **,
-	int flag);
+extern idmap_stat idmap_iter_mappings(idmap_iter_t **, int flag);
 
 /* Iterate through the SID to UID/GID mappings */
 extern idmap_stat idmap_iter_next_mapping(idmap_iter_t *, char **,
@@ -116,7 +114,7 @@
 	boolean_t *, int *, idmap_info *);
 
 /* Create a iterator to get name-based mapping rules */
-extern idmap_stat idmap_iter_namerules(idmap_handle_t *, const char *,
+extern idmap_stat idmap_iter_namerules(const char *,
 	boolean_t, boolean_t, const char *, const char *, idmap_iter_t **);
 
 /* Iterate through the name-based mapping rules */
@@ -133,11 +131,11 @@
 /*
  * Get mapping
  */
-extern idmap_stat idmap_get_w2u_mapping(idmap_handle_t *, const char *,
+extern idmap_stat idmap_get_w2u_mapping(const char *,
 	idmap_rid_t *, const char *, const char *, int, int *, int *,
 	uid_t *, char **, int *, idmap_info *);
 
-extern idmap_stat idmap_get_u2w_mapping(idmap_handle_t *, uid_t *,
+extern idmap_stat idmap_get_u2w_mapping(uid_t *,
 	const char *, int, int, int *, char **, idmap_rid_t *, char **,
 	char **, int *, idmap_info *);
 
@@ -188,10 +186,8 @@
 	char **, idmap_rid_t *, idmap_info *, idmap_stat *);
 
 /* Properties */
-extern idmap_stat idmap_get_prop_ds(idmap_handle_t *, idmap_prop_type,
-    idmap_ad_disc_ds_t *);
-extern idmap_stat idmap_get_prop_str(idmap_handle_t *, idmap_prop_type,
-    char **);
+extern idmap_stat idmap_get_prop_ds(idmap_prop_type, idmap_ad_disc_ds_t *);
+extern idmap_stat idmap_get_prop_str(idmap_prop_type, char **);
 
 /*
  * Trace
--- a/usr/src/lib/libidmap/common/mapfile-vers	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libidmap/common/mapfile-vers	Mon Jul 26 15:02:13 2010 -0700
@@ -60,7 +60,6 @@
 	directory_sid_from_group_name;
 	directory_sid_from_name;
 	directory_sid_from_user_name;
-	idmap_fini;
 	idmap_flush;
 	idmap_free;
 	idmap_get_create;
@@ -87,7 +86,6 @@
 	idmap_how_clear;
 	idmap_info_free;
 	idmap_info_mov;
-	idmap_init;
 	idmap_iter_destroy;
 	idmap_iter_mappings;
 	idmap_iter_namerules;
--- a/usr/src/lib/libidmap/common/utils.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libidmap/common/utils.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,12 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Utility routines
  */
@@ -33,6 +30,9 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <libintl.h>
+#include <assert.h>
+#include <ucontext.h>
+#include <pthread.h>
 #include "idmap_impl.h"
 
 #define	_UDT_SIZE_INCR	1
@@ -41,6 +41,21 @@
 
 static struct timeval TIMEOUT = { 25, 0 };
 
+struct idmap_handle {
+	CLIENT		*client;
+	boolean_t	failed;
+	rwlock_t	lock;
+};
+
+static struct idmap_handle idmap_handle = {
+	NULL,		/* client */
+	B_TRUE,		/* failed */
+	DEFAULTRWLOCK,	/* lock */
+};
+
+static idmap_stat _idmap_clnt_connect(void);
+static void _idmap_clnt_disconnect(void);
+
 idmap_retcode
 _udt_extend_batch(idmap_udt_handle_t *udthandle)
 {
@@ -103,13 +118,10 @@
 		void *arg, uchar_t **list, size_t valsize,
 		xdrproc_t xdr_arg_proc, xdrproc_t xdr_res_proc)
 {
-
-	CLIENT		*clnt;
-	enum clnt_stat	clntstat;
+	idmap_stat rc;
 
 	iter->next = 0;
 	iter->retlist = NULL;
-	_IDMAP_GET_CLIENT_HANDLE(iter->ih, clnt);
 
 	/* init the result */
 	if (*list) {
@@ -122,20 +134,25 @@
 	}
 	(void) memset(*list, 0, valsize);
 
-	clntstat = clnt_call(clnt, type,
+	rc = _idmap_clnt_call(type,
 	    xdr_arg_proc, (caddr_t)arg,
 	    xdr_res_proc, (caddr_t)*list,
 	    TIMEOUT);
-	if (clntstat != RPC_SUCCESS) {
+	if (rc != IDMAP_SUCCESS) {
 		free(*list);
-		return (_idmap_rpc2stat(clnt));
+		return (rc);
 	}
 	iter->retlist = *list;
 	return (IDMAP_SUCCESS);
 }
 
+/*
+ * Convert the return values from an RPC request into an idmap return code.
+ * Set errno on error.
+ */
+static
 idmap_stat
-_idmap_rpc2stat(CLIENT *clnt)
+_idmap_rpc2stat(enum clnt_stat clntstat, CLIENT *clnt)
 {
 	/*
 	 * We only deal with door_call(3C) errors here. We look at
@@ -144,19 +161,191 @@
 	 * and others.
 	 */
 	struct rpc_err r_err;
-	if (clnt) {
-		clnt_geterr(clnt, &r_err);
-		errno = r_err.re_errno;
-		switch (r_err.re_errno) {
-		case ENOMEM:
-			return (IDMAP_ERR_MEMORY);
-		case EBADF:
-			return (IDMAP_ERR_RPC_HANDLE);
-		default:
-			return (IDMAP_ERR_RPC);
+
+	if (clntstat == RPC_SUCCESS)
+		return (IDMAP_SUCCESS);
+
+	clnt_geterr(clnt, &r_err);
+	errno = r_err.re_errno;
+	switch (r_err.re_errno) {
+	case ENOMEM:
+		return (IDMAP_ERR_MEMORY);
+	case EBADF:
+		return (IDMAP_ERR_RPC_HANDLE);
+	default:
+		return (IDMAP_ERR_RPC);
+	}
+}
+
+/*
+ * Management of the connection to idmapd.
+ *
+ * The intent is that connections to idmapd are automatically maintained,
+ * reconnecting if necessary.  No attempt is made to retry connnection
+ * attempts; a failure to connect yields an immediate error return.
+ *
+ * State of the connection is maintained through the "client" and "failed"
+ * elements of the handle structure:
+ *
+ * client   failed
+ * NULL     true     Failed on a previous request and was not recovered.
+ * NULL     false    Should never happen.
+ * nonNULL  true     Structure exists, but an error has occurred.  Waiting
+ *                   for a chance to attempt to reconnect.
+ * nonNULL  false    Connection is good.
+ *
+ * Note that the initial state is NULL/true, so that the first request
+ * will establish the initial connection.
+ *
+ * Concurrency is managed through the rw lock "lock".  Only the writer is
+ * allowed to connect or disconnect, and thus only the writer can set
+ * "failed" to "false".  Readers are allowed to use the "client" pointer,
+ * and to set "failed" to "true", indicating that they have encountered a
+ * failure.  The "client" pointer is only valid while one holds a reader
+ * lock.  Once "failed" has been set to "true", all requests (including
+ * the retry of the failing request) will attempt to gain the writer lock.
+ * When they succeed, indicating that there are no requests in flight and
+ * thus no outstanding references to the CLIENT structure, they check
+ * again to see if the connection is still failed (since another thread
+ * might have fixed it), and then if it is still failed they disconnect
+ * and reconnect.
+ */
+
+/*
+ * Make an RPC call.  Automatically reconnect if the connection to idmapd
+ * fails.  Convert RPC results to idmap return codes.
+ */
+idmap_stat
+_idmap_clnt_call(
+    const rpcproc_t procnum,
+    const xdrproc_t inproc,
+    const caddr_t in,
+    const xdrproc_t outproc,
+    caddr_t out,
+    const struct timeval tout)
+{
+	enum clnt_stat	clntstat;
+	idmap_stat rc;
+
+	(void) rw_rdlock(&idmap_handle.lock);
+	for (;;) {
+		if (idmap_handle.failed) {
+			/* No connection.  Bid to see if we should fix it. */
+			(void) rw_unlock(&idmap_handle.lock);
+			/* Somebody else might fix it here. */
+			(void) rw_wrlock(&idmap_handle.lock);
+			/*
+			 * At this point, everybody else is asleep waiting
+			 * for us.  Check to see if somebody else has already
+			 * fixed the problem.
+			 */
+			if (idmap_handle.failed) {
+				/* It's our job to fix. */
+				_idmap_clnt_disconnect();
+				rc = _idmap_clnt_connect();
+				if (rc != IDMAP_SUCCESS) {
+					/* We couldn't fix it. */
+					assert(idmap_handle.failed);
+					assert(idmap_handle.client == NULL);
+					break;
+				}
+				/* We fixed it. */
+				idmap_handle.failed = B_FALSE;
+			}
+
+			/* It's fixed now. */
+			(void) rw_unlock(&idmap_handle.lock);
+			/*
+			 * Starting here, somebody might declare it failed
+			 * again.
+			 */
+			(void) rw_rdlock(&idmap_handle.lock);
+			continue;
+		}
+
+		clntstat = clnt_call(idmap_handle.client, procnum, inproc, in,
+		    outproc, out, tout);
+		rc = _idmap_rpc2stat(clntstat, idmap_handle.client);
+		if (rc == IDMAP_ERR_RPC_HANDLE) {
+			/* Failed.  Needs to be reconnected. */
+			idmap_handle.failed = B_TRUE;
+			continue;
+		}
+
+		/* Success or unrecoverable failure. */
+		break;
+	}
+	(void) rw_unlock(&idmap_handle.lock);
+	return (rc);
+}
+
+#define	MIN_STACK_NEEDS	65536
+
+/*
+ * Connect to idmapd.
+ * Must be single-threaded through rw_wrlock(&idmap_handle.lock).
+ */
+static
+idmap_stat
+_idmap_clnt_connect(void)
+{
+	uint_t			sendsz = 0;
+	stack_t			st;
+
+	/*
+	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
+	 * the call args buffer and once for the call result buffer), so
+	 * we want to pick a sendsz that will be large enough, but not
+	 * too large.
+	 */
+	if (stack_getbounds(&st) == 0) {
+		/*
+		 * Estimate how much stack space is left;
+		 * st.ss_sp is the top of stack.
+		 */
+		if ((char *)&sendsz < (char *)st.ss_sp)
+			/* stack grows up */
+			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
+		else
+			/* stack grows down */
+			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
+
+		if (sendsz <= MIN_STACK_NEEDS) {
+			sendsz = 0;	/* RPC call may fail */
+		} else {
+			/* Leave 64Kb (just a guess) for our needs */
+			sendsz -= MIN_STACK_NEEDS;
+
+			/* Divide the stack space left by two */
+			sendsz = RNDUP(sendsz / 2);
+
+			/* Limit sendsz to 256KB */
+			if (sendsz > IDMAP_MAX_DOOR_RPC)
+				sendsz = IDMAP_MAX_DOOR_RPC;
 		}
 	}
 
-	/* null handle */
-	return (IDMAP_ERR_RPC_HANDLE);
+	idmap_handle.client = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
+	if (idmap_handle.client == NULL)
+		return (IDMAP_ERR_RPC);
+
+	return (IDMAP_SUCCESS);
 }
+
+/*
+ * Disconnect from idmapd, if we're connected.
+ */
+static
+void
+_idmap_clnt_disconnect(void)
+{
+	CLIENT *clnt;
+
+	clnt = idmap_handle.client;
+	if (clnt != NULL) {
+		if (clnt->cl_auth)
+			auth_destroy(clnt->cl_auth);
+		clnt_destroy(clnt);
+		idmap_handle.client = NULL;
+	}
+}
--- a/usr/src/lib/libsec/common/acltext.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libsec/common/acltext.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*LINTLIBRARY*/
@@ -120,7 +119,6 @@
 static int
 getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve)
 {
-	idmap_handle_t *idmap_hdl = NULL;
 	idmap_get_handle_t *get_hdl = NULL;
 	idmap_stat status;
 	idmap_rid_t rid;
@@ -144,8 +142,7 @@
 			    IDMAP_REQ_FLG_USE_CACHE, &name, &domain);
 	}
 	if (error != IDMAP_SUCCESS) {
-		if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS &&
-		    idmap_get_create(idmap_hdl, &get_hdl) == IDMAP_SUCCESS) {
+		if (idmap_get_create(&get_hdl) == IDMAP_SUCCESS) {
 			if (user)
 				error = idmap_get_sidbyuid(get_hdl, who,
 				    IDMAP_REQ_FLG_USE_CACHE, &domain, &rid,
@@ -168,8 +165,6 @@
 		}
 		if (get_hdl)
 			idmap_get_destroy(get_hdl);
-		if (idmap_hdl)
-			(void) idmap_fini(idmap_hdl);
 	} else {
 		int len;
 
--- a/usr/src/lib/libsec/common/aclutils.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libsec/common/aclutils.c	Mon Jul 26 15:02:13 2010 -0700
@@ -740,7 +740,6 @@
 int
 sid_to_id(char *sid, boolean_t user, uid_t *id)
 {
-	idmap_handle_t *idmap_hdl = NULL;
 	idmap_get_handle_t *get_hdl = NULL;
 	char *rid_start = NULL;
 	idmap_stat status;
@@ -757,8 +756,7 @@
 		errno = 0;
 		rid = strtoul(rid_start--, &end, 10);
 		if (errno == 0 && *end == '\0') {
-			if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS &&
-			    idmap_get_create(idmap_hdl, &get_hdl) ==
+			if (idmap_get_create(&get_hdl) ==
 			    IDMAP_SUCCESS) {
 				if (user)
 					error = idmap_get_uidbysid(get_hdl,
@@ -781,8 +779,6 @@
 			}
 			if (get_hdl)
 				idmap_get_destroy(get_hdl);
-			if (idmap_hdl)
-				(void) idmap_fini(idmap_hdl);
 		} else {
 			error = 1;
 		}
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Mon Jul 26 15:02:13 2010 -0700
@@ -2201,14 +2201,11 @@
 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
     char **domainp, idmap_rid_t *ridp)
 {
-	idmap_handle_t *idmap_hdl = NULL;
 	idmap_get_handle_t *get_hdl = NULL;
 	idmap_stat status;
 	int err = EINVAL;
 
-	if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS)
-		goto out;
-	if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS)
+	if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
 		goto out;
 
 	if (isuser) {
@@ -2227,8 +2224,6 @@
 out:
 	if (get_hdl)
 		idmap_get_destroy(get_hdl);
-	if (idmap_hdl)
-		(void) idmap_fini(idmap_hdl);
 	return (err);
 }
 
--- a/usr/src/lib/nsswitch/ad/common/ad_common.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/nsswitch/ad/common/ad_common.h	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef	_AD_COMMON_H
@@ -82,7 +81,6 @@
 	fnf			adobj2str;
 	char			*buffer;
 	int			buflen;
-	idmap_handle_t		*ih;
 	uid_t			uid;
 	adutils_result_t	*result;
 	nss_ad_db_type_t	db_type;
--- a/usr/src/lib/nsswitch/ad/common/getgrent.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/nsswitch/ad/common/getgrent.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <grp.h>
@@ -72,7 +71,6 @@
 	idmap_stat	idmaprc;
 	gid_t		gid;
 	int		is_user, is_wuser;
-	idmap_handle_t	*ih;
 
 	be->db_type = NSS_AD_DB_GROUP_BYNAME;
 
@@ -89,14 +87,10 @@
 	/*
 	 * Map the name to gid using idmap service.
 	 */
-	idmaprc = idmap_init(&ih);
-	if (idmaprc != IDMAP_SUCCESS)
-		return ((nss_status_t)NSS_NOTFOUND);
 	is_wuser = -1;
 	is_user = 0; /* Map name to gid */
-	idmaprc = idmap_get_w2u_mapping(ih, NULL, NULL, name, dname,
+	idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
 	    0, &is_user, &is_wuser, &gid, NULL, NULL, NULL);
-	(void) idmap_fini(ih);
 	if (idmaprc != IDMAP_SUCCESS) {
 		RESET_ERRNO();
 		return ((nss_status_t)NSS_NOTFOUND);
@@ -134,9 +128,7 @@
 		goto out;
 
 	/* Map the given GID to a SID using the idmap service */
-	if (idmap_init(&be->ih) != 0)
-		goto out;
-	if (idmap_get_u2w_mapping(be->ih, &argp->key.gid, NULL, 0,
+	if (idmap_get_u2w_mapping(&argp->key.gid, NULL, 0,
 	    0, NULL, NULL, NULL, &winname, &windomain,
 	    NULL, NULL) != 0) {
 		RESET_ERRNO();
@@ -161,8 +153,6 @@
 out:
 	idmap_free(winname);
 	idmap_free(windomain);
-	(void) idmap_fini(be->ih);
-	be->ih = NULL;
 	return (stat);
 }
 
--- a/usr/src/lib/nsswitch/ad/common/getpwnam.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/nsswitch/ad/common/getpwnam.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <pwd.h>
@@ -192,9 +191,7 @@
 	nss_result = NSS_STR_PARSE_PARSE;
 
 	/* Create handles for idmap service */
-	if (be->ih == NULL && idmap_init(&be->ih) != 0)
-		goto result_pwd2str;
-	if (idmap_get_create(be->ih, &ig) != 0)
+	if (idmap_get_create(&ig) != 0)
 		goto result_pwd2str;
 
 	/* Get name */
@@ -278,8 +275,6 @@
 
 result_pwd2str:
 	idmap_get_destroy(ig);
-	(void) idmap_fini(be->ih);
-	be->ih = NULL;
 	(void) adutils_freeresult(&be->result);
 	free(domain);
 	if (homedir != NULL_STR && homedir_v != NULL &&
@@ -310,7 +305,6 @@
 	uid_t		uid;
 	gid_t		gid;
 	int		is_user, is_wuser, try_idmap;
-	idmap_handle_t	*ih;
 
 	be->db_type = NSS_AD_DB_PASSWD_BYNAME;
 
@@ -329,17 +323,13 @@
 	 * call fails then this will save us doing AD discovery and
 	 * AD lookup here.
 	 */
-	if (idmap_init(&be->ih) != IDMAP_SUCCESS)
-		return ((nss_status_t)NSS_NOTFOUND);
 	flag = (strcasecmp(dname, WK_DOMAIN) == 0) ?
 	    IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0;
 	is_wuser = -1;
 	is_user = 1;
-	if (idmap_get_w2u_mapping(be->ih, NULL, NULL, name,
+	if (idmap_get_w2u_mapping(NULL, NULL, name,
 	    dname, flag, &is_user, &is_wuser, &be->uid, NULL,
 	    NULL, NULL) != IDMAP_SUCCESS) {
-		(void) idmap_fini(be->ih);
-		be->ih = NULL;
 		RESET_ERRNO();
 		return ((nss_status_t)NSS_NOTFOUND);
 	}
@@ -357,11 +347,8 @@
 		    dname, &try_idmap);
 		free(searchfilter);
 
-		if (!try_idmap) {
-			(void) idmap_fini(be->ih);
-			be->ih = NULL;
+		if (!try_idmap)
 			return (stat);
-		}
 
 	}
 
@@ -372,10 +359,8 @@
 	 */
 	is_wuser = -1;
 	is_user = 0; /* Map name to primary gid */
-	idmaprc = idmap_get_w2u_mapping(be->ih, NULL, NULL, name, dname,
+	idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
 	    flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL);
-	(void) idmap_fini(be->ih);
-	be->ih = NULL;
 	if (idmaprc != IDMAP_SUCCESS) {
 		RESET_ERRNO();
 		return ((nss_status_t)NSS_NOTFOUND);
@@ -424,9 +409,7 @@
 		goto out;
 
 	/* Map the given UID to a SID using the idmap service */
-	if (idmap_init(&be->ih) != 0)
-		goto out;
-	if (idmap_get_u2w_mapping(be->ih, &argp->key.uid, NULL, 0,
+	if (idmap_get_u2w_mapping(&argp->key.uid, NULL, 0,
 	    1, NULL, &sidprefix, &rid, &winname, &windomain,
 	    NULL, NULL) != 0) {
 		RESET_ERRNO();
@@ -461,13 +444,10 @@
 	/* Map winname to primary gid using idmap service */
 	is_user = 0;
 	is_wuser = -1;
-	idmaprc = idmap_get_w2u_mapping(be->ih, NULL, NULL,
+	idmaprc = idmap_get_w2u_mapping(NULL, NULL,
 	    winname, windomain, 0, &is_user, &is_wuser, &gid,
 	    NULL, NULL, NULL);
 
-	(void) idmap_fini(be->ih);
-	be->ih = NULL;
-
 	if (idmaprc != IDMAP_SUCCESS) {
 		RESET_ERRNO();
 		goto out;
@@ -486,8 +466,6 @@
 	idmap_free(sidprefix);
 	idmap_free(winname);
 	idmap_free(windomain);
-	(void) idmap_fini(be->ih);
-	be->ih = NULL;
 	return (stat);
 }
 
--- a/usr/src/lib/nsswitch/ad/common/getspent.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/nsswitch/ad/common/getspent.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <shadow.h>
@@ -80,7 +79,6 @@
 	idmap_stat	idmaprc;
 	uid_t		uid;
 	int		is_user, is_wuser;
-	idmap_handle_t	*ih;
 
 	be->db_type = NSS_AD_DB_SHADOW_BYNAME;
 
@@ -98,14 +96,10 @@
 	 * Use idmap service to verify that the given
 	 * name is a valid Windows name.
 	 */
-	idmaprc = idmap_init(&ih);
-	if (idmaprc != IDMAP_SUCCESS)
-		return ((nss_status_t)NSS_NOTFOUND);
 	is_wuser = -1;
 	is_user = 1;
-	idmaprc = idmap_get_w2u_mapping(ih, NULL, NULL, name, dname,
+	idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
 	    0, &is_user, &is_wuser, &uid, NULL, NULL, NULL);
-	(void) idmap_fini(ih);
 	if (idmaprc != IDMAP_SUCCESS) {
 		RESET_ERRNO();
 		return ((nss_status_t)NSS_NOTFOUND);
--- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -78,3 +77,20 @@
 	ndr_rpc_unbind(&handle);
 	return (0);
 }
+
+int
+dssetup_check_service(void)
+{
+	ds_primary_domain_info_t	ds_info;
+	int				rc;
+
+	bzero(&ds_info, sizeof (ds_primary_domain_info_t));
+
+	if ((rc = dssetup_get_domain_info(&ds_info)) == 0) {
+		free(ds_info.nt_domain);
+		free(ds_info.dns_domain);
+		free(ds_info.forest);
+	}
+
+	return (rc);
+}
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Mon Jul 26 15:02:13 2010 -0700
@@ -60,11 +60,11 @@
 
 extern boolean_t smb_locate_dc(char *, char *, smb_domainex_t *);
 
+extern int dssetup_check_service(void);
 extern void dssetup_clear_domain_info(void);
 extern void mlsvc_disconnect(const char *);
 extern int mlsvc_init(void);
 extern void mlsvc_fini(void);
-extern int mlsvc_ping(const char *);
 extern DWORD mlsvc_netlogon(char *, char *);
 extern DWORD mlsvc_join(smb_domainex_t *, char *, char *);
 
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Mon Jul 26 15:02:13 2010 -0700
@@ -42,6 +42,7 @@
     global:
 	dfs_get_referrals;
 	dfs_info_free;
+	dssetup_check_service;
 	dssetup_clear_domain_info;
 	lsa_lookup_name;
 	lsa_lookup_sid;
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -142,12 +141,6 @@
 	return (status);
 }
 
-int
-mlsvc_ping(const char *server)
-{
-	return (smbrdr_echo(server));
-}
-
 void
 mlsvc_disconnect(const char *server)
 {
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Mon Jul 26 15:02:13 2010 -0700
@@ -151,18 +151,11 @@
 	mlsvc_handle_t netr_handle;
 	smb_domainex_t di;
 	uint32_t status;
-	int retries = 0, server_changed = 0;
+	int retries = 0;
 
 	(void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN);
 
-	if (!smb_domain_getinfo(&di))
-		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
-
-	if (mlsvc_ping(di.d_dc) < 0) {
-		/*
-		 * We had a session to the DC but it's not responding.
-		 * So drop the credential chain.
-		 */
+	if (!smb_domain_getinfo(&di)) {
 		netr_invalidate_chain();
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 	}
@@ -175,12 +168,12 @@
 		if (di.d_dc && (*netr_global_info.server != '\0')) {
 			(void) snprintf(server, sizeof (server),
 			    "\\\\%s", di.d_dc);
-			server_changed = strncasecmp(netr_global_info.server,
-			    server, strlen(server));
+			if (strncasecmp(netr_global_info.server,
+			    server, strlen(server)) != 0)
+				netr_invalidate_chain();
 		}
 
-		if (server_changed ||
-		    (netr_global_info.flags & NETR_FLG_VALID) == 0 ||
+		if ((netr_global_info.flags & NETR_FLG_VALID) == 0 ||
 		    !smb_match_netlogon_seqnum()) {
 			status = netlogon_auth(di.d_dc, &netr_handle,
 			    NETR_FLG_NULL);
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <unistd.h>
@@ -136,7 +135,7 @@
 smb_token_sids2ids(smb_token_t *token)
 {
 	idmap_stat stat;
-	int nmaps, retries = 0;
+	int nmaps;
 	smb_idmap_batch_t sib;
 
 	/*
@@ -148,21 +147,19 @@
 	else
 		nmaps = token->tkn_win_grps.i_cnt + 3;
 
-	do {
-		stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID);
-		if (stat != IDMAP_SUCCESS)
-			return (-1);
+	stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID);
+	if (stat != IDMAP_SUCCESS)
+		return (-1);
 
-		stat = smb_token_idmap(token, &sib);
-		if (stat != IDMAP_SUCCESS) {
-			smb_idmap_batch_destroy(&sib);
-			return (-1);
-		}
+	stat = smb_token_idmap(token, &sib);
+	if (stat != IDMAP_SUCCESS) {
+		smb_idmap_batch_destroy(&sib);
+		return (-1);
+	}
 
-		stat = smb_idmap_batch_getmappings(&sib);
-		smb_idmap_batch_destroy(&sib);
-		smb_idmap_check("smb_idmap_batch_getmappings", stat);
-	} while (stat == IDMAP_ERR_RPC_HANDLE && retries++ < 3);
+	stat = smb_idmap_batch_getmappings(&sib);
+	smb_idmap_batch_destroy(&sib);
+	smb_idmap_check("smb_idmap_batch_getmappings", stat);
 
 	return (stat == IDMAP_SUCCESS ? 0 : -1);
 }
--- a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c	Mon Jul 26 15:02:13 2010 -0700
@@ -168,11 +168,17 @@
 	spoolss_stub_table		/* stub_table */
 };
 
+/*
+ * Defer calling spoolss_cups_init() until something actually
+ * needs access to CUPS due to the libcups dependency on OpenSSL.
+ * OpenSSL is not MT-safe and initializing CUPS here can crash
+ * OpenSSL if it collides with other threads that are in other
+ * libraries that are attempting to use OpenSSL.
+ */
 void
 spoolss_initialize(void)
 {
 	(void) ndr_svc_register(&spoolss_service);
-	(void) spoolss_cups_init();
 }
 
 void
--- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c	Mon Jul 26 15:02:13 2010 -0700
@@ -19,37 +19,17 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <syslog.h>
 #include <strings.h>
-#include <synch.h>
 #include <smbsrv/libsmb.h>
 
-static idmap_handle_t *smb_idmap_hd;
-static mutex_t smb_idmap_mutex;
-
 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
 
-static void
-smb_idmap_reset(void)
-{
-	(void) mutex_lock(&smb_idmap_mutex);
-
-	if (smb_idmap_hd != NULL) {
-		(void) idmap_fini(smb_idmap_hd);
-		smb_idmap_hd = NULL;
-	}
-
-	(void) mutex_unlock(&smb_idmap_mutex);
-}
-
 /*
- * Report an idmap error.  If the error appears to be connection
- * related, use fini to reset.  A new handle will be generated on
- * the next open.
+ * Report an idmap error.
  */
 void
 smb_idmap_check(const char *s, idmap_stat stat)
@@ -58,46 +38,10 @@
 		if (s == NULL)
 			s = "smb_idmap_check";
 
-		syslog(LOG_ERR, "%s: %s", s, idmap_stat2string(NULL, stat));
-
-		switch (stat) {
-		case IDMAP_ERR_RPC_HANDLE:
-		case IDMAP_ERR_RPC:
-		case IDMAP_ERR_CLIENT_HANDLE:
-			smb_idmap_reset();
-			break;
-		default:
-			break;
-		}
+		syslog(LOG_ERR, "%s: %s", s, idmap_stat2string(stat));
 	}
 }
 
-static idmap_handle_t *
-smb_idmap_enter(void)
-{
-	idmap_stat stat;
-
-	(void) mutex_lock(&smb_idmap_mutex);
-
-	if (smb_idmap_hd == NULL) {
-		if ((stat = idmap_init(&smb_idmap_hd)) < 0) {
-			syslog(LOG_ERR,
-			    "smb_idmap_enter: idmap_init failed: %s",
-			    idmap_stat2string(NULL, stat));
-			(void) mutex_unlock(&smb_idmap_mutex);
-			return (NULL);
-		}
-	}
-
-	return (smb_idmap_hd);
-}
-
-static void
-smb_idmap_exit(void)
-{
-	(void) mutex_unlock(&smb_idmap_mutex);
-}
-
 /*
  * smb_idmap_getsid
  *
@@ -180,18 +124,13 @@
 idmap_stat
 smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
 {
-	idmap_handle_t	*hd;
 	idmap_stat	stat;
 
 	if (!sib)
 		return (IDMAP_ERR_ARG);
 
-	if ((hd = smb_idmap_enter()) == NULL)
-		return (IDMAP_ERR_OTHER);
-
 	bzero(sib, sizeof (smb_idmap_batch_t));
-	stat = idmap_get_create(hd, &sib->sib_idmaph);
-	smb_idmap_exit();
+	stat = idmap_get_create(&sib->sib_idmaph);
 
 	if (stat != IDMAP_SUCCESS) {
 		smb_idmap_check("idmap_get_create", stat);
@@ -380,10 +319,8 @@
 	smb_idmap_t *sim;
 	int i;
 
-	(void) mutex_lock(&smb_idmap_mutex);
 	if ((stat = idmap_get_mappings(sib->sib_idmaph)) != IDMAP_SUCCESS) {
 		smb_idmap_check("idmap_get_mappings", stat);
-		(void) mutex_unlock(&smb_idmap_mutex);
 		return (stat);
 	}
 
@@ -396,7 +333,6 @@
 				smb_tracef("[%d] %d (%d)", sim->sim_idtype,
 				    sim->sim_rid, sim->sim_stat);
 			}
-			(void) mutex_unlock(&smb_idmap_mutex);
 			return (sim->sim_stat);
 		}
 	}
@@ -404,7 +340,6 @@
 	if (smb_idmap_batch_binsid(sib) != 0)
 		stat = IDMAP_ERR_OTHER;
 
-	(void) mutex_unlock(&smb_idmap_mutex);
 	return (stat);
 }
 
--- a/usr/src/lib/smbsrv/libsmb/common/smb_sd.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_sd.c	Mon Jul 26 15:02:13 2010 -0700
@@ -29,6 +29,7 @@
 
 #include <strings.h>
 #include <assert.h>
+#include <errno.h>
 #include <smbsrv/ntifs.h>
 #include <smbsrv/smb_idmap.h>
 #include <smbsrv/libsmb.h>
@@ -156,11 +157,18 @@
 	ace_t *z_ace;
 
 	fs_sd->sd_gid = fs_sd->sd_uid = 0;
-	if (acl_trivial(path) != 1)
-		return (NT_STATUS_INTERNAL_ERROR);
 
-	if (acl_get(path, ACL_NO_TRIVIAL, &z_acl) != 0)
-		return (NT_STATUS_INTERNAL_ERROR);
+	errno = 0;
+	if (acl_get(path, 0, &z_acl) != 0) {
+		switch (errno) {
+		case EACCES:
+			return (NT_STATUS_ACCESS_DENIED);
+		case ENOENT:
+			return (NT_STATUS_OBJECT_PATH_NOT_FOUND);
+		default:
+			return (NT_STATUS_INTERNAL_ERROR);
+		}
+	}
 
 	if ((z_ace = (ace_t *)z_acl->acl_aclp) == NULL)
 		return (NT_STATUS_INVALID_ACL);
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c	Mon Jul 26 15:02:13 2010 -0700
@@ -943,6 +943,7 @@
 	SMB_OFILE_VALID(of);
 	ASSERT(of->f_refcnt == 0);
 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
+	ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of));
 
 	tree = of->f_tree;
 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
--- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c	Mon Jul 26 15:02:13 2010 -0700
@@ -56,12 +56,12 @@
 static void smb_oplock_wait_ack(smb_node_t *, uint32_t);
 static void smb_oplock_timedout(smb_node_t *);
 
-static smb_oplock_grant_t *smb_oplock_create_grant(smb_ofile_t *, uint8_t);
-void smb_oplock_delete_grant(smb_oplock_grant_t *);
+static smb_oplock_grant_t *smb_oplock_set_grant(smb_ofile_t *, uint8_t);
+void smb_oplock_clear_grant(smb_oplock_grant_t *);
 static int smb_oplock_insert_grant(smb_node_t *, smb_oplock_grant_t *);
 static void smb_oplock_remove_grant(smb_node_t *, smb_oplock_grant_t *);
 static smb_oplock_grant_t *smb_oplock_exclusive_grant(list_t *);
-static smb_oplock_grant_t *smb_oplock_find_grant(list_t *, smb_ofile_t *);
+static smb_oplock_grant_t *smb_oplock_get_grant(smb_oplock_t *, smb_ofile_t *);
 
 static smb_oplock_break_t *smb_oplock_create_break(smb_node_t *);
 static smb_oplock_break_t *smb_oplock_get_break(void);
@@ -73,7 +73,6 @@
 /* levelII oplock break requests (smb_oplock_break_t) */
 static boolean_t	smb_oplock_initialized = B_FALSE;
 static kmem_cache_t	*smb_oplock_break_cache = NULL;
-static kmem_cache_t	*smb_oplock_grant_cache = NULL;
 static smb_llist_t	smb_oplock_breaks;
 static smb_thread_t	smb_oplock_thread;
 
@@ -95,9 +94,6 @@
 	smb_oplock_break_cache = kmem_cache_create("smb_oplock_break_cache",
 	    sizeof (smb_oplock_break_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 
-	smb_oplock_grant_cache = kmem_cache_create("smb_oplock_grant_cache",
-	    sizeof (smb_oplock_grant_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
-
 	smb_llist_constructor(&smb_oplock_breaks, sizeof (smb_oplock_break_t),
 	    offsetof(smb_oplock_break_t, ob_lnd));
 
@@ -109,7 +105,6 @@
 		smb_thread_destroy(&smb_oplock_thread);
 		smb_llist_destructor(&smb_oplock_breaks);
 		kmem_cache_destroy(smb_oplock_break_cache);
-		kmem_cache_destroy(smb_oplock_grant_cache);
 		return (rc);
 	}
 
@@ -141,7 +136,6 @@
 	smb_llist_destructor(&smb_oplock_breaks);
 
 	kmem_cache_destroy(smb_oplock_break_cache);
-	kmem_cache_destroy(smb_oplock_grant_cache);
 }
 
 /*
@@ -259,9 +253,9 @@
 
 	nbl_end_crit(node->vp);
 
-	og = smb_oplock_create_grant(ofile, op->op_oplock_level);
+	og = smb_oplock_set_grant(ofile, op->op_oplock_level);
 	if (smb_oplock_insert_grant(node, og) != 0) {
-		smb_oplock_delete_grant(og);
+		smb_oplock_clear_grant(og);
 		op->op_oplock_level = SMB_OPLOCK_NONE;
 		mutex_exit(&ol->ol_mutex);
 		return;
@@ -471,7 +465,7 @@
 		smb_session_oplock_break(og->og_session,
 		    og->og_tid, og->og_fid, SMB_OPLOCK_BREAK_TO_NONE);
 		smb_oplock_remove_grant(node, og);
-		smb_oplock_delete_grant(og);
+		smb_oplock_clear_grant(og);
 	}
 
 	mutex_exit(&ol->ol_mutex);
@@ -527,7 +521,7 @@
 		case SMB_OPLOCK_BREAK_TO_NONE:
 			og->og_level = SMB_OPLOCK_NONE;
 			smb_oplock_remove_grant(node, og);
-			smb_oplock_delete_grant(og);
+			smb_oplock_clear_grant(og);
 			break;
 		case SMB_OPLOCK_BREAK_TO_LEVEL_II:
 			og->og_level = SMB_OPLOCK_LEVEL_II;
@@ -552,18 +546,15 @@
 {
 	smb_oplock_t		*ol;
 	smb_oplock_grant_t	*og;
-	list_t			*grants;
 
 	ol = &node->n_oplock;
-	grants = &ol->ol_grants;
-
 	mutex_enter(&ol->ol_mutex);
 	smb_oplock_wait(node);
 
-	og = smb_oplock_find_grant(grants, of);
+	og = smb_oplock_get_grant(ol, of);
 	if (og) {
 		smb_oplock_remove_grant(node, og);
-		smb_oplock_delete_grant(og);
+		smb_oplock_clear_grant(og);
 
 		if (ol->ol_break != SMB_OPLOCK_NO_BREAK) {
 			ol->ol_break = SMB_OPLOCK_NO_BREAK;
@@ -594,17 +585,14 @@
 {
 	smb_oplock_t		*ol;
 	smb_oplock_grant_t	*og;
-	list_t			*grants;
 	boolean_t		brk_to_none = B_FALSE;
 
 	ol = &node->n_oplock;
-	grants = &ol->ol_grants;
-
 	mutex_enter(&ol->ol_mutex);
 	smb_oplock_wait(node);
 
 	if ((ol->ol_break == SMB_OPLOCK_NO_BREAK) ||
-	    ((og = smb_oplock_find_grant(grants, of)) == NULL)) {
+	    ((og = smb_oplock_get_grant(ol, of)) == NULL)) {
 		mutex_exit(&ol->ol_mutex);
 		return;
 	}
@@ -628,7 +616,7 @@
 
 	if (og->og_level == SMB_OPLOCK_NONE) {
 		smb_oplock_remove_grant(node, og);
-		smb_oplock_delete_grant(og);
+		smb_oplock_clear_grant(og);
 	}
 
 	ol->ol_break = SMB_OPLOCK_NO_BREAK;
@@ -690,14 +678,15 @@
 }
 
 /*
- * smb_oplock_create_grant
+ * smb_oplock_set_grant
  */
 static smb_oplock_grant_t *
-smb_oplock_create_grant(smb_ofile_t *of, uint8_t level)
+smb_oplock_set_grant(smb_ofile_t *of, uint8_t level)
 {
 	smb_oplock_grant_t	*og;
 
-	og = kmem_cache_alloc(smb_oplock_grant_cache, KM_SLEEP);
+	og = &of->f_oplock_grant;
+
 	og->og_magic = SMB_OPLOCK_GRANT_MAGIC;
 	og->og_level = level;
 	og->og_ofile = of;
@@ -709,12 +698,12 @@
 }
 
 /*
- * smb_oplock_delete_grant
+ * smb_oplock_clear_grant
  */
 void
-smb_oplock_delete_grant(smb_oplock_grant_t *og)
+smb_oplock_clear_grant(smb_oplock_grant_t *og)
 {
-	kmem_cache_free(smb_oplock_grant_cache, og);
+	bzero(og, sizeof (smb_oplock_grant_t));
 }
 
 /*
@@ -782,23 +771,19 @@
 }
 
 /*
- * smb_oplock_find_grant
+ * smb_oplock_get_grant
  *
  * Find oplock grant corresponding to the specified ofile.
  */
 static smb_oplock_grant_t *
-smb_oplock_find_grant(list_t *grants, smb_ofile_t *ofile)
+smb_oplock_get_grant(smb_oplock_t *ol, smb_ofile_t *ofile)
 {
-	smb_oplock_grant_t	*og = NULL;
+	ASSERT(MUTEX_HELD(&ol->ol_mutex));
 
-	for (og = list_head(grants);
-	    og != NULL;
-	    og = list_next(grants, og)) {
-		SMB_OPLOCK_GRANT_VALID(og);
-		if (og->og_ofile == ofile)
-			break;
-	}
-	return (og);
+	if (SMB_OFILE_OPLOCK_GRANTED(ofile))
+		return (&ofile->f_oplock_grant);
+	else
+		return (NULL);
 }
 
 /*
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h	Mon Jul 26 14:06:42 2010 -0700
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h	Mon Jul 26 15:02:13 2010 -0700
@@ -572,6 +572,8 @@
 #define	SMB_OPLOCK_GRANT_MAGIC	0x4F4C4B47	/* OLKG */
 #define	SMB_OPLOCK_GRANT_VALID(p) \
 	ASSERT((p)->og_magic == SMB_OPLOCK_GRANT_MAGIC)
+#define	SMB_OFILE_OPLOCK_GRANTED(p) \
+	((p)->f_oplock_grant.og_magic == SMB_OPLOCK_GRANT_MAGIC)
 typedef struct smb_oplock_grant {
 	uint32_t		og_magic;
 	list_node_t		og_lnd;
@@ -1255,6 +1257,7 @@
 	pid_t			f_pid;
 	uint32_t		f_explicit_times;
 	char			f_quota_resume[SMB_SID_STRSZ];
+	smb_oplock_grant_t	f_oplock_grant;
 } smb_ofile_t;
 
 #define	SMB_ODIR_MAGIC 		0x4F444952	/* 'ODIR' */