changeset 10717:fe0545fc3cdd

6612607 CIFS ADS client should use ldap_sasl_interactive_bind_s API 6877755 smbd should not route stderr, stdout to /dev/null 6882701 Wrong error message for attempt to map local user to Windows group, or vice versa 6885105 Potential for deadlock in smb_node_set_delete_on_close() 6881928 smbd core generated when running a script to join domain, set abe properties 6885538 Reduce dependencies on libsmbrdr 6820325 cifs service can't start on multi vlan+ipmp configuration
author Alan Wright <amw@Sun.COM>
date Mon, 05 Oct 2009 11:03:34 -0700
parents b17df522be57
children 77613d4558c6
files usr/src/cmd/idmap/idmapd/dbutils.c usr/src/cmd/smbsrv/smbadm/smbadm.c usr/src/cmd/smbsrv/smbd/Makefile usr/src/cmd/smbsrv/smbd/smbd_door_ops.c usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c usr/src/cmd/smbsrv/smbd/smbd_join.c usr/src/cmd/smbsrv/smbd/smbd_main.c usr/src/cmd/smbsrv/smbd/smbd_vss.c usr/src/common/smbsrv/smb_native.c usr/src/common/smbsrv/smb_sid.c usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h usr/src/lib/smbsrv/libmlsvc/common/lsalib.c usr/src/lib/smbsrv/libmlsvc/common/lsalib.h usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c usr/src/lib/smbsrv/libmlsvc/common/samlib.c usr/src/lib/smbsrv/libmlsvc/common/samr_open.c usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c usr/src/lib/smbsrv/libsmb/common/libsmb.h usr/src/lib/smbsrv/libsmb/common/mapfile-vers usr/src/lib/smbsrv/libsmb/common/smb_domain.c usr/src/lib/smbsrv/libsmb/common/smb_info.c usr/src/lib/smbsrv/libsmb/common/smb_sam.c usr/src/lib/smbsrv/libsmbns/common/libsmbns.h usr/src/lib/smbsrv/libsmbns/common/mapfile-vers usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c usr/src/lib/smbsrv/libsmbrdr/Makefile.com usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c usr/src/uts/common/fs/smbsrv/smb_node.c usr/src/uts/common/fs/smbsrv/smb_server.c usr/src/uts/common/fs/smbsrv/smb_session.c usr/src/uts/common/smbsrv/cifs.h usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl usr/src/uts/common/smbsrv/ndl/samrpc.ndl usr/src/uts/common/smbsrv/ndl/srvsvc.ndl usr/src/uts/common/smbsrv/ndr.h usr/src/uts/common/smbsrv/netbios.h usr/src/uts/common/smbsrv/smbinfo.h usr/src/uts/common/smbsrv/wintypes.h
diffstat 68 files changed, 2029 insertions(+), 4812 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/idmap/idmapd/dbutils.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/idmap/idmapd/dbutils.c	Mon Oct 05 11:03:34 2009 -0700
@@ -2572,9 +2572,9 @@
 	 * way we generate localSIDs.
 	 */
 	if (is_user && res->id.idtype == IDMAP_GSID)
-		return (IDMAP_ERR_NOMAPPING);
+		return (IDMAP_ERR_NOTGROUP);
 	if (!is_user && res->id.idtype == IDMAP_USID)
-		return (IDMAP_ERR_NOMAPPING);
+		return (IDMAP_ERR_NOTUSER);
 
 	/* Skip 1000 UIDs */
 	if (is_user &&
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c	Mon Oct 05 11:03:34 2009 -0700
@@ -817,7 +817,7 @@
 		    srvname, fqdn, ipstr);
 	}
 
-	nt_domain_show();
+	smb_domain_show();
 	return (0);
 }
 
--- a/usr/src/cmd/smbsrv/smbd/Makefile	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbd/Makefile	Mon Oct 05 11:03:34 2009 -0700
@@ -47,7 +47,7 @@
 
 include ../Makefile.smbsrv.defs
 
-LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lmlsvc -lmlrpc -lsmbrdr -lsmbns -lsmb \
+LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lmlsvc -lmlrpc -lsmbns -lsmb \
 	-lzfs -lbsm -lnsl -lumem
 LDFLAGS += -R/usr/lib/smbsrv
 
--- a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c	Mon Oct 05 11:03:34 2009 -0700
@@ -299,17 +299,17 @@
     door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
 {
 	char *rbuf = NULL;
-	smb_domain_t dinfo;
+	smb_domainex_t dxi;
 
 	*err = SMB_DR_OP_SUCCESS;
 	*rbufsize = 0;
 
-	if (!smb_domain_getinfo(&dinfo)) {
+	if (!smb_domain_getinfo(&dxi)) {
 		*err = SMB_DR_OP_ERR_EMPTYBUF;
 		return (NULL);
 	}
 
-	if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, dinfo.d_dc,
+	if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, dxi.d_dc,
 	    rbufsize)) == NULL) {
 		*err = SMB_DR_OP_ERR_ENCODE;
 		*rbufsize = 0;
--- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * SMBd door server
  */
@@ -178,8 +176,6 @@
 		goto door_return;
 	}
 
-	syslog(LOG_DEBUG, "smb_door_srv_func: execute server routine"
-	    "(opcode=%d)", opcode);
 	if (smb_dr_is_valid_opcode(opcode) != 0) {
 		tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_INVALID_OPCODE,
 		    &rbufsize);
--- a/usr/src/cmd/smbsrv/smbd/smbd_join.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c	Mon Oct 05 11:03:34 2009 -0700
@@ -32,7 +32,6 @@
 #include <sys/errno.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libsmbns.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
@@ -81,7 +80,7 @@
  *
  * Since the kclient has updated the machine password stored in SMF
  * repository, the cached ipc_info must be updated accordingly by calling
- * smbrdr_ipc_commit.
+ * smb_ipc_commit.
  *
  * Due to potential replication delays in a multiple DC environment, the
  * NETLOGON rpc request must be sent to the DC, to which the KPASSWD request
@@ -99,10 +98,11 @@
 	char kpasswd_srv[MAXHOSTNAMELEN];
 	char kpasswd_domain[MAXHOSTNAMELEN];
 	char sam_acct[SMB_SAMACCT_MAXLEN];
-	char *ipc_usr, *dom;
+	char ipc_usr[SMB_USERNAME_MAXLEN];
+	char *dom;
 	boolean_t new_domain = B_FALSE;
-	smb_domain_t domain;
-	nt_domain_t *di;
+	smb_domainex_t dxi;
+	smb_domain_t *di;
 
 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
 		return (B_FALSE);
@@ -121,12 +121,12 @@
 	 * progress, don't do anything.
 	 */
 	(void) smb_getsamaccount(sam_acct, sizeof (sam_acct));
-	ipc_usr = smbrdr_ipc_get_user();
+	smb_ipc_get_user(ipc_usr, SMB_USERNAME_MAXLEN);
 	if (utf8_strcasecmp(ipc_usr, sam_acct))
 		return (B_FALSE);
 
-	di = &domain.d_info;
-	if (!smb_domain_getinfo(&domain))
+	di = &dxi.d_primary;
+	if (!smb_domain_getinfo(&dxi))
 		(void) smb_getfqdomainname(di->di_fqname, MAXHOSTNAMELEN);
 
 	(void) smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kpasswd_domain,
@@ -145,20 +145,20 @@
 	 * currently cached or the SMB daemon has previously discovered a DC
 	 * that is different than the kpasswd server.
 	 */
-	if (new_domain || utf8_strcasecmp(domain.d_dc, kpasswd_srv) != 0) {
-		if (*domain.d_dc != '\0')
-			mlsvc_disconnect(domain.d_dc);
+	if (new_domain || utf8_strcasecmp(dxi.d_dc, kpasswd_srv) != 0) {
+		if (*dxi.d_dc != '\0')
+			mlsvc_disconnect(dxi.d_dc);
 
-		if (!smb_locate_dc(dom, kpasswd_srv, &domain)) {
-			if (!smb_locate_dc(di->di_fqname, "", &domain)) {
-				smbrdr_ipc_commit();
+		if (!smb_locate_dc(dom, kpasswd_srv, &dxi)) {
+			if (!smb_locate_dc(di->di_fqname, "", &dxi)) {
+				smb_ipc_commit();
 				return (B_FALSE);
 			}
 		}
 	}
 
-	smbrdr_ipc_commit();
-	if (mlsvc_netlogon(domain.d_dc, di->di_nbname)) {
+	smb_ipc_commit();
+	if (mlsvc_netlogon(dxi.d_dc, di->di_nbname)) {
 		syslog(LOG_ERR,
 		    "failed to establish NETLOGON credential chain");
 		return (B_TRUE);
@@ -209,8 +209,8 @@
 smbd_locate_dc_thread(void *arg)
 {
 	char domain[MAXHOSTNAMELEN];
-	smb_domain_t new_domain;
-	nt_domain_t *di;
+	smb_domainex_t new_domain;
+	smb_domain_t *di;
 
 	if (!smb_match_netlogon_seqnum()) {
 		(void) smbd_set_netlogon_cred();
@@ -221,7 +221,7 @@
 		}
 
 		if (smb_locate_dc(domain, "", &new_domain)) {
-			di = &new_domain.d_info;
+			di = &new_domain.d_primary;
 			smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
 			    di->di_sid,
 			    di->di_u.di_dns.ddi_forest,
@@ -298,8 +298,8 @@
 	uint32_t status;
 	unsigned char passwd_hash[SMBAUTH_HASH_SZ];
 	char dc[MAXHOSTNAMELEN];
-	smb_domain_t domain_info;
-	nt_domain_t *di;
+	smb_domainex_t dxi;
+	smb_domain_t *di;
 
 	/*
 	 * Ensure that any previous membership of this domain has
@@ -317,32 +317,32 @@
 		return (NT_STATUS_INTERNAL_ERROR);
 	}
 
-	smbrdr_ipc_set(info->domain_username, passwd_hash);
+	smb_ipc_set(info->domain_username, passwd_hash);
 
 	(void) smbd_get_kpasswd_srv(dc, sizeof (dc));
 	/* info->domain_name could either be NetBIOS domain name or FQDN */
-	if (smb_locate_dc(info->domain_name, dc, &domain_info)) {
-		status = mlsvc_join(&domain_info, info->domain_username,
+	if (smb_locate_dc(info->domain_name, dc, &dxi)) {
+		status = mlsvc_join(&dxi, info->domain_username,
 		    info->domain_passwd);
 
 		if (status == NT_STATUS_SUCCESS) {
-			di = &domain_info.d_info;
+			di = &dxi.d_primary;
 			smbd_set_secmode(SMB_SECMODE_DOMAIN);
 			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);
-			smbrdr_ipc_commit();
+			smb_ipc_commit();
 			return (status);
 		}
 
-		smbrdr_ipc_rollback();
+		smb_ipc_rollback();
 		syslog(LOG_ERR, "smbd: failed joining %s (%s)",
 		    info->domain_name, xlate_nt_status(status));
 		return (status);
 	}
 
-	smbrdr_ipc_rollback();
+	smb_ipc_rollback();
 	syslog(LOG_ERR, "smbd: failed locating domain controller for %s",
 	    info->domain_name);
 	return (NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c	Mon Oct 05 11:03:34 2009 -0700
@@ -54,7 +54,6 @@
 #include <smbsrv/smb_ioctl.h>
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libsmbns.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlsvc.h>
 #include "smbd.h"
 
@@ -387,13 +386,6 @@
 
 	(void) close(fd);
 
-	if ((fd = open("/dev/null", O_RDWR)) >= 0) {
-		(void) fcntl(fd, F_DUP2FD, STDIN_FILENO);
-		(void) fcntl(fd, F_DUP2FD, STDOUT_FILENO);
-		(void) fcntl(fd, F_DUP2FD, STDERR_FILENO);
-		(void) close(fd);
-	}
-
 	pset = priv_allocset();
 	if (pset == NULL)
 		return;
@@ -453,7 +445,7 @@
 		smbd_report("NIC monitoring failed to start");
 
 	(void) dyndns_start();
-	smbrdr_init();
+	smb_ipc_init();
 
 	if (smb_netbios_start() != 0)
 		smbd_report("NetBIOS services failed to start");
@@ -467,7 +459,7 @@
 	}
 
 	smbd.s_secmode = smb_config_get_secmode();
-	if ((rc = nt_domain_init(smbd.s_secmode)) != 0) {
+	if ((rc = smb_domain_init(smbd.s_secmode)) != 0) {
 		if (rc == SMB_DOMAIN_NOMACHINE_SID) {
 			smbd_report(
 			    "no machine SID: check idmap configuration");
@@ -552,9 +544,10 @@
 	smb_lgrp_stop();
 	smb_ccache_remove(SMB_CCACHE_PATH);
 	smb_pwd_fini();
-	nt_domain_fini();
+	smb_domain_fini();
 	mlsvc_fini();
 	smb_ads_fini();
+	smb_netbios_stop();
 }
 
 
--- a/usr/src/cmd/smbsrv/smbd/smbd_vss.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/cmd/smbsrv/smbd/smbd_vss.c	Mon Oct 05 11:03:34 2009 -0700
@@ -32,7 +32,6 @@
 #include <libzfs.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libsmbns.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
--- a/usr/src/common/smbsrv/smb_native.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/common/smbsrv/smb_native.c	Mon Oct 05 11:03:34 2009 -0700
@@ -79,8 +79,6 @@
 		{ NATIVE_OS_WIN95,	"Windows 4.0"		},
 		{ NATIVE_OS_WIN2000,	"Windows 5.0"		},
 		{ NATIVE_OS_WIN2000,	"Windows 5.1"		},
-		{ NATIVE_OS_WIN2000,	"Windows 2000 5.0"	},
-		{ NATIVE_OS_NT5_1,	"Windows 2000 5.1"	},
 		{ NATIVE_OS_WIN2000,	"Windows 2000"		},
 		{ NATIVE_OS_WIN2000,	"Windows 2002"		},
 		{ NATIVE_OS_WIN2000,	"Windows .NET"		},
--- a/usr/src/common/smbsrv/smb_sid.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/common/smbsrv/smb_sid.c	Mon Oct 05 11:03:34 2009 -0700
@@ -265,10 +265,10 @@
 boolean_t
 smb_sid_islocal(smb_sid_t *sid)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	boolean_t islocal = B_FALSE;
 
-	if (nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di))
+	if (smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
 		islocal = smb_sid_indomain(di.di_binsid, sid);
 
 	return (islocal);
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1186,10 +1186,8 @@
 
 		if (ti == &ndt_s_wchar) {
 			/*
-			 * size_is is the number of characters in the string,
-			 * including the null. We assume valp is UTF-8 encoded.
-			 * We can use mts_wcequiv_strlen for ASCII, extended
-			 * ASCII or Unicode (UCS-2).
+			 * size_is is the number of characters in the
+			 * (multibyte) string, including the null.
 			 */
 			size_is = (mts_wcequiv_strlen(valp) /
 			    sizeof (mts_wchar_t)) + 1;
--- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c	Mon Oct 05 11:03:34 2009 -0700
@@ -31,7 +31,6 @@
 #include <strings.h>
 #include <smbsrv/wintypes.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/ndl/dssetup.ndl>
 #include <smbsrv/libmlsvc.h>
 
@@ -40,7 +39,7 @@
 {
 	dssetup_DsRoleGetPrimaryDomainInfo_t arg;
 	struct dssetup_DsRolePrimaryDomInfo1 *info;
-	smb_domain_t di;
+	smb_domainex_t di;
 	mlsvc_handle_t handle;
 	int opnum;
 	int rc;
@@ -48,7 +47,7 @@
 	if (!smb_domain_getinfo(&di))
 		return (-1);
 
-	if (ndr_rpc_bind(&handle, di.d_dc, di.d_info.di_nbname,
+	if (ndr_rpc_bind(&handle, di.d_dc, di.d_primary.di_nbname,
 	    MLSVC_ANON_USER, "DSSETUP") != 0)
 		return (-1);
 
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h	Mon Oct 05 11:03:34 2009 -0700
@@ -42,7 +42,6 @@
 #include <smbsrv/smb_share.h>
 #include <smbsrv/smb_xdr.h>
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlrpc.h>
 #include <smbsrv/ndl/lsarpc.ndl>
 
@@ -58,15 +57,15 @@
  * information.
  */
 
-extern boolean_t smb_locate_dc(char *, char *, smb_domain_t *);
-extern boolean_t smb_domain_getinfo(smb_domain_t *);
-
+extern boolean_t smb_locate_dc(char *, char *, smb_domainex_t *);
 
 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_domain_t *, char *, char *);
+extern DWORD mlsvc_join(smb_domainex_t *, char *, char *);
 
 
 /*
@@ -136,6 +135,7 @@
 	uint32_t	sv_version_minor;
 	uint32_t	sv_type;
 	char		*sv_comment;
+	uint32_t	sv_os;
 } srvsvc_server_info_t;
 
 int srvsvc_net_server_getinfo(char *, char *, srvsvc_server_info_t *);
@@ -151,16 +151,16 @@
 typedef struct mlsvc_handle {
 	ndr_hdid_t			handle;
 	ndr_client_t			*clnt;
-	int				remote_os;
+	uint32_t			remote_os;
 	srvsvc_server_info_t		svinfo;
 } mlsvc_handle_t;
 
+void ndr_rpc_init(void);
+void ndr_rpc_fini(void);
 int ndr_rpc_bind(mlsvc_handle_t *, char *, char *, char *, const char *);
 void ndr_rpc_unbind(mlsvc_handle_t *);
 int ndr_rpc_call(mlsvc_handle_t *, int, void *);
-void ndr_rpc_server_setinfo(mlsvc_handle_t *, const srvsvc_server_info_t *);
-void ndr_rpc_server_getinfo(mlsvc_handle_t *, srvsvc_server_info_t *);
-int ndr_rpc_server_os(mlsvc_handle_t *);
+uint32_t ndr_rpc_server_os(mlsvc_handle_t *);
 int ndr_rpc_get_ssnkey(mlsvc_handle_t *, unsigned char *, size_t);
 void *ndr_rpc_malloc(mlsvc_handle_t *, size_t);
 ndr_heap_t *ndr_rpc_get_heap(mlsvc_handle_t *);
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c	Mon Oct 05 11:03:34 2009 -0700
@@ -32,7 +32,6 @@
 
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libmlsvc.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/ntstatus.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/smb_token.h>
@@ -139,11 +138,13 @@
  */
 DWORD
 lsa_query_primary_domain_info(char *server, char *domain,
-    nt_domain_t *info)
+    smb_domain_t *info)
 {
 	mlsvc_handle_t domain_handle;
 	DWORD status;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
@@ -165,11 +166,13 @@
  */
 DWORD
 lsa_query_account_domain_info(char *server, char *domain,
-    nt_domain_t *info)
+    smb_domain_t *info)
 {
 	mlsvc_handle_t domain_handle;
 	DWORD status;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
@@ -192,11 +195,13 @@
  * Returns NT status codes.
  */
 DWORD
-lsa_query_dns_domain_info(char *server, char *domain, nt_domain_t *info)
+lsa_query_dns_domain_info(char *server, char *domain, smb_domain_t *info)
 {
 	mlsvc_handle_t domain_handle;
 	DWORD status;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
@@ -224,7 +229,9 @@
 	mlsvc_handle_t domain_handle;
 	DWORD enum_context;
 	DWORD status;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
@@ -261,7 +268,9 @@
 	mlsvc_handle_t domain_handle;
 	DWORD enum_context;
 	DWORD status;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
@@ -335,14 +344,16 @@
 lsa_lookup_name_domain(char *account_name, smb_account_t *info)
 {
 	mlsvc_handle_t domain_handle;
-	smb_domain_t dinfo;
-	char *user = smbrdr_ipc_get_user();
+	smb_domainex_t dinfo;
 	uint32_t status;
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if (!smb_domain_getinfo(&dinfo))
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 
-	if (lsar_open(dinfo.d_dc, dinfo.d_info.di_nbname, user,
+	if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user,
 	    &domain_handle) != 0)
 		return (NT_STATUS_INVALID_PARAMETER);
 
@@ -378,13 +389,15 @@
 {
 	mlsvc_handle_t domain_handle;
 	int rc;
-	char *user = smbrdr_ipc_get_user();
-	smb_domain_t dinfo;
+	smb_domainex_t dinfo;
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if (!smb_domain_getinfo(&dinfo))
 		return (-1);
 
-	if ((lsar_open(dinfo.d_dc, dinfo.d_info.di_nbname, user,
+	if ((lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user,
 	    &domain_handle)) != 0)
 		return (-1);
 
@@ -409,7 +422,9 @@
 	mlsvc_handle_t domain_handle;
 	int rc;
 	int i;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	rc = lsar_open(server, domain, user, &domain_handle);
 	if (rc != 0)
@@ -519,14 +534,16 @@
 lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo)
 {
 	mlsvc_handle_t domain_handle;
-	char *user = smbrdr_ipc_get_user();
 	uint32_t status;
-	smb_domain_t dinfo;
+	smb_domainex_t dinfo;
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if (!smb_domain_getinfo(&dinfo))
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 
-	if (lsar_open(dinfo.d_dc, dinfo.d_info.di_nbname, user,
+	if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user,
 	    &domain_handle) != 0)
 		return (NT_STATUS_INVALID_PARAMETER);
 
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h	Mon Oct 05 11:03:34 2009 -0700
@@ -50,9 +50,9 @@
  */
 uint32_t lsa_lookup_name(char *, uint16_t, smb_account_t *);
 uint32_t lsa_lookup_sid(smb_sid_t *, smb_account_t *);
-DWORD lsa_query_primary_domain_info(char *, char *, nt_domain_t *);
-DWORD lsa_query_account_domain_info(char *, char *, nt_domain_t *);
-DWORD lsa_query_dns_domain_info(char *, char *, nt_domain_t *);
+DWORD lsa_query_primary_domain_info(char *, char *, smb_domain_t *);
+DWORD lsa_query_account_domain_info(char *, char *, smb_domain_t *);
+DWORD lsa_query_dns_domain_info(char *, char *, smb_domain_t *);
 DWORD lsa_enum_trusted_domains(char *, char *, smb_trusted_domains_t *);
 DWORD lsa_enum_trusted_domains_ex(char *, char *, smb_trusted_domains_t *);
 
@@ -68,7 +68,7 @@
  * lsar_lookup.c
  */
 int lsar_query_security_desc(mlsvc_handle_t *);
-DWORD lsar_query_info_policy(mlsvc_handle_t *, WORD, nt_domain_t *);
+DWORD lsar_query_info_policy(mlsvc_handle_t *, WORD, smb_domain_t *);
 uint32_t lsar_lookup_names(mlsvc_handle_t *, char *, smb_account_t *);
 uint32_t lsar_lookup_names2(mlsvc_handle_t *, char *, smb_account_t *);
 uint32_t lsar_lookup_sids(mlsvc_handle_t *, struct mslsa_sid *,
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c	Mon Oct 05 11:03:34 2009 -0700
@@ -103,7 +103,7 @@
  */
 DWORD
 lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
-    nt_domain_t *info)
+    smb_domain_t *info)
 {
 	struct mslsa_QueryInfoPolicy arg;
 	struct mslsa_PrimaryDomainInfo *pd_info;
@@ -119,7 +119,7 @@
 
 	opnum = LSARPC_OPNUM_QueryInfoPolicy;
 
-	bzero(info, sizeof (nt_domain_t));
+	bzero(info, sizeof (smb_domain_t));
 	bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy));
 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
 
@@ -137,8 +137,8 @@
 			pd_info = &arg.ru.pd_info;
 
 			smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr);
-			info->di_type = NT_DOMAIN_PRIMARY;
-			nt_domain_set_basic_info(sidstr,
+			info->di_type = SMB_DOMAIN_PRIMARY;
+			smb_domain_set_basic_info(sidstr,
 			    (char *)pd_info->name.str, "", info);
 
 			status = NT_STATUS_SUCCESS;
@@ -148,8 +148,8 @@
 			ad_info = &arg.ru.ad_info;
 
 			smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr);
-			info->di_type = NT_DOMAIN_ACCOUNT;
-			nt_domain_set_basic_info(sidstr,
+			info->di_type = SMB_DOMAIN_ACCOUNT;
+			smb_domain_set_basic_info(sidstr,
 			    (char *)ad_info->name.str, "", info);
 
 			status = NT_STATUS_SUCCESS;
@@ -161,8 +161,8 @@
 			    guid_str);
 			smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr);
 
-			info->di_type = NT_DOMAIN_PRIMARY;
-			nt_domain_set_dns_info(sidstr,
+			info->di_type = SMB_DOMAIN_PRIMARY;
+			smb_domain_set_dns_info(sidstr,
 			    (char *)dns_info->nb_domain.str,
 			    (char *)dns_info->dns_domain.str,
 			    (char *)dns_info->forest.str,
@@ -884,7 +884,8 @@
 		return;
 
 	list->td_num = 0;
-	list->td_domains = calloc(enum_buf->entries_read, sizeof (nt_domain_t));
+	list->td_domains = calloc(enum_buf->entries_read,
+	    sizeof (smb_domain_t));
 
 	if (list->td_domains == NULL)
 		return;
@@ -892,7 +893,7 @@
 	list->td_num = enum_buf->entries_read;
 	for (i = 0; i < list->td_num; i++) {
 		smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
-		nt_domain_set_trust_info(
+		smb_domain_set_trust_info(
 		    sidstr,
 		    (char *)enum_buf->info[i].nb_name.str,
 		    (char *)enum_buf->info[i].dns_name.str,
@@ -914,7 +915,8 @@
 		return;
 
 	list->td_num = 0;
-	list->td_domains = calloc(enum_buf->entries_read, sizeof (nt_domain_t));
+	list->td_domains = calloc(enum_buf->entries_read,
+	    sizeof (smb_domain_t));
 
 	if (list->td_domains == NULL)
 		return;
@@ -922,7 +924,7 @@
 	list->td_num = enum_buf->entries_read;
 	for (i = 0; i < list->td_num; i++) {
 		smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
-		nt_domain_set_trust_info(
+		smb_domain_set_trust_info(
 		    sidstr, (char *)enum_buf->info[i].name.str,
 		    "", 0, 0, 0, &list->td_domains[i]);
 	}
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,7 +32,6 @@
 #include <strings.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/ntaccess.h>
@@ -104,7 +103,7 @@
 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
 	arg.attributes.length = sizeof (struct mslsa_object_attributes);
 
-	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_NT5_0) {
+	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
 		arg.desiredAccess = MAXIMUM_ALLOWED;
 	} else {
 		arg.desiredAccess = GENERIC_EXECUTE
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Mon Oct 05 11:03:34 2009 -0700
@@ -41,6 +41,7 @@
 SUNWprivate {
     global:
 	dssetup_clear_domain_info;
+	mlsvc_disconnect;
 	mlsvc_fini;
 	mlsvc_init;
 	mlsvc_join;
@@ -49,7 +50,6 @@
 	mlsvc_netlogon;
 	smb_autohome_add;
 	smb_autohome_remove;
-	smb_domain_getinfo;
 	smb_locate_dc;
 	smb_logon;
 	smb_shr_add;
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c	Mon Oct 05 11:03:34 2009 -0700
@@ -27,14 +27,39 @@
  * Client NDR RPC interface.
  */
 
+#include <sys/types.h>
 #include <sys/errno.h>
+#include <time.h>
 #include <strings.h>
 #include <assert.h>
+#include <thread.h>
+#include <synch.h>
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 
+/*
+ * Server info cache entry expiration in seconds.
+ */
+#define	NDR_SVINFO_TIMEOUT	1800
+
+typedef struct ndr_svinfo {
+	list_node_t		svi_lnd;
+	time_t			svi_tcached;
+	char			svi_server[MAXNAMELEN];
+	char			svi_domain[MAXNAMELEN];
+	srvsvc_server_info_t	svi_svinfo;
+} ndr_svinfo_t;
+
+typedef struct ndr_svlist {
+	list_t		svl_list;
+	mutex_t		svl_mtx;
+	boolean_t	svl_init;
+} ndr_svlist_t;
+
+static ndr_svlist_t ndr_svlist;
+
 static int ndr_xa_init(ndr_client_t *, ndr_xa_t *);
 static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *);
 static int ndr_xa_read(ndr_client_t *, ndr_xa_t *);
@@ -42,6 +67,54 @@
 static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *);
 static void ndr_xa_release(ndr_client_t *);
 
+static int ndr_svinfo_lookup(char *, char *, srvsvc_server_info_t *);
+static boolean_t ndr_svinfo_match(const char *, const char *, const
+    ndr_svinfo_t *);
+static boolean_t ndr_svinfo_expired(ndr_svinfo_t *);
+
+/*
+ * Initialize the RPC client interface: create the server info cache.
+ */
+void
+ndr_rpc_init(void)
+{
+	(void) mutex_lock(&ndr_svlist.svl_mtx);
+
+	if (!ndr_svlist.svl_init) {
+		list_create(&ndr_svlist.svl_list, sizeof (ndr_svinfo_t),
+		    offsetof(ndr_svinfo_t, svi_lnd));
+		ndr_svlist.svl_init = B_TRUE;
+	}
+
+	(void) mutex_unlock(&ndr_svlist.svl_mtx);
+}
+
+/*
+ * Terminate the RPC client interface: flush and destroy the server info
+ * cache.
+ */
+void
+ndr_rpc_fini(void)
+{
+	ndr_svinfo_t *svi;
+
+	(void) mutex_lock(&ndr_svlist.svl_mtx);
+
+	if (ndr_svlist.svl_init) {
+		while ((svi = list_head(&ndr_svlist.svl_list)) != NULL) {
+			list_remove(&ndr_svlist.svl_list, svi);
+			free(svi->svi_svinfo.sv_name);
+			free(svi->svi_svinfo.sv_comment);
+			free(svi);
+		}
+
+		list_destroy(&ndr_svlist.svl_list);
+		ndr_svlist.svl_init = B_FALSE;
+	}
+
+	(void) mutex_unlock(&ndr_svlist.svl_mtx);
+}
+
 /*
  * This call must be made to initialize an RPC client structure and bind
  * to the remote service before any RPCs can be exchanged with that service.
@@ -61,7 +134,8 @@
 {
 	ndr_client_t		*clnt;
 	ndr_service_t		*svc;
-	smbrdr_session_info_t	si;
+	srvsvc_server_info_t	svinfo;
+	int			remote_os;
 	int			fid;
 	int			rc;
 
@@ -72,6 +146,20 @@
 	if ((svc = ndr_svc_lookup_name(service)) == NULL)
 		return (-1);
 
+	/*
+	 * Set the default based on the assumption that most
+	 * servers will be Windows 2000 or later.
+	 * Don't lookup the svinfo if this is a SRVSVC request
+	 * because the SRVSVC is used to get the server info.
+	 * None of the SRVSVC calls depend on the remote OS.
+	 */
+	remote_os = NATIVE_OS_WIN2000;
+
+	if (strcasecmp(service, "SRVSVC") != 0) {
+		if (ndr_svinfo_lookup(server, domain, &svinfo) == 0)
+			remote_os = svinfo.sv_os;
+	}
+
 	if ((clnt = malloc(sizeof (ndr_client_t))) == NULL)
 		return (-1);
 
@@ -95,10 +183,9 @@
 	clnt->xa_destruct = ndr_xa_destruct;
 	clnt->xa_release = ndr_xa_release;
 
-	(void) smbrdr_session_info(fid, &si);
 	bzero(&handle->handle, sizeof (ndr_hdid_t));
 	handle->clnt = clnt;
-	handle->remote_os = si.si_server_os;
+	handle->remote_os = remote_os;
 
 	if (ndr_rpc_get_heap(handle) == NULL) {
 		free(clnt);
@@ -170,39 +257,9 @@
 }
 
 /*
- * Set information about the remote RPC server in the handle.
- */
-void
-ndr_rpc_server_setinfo(mlsvc_handle_t *handle,
-    const srvsvc_server_info_t *svinfo)
-{
-	bcopy(svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t));
-	handle->svinfo.sv_name = NULL;
-	handle->svinfo.sv_comment = NULL;
-
-	if (svinfo->sv_version_major > 4)
-		handle->remote_os = NATIVE_OS_WIN2000;
-	else
-		handle->remote_os = NATIVE_OS_WINNT;
-
-	smb_tracef("NdrRpcServerSetInfo: %s (version %d.%d)",
-	    svinfo->sv_name ? svinfo->sv_name : "<unknown>",
-	    svinfo->sv_version_major, svinfo->sv_version_minor);
-}
-
-/*
- * Get information about the remote RPC server from the handle.
- */
-void
-ndr_rpc_server_getinfo(mlsvc_handle_t *handle, srvsvc_server_info_t *svinfo)
-{
-	bcopy(&handle->svinfo, svinfo, sizeof (srvsvc_server_info_t));
-}
-
-/*
  * Returns the Native-OS of the RPC server.
  */
-int
+uint32_t
 ndr_rpc_server_os(mlsvc_handle_t *handle)
 {
 	return (handle->remote_os);
@@ -468,3 +525,90 @@
 		clnt->heap_preserved = B_FALSE;
 	}
 }
+
+/*
+ * Lookup platform, type and version information about a server.
+ * If the cache doesn't already contain the data, contact the server and
+ * cache the response before returning the server info to the caller.
+ */
+static int
+ndr_svinfo_lookup(char *server, char *domain, srvsvc_server_info_t *svinfo)
+{
+	ndr_svinfo_t *svi;
+
+	(void) mutex_lock(&ndr_svlist.svl_mtx);
+	assert(ndr_svlist.svl_init == B_TRUE);
+
+	svi = list_head(&ndr_svlist.svl_list);
+	while (svi != NULL) {
+		if (ndr_svinfo_expired(svi)) {
+			svi = list_head(&ndr_svlist.svl_list);
+			continue;
+		}
+
+		if (ndr_svinfo_match(server, domain, svi)) {
+			bcopy(&svi->svi_svinfo, svinfo,
+			    sizeof (srvsvc_server_info_t));
+			(void) mutex_unlock(&ndr_svlist.svl_mtx);
+			return (0);
+		}
+
+		svi = list_next(&ndr_svlist.svl_list, svi);
+	}
+
+	if ((svi = malloc(sizeof (ndr_svinfo_t))) == NULL) {
+		(void) mutex_unlock(&ndr_svlist.svl_mtx);
+		return (-1);
+	}
+
+	if (srvsvc_net_server_getinfo(server, domain, &svi->svi_svinfo) < 0) {
+		(void) mutex_unlock(&ndr_svlist.svl_mtx);
+		free(svi);
+		return (-1);
+	}
+
+	(void) time(&svi->svi_tcached);
+	(void) strlcpy(svi->svi_server, server, MAXNAMELEN);
+	(void) strlcpy(svi->svi_domain, domain, MAXNAMELEN);
+	list_insert_tail(&ndr_svlist.svl_list, svi);
+	bcopy(&svi->svi_svinfo, svinfo, sizeof (srvsvc_server_info_t));
+	(void) mutex_unlock(&ndr_svlist.svl_mtx);
+	return (0);
+}
+
+static boolean_t
+ndr_svinfo_match(const char *server, const char *domain,
+    const ndr_svinfo_t *svi)
+{
+	if ((utf8_strcasecmp(server, svi->svi_server) == 0) &&
+	    (utf8_strcasecmp(domain, svi->svi_domain) == 0)) {
+		return (B_TRUE);
+	}
+
+	return (B_FALSE);
+}
+
+/*
+ * If the server info in the cache has expired, discard it and return true.
+ * Otherwise return false.
+ *
+ * This is a private function to support ndr_svinfo_lookup() that assumes
+ * the list mutex is held.
+ */
+static boolean_t
+ndr_svinfo_expired(ndr_svinfo_t *svi)
+{
+	time_t	tnow;
+
+	(void) time(&tnow);
+
+	if (difftime(tnow, svi->svi_tcached) > NDR_SVINFO_TIMEOUT) {
+		list_remove(&ndr_svlist.svl_list, svi);
+		free(svi->svi_svinfo.sv_name);
+		free(svi->svi_svinfo.sv_comment);
+		free(svi);
+		return (B_TRUE);
+	}
+
+	return (B_FALSE);
+}
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c	Mon Oct 05 11:03:34 2009 -0700
@@ -38,7 +38,6 @@
 #include <assert.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libsmbns.h>
 #include <smbsrv/libmlsvc.h>
 
@@ -49,7 +48,7 @@
 /*
  * DC Locator
  */
-#define	SMB_DCLOCATOR_TIMEOUT	45
+#define	SMB_DCLOCATOR_TIMEOUT	45	/* seconds */
 #define	SMB_IS_FQDN(domain)	(strchr(domain, '.') != NULL)
 
 typedef struct smb_dclocator {
@@ -64,15 +63,15 @@
 static smb_dclocator_t smb_dclocator;
 static pthread_t smb_dclocator_thr;
 
-static void *smb_dclocator_main(void *);
-static void smb_domain_update(char *, char *);
-static boolean_t smb_domain_query_dns(char *, char *, smb_domain_t *);
-static boolean_t smb_domain_query_nbt(char *, char *, smb_domain_t *);
-static boolean_t smb_domain_match(char *, char *, uint32_t);
-static uint32_t smb_domain_query(char *, char *, smb_domain_t *);
-static void smb_domain_enum_trusted(char *, char *, smb_trusted_domains_t *);
-static uint32_t smb_domain_use_config(char *, nt_domain_t *);
-static void smb_domain_free(smb_domain_t *di);
+static void *smb_ddiscover_service(void *);
+static void smb_ddiscover_main(char *, char *);
+static boolean_t smb_ddiscover_dns(char *, char *, smb_domainex_t *);
+static boolean_t smb_ddiscover_nbt(char *, char *, smb_domainex_t *);
+static boolean_t smb_ddiscover_domain_match(char *, char *, uint32_t);
+static uint32_t smb_ddiscover_qinfo(char *, char *, smb_domainex_t *);
+static void smb_ddiscover_enum_trusted(char *, char *, smb_domainex_t *);
+static uint32_t smb_ddiscover_use_config(char *, smb_domainex_t *);
+static void smb_domainex_free(smb_domainex_t *);
 
 /*
  * ===================================================================
@@ -82,8 +81,6 @@
  */
 
 /*
- * smb_dclocator_init
- *
  * Initialization of the DC locator thread.
  * Returns 0 on success, an error number if thread creation fails.
  */
@@ -96,14 +93,12 @@
 	(void) pthread_attr_init(&tattr);
 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
 	rc = pthread_create(&smb_dclocator_thr, &tattr,
-	    smb_dclocator_main, 0);
+	    smb_ddiscover_service, 0);
 	(void) pthread_attr_destroy(&tattr);
 	return (rc);
 }
 
 /*
- * smb_locate_dc
- *
  * This is the entry point for discovering a domain controller for the
  * specified domain.
  *
@@ -121,11 +116,11 @@
  * Returns B_TRUE if the DC/domain info is available.
  */
 boolean_t
-smb_locate_dc(char *domain, char *dc, smb_domain_t *dp)
+smb_locate_dc(char *domain, char *dc, smb_domainex_t *dp)
 {
 	int rc;
 	timestruc_t to;
-	smb_domain_t domain_info;
+	smb_domainex_t domain_info;
 
 	if (domain == NULL || *domain == '\0')
 		return (B_FALSE);
@@ -160,31 +155,21 @@
 }
 
 /*
- * Returns a copy of primary domain information plus
- * the selected domain controller
- */
-boolean_t
-smb_domain_getinfo(smb_domain_t *dp)
-{
-	return (nt_domain_get_primary(dp));
-}
-
-/*
  * ==========================================================
  * DC discovery functions
  * ==========================================================
  */
 
 /*
- * This is the DC discovery thread: it gets woken up whenever someone
- * wants to locate a domain controller.
+ * This is the domain and DC discovery service: it gets woken up whenever
+ * there is need to locate a domain controller.
  *
  * Upon success, the SMB domain cache will be populated with the discovered
  * DC and domain info.
  */
 /*ARGSUSED*/
 static void *
-smb_dclocator_main(void *arg)
+smb_ddiscover_service(void *arg)
 {
 	char domain[SMB_PI_MAX_DOMAIN];
 	char sought_dc[MAXHOSTNAMELEN];
@@ -201,7 +186,7 @@
 		(void) strlcpy(sought_dc, smb_dclocator.sdl_dc, MAXHOSTNAMELEN);
 		(void) mutex_unlock(&smb_dclocator.sdl_mtx);
 
-		smb_domain_update(domain, sought_dc);
+		smb_ddiscover_main(domain, sought_dc);
 
 		(void) mutex_lock(&smb_dclocator.sdl_mtx);
 		smb_dclocator.sdl_locate = B_FALSE;
@@ -223,29 +208,30 @@
  * obtained information.
  */
 static void
-smb_domain_update(char *domain, char *server)
+smb_ddiscover_main(char *domain, char *server)
 {
-	smb_domain_t di;
-	boolean_t query_ok;
+	smb_domainex_t dxi;
+	boolean_t discovered;
 
-	bzero(&di, sizeof (smb_domain_t));
+	bzero(&dxi, sizeof (smb_domainex_t));
 
-	nt_domain_start_update();
+	if (smb_domain_start_update() != SMB_DOMAIN_SUCCESS)
+		return;
 
 	if (SMB_IS_FQDN(domain))
-		query_ok = smb_domain_query_dns(domain, server, &di);
+		discovered = smb_ddiscover_dns(domain, server, &dxi);
 	else
-		query_ok = smb_domain_query_nbt(domain, server, &di);
+		discovered = smb_ddiscover_nbt(domain, server, &dxi);
 
-	if (query_ok)
-		nt_domain_update(&di);
+	if (discovered)
+		smb_domain_update(&dxi);
 
-	nt_domain_end_update();
+	smb_domain_end_update();
 
-	smb_domain_free(&di);
+	smb_domainex_free(&dxi);
 
-	if (query_ok)
-		nt_domain_save();
+	if (discovered)
+		smb_domain_save();
 }
 
 /*
@@ -253,13 +239,14 @@
  * primary and trusted domains information will be queried.
  */
 static boolean_t
-smb_domain_query_dns(char *domain, char *server, smb_domain_t *di)
+smb_ddiscover_dns(char *domain, char *server, smb_domainex_t *dxi)
 {
 	uint32_t status;
-	if (!smb_ads_lookup_msdcs(domain, server, di->d_dc, MAXHOSTNAMELEN))
+
+	if (!smb_ads_lookup_msdcs(domain, server, dxi->d_dc, MAXHOSTNAMELEN))
 		return (B_FALSE);
 
-	status = smb_domain_query(domain, di->d_dc, di);
+	status = smb_ddiscover_qinfo(domain, dxi->d_dc, dxi);
 	return (status == NT_STATUS_SUCCESS);
 }
 
@@ -277,30 +264,30 @@
  * actually for another domain, whose first label of its FQDN somehow
  * matches with the NetBIOS name of the domain we're interested in.
  */
-
 static boolean_t
-smb_domain_query_nbt(char *domain, char *server, smb_domain_t *di)
+smb_ddiscover_nbt(char *domain, char *server, smb_domainex_t *dxi)
 {
 	char dnsdomain[MAXHOSTNAMELEN];
 	uint32_t status;
 
 	*dnsdomain = '\0';
 
-	if (!smb_browser_netlogon(domain, di->d_dc, MAXHOSTNAMELEN)) {
-		if (!smb_domain_match(domain, dnsdomain, MAXHOSTNAMELEN))
+	if (!smb_browser_netlogon(domain, dxi->d_dc, MAXHOSTNAMELEN)) {
+		if (!smb_ddiscover_domain_match(domain, dnsdomain,
+		    MAXHOSTNAMELEN))
 			return (B_FALSE);
 
-		if (!smb_ads_lookup_msdcs(dnsdomain, server, di->d_dc,
+		if (!smb_ads_lookup_msdcs(dnsdomain, server, dxi->d_dc,
 		    MAXHOSTNAMELEN))
 			return (B_FALSE);
 	}
 
-	status = smb_domain_query(domain, di->d_dc, di);
+	status = smb_ddiscover_qinfo(domain, dxi->d_dc, dxi);
 	if (status != NT_STATUS_SUCCESS)
 		return (B_FALSE);
 
 	if ((*dnsdomain != '\0') &&
-	    utf8_strcasecmp(domain, di->d_info.di_nbname))
+	    utf8_strcasecmp(domain, dxi->d_primary.di_nbname))
 		return (B_FALSE);
 
 	/*
@@ -309,8 +296,8 @@
 	 * if we previously locate a DC via NetBIOS. On success,
 	 * ADS cache will be populated.
 	 */
-	if (smb_ads_lookup_msdcs(di->d_info.di_fqname, server,
-	    di->d_dc, MAXHOSTNAMELEN) == 0)
+	if (smb_ads_lookup_msdcs(dxi->d_primary.di_fqname, server,
+	    dxi->d_dc, MAXHOSTNAMELEN) == 0)
 		return (B_FALSE);
 
 	return (B_TRUE);
@@ -322,7 +309,7 @@
  * If a match is found, it'll be returned in the passed buffer.
  */
 static boolean_t
-smb_domain_match(char *nb_domain, char *buf, uint32_t len)
+smb_ddiscover_domain_match(char *nb_domain, char *buf, uint32_t len)
 {
 	struct __res_state res_state;
 	int i;
@@ -373,22 +360,22 @@
  * domain - either NetBIOS or fully-qualified domain name
  */
 static uint32_t
-smb_domain_query(char *domain, char *server, smb_domain_t *di)
+smb_ddiscover_qinfo(char *domain, char *server, smb_domainex_t *dxi)
 {
 	uint32_t status;
 
 	mlsvc_disconnect(server);
 
-	status = lsa_query_dns_domain_info(server, domain, &di->d_info);
+	status = lsa_query_dns_domain_info(server, domain, &dxi->d_primary);
 	if (status != NT_STATUS_SUCCESS) {
-		status = smb_domain_use_config(domain, &di->d_info);
+		status = smb_ddiscover_use_config(domain, dxi);
 		if (status != NT_STATUS_SUCCESS)
 			status = lsa_query_primary_domain_info(server, domain,
-			    &di->d_info);
+			    &dxi->d_primary);
 	}
 
 	if (status == NT_STATUS_SUCCESS)
-		smb_domain_enum_trusted(domain, server, &di->d_trusted);
+		smb_ddiscover_enum_trusted(domain, server, dxi);
 
 	return (status);
 }
@@ -399,10 +386,12 @@
  * domain - either NetBIOS or fully-qualified domain name.
  */
 static void
-smb_domain_enum_trusted(char *domain, char *server, smb_trusted_domains_t *list)
+smb_ddiscover_enum_trusted(char *domain, char *server, smb_domainex_t *dxi)
 {
+	smb_trusted_domains_t *list;
 	uint32_t status;
 
+	list = &dxi->d_trusted;
 	status = lsa_enum_trusted_domains_ex(server, domain, list);
 	if (status != NT_STATUS_SUCCESS)
 		(void) lsa_enum_trusted_domains(server, domain, list);
@@ -410,15 +399,17 @@
 
 /*
  * If the domain to be discovered matches the current domain (i.e the
- * value of either domain or fqdn configuration), the output parameter
- * 'dinfo' will be set to the information stored in SMF.
+ * value of either domain or fqdn configuration), then get the primary
+ * domain information from SMF.
  */
 static uint32_t
-smb_domain_use_config(char *domain, nt_domain_t *dinfo)
+smb_ddiscover_use_config(char *domain, smb_domainex_t *dxi)
 {
 	boolean_t use;
+	smb_domain_t *dinfo;
 
-	bzero(dinfo, sizeof (nt_domain_t));
+	dinfo = &dxi->d_primary;
+	bzero(dinfo, sizeof (smb_domain_t));
 
 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
 		return (NT_STATUS_UNSUCCESSFUL);
@@ -440,7 +431,7 @@
 }
 
 static void
-smb_domain_free(smb_domain_t *di)
+smb_domainex_free(smb_domainex_t *dxi)
 {
-	free(di->d_trusted.td_domains);
+	free(dxi->d_trusted.td_domains);
 }
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c	Mon Oct 05 11:03:34 2009 -0700
@@ -60,6 +60,7 @@
 	if ((rc = smb_dclocator_init()) != 0)
 		return (rc);
 
+	ndr_rpc_init();
 	srvsvc_initialize();
 	wkssvc_initialize();
 	lsarpc_initialize();
@@ -86,6 +87,7 @@
 	smb_logon_fini();
 	svcctl_finalize();
 	logr_finalize();
+	ndr_rpc_fini();
 }
 
 /*ARGSUSED*/
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c	Mon Oct 05 11:03:34 2009 -0700
@@ -520,7 +520,7 @@
 	struct mslsa_GetConnectedUser *param = arg;
 	smb_netuserinfo_t *user = &mxa->pipe->np_user;
 	DWORD status = NT_STATUS_SUCCESS;
-	smb_domain_t di;
+	smb_domainex_t di;
 	int rc1;
 	int rc2;
 
@@ -638,16 +638,16 @@
 lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *info,
     ndr_xa_t *mxa)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	boolean_t found;
 	int rc;
 
 	bzero(info, sizeof (struct mslsa_PrimaryDomainInfo));
 
 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
-		found = nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di);
+		found = smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di);
 	else
-		found = nt_domain_lookup_type(NT_DOMAIN_PRIMARY, &di);
+		found = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &di);
 
 	if (!found)
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
@@ -676,12 +676,12 @@
 lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *info,
     ndr_xa_t *mxa)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	int rc;
 
 	bzero(info, sizeof (struct mslsa_AccountDomainInfo));
 
-	if (!nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di))
+	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 
 	rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c	Mon Oct 05 11:03:34 2009 -0700
@@ -59,7 +59,7 @@
 
 typedef struct samr_keydata {
 	samr_key_t kd_key;
-	nt_domain_type_t kd_type;
+	smb_domain_type_t kd_type;
 	DWORD kd_rid;
 } samr_keydata_t;
 
@@ -93,7 +93,7 @@
 
 #define	SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
 
-static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, nt_domain_type_t,
+static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
     DWORD);
 static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
 static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t);
@@ -147,7 +147,7 @@
  * Handle allocation wrapper to setup the local context.
  */
 static ndr_hdid_t *
-samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, nt_domain_type_t domain_type,
+samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
     DWORD rid)
 {
 	samr_keydata_t *data;
@@ -213,7 +213,7 @@
 	struct samr_ConnectAnon *param = arg;
 	ndr_hdid_t *id;
 
-	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0);
+	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
 	if (id) {
 		bcopy(id, &param->handle, sizeof (samr_handle_t));
 		param->status = 0;
@@ -257,7 +257,7 @@
 {
 	struct samr_LookupDomain *param = arg;
 	char *domain_name;
-	nt_domain_t di;
+	smb_domain_t di;
 
 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
 		bzero(param, sizeof (struct samr_LookupDomain));
@@ -265,7 +265,7 @@
 		return (NDR_DRC_OK);
 	}
 
-	if (!nt_domain_lookup_name(domain_name, &di)) {
+	if (!smb_domain_lookup_name(domain_name, &di)) {
 		bzero(param, sizeof (struct samr_LookupDomain));
 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
 		return (NDR_DRC_OK);
@@ -370,7 +370,7 @@
 {
 	struct samr_OpenDomain *param = arg;
 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
-	nt_domain_t domain;
+	smb_domain_t domain;
 
 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
 		bzero(&param->domain_handle, sizeof (samr_handle_t));
@@ -378,14 +378,14 @@
 		return (NDR_DRC_OK);
 	}
 
-	if (!nt_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
+	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
 		bzero(&param->domain_handle, sizeof (samr_handle_t));
 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 		return (NDR_DRC_OK);
 	}
 
-	if ((domain.di_type != NT_DOMAIN_BUILTIN) &&
-	    (domain.di_type != NT_DOMAIN_LOCAL)) {
+	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
+	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
 		bzero(&param->domain_handle, sizeof (samr_handle_t));
 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 		return (NDR_DRC_OK);
@@ -444,13 +444,13 @@
 	data = (samr_keydata_t *)hd->nh_data;
 
 	switch (data->kd_type) {
-	case NT_DOMAIN_BUILTIN:
+	case SMB_DOMAIN_BUILTIN:
 		domain = "BUILTIN";
 		user_cnt = 0;
 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
 		break;
 
-	case NT_DOMAIN_LOCAL:
+	case SMB_DOMAIN_LOCAL:
 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
 		if (rc == 0) {
 			domain = hostname;
@@ -560,7 +560,7 @@
 	data = (samr_keydata_t *)hd->nh_data;
 
 	switch (data->kd_type) {
-	case NT_DOMAIN_BUILTIN:
+	case SMB_DOMAIN_BUILTIN:
 		wka = smb_wka_lookup_name((char *)param->name.str);
 		if (wka != NULL) {
 			param->rids.n_entry = 1;
@@ -573,7 +573,7 @@
 		}
 		break;
 
-	case NT_DOMAIN_LOCAL:
+	case SMB_DOMAIN_LOCAL:
 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
 		    SidTypeUnknown, &account);
 		if (status == NT_STATUS_SUCCESS) {
@@ -697,7 +697,7 @@
 	smb_sid_t *user_sid = NULL;
 	smb_group_t grp;
 	smb_giter_t gi;
-	nt_domain_t di;
+	smb_domain_t di;
 	uint32_t status;
 	int size;
 	int ngrp_max;
@@ -709,9 +709,9 @@
 
 	data = (samr_keydata_t *)hd->nh_data;
 	switch (data->kd_type) {
-	case NT_DOMAIN_BUILTIN:
-	case NT_DOMAIN_LOCAL:
-		if (!nt_domain_lookup_type(data->kd_type, &di)) {
+	case SMB_DOMAIN_BUILTIN:
+	case SMB_DOMAIN_LOCAL:
+		if (!smb_domain_lookup_type(data->kd_type, &di)) {
 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 			goto query_error;
 		}
@@ -828,7 +828,7 @@
 	struct samr_Connect *param = arg;
 	ndr_hdid_t *id;
 
-	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0);
+	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
 	if (id) {
 		bcopy(id, &param->handle, sizeof (samr_handle_t));
 		param->status = 0;
@@ -956,10 +956,10 @@
 	data = (samr_keydata_t *)hd->nh_data;
 
 	switch (data->kd_type) {
-	case NT_DOMAIN_BUILTIN:
+	case SMB_DOMAIN_BUILTIN:
 		goto no_info;
 
-	case NT_DOMAIN_LOCAL:
+	case SMB_DOMAIN_LOCAL:
 		num_users = smb_sam_usr_cnt();
 		start_idx = param->start_idx;
 		if ((num_users == 0) || (start_idx >= num_users))
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Mon Oct 05 11:03:34 2009 -0700
@@ -38,9 +38,9 @@
 #include <syslog.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libsmbns.h>
 #include <smbsrv/libmlsvc.h>
+#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/smbinfo.h>
 #include <lsalib.h>
 #include <samlib.h>
@@ -138,21 +138,21 @@
  * Returns NT status codes.
  */
 DWORD
-mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text)
+mlsvc_join(smb_domainex_t *dxi, char *user, char *plain_text)
 {
 	int erc;
 	DWORD status;
 	char machine_passwd[NETR_MACHINE_ACCT_PASSWD_MAX];
 	smb_adjoin_status_t err;
-	nt_domain_t *domain;
+	smb_domain_t *domain;
 
 	machine_passwd[0] = '\0';
 
-	domain = &dinfo->d_info;
+	domain = &dxi->d_primary;
 
-	mlsvc_disconnect(dinfo->d_dc);
+	mlsvc_disconnect(dxi->d_dc);
 
-	erc = mlsvc_logon(dinfo->d_dc, domain->di_nbname, user);
+	erc = smbrdr_logon(dxi->d_dc, domain->di_nbname, user);
 
 	if (erc == AUTH_USER_GRANT) {
 		if (mlsvc_ntjoin_support == B_FALSE) {
@@ -167,7 +167,7 @@
 			}
 		} else {
 
-			status = sam_create_trust_account(dinfo->d_dc,
+			status = sam_create_trust_account(dxi->d_dc,
 			    domain->di_nbname);
 			if (status == NT_STATUS_SUCCESS) {
 				(void) smb_getnetbiosname(machine_passwd,
@@ -177,7 +177,7 @@
 		}
 
 		if (status == NT_STATUS_SUCCESS) {
-			erc = smb_setdomainprops(NULL, dinfo->d_dc,
+			erc = smb_setdomainprops(NULL, dxi->d_dc,
 			    machine_passwd);
 			if (erc != 0) {
 				syslog(LOG_NOTICE, "Failed to update CIFS "
@@ -185,7 +185,7 @@
 				return (NT_STATUS_UNSUCCESSFUL);
 			}
 
-			status = mlsvc_netlogon(dinfo->d_dc, domain->di_nbname);
+			status = mlsvc_netlogon(dxi->d_dc, domain->di_nbname);
 		}
 	} else {
 		status = NT_STATUS_LOGON_FAILURE;
@@ -193,3 +193,15 @@
 
 	return (status);
 }
+
+int
+mlsvc_ping(const char *server)
+{
+	return (smbrdr_echo(server));
+}
+
+void
+mlsvc_disconnect(const char *server)
+{
+	smbrdr_disconnect(server);
+}
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c	Mon Oct 05 11:03:34 2009 -0700
@@ -40,7 +40,6 @@
 #include <security/pkcs11.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libsmbns.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/netlogon.ndl>
@@ -127,18 +126,13 @@
 int
 netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle)
 {
-	srvsvc_server_info_t svinfo;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
 
-	if (srvsvc_net_server_getinfo(server, domain, &svinfo) < 0)
-		return (-1);
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if (ndr_rpc_bind(netr_handle, server, domain, user, "NETR") < 0)
 		return (-1);
 
-	ndr_rpc_server_setinfo(netr_handle, &svinfo);
-	free(svinfo.sv_name);
-	free(svinfo.sv_comment);
 	return (0);
 }
 
@@ -214,7 +208,7 @@
 	arg.hostname = (unsigned char *)netr_info->hostname;
 	arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS;
 
-	if (ndr_rpc_server_os(netr_handle) != NATIVE_OS_WINNT) {
+	if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) {
 		arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG;
 		if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS)
 			return (-1);
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Mon Oct 05 11:03:34 2009 -0700
@@ -37,7 +37,6 @@
 #include <thread.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/ndl/netlogon.ndl>
@@ -104,7 +103,7 @@
 	char resource_domain[SMB_PI_MAX_DOMAIN];
 	char server[NETBIOS_NAME_SZ * 2];
 	mlsvc_handle_t netr_handle;
-	smb_domain_t di;
+	smb_domainex_t di;
 	uint32_t status;
 	int retries = 0, server_changed = 0;
 
@@ -113,7 +112,7 @@
 	if (!smb_domain_getinfo(&di))
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 
-	if ((mlsvc_echo(di.d_dc)) < 0) {
+	if (mlsvc_ping(di.d_dc) < 0) {
 		/*
 		 * We had a session to the DC but it's not responding.
 		 * So drop the credential chain.
@@ -123,7 +122,8 @@
 	}
 
 	do {
-		if (netr_open(di.d_dc, di.d_info.di_nbname, &netr_handle) != 0)
+		if (netr_open(di.d_dc, di.d_primary.di_nbname, &netr_handle)
+		    != 0)
 			return (NT_STATUS_OPEN_FAILED);
 
 		if (di.d_dc && (*netr_global_info.server != '\0')) {
@@ -677,13 +677,13 @@
 static boolean_t
 netr_isadmin(struct netr_validation_info3 *info3)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	int i;
 
-	if (!nt_domain_lookup_sid((smb_sid_t *)info3->LogonDomainId, &di))
+	if (!smb_domain_lookup_sid((smb_sid_t *)info3->LogonDomainId, &di))
 		return (B_FALSE);
 
-	if (di.di_type != NT_DOMAIN_PRIMARY)
+	if (di.di_type != SMB_DOMAIN_PRIMARY)
 		return (B_FALSE);
 
 	if ((info3->UserId == DOMAIN_USER_RID_ADMIN) ||
--- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c	Mon Oct 05 11:03:34 2009 -0700
@@ -31,7 +31,6 @@
 #include <alloca.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlsvc.h>
 
 #include <smbsrv/ntstatus.h>
@@ -114,7 +113,9 @@
 	DWORD rid;
 	DWORD status;
 	int rc;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT,
 	    &samr_handle);
@@ -199,7 +200,9 @@
 	DWORD access_mask;
 	DWORD status;
 	int rc;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
 	    &samr_handle);
@@ -250,7 +253,9 @@
 	DWORD access_mask;
 	DWORD status;
 	int rc;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
 	    &samr_handle);
@@ -306,7 +311,9 @@
 	struct samr_sid *domain_sid;
 	int rc;
 	DWORD status;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	*rid_ret = 0;
 
@@ -352,7 +359,9 @@
 	mlsvc_handle_t samr_handle;
 	DWORD status;
 	int rc;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	rc = samr_open(server, domain_name, user, SAM_ENUM_LOCAL_DOMAIN,
 	    &samr_handle);
@@ -399,21 +408,20 @@
 static struct samr_sid *
 sam_get_domain_sid(mlsvc_handle_t *samr_handle, char *server, char *domain_name)
 {
-	struct samr_sid *sid = NULL;
-	smb_domain_t domain;
+	smb_sid_t *sid = NULL;
+	smb_domainex_t domain;
 
 	if (ndr_rpc_server_os(samr_handle) == NATIVE_OS_WIN2000) {
 		if (!smb_domain_getinfo(&domain)) {
 			if (lsa_query_account_domain_info(server, domain_name,
-			    &domain.d_info) != NT_STATUS_SUCCESS)
+			    &domain.d_primary) != NT_STATUS_SUCCESS)
 				return (NULL);
 		}
 
-		sid = (struct samr_sid *)smb_sid_fromstr(domain.d_info.di_sid);
+		sid = smb_sid_fromstr(domain.d_primary.di_sid);
 	} else {
-		sid = (struct samr_sid *)samr_lookup_domain(samr_handle,
-		    domain_name);
+		sid = samr_lookup_domain(samr_handle, domain_name);
 	}
 
-	return (sid);
+	return ((struct samr_sid *)sid);
 }
--- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c	Mon Oct 05 11:03:34 2009 -0700
@@ -41,7 +41,6 @@
 #include <sys/param.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
@@ -55,6 +54,9 @@
 static DWORD samr_connect3(char *, char *, char *, DWORD, mlsvc_handle_t *);
 static DWORD samr_connect4(char *, char *, char *, DWORD, mlsvc_handle_t *);
 
+typedef DWORD (*samr_connop_t)(char *, char *, char *, DWORD,
+    mlsvc_handle_t *);
+
 /*
  * samr_open
  *
@@ -71,7 +73,7 @@
 samr_open(char *server, char *domain, char *username, DWORD access_mask,
     mlsvc_handle_t *samr_handle)
 {
-	smb_domain_t di;
+	smb_domainex_t di;
 	int rc;
 
 	if (server == NULL || domain == NULL) {
@@ -79,7 +81,7 @@
 			return (-1);
 
 		server = di.d_dc;
-		domain = di.d_info.di_nbname;
+		domain = di.d_primary.di_nbname;
 	}
 
 	if (username == NULL)
@@ -93,38 +95,41 @@
 /*
  * samr_connect
  *
- * Connect to the SAM on the specified server (domain controller).
- * This is the entry point for the various SAM connect calls.  We do
- * parameter validation and open the samr named pipe here.  The actual
- * RPC is based on the native OS of the server.
+ * Connect to the SAMR service on the specified server (domain controller).
+ * New SAM connect calls have been added to Windows over time:
  *
- * Returns 0 on success. Otherwise returns a -ve error code.
+ *	Windows NT3.x:	SamrConnect
+ *	Windows NT4.0:	SamrConnect2
+ *	Windows 2000:	SamrConnect3
+ *	Windows XP:	SamrConnect4
+ *
+ * Try the calls from most recent to oldest until the server responds with
+ * something other than an RPC protocol error.  We don't use the original
+ * connect call because all supported servers should support SamrConnect2.
  */
 int
 samr_connect(char *server, char *domain, char *username, DWORD access_mask,
     mlsvc_handle_t *samr_handle)
 {
-	DWORD status;
+	static samr_connop_t samr_connop[] = {
+		samr_connect4,
+		samr_connect3,
+		samr_connect2
+	};
+
+	int	n_op = (sizeof (samr_connop) / sizeof (samr_connop[0]));
+	DWORD	status;
+	int	i;
 
 	if (ndr_rpc_bind(samr_handle, server, domain, username, "SAMR") < 0)
 		return (-1);
 
-	switch (ndr_rpc_server_os(samr_handle)) {
-	case NATIVE_OS_NT5_1:
-		status = samr_connect4(server, domain, username, access_mask,
-		    samr_handle);
-		break;
+	for (i = 0; i < n_op; ++i) {
+		status = (*samr_connop[i])(server, domain, username,
+		    access_mask, samr_handle);
 
-	case NATIVE_OS_NT5_0:
-		status = samr_connect3(server, domain, username, access_mask,
-		    samr_handle);
-		break;
-
-	case NATIVE_OS_NT4_0:
-	default:
-		status = samr_connect2(server, domain, username, access_mask,
-		    samr_handle);
-		break;
+		if (status != NT_STATUS_UNSUCCESSFUL)
+			break;
 	}
 
 	if (status != NT_STATUS_SUCCESS) {
@@ -244,7 +249,7 @@
 	len = strlen(server) + 4;
 	arg.servername = ndr_rpc_malloc(samr_handle, len);
 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
-	arg.unknown_02 = 0x00000002;
+	arg.revision = SAMR_REVISION_2;
 	arg.access_mask = access_mask;
 
 	if (ndr_rpc_call(samr_handle, opnum, &arg) != 0) {
@@ -283,7 +288,7 @@
 	int len;
 	int opnum;
 	DWORD status;
-	smb_domain_t dinfo;
+	smb_domainex_t dinfo;
 
 	bzero(&arg, sizeof (struct samr_Connect4));
 	opnum = SAMR_OPNUM_Connect;
@@ -292,12 +297,12 @@
 	if (!smb_domain_getinfo(&dinfo))
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 
-	len = strlen(server) + strlen(dinfo.d_info.di_fqname) + 4;
+	len = strlen(server) + strlen(dinfo.d_primary.di_fqname) + 4;
 	arg.servername = ndr_rpc_malloc(samr_handle, len);
 
-	if (*dinfo.d_info.di_fqname != '\0')
+	if (*dinfo.d_primary.di_fqname != '\0')
 		(void) snprintf((char *)arg.servername, len, "\\\\%s.%s",
-		    server, dinfo.d_info.di_fqname);
+		    server, dinfo.d_primary.di_fqname);
 	else
 		(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
 
@@ -572,7 +577,7 @@
 	ndr_heap_mkvcs(heap, username, (ndr_vcstr_t *)&arg.username);
 
 	arg.account_flags = account_flags;
-	arg.unknown_e00500b0 = 0xE00500B0;
+	arg.desired_access = 0xE00500B0;
 
 	rc = ndr_rpc_call(domain_handle, opnum, &arg);
 	if (rc != 0) {
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c	Mon Oct 05 11:03:34 2009 -0700
@@ -490,13 +490,13 @@
 	char guest[SMB_USERNAME_MAXLEN];
 	smb_passwd_t smbpw;
 	uint32_t status;
-	nt_domain_t domain;
+	smb_domain_t domain;
 	boolean_t isguest;
 
 	/* Make sure this is not a domain user */
 	if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) {
-		if (nt_domain_lookup_name(clnt->e_domain, &domain)) {
-			if (domain.di_type != NT_DOMAIN_LOCAL)
+		if (smb_domain_lookup_name(clnt->e_domain, &domain)) {
+			if (domain.di_type != SMB_DOMAIN_LOCAL)
 				return (NT_STATUS_INVALID_LOGON_TYPE);
 		}
 	}
--- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c	Mon Oct 05 11:03:34 2009 -0700
@@ -39,7 +39,6 @@
 #include <time.h>
 
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbrdr.h>
 #include <smbsrv/libmlsvc.h>
 #include <smbsrv/smbinfo.h>
 #include <smbsrv/ntstatus.h>
@@ -61,14 +60,14 @@
 static int
 srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle)
 {
-	smb_domain_t di;
+	smb_domainex_t di;
 
 	if (server == NULL || domain == NULL) {
 		if (!smb_domain_getinfo(&di))
 			return (-1);
 
 		server = di.d_dc;
-		domain = di.d_info.di_nbname;
+		domain = di.d_primary.di_nbname;
 	}
 
 	if (username == NULL)
@@ -105,13 +104,13 @@
 	struct mslm_NetShareInfo_1 *info1;
 	struct mslm_NetShareInfo_2 *info2;
 	int len;
-	char *user = NULL;
+	char user[SMB_USERNAME_MAXLEN];
 
 	if (netname == NULL)
 		return (-1);
 
 	if (srvsvc_info_level == 2)
-		user = smbrdr_ipc_get_user();
+		smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if (srvsvc_open(server, domain, user, &handle) != 0)
 		return (-1);
@@ -195,11 +194,13 @@
 	struct mslm_infonres infonres;
 	struct mslm_SESSION_INFO_1 *nsi1;
 	int len;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
 
 	if (netname == NULL)
 		return (-1);
 
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
+
 	rc = srvsvc_open(server, domain, user, &handle);
 	if (rc != 0)
 		return (-1);
@@ -260,11 +261,13 @@
 	struct mslm_NetConnectInfo0 info0;
 	struct mslm_NetConnectInfoBuf1 *cib1;
 	int len;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
 
 	if (netname == NULL)
 		return (-1);
 
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
+
 	rc = srvsvc_open(server, domain, user, &handle);
 	if (rc != 0)
 		return (-1);
@@ -347,6 +350,10 @@
 	return (0);
 }
 
+/*
+ * Windows 95+ and Windows NT4.0 both report the version as 4.0.
+ * Windows 2000+ reports the version as 5.x.
+ */
 int
 srvsvc_net_server_getinfo(char *server, char *domain,
     srvsvc_server_info_t *svinfo)
@@ -355,7 +362,9 @@
 	struct mslm_NetServerGetInfo arg;
 	struct mslm_SERVER_INFO_101 *sv101;
 	int len, opnum, rc;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	if (srvsvc_open(server, domain, user, &handle) != 0)
 		return (-1);
@@ -389,6 +398,16 @@
 	if (sv101->sv101_comment)
 		svinfo->sv_comment = strdup((char *)sv101->sv101_comment);
 
+	if (svinfo->sv_type & SV_TYPE_WFW)
+		svinfo->sv_os = NATIVE_OS_WIN95;
+	if (svinfo->sv_type & SV_TYPE_WINDOWS)
+		svinfo->sv_os = NATIVE_OS_WIN95;
+	if ((svinfo->sv_type & SV_TYPE_NT) ||
+	    (svinfo->sv_type & SV_TYPE_SERVER_NT))
+		svinfo->sv_os = NATIVE_OS_WINNT;
+	if (svinfo->sv_version_major > 4)
+		svinfo->sv_os = NATIVE_OS_WIN2000;
+
 	srvsvc_close(&handle);
 	return (0);
 }
@@ -399,7 +418,7 @@
 void
 srvsvc_timesync(void)
 {
-	smb_domain_t di;
+	smb_domainex_t di;
 	struct timeval tv;
 	struct tm tm;
 	time_t tsecs;
@@ -407,7 +426,8 @@
 	if (!smb_domain_getinfo(&di))
 		return;
 
-	if (srvsvc_net_remote_tod(di.d_dc, di.d_info.di_nbname, &tv, &tm) != 0)
+	if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm)
+	    != 0)
 		return;
 
 	if (settimeofday(&tv, 0))
@@ -424,14 +444,15 @@
 int
 srvsvc_gettime(unsigned long *t)
 {
-	smb_domain_t di;
+	smb_domainex_t di;
 	struct timeval tv;
 	struct tm tm;
 
 	if (!smb_domain_getinfo(&di))
 		return (-1);
 
-	if (srvsvc_net_remote_tod(di.d_dc, di.d_info.di_nbname, &tv, &tm) != 0)
+	if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm)
+	    != 0)
 		return (-1);
 
 	*t = tv.tv_sec;
@@ -477,7 +498,9 @@
 	int rc;
 	int opnum;
 	int len;
-	char *user = smbrdr_ipc_get_user();
+	char user[SMB_USERNAME_MAXLEN];
+
+	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
 
 	rc = srvsvc_open(server, domain, user, &handle);
 	if (rc != 0)
@@ -535,14 +558,14 @@
 void
 srvsvc_net_test(char *server, char *domain, char *netname)
 {
-	smb_domain_t di;
+	smb_domainex_t di;
 	srvsvc_server_info_t svinfo;
 
 	(void) smb_tracef("%s %s %s", server, domain, netname);
 
 	if (smb_domain_getinfo(&di)) {
 		server = di.d_dc;
-		domain = di.d_info.di_nbname;
+		domain = di.d_primary.di_nbname;
 	}
 
 	if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) {
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Mon Oct 05 11:03:34 2009 -0700
@@ -484,6 +484,16 @@
     unsigned char *, int, char *, char *, uchar_t *);
 
 /*
+ * SMB authenticated IPC
+ */
+extern void smb_ipc_commit(void);
+extern void smb_ipc_get_user(char *, size_t);
+extern void smb_ipc_get_passwd(uint8_t *, size_t);
+extern void smb_ipc_init(void);
+extern void smb_ipc_rollback(void);
+extern void smb_ipc_set(char *, uint8_t *);
+
+/*
  * SMB MAC Signing
  */
 
@@ -553,16 +563,16 @@
  * that the system joined. All other domains are either
  * trusted or untrusted, as defined by the primary domain PDC.
  */
-typedef enum nt_domain_type {
-	NT_DOMAIN_NULL,
-	NT_DOMAIN_BUILTIN,
-	NT_DOMAIN_LOCAL,
-	NT_DOMAIN_PRIMARY,
-	NT_DOMAIN_ACCOUNT,
-	NT_DOMAIN_TRUSTED,
-	NT_DOMAIN_UNTRUSTED,
-	NT_DOMAIN_NUM_TYPES
-} nt_domain_type_t;
+typedef enum smb_domain_type {
+	SMB_DOMAIN_NULL,
+	SMB_DOMAIN_BUILTIN,
+	SMB_DOMAIN_LOCAL,
+	SMB_DOMAIN_PRIMARY,
+	SMB_DOMAIN_ACCOUNT,
+	SMB_DOMAIN_TRUSTED,
+	SMB_DOMAIN_UNTRUSTED,
+	SMB_DOMAIN_NUM_TYPES
+} smb_domain_type_t;
 
 /*
  * Information specific to trusted domains
@@ -586,9 +596,9 @@
 /*
  * This is the information that is held about each domain.
  */
-typedef struct nt_domain {
+typedef struct smb_domain {
 	list_node_t		di_lnd;
-	nt_domain_type_t	di_type;
+	smb_domain_type_t	di_type;
 	char			di_sid[SMB_SID_STRSZ];
 	char			di_nbname[NETBIOS_NAME_SZ];
 	char			di_fqname[MAXHOSTNAMELEN];
@@ -597,11 +607,11 @@
 		smb_domain_dns_t	di_dns;
 		smb_domain_trust_t	di_trust;
 	} di_u;
-} nt_domain_t;
+} smb_domain_t;
 
 typedef struct smb_trusted_domains {
 	uint32_t	td_num;
-	nt_domain_t	*td_domains;
+	smb_domain_t	*td_domains;
 } smb_trusted_domains_t;
 
 #define	SMB_DOMAIN_SUCCESS		0
@@ -611,29 +621,38 @@
 #define	SMB_DOMAIN_INTERNAL_ERR		4
 #define	SMB_DOMAIN_INVALID_ARG		5
 #define	SMB_DOMAIN_NO_MEMORY		6
+#define	SMB_DOMAIN_NO_CACHE		7
 
-typedef struct smb_domain {
+/*
+ * This structure could contain information about
+ * the primary domain the name of selected domain controller
+ * for the primary domain and a list of trusted domains if
+ * any. The "ex" in the structure name stands for extended.
+ * This is to differentiate this structure from smb_domain_t
+ * which only contains information about a single domain.
+ */
+typedef struct smb_domainex {
 	char			d_dc[MAXHOSTNAMELEN];
-	nt_domain_t		d_info;
+	smb_domain_t		d_primary;
 	smb_trusted_domains_t	d_trusted;
-} smb_domain_t;
+} smb_domainex_t;
 
-int nt_domain_init(uint32_t);
-void nt_domain_fini(void);
-void nt_domain_show(void);
-void nt_domain_save(void);
-boolean_t nt_domain_lookup_name(char *, nt_domain_t *);
-boolean_t nt_domain_lookup_sid(smb_sid_t *, nt_domain_t *);
-boolean_t nt_domain_lookup_type(nt_domain_type_t, nt_domain_t *);
-boolean_t nt_domain_get_primary(smb_domain_t *);
-void nt_domain_update(smb_domain_t *);
-void nt_domain_start_update(void);
-void nt_domain_end_update(void);
-void nt_domain_set_basic_info(char *, char *, char *, nt_domain_t *);
-void nt_domain_set_dns_info(char *, char *, char *, char *, char *,
-    nt_domain_t *);
-void nt_domain_set_trust_info(char *, char *, char *,
-    uint32_t, uint32_t, uint32_t, nt_domain_t *);
+int smb_domain_init(uint32_t);
+void smb_domain_fini(void);
+void smb_domain_show(void);
+void smb_domain_save(void);
+boolean_t smb_domain_lookup_name(char *, smb_domain_t *);
+boolean_t smb_domain_lookup_sid(smb_sid_t *, smb_domain_t *);
+boolean_t smb_domain_lookup_type(smb_domain_type_t, smb_domain_t *);
+boolean_t smb_domain_getinfo(smb_domainex_t *);
+void smb_domain_update(smb_domainex_t *);
+uint32_t smb_domain_start_update(void);
+void smb_domain_end_update(void);
+void smb_domain_set_basic_info(char *, char *, char *, smb_domain_t *);
+void smb_domain_set_dns_info(char *, char *, char *, char *, char *,
+    smb_domain_t *);
+void smb_domain_set_trust_info(char *, char *, char *,
+    uint32_t, uint32_t, uint32_t, smb_domain_t *);
 
 typedef enum {
 	SMB_LGRP_BUILTIN = 1,
@@ -823,7 +842,7 @@
 uint32_t smb_sam_lookup_sid(smb_sid_t *, smb_account_t *);
 int smb_sam_usr_cnt(void);
 uint32_t smb_sam_usr_groups(smb_sid_t *, smb_ids_t *);
-int smb_sam_grp_cnt(nt_domain_type_t);
+int smb_sam_grp_cnt(smb_domain_type_t);
 void smb_account_free(smb_account_t *);
 boolean_t smb_account_validate(smb_account_t *);
 
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Mon Oct 05 11:03:34 2009 -0700
@@ -84,20 +84,6 @@
 	mts_wctomb;
 	netr_client_mkabsolute;
 	netr_client_xfree;
-	nt_domain_end_update;
-	nt_domain_fini;
-	nt_domain_get_primary;
-	nt_domain_init;
-	nt_domain_lookup_name;
-	nt_domain_lookup_sid;
-	nt_domain_lookup_type;
-	nt_domain_save;
-	nt_domain_set_basic_info;
-	nt_domain_set_dns_info;
-	nt_domain_set_trust_info;
-	nt_domain_show;
-	nt_domain_start_update;
-	nt_domain_update;
 	oem_get_smb_cpid;
 	oem_get_telnet_cpid;
 	oem_language_set;
@@ -149,6 +135,20 @@
 	smb_ctxbuf_printf;
 	smb_dlclose;
 	smb_dlopen;
+	smb_domain_end_update;
+	smb_domain_fini;
+	smb_domain_getinfo;
+	smb_domain_init;
+	smb_domain_lookup_name;
+	smb_domain_lookup_sid;
+	smb_domain_lookup_type;
+	smb_domain_save;
+	smb_domain_set_basic_info;
+	smb_domain_set_dns_info;
+	smb_domain_set_trust_info;
+	smb_domain_show;
+	smb_domain_start_update;
+	smb_domain_update;
 	smb_dr_clnt_call;
 	smb_dr_clnt_cleanup;
 	smb_dr_clnt_setup;
@@ -220,6 +220,12 @@
 	smb_inet_equal;
 	smb_inet_iszero;
 	smb_inet_ntop;
+	smb_ipc_set;
+	smb_ipc_commit;
+	smb_ipc_init;
+	smb_ipc_rollback;
+	smb_ipc_get_user;
+	smb_ipc_get_passwd;
 	smb_kmod_bind;
 	smb_kmod_enum;
 	smb_kmod_enum_init;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c	Mon Oct 05 11:03:34 2009 -0700
@@ -77,21 +77,21 @@
 
 static smb_domain_cache_t smb_dcache;
 
-static uint32_t nt_domain_add(nt_domain_type_t, nt_domain_t *);
-static uint32_t nt_domain_add_local(void);
-static uint32_t nt_domain_add_primary(uint32_t);
-static void nt_domain_unlink(void);
+static uint32_t smb_domain_add(smb_domain_type_t, smb_domain_t *);
+static uint32_t smb_domain_add_local(void);
+static uint32_t smb_domain_add_primary(uint32_t);
+static void smb_domain_unlink(void);
 
 static void smb_dcache_create(void);
 static void smb_dcache_destroy(void);
 static uint32_t smb_dcache_lock(int);
 static void smb_dcache_unlock(void);
-static void smb_dcache_remove(nt_domain_t *);
-static uint32_t smb_dcache_add(nt_domain_t *);
+static void smb_dcache_remove(smb_domain_t *);
+static uint32_t smb_dcache_add(smb_domain_t *);
 static void smb_dcache_getdc(char *, size_t);
 static void smb_dcache_setdc(char *);
 static boolean_t smb_dcache_wait(void);
-static void smb_dcache_updating(void);
+static uint32_t smb_dcache_updating(void);
 static void smb_dcache_ready(void);
 
 /*
@@ -101,30 +101,30 @@
  * Returns 0 on success and an error code on failure.
  */
 int
-nt_domain_init(uint32_t secmode)
+smb_domain_init(uint32_t secmode)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	int rc;
 
 	smb_dcache_create();
 
-	if ((rc = nt_domain_add_local()) != 0)
+	if ((rc = smb_domain_add_local()) != 0)
 		return (rc);
 
-	nt_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di);
-	(void) nt_domain_add(NT_DOMAIN_BUILTIN, &di);
+	smb_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di);
+	(void) smb_domain_add(SMB_DOMAIN_BUILTIN, &di);
 
-	return (nt_domain_add_primary(secmode));
+	return (smb_domain_add_primary(secmode));
 }
 
 /*
  * Destroys the cache upon service termination
  */
 void
-nt_domain_fini(void)
+smb_domain_fini(void)
 {
 	smb_dcache_destroy();
-	nt_domain_unlink();
+	smb_domain_unlink();
 }
 
 /*
@@ -132,7 +132,7 @@
  * for duplicates.
  */
 static uint32_t
-nt_domain_add(nt_domain_type_t type, nt_domain_t *di)
+smb_domain_add(smb_domain_type_t type, smb_domain_t *di)
 {
 	uint32_t res;
 
@@ -160,13 +160,13 @@
  * If the domain is not in the cache B_FALSE is returned.
  */
 boolean_t
-nt_domain_lookup_name(char *name, nt_domain_t *di)
+smb_domain_lookup_name(char *name, smb_domain_t *di)
 {
 	boolean_t found = B_FALSE;
-	nt_domain_t *dcnode;
+	smb_domain_t *dcnode;
 	char *p;
 
-	bzero(di, sizeof (nt_domain_t));
+	bzero(di, sizeof (smb_domain_t));
 
 	if (name == NULL || *name == '\0')
 		return (B_FALSE);
@@ -214,13 +214,13 @@
  * If the domain is not in the cache B_FALSE is returned.
  */
 boolean_t
-nt_domain_lookup_sid(smb_sid_t *sid, nt_domain_t *di)
+smb_domain_lookup_sid(smb_sid_t *sid, smb_domain_t *di)
 {
 	boolean_t found = B_FALSE;
-	nt_domain_t *dcnode;
+	smb_domain_t *dcnode;
 	char sidstr[SMB_SID_STRSZ];
 
-	bzero(di, sizeof (nt_domain_t));
+	bzero(di, sizeof (smb_domain_t));
 
 	if (sid == NULL)
 		return (B_FALSE);
@@ -257,12 +257,12 @@
  * If the domain is not in the cache B_FALSE is returned.
  */
 boolean_t
-nt_domain_lookup_type(nt_domain_type_t type, nt_domain_t *di)
+smb_domain_lookup_type(smb_domain_type_t type, smb_domain_t *di)
 {
 	boolean_t found = B_FALSE;
-	nt_domain_t *dcnode;
+	smb_domain_t *dcnode;
 
-	bzero(di, sizeof (nt_domain_t));
+	bzero(di, sizeof (smb_domain_t));
 
 	if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS)
 		return (B_FALSE);
@@ -288,13 +288,13 @@
  * the selected domain controller.
  */
 boolean_t
-nt_domain_get_primary(smb_domain_t *domain)
+smb_domain_getinfo(smb_domainex_t *dxi)
 {
 	boolean_t success;
 
-	success = nt_domain_lookup_type(NT_DOMAIN_PRIMARY, &domain->d_info);
+	success = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary);
 	if (success)
-		smb_dcache_getdc(domain->d_dc, sizeof (domain->d_dc));
+		smb_dcache_getdc(dxi->d_dc, sizeof (dxi->d_dc));
 
 	return (success);
 }
@@ -304,17 +304,17 @@
  * In this state any request for reading the cache would
  * be blocked until the update is finished.
  */
-void
-nt_domain_start_update(void)
+uint32_t
+smb_domain_start_update(void)
 {
-	smb_dcache_updating();
+	return (smb_dcache_updating());
 }
 
 /*
  * Transfer the cache from updating to ready state.
  */
 void
-nt_domain_end_update(void)
+smb_domain_end_update(void)
 {
 	smb_dcache_ready();
 }
@@ -328,9 +328,9 @@
  * primary and trusted will be removed from cache.
  */
 void
-nt_domain_update(smb_domain_t *domain)
+smb_domain_update(smb_domainex_t *dxi)
 {
-	nt_domain_t *dcnode;
+	smb_domain_t *dcnode;
 	int i;
 
 	if (smb_dcache_lock(SMB_DCACHE_WRLOCK) != SMB_DOMAIN_SUCCESS)
@@ -338,8 +338,8 @@
 
 	dcnode = list_head(&smb_dcache.dc_cache);
 	while (dcnode) {
-		if ((dcnode->di_type == NT_DOMAIN_PRIMARY) ||
-		    (dcnode->di_type == NT_DOMAIN_TRUSTED)) {
+		if ((dcnode->di_type == SMB_DOMAIN_PRIMARY) ||
+		    (dcnode->di_type == SMB_DOMAIN_TRUSTED)) {
 			smb_dcache_remove(dcnode);
 			dcnode = list_head(&smb_dcache.dc_cache);
 		} else {
@@ -347,11 +347,11 @@
 		}
 	}
 
-	if (smb_dcache_add(&domain->d_info) == SMB_DOMAIN_SUCCESS) {
-		for (i = 0; i < domain->d_trusted.td_num; i++)
-			(void) smb_dcache_add(&domain->d_trusted.td_domains[i]);
+	if (smb_dcache_add(&dxi->d_primary) == SMB_DOMAIN_SUCCESS) {
+		for (i = 0; i < dxi->d_trusted.td_num; i++)
+			(void) smb_dcache_add(&dxi->d_trusted.td_domains[i]);
 
-		smb_dcache_setdc(domain->d_dc);
+		smb_dcache_setdc(dxi->d_dc);
 	}
 
 	smb_dcache_unlock();
@@ -361,11 +361,11 @@
  * Write the list of domains to /var/run/smb/domains.
  */
 void
-nt_domain_save(void)
+smb_domain_save(void)
 {
 	char		fname[MAXPATHLEN];
 	char		tag;
-	nt_domain_t	*domain;
+	smb_domain_t	*domain;
 	FILE		*fp;
 	struct passwd	*pwd;
 	struct group	*grp;
@@ -393,16 +393,16 @@
 	domain = list_head(&smb_dcache.dc_cache);
 	while (domain) {
 		switch (domain->di_type) {
-		case NT_DOMAIN_PRIMARY:
+		case SMB_DOMAIN_PRIMARY:
 			tag = '*';
 			break;
 
-		case NT_DOMAIN_TRUSTED:
-		case NT_DOMAIN_UNTRUSTED:
+		case SMB_DOMAIN_TRUSTED:
+		case SMB_DOMAIN_UNTRUSTED:
 			tag = '-';
 			break;
 
-		case NT_DOMAIN_LOCAL:
+		case SMB_DOMAIN_LOCAL:
 			tag = '.';
 			break;
 		default:
@@ -425,7 +425,7 @@
  * List the domains in /var/run/smb/domains.
  */
 void
-nt_domain_show(void)
+smb_domain_show(void)
 {
 	char buf[MAXPATHLEN];
 	char *p;
@@ -449,8 +449,8 @@
 }
 
 void
-nt_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain,
-    nt_domain_t *di)
+smb_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain,
+    smb_domain_t *di)
 {
 	if (sid == NULL || nb_domain == NULL || fq_domain == NULL ||
 	    di == NULL)
@@ -464,31 +464,31 @@
 }
 
 void
-nt_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain,
-    char *forest, char *guid, nt_domain_t *di)
+smb_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain,
+    char *forest, char *guid, smb_domain_t *di)
 {
 	if (di == NULL || forest == NULL || guid == NULL)
 		return;
 
-	nt_domain_set_basic_info(sid, nb_domain, fq_domain, di);
+	smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
 	(void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN);
 	(void) strlcpy(di->di_u.di_dns.ddi_guid, guid,
 	    UUID_PRINTABLE_STRING_LENGTH);
 }
 
 void
-nt_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain,
+smb_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain,
     uint32_t trust_dir, uint32_t trust_type, uint32_t trust_attrs,
-    nt_domain_t *di)
+    smb_domain_t *di)
 {
 	smb_domain_trust_t *ti;
 
 	if (di == NULL)
 		return;
 
-	di->di_type = NT_DOMAIN_TRUSTED;
+	di->di_type = SMB_DOMAIN_TRUSTED;
 	ti = &di->di_u.di_trust;
-	nt_domain_set_basic_info(sid, nb_domain, fq_domain, di);
+	smb_domain_set_basic_info(sid, nb_domain, fq_domain, di);
 	ti->dti_trust_direction = trust_dir;
 	ti->dti_trust_type = trust_type;
 	ti->dti_trust_attrs = trust_attrs;
@@ -498,7 +498,7 @@
  * Remove the /var/run/smb/domains file.
  */
 static void
-nt_domain_unlink(void)
+smb_domain_unlink(void)
 {
 	char fname[MAXPATHLEN];
 
@@ -511,12 +511,12 @@
  * Add an entry for the local domain to the domain cache
  */
 static uint32_t
-nt_domain_add_local(void)
+smb_domain_add_local(void)
 {
 	char *lsidstr;
 	char hostname[NETBIOS_NAME_SZ];
 	char fq_name[MAXHOSTNAMELEN];
-	nt_domain_t di;
+	smb_domain_t di;
 
 	if ((lsidstr = smb_config_get_localsid()) == NULL)
 		return (SMB_DOMAIN_NOMACHINE_SID);
@@ -528,8 +528,8 @@
 
 	*fq_name = '\0';
 	(void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN);
-	nt_domain_set_basic_info(lsidstr, hostname, fq_name, &di);
-	(void) nt_domain_add(NT_DOMAIN_LOCAL, &di);
+	smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di);
+	(void) smb_domain_add(SMB_DOMAIN_LOCAL, &di);
 
 	free(lsidstr);
 	return (SMB_DOMAIN_SUCCESS);
@@ -539,12 +539,12 @@
  * Add an entry for the primary domain to the domain cache
  */
 static uint32_t
-nt_domain_add_primary(uint32_t secmode)
+smb_domain_add_primary(uint32_t secmode)
 {
 	char sidstr[SMB_SID_STRSZ];
 	char fq_name[MAXHOSTNAMELEN];
 	char nb_name[NETBIOS_NAME_SZ];
-	nt_domain_t di;
+	smb_domain_t di;
 	int rc;
 
 	if (secmode != SMB_SECMODE_DOMAIN)
@@ -559,8 +559,8 @@
 		return (SMB_DOMAIN_NODOMAIN_NAME);
 
 	(void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN);
-	nt_domain_set_basic_info(sidstr, nb_name, fq_name, &di);
-	(void) nt_domain_add(NT_DOMAIN_PRIMARY, &di);
+	smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di);
+	(void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di);
 	return (SMB_DOMAIN_SUCCESS);
 }
 
@@ -577,8 +577,8 @@
 		return;
 	}
 
-	list_create(&smb_dcache.dc_cache, sizeof (nt_domain_t),
-	    offsetof(nt_domain_t, di_lnd));
+	list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t),
+	    offsetof(smb_domain_t, di_lnd));
 
 	smb_dcache.dc_nops = 0;
 	*smb_dcache.dc_server = '\0';
@@ -592,7 +592,7 @@
 static void
 smb_dcache_flush(void)
 {
-	nt_domain_t *di;
+	smb_domain_t *di;
 
 	(void) rw_wrlock(&smb_dcache.dc_cache_lck);
 	while ((di = list_head(&smb_dcache.dc_cache)) != NULL)
@@ -687,11 +687,11 @@
 }
 
 static uint32_t
-smb_dcache_add(nt_domain_t *di)
+smb_dcache_add(smb_domain_t *di)
 {
-	nt_domain_t *dcnode;
+	smb_domain_t *dcnode;
 
-	if ((dcnode = malloc(sizeof (nt_domain_t))) == NULL)
+	if ((dcnode = malloc(sizeof (smb_domain_t))) == NULL)
 		return (SMB_DOMAIN_NO_MEMORY);
 
 	*dcnode = *di;
@@ -706,7 +706,7 @@
 }
 
 static void
-smb_dcache_remove(nt_domain_t *di)
+smb_dcache_remove(smb_domain_t *di)
 {
 	list_remove(&smb_dcache.dc_cache, di);
 	smb_sid_free(di->di_binsid);
@@ -729,6 +729,11 @@
 	(void) mutex_unlock(&smb_dcache.dc_mtx);
 }
 
+/*
+ * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in
+ * UPDATING state. Upon wake up returns true if cache is
+ * ready to be used, otherwise it returns false.
+ */
 static boolean_t
 smb_dcache_wait(void)
 {
@@ -747,24 +752,77 @@
 	return (smb_dcache.dc_state == SMB_DCACHE_STATE_READY);
 }
 
-static void
+/*
+ * Transfers the cache into UPDATING state, this will ensure
+ * any read access to the cache will be stalled until the
+ * update is finished. This is to avoid providing incomplete,
+ * inconsistent or stale information.
+ *
+ * If another thread is already updating the cache, other
+ * callers will wait until cache is no longer in UPDATING
+ * state. The return code is decided based on the new
+ * state of the cache.
+ */
+static uint32_t
 smb_dcache_updating(void)
 {
+	uint32_t rc;
+
 	(void) mutex_lock(&smb_dcache.dc_mtx);
-	if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY)
+	switch (smb_dcache.dc_state) {
+	case SMB_DCACHE_STATE_READY:
 		smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
-	else
-		assert(0);
+		rc = SMB_DOMAIN_SUCCESS;
+		break;
+
+	case SMB_DCACHE_STATE_UPDATING:
+		while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)
+			(void) cond_wait(&smb_dcache.dc_cv,
+			    &smb_dcache.dc_mtx);
+
+		if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) {
+			smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING;
+			rc = SMB_DOMAIN_SUCCESS;
+		} else {
+			rc = SMB_DOMAIN_NO_CACHE;
+		}
+		break;
+
+	case SMB_DCACHE_STATE_NONE:
+	case SMB_DCACHE_STATE_DESTROYING:
+		rc = SMB_DOMAIN_NO_CACHE;
+		break;
+
+	default:
+		break;
+	}
+
 	(void) mutex_unlock(&smb_dcache.dc_mtx);
+	return (rc);
 }
 
+/*
+ * Transfers the cache from UPDATING to READY state.
+ *
+ * Nothing will happen if the cache is no longer available
+ * or it is being destroyed.
+ */
 static void
 smb_dcache_ready(void)
 {
 	(void) mutex_lock(&smb_dcache.dc_mtx);
-	if (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING)
+	switch (smb_dcache.dc_state) {
+	case SMB_DCACHE_STATE_UPDATING:
 		smb_dcache.dc_state = SMB_DCACHE_STATE_READY;
-	else
+		(void) cond_broadcast(&smb_dcache.dc_cv);
+		break;
+
+	case SMB_DCACHE_STATE_NONE:
+	case SMB_DCACHE_STATE_DESTROYING:
+		break;
+
+	default:
 		assert(0);
+	}
 	(void) mutex_unlock(&smb_dcache.dc_mtx);
 }
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c	Mon Oct 05 11:03:34 2009 -0700
@@ -48,6 +48,18 @@
 static mutex_t seqnum_mtx;
 
 /*
+ * IPC connection information that may be passed to the SMB Redirector.
+ */
+typedef struct {
+	char	user[SMB_USERNAME_MAXLEN];
+	uint8_t	passwd[SMBAUTH_HASH_SZ];
+} smb_ipc_t;
+
+static smb_ipc_t	ipc_info;
+static smb_ipc_t	ipc_orig_info;
+static rwlock_t		smb_ipc_lock;
+
+/*
  * Some older clients (Windows 98) only handle the low byte
  * of the max workers value. If the low byte is less than
  * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN.
@@ -282,6 +294,108 @@
 	return (rc);
 }
 
+static int
+smb_get_machine_passwd(uint8_t *buf, size_t buflen)
+{
+	char pwd[SMB_PASSWD_MAXLEN + 1];
+	int rc;
+
+	if (buflen < SMBAUTH_HASH_SZ)
+		return (-1);
+
+	rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd));
+	if ((rc != SMBD_SMF_OK) || *pwd == '\0')
+		return (-1);
+
+	if (smb_auth_ntlm_hash(pwd, buf) != 0)
+		return (-1);
+
+	return (rc);
+}
+
+/*
+ * Set up IPC connection credentials.
+ */
+void
+smb_ipc_init(void)
+{
+	int rc;
+
+	(void) rw_wrlock(&smb_ipc_lock);
+	bzero(&ipc_info, sizeof (smb_ipc_t));
+	bzero(&ipc_orig_info, sizeof (smb_ipc_t));
+
+	(void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
+	rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
+	if (rc != 0)
+		*ipc_info.passwd = 0;
+	(void) rw_unlock(&smb_ipc_lock);
+
+}
+
+/*
+ * Set the IPC username and password hash in memory.  If the domain
+ * join succeeds, the credentials will be committed for use with
+ * authenticated IPC.  Otherwise, they should be rolled back.
+ */
+void
+smb_ipc_set(char *plain_user, uint8_t *passwd_hash)
+{
+	(void) rw_wrlock(&smb_ipc_lock);
+	(void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user));
+	(void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ);
+	(void) rw_unlock(&smb_ipc_lock);
+
+}
+
+/*
+ * Save the host credentials to be used for authenticated IPC.
+ * The credentials are also saved to the original IPC info as
+ * rollback data in case the join domain process fails later.
+ */
+void
+smb_ipc_commit(void)
+{
+	(void) rw_wrlock(&smb_ipc_lock);
+	(void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
+	(void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
+	(void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t));
+	(void) rw_unlock(&smb_ipc_lock);
+}
+
+/*
+ * Restore the original credentials
+ */
+void
+smb_ipc_rollback(void)
+{
+	(void) rw_wrlock(&smb_ipc_lock);
+	(void) strlcpy(ipc_info.user, ipc_orig_info.user,
+	    sizeof (ipc_info.user));
+	(void) memcpy(ipc_info.passwd, ipc_orig_info.passwd,
+	    sizeof (ipc_info.passwd));
+	(void) rw_unlock(&smb_ipc_lock);
+}
+
+void
+smb_ipc_get_user(char *buf, size_t buflen)
+{
+	(void) rw_rdlock(&smb_ipc_lock);
+	(void) strlcpy(buf, ipc_info.user, buflen);
+	(void) rw_unlock(&smb_ipc_lock);
+}
+
+void
+smb_ipc_get_passwd(uint8_t *buf, size_t buflen)
+{
+	if (buflen < SMBAUTH_HASH_SZ)
+		return;
+
+	(void) rw_rdlock(&smb_ipc_lock);
+	(void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ);
+	(void) rw_unlock(&smb_ipc_lock);
+}
+
 /*
  * smb_match_netlogon_seqnum
  *
--- a/usr/src/lib/smbsrv/libsmb/common/smb_sam.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_sam.c	Mon Oct 05 11:03:34 2009 -0700
@@ -96,7 +96,7 @@
 smb_sam_lookup_name(char *domain, char *name, uint16_t type,
     smb_account_t *account)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	smb_sid_t *sid;
 	uint32_t status;
 	smb_lwka_t *lwka;
@@ -104,15 +104,15 @@
 	bzero(account, sizeof (smb_account_t));
 
 	if (domain != NULL) {
-		if (!nt_domain_lookup_name(domain, &di) ||
-		    (di.di_type != NT_DOMAIN_LOCAL))
+		if (!smb_domain_lookup_name(domain, &di) ||
+		    (di.di_type != SMB_DOMAIN_LOCAL))
 			return (NT_STATUS_NOT_FOUND);
 
 		/* Only Netbios hostname is accepted */
 		if (utf8_strcasecmp(domain, di.di_nbname) != 0)
 			return (NT_STATUS_NONE_MAPPED);
 	} else {
-		if (!nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di))
+		if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
 			return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 	}
 
@@ -209,7 +209,7 @@
 	smb_passwd_t smbpw;
 	smb_group_t grp;
 	smb_lwka_t *lwka;
-	nt_domain_t di;
+	smb_domain_t di;
 	uint32_t rid;
 	uid_t id;
 	int id_type;
@@ -217,7 +217,7 @@
 
 	bzero(account, sizeof (smb_account_t));
 
-	if (!nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di))
+	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 
 	if (smb_sid_cmp(sid, di.di_binsid)) {
@@ -362,17 +362,17 @@
  * in /var/smb/smbgroup.db
  */
 int
-smb_sam_grp_cnt(nt_domain_type_t dtype)
+smb_sam_grp_cnt(smb_domain_type_t dtype)
 {
 	int grpcnt;
 	int rc;
 
 	switch (dtype) {
-	case NT_DOMAIN_BUILTIN:
+	case SMB_DOMAIN_BUILTIN:
 		rc = smb_lgrp_numbydomain(SMB_LGRP_BUILTIN, &grpcnt);
 		break;
 
-	case NT_DOMAIN_LOCAL:
+	case SMB_DOMAIN_LOCAL:
 		rc = smb_lgrp_numbydomain(SMB_LGRP_LOCAL, &grpcnt);
 		break;
 
--- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h	Mon Oct 05 11:03:34 2009 -0700
@@ -37,8 +37,6 @@
 
 
 typedef struct smb_ads_handle {
-	char *user;		/* admin user to create share in ADS */
-	char *pwd;		/* user password */
 	char *domain;		/* ADS domain */
 	char *domain_dn;	/* domain in Distinquish Name format */
 	char *ip_addr;		/* ip addr in string format */
@@ -103,14 +101,13 @@
 extern void dyndns_update_zones(void);
 extern void dyndns_clear_zones(void);
 
-/* Kerberos initialization function */
-extern int smb_kinit(char *, char *);
+/* Kerberos cache management function */
 extern int smb_ccache_init(char *, char *);
 extern void smb_ccache_remove(char *);
 
 /* NETBIOS Functions */
 extern int smb_netbios_start(void);
-extern void smb_netbios_shutdown(void);
+extern void smb_netbios_stop(void);
 extern void smb_netbios_name_reconfig(void);
 
 /* Browser Functions */
--- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers	Mon Oct 05 11:03:34 2009 -0700
@@ -62,10 +62,9 @@
 	smb_browser_reconfig;
 	smb_ccache_init;
 	smb_ccache_remove;
-	smb_kinit;
 	smb_netbios_name_reconfig;
 	smb_netbios_start;
-	smb_netbios_shutdown;
+	smb_netbios_stop;
     local:
 	*;
 };
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c	Mon Oct 05 11:03:34 2009 -0700
@@ -26,7 +26,6 @@
 #include <sys/param.h>
 #include <ldap.h>
 #include <stdlib.h>
-#include <gssapi/gssapi.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -44,6 +43,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <assert.h>
+#include <sasl/sasl.h>
+#include <note.h>
 
 #include <smbsrv/libsmbns.h>
 #include <smbns_dyndns.h>
@@ -176,7 +177,6 @@
 } smb_ads_host_list_t;
 
 static smb_ads_handle_t *smb_ads_open_main(char *, char *, char *);
-static int smb_ads_bind(smb_ads_handle_t *);
 static int smb_ads_add_computer(smb_ads_handle_t *, int, char *);
 static int smb_ads_modify_computer(smb_ads_handle_t *, int, char *);
 static int smb_ads_computer_op(smb_ads_handle_t *, int, int, char *);
@@ -595,7 +595,7 @@
 /*
  * smb_ads_hlist_alloc
  */
-smb_ads_host_list_t *
+static smb_ads_host_list_t *
 smb_ads_hlist_alloc(int count)
 {
 	int size;
@@ -1034,6 +1034,24 @@
 	return (smb_ads_open_main(domain, NULL, NULL));
 }
 
+static int
+smb_ads_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts)
+{
+	NOTE(ARGUNUSED(ld, defaults));
+	sasl_interact_t *interact;
+
+	if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
+		return (LDAP_PARAM_ERROR);
+
+	/* There should be no extra arguemnts for SASL/GSSAPI authentication */
+	for (interact = prompts; interact->id != SASL_CB_LIST_END;
+	    interact++) {
+		interact->result = NULL;
+		interact->len = 0;
+	}
+	return (LDAP_SUCCESS);
+}
+
 /*
  * smb_ads_open_main
  * Open a LDAP connection to an ADS server.
@@ -1048,7 +1066,7 @@
  * After the LDAP connection, the LDAP version will be set to 3 using
  * ldap_set_option().
  *
- * The smb_ads_bind() routine is also called before the ADS handle is returned.
+ * The LDAP connection is bound before the ADS handle is returned.
  * Parameters:
  *   domain - fully-qualified domain name
  *   user   - the user account for whom the Kerberos TGT ticket and ADS
@@ -1066,6 +1084,14 @@
 	LDAP *ld;
 	int version = 3;
 	smb_ads_host_info_t *ads_host = NULL;
+	int rc;
+
+	if (user != NULL) {
+		if (smb_kinit(user, password) == 0)
+			return (NULL);
+		user = NULL;
+		password = NULL;
+	}
 
 	ads_host = smb_ads_find_host(domain, NULL);
 	if (ads_host == NULL)
@@ -1097,8 +1123,6 @@
 
 	(void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
 	ah->ld = ld;
-	ah->user = (user) ? strdup(user) : NULL;
-	ah->pwd = (password) ? strdup(password) : NULL;
 	ah->domain = strdup(domain);
 
 	if (ah->domain == NULL) {
@@ -1133,7 +1157,11 @@
 	}
 	(void) mutex_unlock(&smb_ads_cfg.c_mtx);
 
-	if (smb_ads_bind(ah) == -1) {
+	rc = ldap_sasl_interactive_bind_s(ah->ld, "", "GSSAPI", NULL, NULL,
+	    LDAP_SASL_INTERACTIVE, &smb_ads_saslcallback, NULL);
+	if (rc != LDAP_SUCCESS) {
+		syslog(LOG_ERR, "ldal_sasl_interactive_bind_s failed (%s)",
+		    ldap_err2string(rc));
 		smb_ads_close(ah);
 		free(ads_host);
 		return (NULL);
@@ -1155,22 +1183,12 @@
 void
 smb_ads_close(smb_ads_handle_t *ah)
 {
-	int len;
-
 	if (ah == NULL)
 		return;
 	/* close and free connection resources */
 	if (ah->ld)
 		(void) ldap_unbind(ah->ld);
 
-	free(ah->user);
-	if (ah->pwd) {
-		len = strlen(ah->pwd);
-		/* zero out the memory that contains user's password */
-		if (len > 0)
-			bzero(ah->pwd, len);
-		free(ah->pwd);
-	}
 	free(ah->domain);
 	free(ah->domain_dn);
 	free(ah->hostname);
@@ -1179,31 +1197,6 @@
 }
 
 /*
- * smb_ads_display_stat
- * Display error message for GSS-API routines.
- * Parameters:
- *   maj:  GSS major status
- *   min:  GSS minor status
- * Returns:
- *   None
- */
-static void
-smb_ads_display_stat(OM_uint32 maj, OM_uint32 min)
-{
-	gss_buffer_desc msg;
-	OM_uint32 msg_ctx = 0;
-	OM_uint32 min2;
-	(void) gss_display_status(&min2, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID,
-	    &msg_ctx, &msg);
-	smb_tracef("major status: %s", (char *)msg.value);
-	(void) gss_release_buffer(&min2, &msg);
-	(void) gss_display_status(&min2, min, GSS_C_MECH_CODE, GSS_C_NULL_OID,
-	    &msg_ctx, &msg);
-	smb_tracef("minor status: %s", (char *)msg.value);
-	(void) gss_release_buffer(&min2, &msg);
-}
-
-/*
  * smb_ads_alloc_attr
  *
  * Since the attrs is a null-terminated array, all elements
@@ -1282,290 +1275,6 @@
 }
 
 /*
- * smb_ads_acquire_cred
- * Called by smb_ads_bind() to get a handle to administrative user's credential
- * stored locally on the system.  The credential is the TGT.  If the attempt at
- * getting handle fails then a second attempt will be made after getting a
- * new TGT.
- * Please look at smb_ads_bind() for more information.
- *
- * Paramters:
- *   ah         : handle to ADS server
- *   kinit_retry: if 0 then a second attempt will be made to get handle to the
- *                credential if the first attempt fails
- * Returns:
- *   cred_handle: handle to the administrative user's credential (TGT)
- *   oid        : contains Kerberos 5 object identifier
- *   kinit_retry: A 1 indicates that a second attempt has been made to get
- *                handle to the credential and no further attempts can be made
- *   -1         : error
- *    0         : success
- */
-static int
-smb_ads_acquire_cred(smb_ads_handle_t *ah, gss_cred_id_t *cred_handle,
-    gss_OID *oid, int *kinit_retry)
-{
-	return (krb5_acquire_cred_kinit(ah->user, ah->pwd, cred_handle, oid,
-	    kinit_retry, "ads"));
-}
-
-/*
- * smb_ads_establish_sec_context
- * Called by smb_ads_bind() to establish a security context to an LDAP service
- * on an ADS server. If the attempt at establishing the security context fails
- * then a second attempt will be made by smb_ads_bind() if a new TGT has not
- * been already obtained in ads_acquire_cred.  The second attempt, if allowed,
- * will obtained a new TGT here and a new handle to the credential will also be
- * obtained in ads_acquire_cred.  LDAP SASL bind is used to send and receive
- * the GSS tokens to and from the ADS server.
- * Please look at ads_bind for more information.
- * Paramters:
- *   ah             : handle to ADS server
- *   cred_handle    : handle to administrative user's credential (TGT)
- *   oid            : Kerberos 5 object identifier
- *   kinit_retry    : if 0 then a second attempt can be made to establish a
- *                    security context with ADS server if first attempt fails
- * Returns:
- *   gss_context    : security context to ADS server
- *   sercred        : encrypted ADS server's supported security layers
- *   do_acquire_cred: if 1 then a second attempt will be made to establish a
- *                    security context with ADS server after getting a new
- *                    handle to the user's credential
- *   kinit_retry    : if 1 then a second attempt will be made to establish a
- *                    a security context and no further attempts can be made
- *   -1             : error
- *    0             : success
- */
-static int
-smb_ads_establish_sec_context(smb_ads_handle_t *ah, gss_ctx_id_t *gss_context,
-    gss_cred_id_t cred_handle, gss_OID oid, struct berval **sercred,
-    int *kinit_retry, int *do_acquire_cred)
-{
-	OM_uint32 maj, min, time_rec;
-	char service_name[SMB_ADS_MAXBUFLEN];
-	gss_buffer_desc send_tok, service_buf;
-	gss_name_t target_name;
-	gss_buffer_desc input;
-	gss_buffer_desc *inputptr;
-	struct berval cred;
-	OM_uint32 ret_flags;
-	int stat;
-	int gss_flags;
-
-	(void) snprintf(service_name, SMB_ADS_MAXBUFLEN, "ldap@%s",
-	    ah->hostname);
-	service_buf.value = service_name;
-	service_buf.length = strlen(service_name)+1;
-	if ((maj = gss_import_name(&min, &service_buf,
-	    (gss_OID) gss_nt_service_name,
-	    &target_name)) != GSS_S_COMPLETE) {
-		smb_ads_display_stat(maj, min);
-		if (oid != GSS_C_NO_OID)
-			(void) gss_release_oid(&min, &oid);
-		return (-1);
-	}
-
-	*gss_context = GSS_C_NO_CONTEXT;
-	*sercred = NULL;
-	inputptr = GSS_C_NO_BUFFER;
-	gss_flags = GSS_C_MUTUAL_FLAG;
-	do {
-		if (krb5_establish_sec_ctx_kinit(ah->user, ah->pwd,
-		    cred_handle, gss_context, target_name, oid,
-		    gss_flags, inputptr, &send_tok,
-		    &ret_flags, &time_rec, kinit_retry,
-		    do_acquire_cred, &maj, "ads") == -1) {
-			if (oid != GSS_C_NO_OID)
-				(void) gss_release_oid(&min, &oid);
-			(void) gss_release_name(&min, &target_name);
-			return (-1);
-		}
-
-		cred.bv_val = send_tok.value;
-		cred.bv_len = send_tok.length;
-		if (*sercred) {
-			ber_bvfree(*sercred);
-			*sercred = NULL;
-		}
-		stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI",
-		    &cred, NULL, NULL, sercred);
-		if (stat != LDAP_SUCCESS &&
-		    stat != LDAP_SASL_BIND_IN_PROGRESS) {
-			syslog(LOG_NOTICE, "ldap_sasl_bind: %s",
-			    ldap_err2string(stat));
-			if (oid != GSS_C_NO_OID)
-				(void) gss_release_oid(&min, &oid);
-			(void) gss_release_name(&min, &target_name);
-			(void) gss_release_buffer(&min, &send_tok);
-			return (-1);
-		}
-		input.value = (*sercred)->bv_val;
-		input.length = (*sercred)->bv_len;
-		inputptr = &input;
-		if (send_tok.length > 0)
-			(void) gss_release_buffer(&min, &send_tok);
-	} while (maj != GSS_S_COMPLETE);
-
-	if (oid != GSS_C_NO_OID)
-		(void) gss_release_oid(&min, &oid);
-	(void) gss_release_name(&min, &target_name);
-
-	return (0);
-}
-
-/*
- * smb_ads_negotiate_sec_layer
- * Call by smb_ads_bind() to negotiate additional security layer for further
- * communication after security context establishment.  No additional security
- * is needed so a "no security layer" is negotiated.  The security layer is
- * described in the SASL RFC 2478 and this step is needed for secure LDAP
- * binding.  LDAP SASL bind is used to send and receive the GSS tokens to and
- * from the ADS server.
- * Please look at smb_ads_bind for more information.
- *
- * Paramters:
- *   ah         : handle to ADS server
- *   gss_context: security context to ADS server
- *   sercred    : encrypted ADS server's supported security layers
- * Returns:
- *   -1         : error
- *    0         : success
- */
-static int
-smb_ads_negotiate_sec_layer(smb_ads_handle_t *ah, gss_ctx_id_t gss_context,
-    struct berval *sercred)
-{
-	OM_uint32 maj, min;
-	gss_buffer_desc unwrap_inbuf, unwrap_outbuf;
-	gss_buffer_desc wrap_inbuf, wrap_outbuf;
-	int conf_state, sec_layer;
-	char auth_id[5];
-	struct berval cred;
-	int stat;
-	gss_qop_t qt;
-
-	/* check for server supported security layer */
-	unwrap_inbuf.value = sercred->bv_val;
-	unwrap_inbuf.length = sercred->bv_len;
-	if ((maj = gss_unwrap(&min, gss_context,
-	    &unwrap_inbuf, &unwrap_outbuf,
-	    &conf_state, &qt)) != GSS_S_COMPLETE) {
-		smb_ads_display_stat(maj, min);
-		if (sercred)
-			ber_bvfree(sercred);
-		return (-1);
-	}
-	sec_layer = *((char *)unwrap_outbuf.value);
-	(void) gss_release_buffer(&min, &unwrap_outbuf);
-	if (!(sec_layer & 1)) {
-		if (sercred)
-			ber_bvfree(sercred);
-		return (-1);
-	}
-	if (sercred) ber_bvfree(sercred);
-
-	/* no security layer needed after successful binding */
-	auth_id[0] = 0x01;
-
-	/* byte 2-4: max client recv size in network byte order */
-	auth_id[1] = 0x00;
-	auth_id[2] = 0x40;
-	auth_id[3] = 0x00;
-	wrap_inbuf.value = auth_id;
-	wrap_inbuf.length = 4;
-	conf_state = 0;
-	if ((maj = gss_wrap(&min, gss_context, conf_state, 0, &wrap_inbuf,
-	    &conf_state, &wrap_outbuf)) != GSS_S_COMPLETE) {
-		smb_ads_display_stat(maj, min);
-		return (-1);
-	}
-
-	cred.bv_val = wrap_outbuf.value;
-	cred.bv_len = wrap_outbuf.length;
-	sercred = NULL;
-	stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI", &cred, NULL, NULL,
-	    &sercred);
-	if (stat != LDAP_SUCCESS && stat != LDAP_SASL_BIND_IN_PROGRESS) {
-		syslog(LOG_NOTICE, "ldap_sasl_bind: %s",
-		    ldap_err2string(stat));
-		(void) gss_release_buffer(&min, &wrap_outbuf);
-		return (-1);
-	}
-
-	(void) gss_release_buffer(&min, &wrap_outbuf);
-	if (sercred)
-		ber_bvfree(sercred);
-
-	return (0);
-}
-
-/*
- * smb_ads_bind
- * Use secure binding to bind to ADS server.
- * Use GSS-API with Kerberos 5 as the security mechanism and LDAP SASL with
- * Kerberos 5 as the security mechanisn to authenticate, obtain a security
- * context, and securely bind an administrative user so that other LDAP
- * commands can be used, i.e. add and delete.
- *
- * To obtain the security context, a Kerberos ticket-granting ticket (TGT)
- * for the user is needed to obtain a ticket for the LDAP service.  To get
- * a TGT for the user, the username and password is needed.  Once a TGT is
- * obtained then it will be stored locally and used until it is expired.
- * This routine will automatically obtained a TGT for the first time or when
- * it expired.  LDAP SASL bind is then finally used to send GSS tokens to
- * obtain a security context for the LDAP service on the ADS server.  If
- * there is any problem getting the security context then a new TGT will be
- * obtain to try getting the security context once more.
- *
- * After the security context is obtain and established, the LDAP SASL bind
- * is used to negotiate an additional security layer.  No further security is
- * needed so a "no security layer" is negotiated.  After this the security
- * context can be deleted and further LDAP commands can be sent to the ADS
- * server until a LDAP unbind command is issued to the ADS server.
- * Paramaters:
- *   ah: handle to ADS server
- * Returns:
- *  -1: error
- *   0: success
- */
-static int
-smb_ads_bind(smb_ads_handle_t *ah)
-{
-	OM_uint32 min;
-	gss_cred_id_t cred_handle;
-	gss_ctx_id_t gss_context;
-	gss_OID oid;
-	struct berval *sercred;
-	int kinit_retry, do_acquire_cred;
-	int rc = 0;
-
-	kinit_retry = 0;
-	do_acquire_cred = 0;
-
-acquire_cred:
-
-	if (smb_ads_acquire_cred(ah, &cred_handle, &oid, &kinit_retry))
-		return (-1);
-
-	if (smb_ads_establish_sec_context(ah, &gss_context, cred_handle,
-	    oid, &sercred, &kinit_retry, &do_acquire_cred)) {
-		(void) gss_release_cred(&min, &cred_handle);
-		if (do_acquire_cred) {
-			do_acquire_cred = 0;
-			goto acquire_cred;
-		}
-		return (-1);
-	}
-	rc = smb_ads_negotiate_sec_layer(ah, gss_context, sercred);
-
-	if (cred_handle != GSS_C_NO_CREDENTIAL)
-		(void) gss_release_cred(&min, &cred_handle);
-	(void) gss_delete_sec_context(&min, &gss_context, NULL);
-
-	return ((rc) ? -1 : 0);
-}
-
-/*
  * smb_ads_add_share
  * Call by smb_ads_publish_share to create share object in ADS.
  * This routine specifies the attributes of an ADS LDAP share object. The first
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c	Mon Oct 05 11:03:34 2009 -0700
@@ -23,6 +23,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/tzfile.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -38,10 +39,8 @@
 
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libsmbns.h>
-
 #include <smbsrv/cifs.h>
 #include <smbsrv/mailslot.h>
-
 #include <smbns_browser.h>
 #include <smbns_netbios.h>
 
@@ -83,8 +82,6 @@
 static void smb_browser_infofree(void);
 
 
-
-
 void
 smb_browser_reconfig(void)
 {
@@ -653,7 +650,7 @@
     struct name_entry *result)
 {
 	uint32_t ipaddr, mask, saddr;
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 
 	if (name == NULL)
 		return (-1);
@@ -692,7 +689,7 @@
 	result->addr_list.sin.sin_family = AF_INET;
 	result->addr_list.sinlen = sizeof (result->addr_list.sin);
 	result->addr_list.sin.sin_addr.s_addr = bcast;
-	result->addr_list.sin.sin_port = htons(DGM_SRVC_UDP_PORT);
+	result->addr_list.sin.sin_port = htons(IPPORT_NETBIOS_DGM);
 	result->addr_list.forw = result->addr_list.back = &result->addr_list;
 	return (0);
 }
@@ -772,7 +769,7 @@
 static void
 smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo,
     uint32_t next_announcement, boolean_t remove,
-    struct addr_entry *addr, char suffix)
+    addr_entry_t *addr, char suffix)
 {
 	smb_msgbuf_t mb;
 	int offset, announce_len, data_length;
@@ -801,9 +798,9 @@
 	}
 
 	/* give some extra room */
-	buffer = (unsigned char *)malloc(MAX_DATAGRAM_LENGTH * 2);
-	if (buffer == 0) {
-		syslog(LOG_ERR, "HostAnnouncement: resource shortage");
+	buffer = malloc(MAX_DATAGRAM_LENGTH * 2);
+	if (buffer == NULL) {
+		syslog(LOG_DEBUG, "smb browser: HostAnnouncement: %m");
 		return;
 	}
 
@@ -824,7 +821,7 @@
 	 * specifying a type of 0 just prior to shutting down, to allow it to
 	 * quickly be removed from the list of available servers.
 	 */
-	if (remove || (nb_status.state & NETBIOS_SHUTTING_DOWN))
+	if (remove || (!smb_netbios_running()))
 		type = 0;
 	else
 		type = hinfo->hi_type;
@@ -860,11 +857,11 @@
 	boolean_t h_found = B_FALSE;
 
 	if (strcmp(mailbox, MAILSLOT_LANMAN) != 0) {
-		syslog(LOG_DEBUG, "smb_browse: Wrong Mailbox (%s)", mailbox);
+		syslog(LOG_DEBUG, "smb browser: wrong mailbox (%s)", mailbox);
 		return;
 	}
 
-	(void) sleep(delay);
+	smb_netbios_sleep(delay);
 
 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
 	hinfo = list_head(&smb_binfo.bi_hlist);
@@ -882,7 +879,7 @@
 	if (h_found) {
 		next_announcement = hinfo->hi_nextannouce * 60 * 1000;
 		smb_browser_send_HostAnnouncement(hinfo, next_announcement,
-		    B_FALSE, &datagram->src.addr_list, 0x1D);
+		    B_FALSE, &datagram->src.addr_list, NBT_MB);
 	}
 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
 }
@@ -915,7 +912,7 @@
 	unsigned char 	*data;
 	int		datalen;
 
-	syslog(LOG_DEBUG, "smb_browse: packet_received");
+	syslog(LOG_DEBUG, "smb browser: packet received");
 
 	smb_msgbuf_init(&mb, datagram->data, datagram->data_length, 0);
 	rc = smb_msgbuf_decode(&mb, "Mb27.bwwwwb.w6.wwwwb.wwwws",
@@ -939,7 +936,7 @@
 	    &mailbox);			/* Mailbox address */
 
 	if (rc < 0) {
-		syslog(LOG_ERR, "smb_browser_dispatch: decode error");
+		syslog(LOG_ERR, "smb browser: decode error");
 		smb_msgbuf_term(&mb);
 		free(datagram);
 		return (0);
@@ -972,7 +969,7 @@
 		break;
 
 	default:
-		syslog(LOG_DEBUG, "smb_browse: invalid message_type(%d, %x)",
+		syslog(LOG_DEBUG, "smb browser: invalid message type(%d, %x)",
 		    message_type, message_type);
 		break;
 	}
@@ -1064,7 +1061,7 @@
 	(void) utf8_strupr(resource_domain);
 
 	/* domain<00> */
-	smb_init_name_struct((unsigned char *)resource_domain, 0x00,
+	smb_init_name_struct((unsigned char *)resource_domain, NBT_WKSTA,
 	    0, 0, 0, 0, 0, &name);
 	entry = smb_name_find_name(&name);
 	smb_name_unlock_name(entry);
@@ -1072,9 +1069,9 @@
 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
 	hinfo = list_head(&smb_binfo.bi_hlist);
 	while (hinfo) {
-		smb_init_name_struct((unsigned char *)resource_domain, 0x00, 0,
-		    hinfo->hi_nic.nic_ip.a_ipv4,
-		    htons(DGM_SRVC_UDP_PORT), NAME_ATTR_GROUP,
+		smb_init_name_struct((unsigned char *)resource_domain,
+		    NBT_WKSTA, 0, hinfo->hi_nic.nic_ip.a_ipv4,
+		    htons(IPPORT_NETBIOS_DGM), NAME_ATTR_GROUP,
 		    NAME_ATTR_LOCAL, &name);
 		(void) smb_name_add_name(&name);
 
@@ -1083,7 +1080,7 @@
 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
 
 	/* All our local master browsers */
-	smb_init_name_struct((unsigned char *)resource_domain, 0x1D,
+	smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
 	    0, 0, 0, 0, 0, &dest);
 	entry = smb_name_find_name(&dest);
 
@@ -1094,7 +1091,7 @@
 			rc = smb_browser_addr_of_subnet(entry, hinfo, &master);
 			if (rc == 0) {
 				syslog(LOG_DEBUG,
-				    "smbd: Master browser found at %s",
+				    "smb browser: master browser found at %s",
 				    inet_ntoa(master.addr_list.sin.sin_addr));
 			}
 			hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
@@ -1106,10 +1103,11 @@
 
 	/* Domain master browser */
 	smb_init_name_struct((unsigned char *)resource_domain,
-	    0x1B, 0, 0, 0, 0, 0, &dest);
+	    NBT_DMB, 0, 0, 0, 0, 0, &dest);
 
 	if ((entry = smb_name_find_name(&dest)) != 0) {
-		syslog(LOG_DEBUG, "smbd: Domain Master browser for %s is %s",
+		syslog(LOG_DEBUG,
+		    "smb browser: domain master browser for %s is %s",
 		    resource_domain,
 		    inet_ntoa(entry->addr_list.sin.sin_addr));
 		smb_name_unlock_name(entry);
@@ -1161,8 +1159,9 @@
 		(void) utf8_strupr(hinfo->hi_nbname);
 		/* 0x20: file server service  */
 		smb_init_name_struct((unsigned char *)hinfo->hi_nbname,
-		    0x20, 0, hinfo->hi_nic.nic_ip.a_ipv4,
-		    htons(DGM_SRVC_UDP_PORT), NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL,
+		    NBT_SERVER, 0, hinfo->hi_nic.nic_ip.a_ipv4,
+		    htons(IPPORT_NETBIOS_DGM),
+		    NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL,
 		    &hinfo->hi_netname);
 
 		list_insert_tail(&smb_binfo.bi_hlist, hinfo);
@@ -1186,17 +1185,17 @@
 {
 	struct name_entry name;
 	struct name_entry *dest;
-	struct addr_entry addr;
+	addr_entry_t addr;
 	char resource_domain[SMB_PI_MAX_DOMAIN];
 
 	smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
-	    remove, 0, 0x1D);
+	    remove, 0, NBT_MB);
 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
 		return;
 
 	(void) utf8_strupr(resource_domain);
 
-	smb_init_name_struct((unsigned char *)resource_domain, 0x1D,
+	smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
 	    0, 0, 0, 0, 0, &name);
 
 	if ((dest = smb_name_find_name(&name))) {
@@ -1204,16 +1203,16 @@
 		addr.forw = addr.back = &addr;
 		smb_name_unlock_name(dest);
 		smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
-		    remove, &addr, 0x1D);
+		    remove, &addr, NBT_MB);
 	} else {
-		smb_init_name_struct((unsigned char *)resource_domain, 0x1B,
-		    0, 0, 0, 0, 0, &name);
+		smb_init_name_struct((unsigned char *)resource_domain,
+		    NBT_DMB, 0, 0, 0, 0, 0, &name);
 		if ((dest = smb_name_find_name(&name))) {
 			addr = dest->addr_list;
 			addr.forw = addr.back = &addr;
 			smb_name_unlock_name(dest);
 			smb_browser_send_HostAnnouncement(hinfo,
-			    remove, hinfo->hi_interval, &addr, 0x1B);
+			    remove, hinfo->hi_interval, &addr, NBT_DMB);
 		}
 	}
 
@@ -1235,61 +1234,24 @@
 
 
 /*
- * smb_browser_sleep
- *
- * Put browser in 1 minute sleep if netbios services are not
- * shutting down and both name and datagram services are still
- * running. It'll wake up after 1 minute or if one of the above
- * conditions go false. It checks the conditions again and return
- * 1 if everything is ok or 0 if browser shouldn't continue
- * running.
- */
-static boolean_t
-smb_browser_sleep(void)
-{
-	boolean_t slept = B_FALSE;
-	timestruc_t to;
-
-	(void) mutex_lock(&nb_status.mtx);
-	while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) &&
-	    (nb_status.state & NETBIOS_NAME_SVC_RUNNING) &&
-	    (nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING)) {
-
-		if (slept) {
-			(void) mutex_unlock(&nb_status.mtx);
-			return (B_TRUE);
-		}
-
-		to.tv_sec = 60;  /* 1 minute */
-		to.tv_nsec = 0;
-		(void) cond_reltimedwait(&nb_status.cv, &nb_status.mtx, &to);
-		slept = B_TRUE;
-	}
-	(void) mutex_unlock(&nb_status.mtx);
-
-	return (B_FALSE);
-}
-
-/*
- * smb_browser_daemon
- *
- * Smb Netbios browser daemon.
+ * SMB NetBIOS Browser Service
  */
 /*ARGSUSED*/
 void *
-smb_browser_daemon(void *arg)
+smb_browser_service(void *arg)
 {
 	smb_hostinfo_t *hinfo;
 
 	smb_browser_infoinit();
 	smb_browser_config();
 
-	smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 1);
+	smb_netbios_event(NETBIOS_EVENT_BROWSER_START);
 
 restart:
 	do {
 		(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
 		hinfo = list_head(&smb_binfo.bi_hlist);
+
 		while (hinfo) {
 			if (--hinfo->hi_nextannouce > 0 ||
 			    hinfo->hi_nic.nic_bcast == 0) {
@@ -1312,11 +1274,13 @@
 
 			hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
 		}
+
 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
-	} while (smb_browser_sleep());
+		smb_netbios_sleep(SECSPERMIN);	/* 1 minute */
+	} while (smb_netbios_running());
 
 	smb_browser_infoterm();
-	smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 0);
+	smb_netbios_event(NETBIOS_EVENT_BROWSER_STOP);
 	return (0);
 }
 
@@ -1367,8 +1331,8 @@
 /*
  * smb_browser_infoinit
  *
- * This function is called only once when browser daemon starts
- * to initialize global smb_binfo structure
+ * This function is called only once when the browser starts
+ * to initialize the global smb_binfo structure.
  */
 static void
 smb_browser_infoinit(void)
@@ -1391,8 +1355,8 @@
 /*
  * smb_browser_infoterm
  *
- * This function is called only once when browser daemon stops
- * to destruct smb_binfo structure
+ * This function is called only once when the browser stops
+ * to destroy the smb_binfo structure.
  */
 static void
 smb_browser_infoterm(void)
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c	Mon Oct 05 11:03:34 2009 -0700
@@ -51,500 +51,100 @@
 #include <kerberosv5/krb5.h>
 #include <kerberosv5/com_err.h>
 #include <assert.h>
-#include <string.h>
 #include <stdio.h>
-#include <time.h>
-#include <netdb.h>
 #include <syslog.h>
-#include <locale.h>
-#include <strings.h>
 #include <errno.h>
-#include <sys/synch.h>
-#include <gssapi/gssapi.h>
 
 #include <smbsrv/libsmbns.h>
-
 #include <smbns_krb.h>
 
-static int krb5_acquire_cred_kinit_main();
-
-typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
-
-struct k_opts {
-	/* in seconds */
-	krb5_deltat starttime;
-	krb5_deltat lifetime;
-	krb5_deltat rlife;
-
-	int forwardable;
-	int proxiable;
-	int addresses;
-
-	int not_forwardable;
-	int not_proxiable;
-	int no_addresses;
-
-	int verbose;
-
-	char *principal_name;
-	char *principal_passwd;
-	char *service_name;
-	char *keytab_name;
-	char *k5_cache_name;
-	char *k4_cache_name;
-
-	action_type action;
-};
-
-struct k5_data {
-	krb5_context ctx;
-	krb5_ccache cc;
-	krb5_principal me;
-	char *name;
-};
-
-static int
-k5_begin(struct k_opts *opts, struct k5_data *k5)
+int
+smb_kinit(char *principal_name, char *principal_passwd)
 {
-	int code;
-	code = krb5_init_context(&k5->ctx);
-	if (code) {
-		return (code);
-	}
-
-	if ((code = krb5_cc_default(k5->ctx, &k5->cc))) {
-		return (code);
-	}
-
-	/* Use specified name */
-	if ((code = krb5_parse_name(k5->ctx, opts->principal_name, &k5->me))) {
-		return (code);
-	}
-
-	code = krb5_unparse_name(k5->ctx, k5->me, &k5->name);
-	if (code) {
-		return (code);
-	}
-	opts->principal_name = k5->name;
-
-	return (0);
-}
+	krb5_context ctx = NULL;
+	krb5_ccache cc = NULL;
+	krb5_principal me = NULL;
+	krb5_creds my_creds;
+	krb5_error_code code;
+	const char *errmsg = NULL;
+	const char *doing = NULL;
 
-static void
-k5_end(struct k5_data *k5)
-{
-	if (k5->name)
-		krb5_free_unparsed_name(k5->ctx, k5->name);
-	if (k5->me)
-		krb5_free_principal(k5->ctx, k5->me);
-	if (k5->cc)
-		krb5_cc_close(k5->ctx, k5->cc);
-	if (k5->ctx)
-		krb5_free_context(k5->ctx);
-	(void) memset(k5, 0, sizeof (*k5));
-}
+	assert(principal_name != NULL);
+	assert(principal_passwd != NULL);
 
-static int
-k5_kinit(struct k_opts *opts, struct k5_data *k5)
-{
-	int notix = 1;
-	krb5_keytab keytab = 0;
-	krb5_creds my_creds;
-	krb5_error_code code = 0;
-	krb5_get_init_creds_opt options;
-	const char *errmsg;
-
-	krb5_get_init_creds_opt_init(&options);
 	(void) memset(&my_creds, 0, sizeof (my_creds));
 
 	/*
-	 * From this point on, we can goto cleanup because my_creds is
-	 * initialized.
+	 * From this point on, we can goto cleanup because the key variables
+	 * are initialized.
 	 */
-	if (opts->lifetime)
-		krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime);
-	if (opts->rlife)
-		krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife);
-	if (opts->forwardable)
-		krb5_get_init_creds_opt_set_forwardable(&options, 1);
-	if (opts->not_forwardable)
-		krb5_get_init_creds_opt_set_forwardable(&options, 0);
-	if (opts->proxiable)
-		krb5_get_init_creds_opt_set_proxiable(&options, 1);
-	if (opts->not_proxiable)
-		krb5_get_init_creds_opt_set_proxiable(&options, 0);
-	if (opts->addresses) {
-		krb5_address **addresses = NULL;
-		code = krb5_os_localaddr(k5->ctx, &addresses);
-		if (code != 0) {
-			errmsg = error_message(code);
-			syslog(LOG_ERR, "k5_kinit: getting local addresses "
-			    "(%s)", errmsg);
-			goto cleanup;
-		}
-		krb5_get_init_creds_opt_set_address_list(&options, addresses);
-	}
-	if (opts->no_addresses)
-		krb5_get_init_creds_opt_set_address_list(&options, NULL);
-
-	if ((opts->action == INIT_KT) && opts->keytab_name) {
-		code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);
-		if (code != 0) {
-			errmsg = error_message(code);
-			syslog(LOG_ERR, "k5_kinit: resolving keytab %s (%s)",
-			    errmsg, opts->keytab_name);
-			goto cleanup;
-		}
-	}
 
-	switch (opts->action) {
-	case INIT_PW:
-		code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
-		    opts->principal_passwd, NULL, 0, opts->starttime,
-		    opts->service_name, &options);
-		break;
-	case INIT_KT:
-		code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me,
-		    keytab, opts->starttime, opts->service_name, &options);
-		break;
-	case VALIDATE:
-		code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me,
-		    k5->cc, opts->service_name);
-		break;
-	case RENEW:
-		code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me,
-		    k5->cc, opts->service_name);
-		break;
-	}
-
+	code = krb5_init_context(&ctx);
 	if (code) {
-		char *doing = 0;
-		switch (opts->action) {
-		case INIT_PW:
-		case INIT_KT:
-			doing = "k5_kinit: getting initial credentials";
-			break;
-		case VALIDATE:
-			doing = "k5_kinit: validating credentials";
-			break;
-		case RENEW:
-			doing = "k5_kinit: renewing credentials";
-			break;
-		}
-
-		/*
-		 * If got code == KRB5_AP_ERR_V4_REPLY && got_k4, we should
-		 * let the user know that maybe he/she wants -4.
-		 */
-		if (code == KRB5KRB_AP_ERR_V4_REPLY) {
-			syslog(LOG_ERR, "%s\n"
-			    "The KDC doesn't support v5.  "
-			    "You may want the -4 option in the future", doing);
-			return (1);
-		} else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
-			syslog(LOG_ERR, "%s (Password incorrect)", doing);
-		} else {
-			errmsg = error_message(code);
-			syslog(LOG_ERR, "%s (%s)", doing, errmsg);
-		}
+		doing = "initializing context";
 		goto cleanup;
 	}
 
-	if (!opts->lifetime) {
-		/* We need to figure out what lifetime to use for Kerberos 4. */
-		opts->lifetime = my_creds.times.endtime -
-		    my_creds.times.authtime;
-	}
-
-	code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me);
-	if (code) {
-		errmsg = error_message(code);
-		syslog(LOG_ERR, "k5_kinit: initializing cache %s (%s)",
-		    opts->k5_cache_name ? opts->k5_cache_name : "", errmsg);
+	code = krb5_cc_default(ctx, &cc);
+	if (code != 0) {
+		doing = "resolve default credentials cache";
 		goto cleanup;
 	}
 
-	code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);
-	if (code) {
-		errmsg = error_message(code);
-		syslog(LOG_ERR, "k5_kinit: storing credentials (%s)", errmsg);
+	/* Use specified name */
+	code = krb5_parse_name(ctx, principal_name, &me);
+	if (code != 0) {
+		doing = "parsing principal name";
 		goto cleanup;
 	}
 
-	notix = 0;
-
-	cleanup:
-		if (my_creds.client == k5->me) {
-			my_creds.client = 0;
-		}
-		krb5_free_cred_contents(k5->ctx, &my_creds);
-		if (keytab)
-			krb5_kt_close(k5->ctx, keytab);
-		return (notix?0:1);
-}
+	code = krb5_get_init_creds_password(ctx, &my_creds, me,
+	    principal_passwd, NULL, 0, (krb5_deltat)0,
+	    NULL, NULL);
+	if (code != 0) {
+		doing = "getting initial credentials";
 
-int
-smb_kinit(char *user, char *passwd)
-{
-	struct k_opts opts;
-	struct k5_data k5;
-	int authed_k5 = 0;
-
-	assert(user);
-	assert(passwd);
+		if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+			errmsg = "Password incorrect";
+		}
 
-	(void) memset(&opts, 0, sizeof (opts));
-	opts.action = INIT_PW;
-	opts.principal_name = user;
-	opts.principal_passwd = passwd;
+		goto cleanup;
+	}
 
-	(void) memset(&k5, 0, sizeof (k5));
-
-	if (k5_begin(&opts, &k5) != 0) {
-		syslog(LOG_ERR, "NOT authenticated with Kerberos v5. "
-		    "k5_begin failed\n");
-		return (0);
+	code = krb5_cc_initialize(ctx, cc, me);
+	if (code != 0) {
+		doing = "initializing cache";
+		goto cleanup;
 	}
 
-	authed_k5 = k5_kinit(&opts, &k5);
-	if (authed_k5)
-		syslog(LOG_DEBUG, "Authenticated with Kerberos v5\n");
-	else
-		syslog(LOG_DEBUG, "NOT authenticated with Kerberos v5\n");
-
-	k5_end(&k5);
-
-	return (authed_k5);
-}
-
-/*
- * krb5_display_stat
- * Display error message for GSS-API routines.
- * Parameters:
- *   maj       :  GSS major status
- *   min       :  GSS minor status
- *   caller_mod:  module name that calls this routine so that the module name
- *                can be displayed with the error messages
- * Returns:
- *   None
- */
-static void
-krb5_display_stat(OM_uint32 maj, OM_uint32 min, char *caller_mod)
-{
-	gss_buffer_desc msg;
-	OM_uint32 msg_ctx = 0;
-	OM_uint32 min2;
-	(void) gss_display_status(&min2, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID,
-	    &msg_ctx, &msg);
-	syslog(LOG_ERR, "%s: major status error: %s\n",
-	    caller_mod, (char *)msg.value);
-	(void) gss_release_buffer(&min2, &msg);
-
-	(void) gss_display_status(&min2, min, GSS_C_MECH_CODE, GSS_C_NULL_OID,
-	    &msg_ctx, &msg);
-	syslog(LOG_ERR, "%s: minor status error: %s\n",
-	    caller_mod, (char *)msg.value);
-	(void) gss_release_buffer(&min2, &msg);
-}
-
-/*
- * krb5_acquire_cred_kinit
- *
- * Wrapper for krb5_acquire_cred_kinit_main with mutex to protect credential
- * cache file when calling krb5_acquire_cred or kinit.
- */
-
-int
-krb5_acquire_cred_kinit(char *user, char *pwd, gss_cred_id_t *cred_handle,
-	gss_OID *oid, int *kinit_retry, char *caller_mod)
-{
-	int ret;
-
-	ret = krb5_acquire_cred_kinit_main(user, pwd,
-	    cred_handle, oid, kinit_retry, caller_mod);
-	return (ret);
-}
-
-/*
- * krb5_acquire_cred_kinit_main
- *
- * This routine is called by ADS module to get a handle to administrative
- * user's credential stored locally on the system.  The credential is the TGT.
- * If the attempt at getting handle fails then a second attempt will be made
- * after getting a new TGT.
- *
- * If there's no username then we must be using host credentials and we don't
- * bother trying to acquire a credential for GSS_C_NO_NAME (which should be
- * equivalent to using GSS_C_NO_CREDENTIAL, but it isn't in a very subtle way
- * because mech_krb5 isn't so smart).  Specifically mech_krb5 will try hard
- * to get a non-expired TGT using the keytab if we're running as root (or fake
- * it, using the special app_krb5_user_uid() function), but only when we use
- * the default credential, as opposed to a credential for the default principal.
- *
- * Paramters:
- *   user       : username to retrieve a handle to its credential
- *   pwd        : password of username in case obtaining a new TGT is needed
- *   kinit_retry: if 0 then a second attempt will be made to get handle to the
- *                credential if the first attempt fails
- *   caller_mod : name of module that call this routine so that the module name
- *                can be included with error messages
- * Returns:
- *   cred_handle: handle to the administrative user's credential (TGT)
- *   oid        : contains Kerberos 5 object identifier
- *   kinit_retry: A 1 indicates that a second attempt has been made to get
- *                handle to the credential and no further attempts can be made
- *   -1         : error
- *    0         : success
- */
-static int
-krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle,
-	gss_OID *oid, int *kinit_retry, char *caller_mod)
-{
-	OM_uint32 maj, min;
-	gss_name_t desired_name = GSS_C_NO_NAME;
-	gss_OID_set desired_mechs;
-	gss_buffer_desc oidstr, name_buf;
-	char str[50], user_name[50];
-
-	*cred_handle = GSS_C_NO_CREDENTIAL;
-	*oid = GSS_C_NO_OID;
-	if (user == NULL || *user == '\0')
-		return (0);
-
-	/* Object Identifier for Kerberos 5 */
-	(void) strcpy(str, "{ 1 2 840 113554 1 2 2 }");
-	oidstr.value = str;
-	oidstr.length = strlen(str);
-	if ((maj = gss_str_to_oid(&min, &oidstr, oid)) != GSS_S_COMPLETE) {
-		krb5_display_stat(maj, min, caller_mod);
-		return (-1);
-	}
-	if ((maj = gss_create_empty_oid_set(&min, &desired_mechs))
-	    != GSS_S_COMPLETE) {
-		krb5_display_stat(maj, min, caller_mod);
-		(void) gss_release_oid(&min, oid);
-		return (-1);
-	}
-	if ((maj = gss_add_oid_set_member(&min, *oid, &desired_mechs))
-	    != GSS_S_COMPLETE) {
-		krb5_display_stat(maj, min, caller_mod);
-		(void) gss_release_oid(&min, oid);
-		(void) gss_release_oid_set(&min, &desired_mechs);
-		return (-1);
+	code = krb5_cc_store_cred(ctx, cc, &my_creds);
+	if (code != 0) {
+		doing = "storing credentials";
+		goto cleanup;
 	}
 
-	(void) strcpy(user_name, user);
-	name_buf.value = user_name;
-	name_buf.length = strlen(user_name)+1;
-	if ((maj = gss_import_name(&min, &name_buf, GSS_C_NT_USER_NAME,
-	    &desired_name)) != GSS_S_COMPLETE) {
-		krb5_display_stat(maj, min, caller_mod);
-		(void) gss_release_oid(&min, oid);
-		(void) gss_release_oid_set(&min, &desired_mechs);
-		return (-1);
-	}
+	/* SUCCESS! */
 
-acquire_cred:
-	if ((maj = gss_acquire_cred(&min, desired_name, 0, desired_mechs,
-	    GSS_C_INITIATE, cred_handle, NULL, NULL)) != GSS_S_COMPLETE) {
-		if (!*kinit_retry && pwd != NULL && *pwd != '\0') {
-			(void) smb_kinit(user, pwd);
-			*kinit_retry = 1;
-			goto acquire_cred;
-		} else {
-			krb5_display_stat(maj, min, caller_mod);
-			(void) gss_release_oid(&min, oid);
-			(void) gss_release_oid_set(&min, &desired_mechs);
-			(void) gss_release_name(&min, &desired_name);
-			if (pwd == NULL || *pwd == '\0') {
-				/* See above */
-				*cred_handle = GSS_C_NO_CREDENTIAL;
-				return (0);
-			}
-			return (-1);
-		}
+cleanup:
+	if (code != 0) {
+		if (errmsg == NULL)
+			errmsg = error_message(code);
+		syslog(LOG_ERR, "k5_kinit: %s (%s)", doing, errmsg);
 	}
 
-	(void) gss_release_oid_set(&min, &desired_mechs);
-	(void) gss_release_name(&min, &desired_name);
-
-	return (0);
-}
+	if (my_creds.client == me) {
+		my_creds.client = NULL;
+	}
+	krb5_free_cred_contents(ctx, &my_creds);
 
-/*
- * krb5_establish_sec_ctx_kinit
- *
- * This routine is called by the ADS module to establish a security
- * context before ADS updates are allowed.  If establishing a security context
- * fails for any reason, a second attempt will be made after a new TGT is
- * obtained.  This routine is called many time as needed until a security
- * context is established.
- *
- * The resources use for the security context must be released if security
- * context establishment process fails.
- * Parameters:
- *   user       : user used in establishing a security context for.  Is used for
- *                obtaining a new TGT for a second attempt at establishing
- *                security context
- *   pwd        : password of above user
- *   cred_handle: a handle to the user credential (TGT) stored locally
- *   gss_context: initially set to GSS_C_NO_CONTEXT but will contain a handle
- *                to a security context
- *   target_name: contains service name to establish a security context with,
- *                ie ldap or dns
- *   gss_flags  : flags used in establishing security context
- *   inputptr   : initially set to GSS_C_NO_BUFFER but will be token data
- *                received from service's server to be processed to generate
- *                further token to be sent back to service's server during
- *                security context establishment
- *   kinit_retry: if 0 then a second attempt will be made to get handle to the
- *                credential if the first attempt fails
- *   caller_mod : name of module that call this routine so that the module name
- *                can be included with error messages
- * Returns:
- *   gss_context    : a handle to a security context
- *   out_tok        : token data to be sent to service's server to establish
- *                    security context
- *   ret_flags      : return flags
- *   time_rec       : valid time for security context, not currently used
- *   kinit_retry    : A 1 indicates that a second attempt has been made to get
- *                    handle to the credential and no further attempts can be
- *                    made
- *   do_acquire_cred: A 1 indicates that a new handle to the local credential
- *                    is needed for second attempt at security context
- *                    establishment
- *   maj            : major status code used if determining is security context
- *                    establishment is successful
- */
-int
-krb5_establish_sec_ctx_kinit(char *user, char *pwd,
-    gss_cred_id_t cred_handle, gss_ctx_id_t *gss_context,
-    gss_name_t target_name, gss_OID oid, int gss_flags,
-    gss_buffer_desc *inputptr, gss_buffer_desc* out_tok,
-    OM_uint32 *ret_flags, OM_uint32 *time_rec,
-    int *kinit_retry, int *do_acquire_cred,
-    OM_uint32 *maj, char *caller_mod)
-{
-	OM_uint32 min;
+	if (me)
+		krb5_free_principal(ctx, me);
+	if (cc)
+		krb5_cc_close(ctx, cc);
+	if (ctx)
+		krb5_free_context(ctx);
 
-	*maj = gss_init_sec_context(&min, cred_handle, gss_context,
-	    target_name, oid, gss_flags, 0, NULL, inputptr, NULL,
-	    out_tok, ret_flags, time_rec);
-	if (*maj != GSS_S_COMPLETE && *maj != GSS_S_CONTINUE_NEEDED) {
-		if (*gss_context != NULL)
-			(void) gss_delete_sec_context(&min, gss_context, NULL);
-
-		if ((user != NULL) && (pwd != NULL) && !*kinit_retry) {
-			(void) smb_kinit(user, pwd);
-			*kinit_retry = 1;
-			*do_acquire_cred = 1;
-			return (-1);
-		} else {
-			krb5_display_stat(*maj, min, caller_mod);
-			return (-1);
-		}
-	}
-	return (0);
+	return (code == 0);
 }
 
 /*
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h	Mon Oct 05 11:03:34 2009 -0700
@@ -19,14 +19,13 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#ifndef _SMBSRV_SMB_KRB5_H
-#define	_SMBSRV_SMB_KRB5_H
+#ifndef _SMBSRV_SMB_KRB_H
+#define	_SMBSRV_SMB_KRB_H
 
-#include <gssapi/gssapi.h>
 #include <kerberosv5/krb5.h>
 
 #ifdef __cplusplus
@@ -45,19 +44,7 @@
 	SMBKRB5_SPN_IDX_MAX
 } smb_krb5_spn_idx_t;
 
-extern gss_OID gss_nt_user_name;
-extern gss_OID gss_nt_machine_uid_name;
-extern gss_OID gss_nt_string_uid_name;
-extern gss_OID gss_nt_service_name;
-extern gss_OID gss_nt_exported_name;
-extern gss_OID gss_nt_service_name_v2;
-
-int krb5_acquire_cred_kinit(char *, char *, gss_cred_id_t *,
-    gss_OID *, int *, char *);
-int krb5_establish_sec_ctx_kinit(char *, char *, gss_cred_id_t,
-    gss_ctx_id_t *, gss_name_t, gss_OID, int, gss_buffer_desc *,
-    gss_buffer_desc *, OM_uint32 *, OM_uint32 *, int *,
-    int *, OM_uint32 *, char *);
+int smb_kinit(char *, char *);
 char *smb_krb5_get_spn(smb_krb5_spn_idx_t idx, char *fqhost);
 char *smb_krb5_get_upn(char *spn, char *domain);
 int smb_krb5_ctx_init(krb5_context *ctx);
@@ -76,4 +63,4 @@
 }
 #endif
 
-#endif /* _SMBSRV_SMB_KRB5_H */
+#endif /* _SMBSRV_SMB_KRB_H */
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,175 +19,162 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Main startup code for SMB/NETBIOS and some utility routines
  * for the NETBIOS layer.
  */
 
+#include <sys/tzfile.h>
+#include <assert.h>
 #include <synch.h>
 #include <unistd.h>
 #include <syslog.h>
 #include <string.h>
 #include <strings.h>
 #include <sys/socket.h>
-
+#include <stdio.h>
+#include <pwd.h>
+#include <grp.h>
 #include <smbns_netbios.h>
 
-netbios_status_t nb_status;
+#define	SMB_NETBIOS_DUMP_FILE		"netbios"
 
-static pthread_t smb_nbns_thr; /* name service */
-static pthread_t smb_nbds_thr; /* dgram service */
-static pthread_t smb_nbts_thr; /* timer */
-static pthread_t smb_nbbs_thr; /* browser */
-
-static void *smb_netbios_timer(void *);
+static netbios_service_t nbtd;
 
-void
-smb_netbios_chg_status(uint32_t status, int set)
-{
-	(void) mutex_lock(&nb_status.mtx);
-	if (set)
-		nb_status.state |= status;
-	else
-		nb_status.state &= ~status;
-	(void) cond_broadcast(&nb_status.cv);
-	(void) mutex_unlock(&nb_status.mtx);
-}
+static void smb_netbios_shutdown(void);
+static void *smb_netbios_service(void *);
+static void smb_netbios_dump(void);
 
-void
-smb_netbios_shutdown(void)
-{
-	smb_netbios_chg_status(NETBIOS_SHUTTING_DOWN, 1);
-
-	(void) pthread_join(smb_nbts_thr, 0);
-	(void) pthread_join(smb_nbbs_thr, 0);
-	(void) pthread_join(smb_nbns_thr, 0);
-	(void) pthread_join(smb_nbds_thr, 0);
-
-	nb_status.state = NETBIOS_SHUT_DOWN;
-}
-
+/*
+ * Start the NetBIOS services
+ */
 int
 smb_netbios_start(void)
 {
-	int rc;
-	mutex_t *mp;
-	cond_t *cvp;
+	pthread_t	tid;
+	pthread_attr_t	attr;
+	int		rc;
 
-	/* Startup Netbios named; port 137 */
-	rc = pthread_create(&smb_nbns_thr, 0,
-	    smb_netbios_name_service_daemon, 0);
-	if (rc)
+	if (smb_netbios_cache_init() < 0)
 		return (-1);
 
-	mp = &nb_status.mtx;
-	cvp = &nb_status.cv;
+	(void) pthread_attr_init(&attr);
+	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	rc = pthread_create(&tid, &attr, smb_netbios_service, NULL);
+	(void) pthread_attr_destroy(&attr);
+	return (rc);
+}
+
+/*
+ * Stop the NetBIOS services
+ */
+void
+smb_netbios_stop(void)
+{
+	char	fname[MAXPATHLEN];
+
+	smb_netbios_event(NETBIOS_EVENT_STOP);
+
+	(void) snprintf(fname, MAXPATHLEN, "%s/%s",
+	    SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE);
+	(void) unlink(fname);
 
-	(void) mutex_lock(mp);
-	while (!(nb_status.state & (NETBIOS_NAME_SVC_RUNNING |
-	    NETBIOS_NAME_SVC_FAILED))) {
-		(void) cond_wait(cvp, mp);
+}
+
+/*
+ * Launch the NetBIOS Name Service, Datagram and Browser services
+ * and then sit in a loop providing a 1 second resolution timer.
+ * The timer will:
+ *	- update the netbios stats file every 10 minutes
+ *	- clean the cache every 10 minutes
+ */
+/*ARGSUSED*/
+static void *
+smb_netbios_service(void *arg)
+{
+	static uint32_t	ticks = 0;
+	pthread_t	tid;
+	int		rc;
+
+	smb_netbios_event(NETBIOS_EVENT_START);
+
+	rc = pthread_create(&tid, NULL, smb_netbios_name_service, NULL);
+	if (rc != 0) {
+		smb_netbios_shutdown();
+		return (NULL);
 	}
 
-	if (nb_status.state & NETBIOS_NAME_SVC_FAILED) {
-		(void) mutex_unlock(mp);
+	smb_netbios_wait(NETBIOS_EVENT_NS_START);
+	if (smb_netbios_error()) {
 		smb_netbios_shutdown();
-		return (-1);
+		return (NULL);
 	}
-	(void) mutex_unlock(mp);
 
 	smb_netbios_name_config();
 
-	/* Startup Netbios datagram service; port 138 */
-	rc = pthread_create(&smb_nbds_thr, 0,
-	    smb_netbios_datagram_service_daemon, 0);
+	rc = pthread_create(&tid, NULL, smb_netbios_datagram_service, NULL);
 	if (rc != 0) {
 		smb_netbios_shutdown();
-		return (-1);
-	}
-
-	(void) mutex_lock(mp);
-	while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING |
-	    NETBIOS_DATAGRAM_SVC_FAILED))) {
-		(void) cond_wait(cvp, mp);
-	}
-
-	if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) {
-		(void) mutex_unlock(mp);
-		smb_netbios_shutdown();
-		return (-1);
-	}
-	(void) mutex_unlock(mp);
-
-	/* Startup Netbios browser service */
-	rc = pthread_create(&smb_nbbs_thr, 0, smb_browser_daemon, 0);
-	if (rc) {
-		smb_netbios_shutdown();
-		return (-1);
+		return (NULL);
 	}
 
-	/* Startup Our internal, 1 second resolution, timer */
-	rc = pthread_create(&smb_nbts_thr, 0, smb_netbios_timer, 0);
-	if (rc != 0) {
+	smb_netbios_wait(NETBIOS_EVENT_DGM_START);
+	if (smb_netbios_error()) {
 		smb_netbios_shutdown();
-		return (-1);
-	}
-
-	(void) mutex_lock(mp);
-	while (!(nb_status.state & (NETBIOS_TIMER_RUNNING |
-	    NETBIOS_TIMER_FAILED))) {
-		(void) cond_wait(cvp, mp);
+		return (NULL);
 	}
 
-	if (nb_status.state & NETBIOS_TIMER_FAILED) {
-		(void) mutex_unlock(mp);
+	rc = pthread_create(&tid, NULL, smb_browser_service, NULL);
+	if (rc != 0) {
 		smb_netbios_shutdown();
-		return (-1);
+		return (NULL);
 	}
-	(void) mutex_unlock(mp);
-
-	return (0);
-}
 
-/*ARGSUSED*/
-static void *
-smb_netbios_timer(void *arg)
-{
-	static unsigned int ticks = 0;
+	smb_netbios_event(NETBIOS_EVENT_TIMER_START);
 
-	smb_netbios_chg_status(NETBIOS_TIMER_RUNNING, 1);
-
-	while ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) {
+	for (;;) {
 		(void) sleep(1);
 		ticks++;
 
-		if ((nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING) == 0)
-			break;
-
-		if ((nb_status.state & NETBIOS_NAME_SVC_RUNNING) == 0)
+		if (!smb_netbios_running())
 			break;
 
 		smb_netbios_datagram_tick();
 		smb_netbios_name_tick();
 
-		/* every 10 minutes */
-		if ((ticks % 600) == 0)
+		if ((ticks % 600) == 0) {
+			smb_netbios_event(NETBIOS_EVENT_DUMP);
 			smb_netbios_cache_clean();
+		}
 	}
 
-	nb_status.state &= ~NETBIOS_TIMER_RUNNING;
-	if ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) {
-		/* either name or datagram service has failed */
-		smb_netbios_shutdown();
+	smb_netbios_event(NETBIOS_EVENT_TIMER_STOP);
+	smb_netbios_shutdown();
+	return (NULL);
+}
+
+static void
+smb_netbios_shutdown(void)
+{
+	(void) pthread_join(nbtd.nbs_browser.s_tid, 0);
+	(void) pthread_join(nbtd.nbs_dgm.s_tid, 0);
+	(void) pthread_join(nbtd.nbs_ns.s_tid, 0);
+
+	nbtd.nbs_browser.s_tid = 0;
+	nbtd.nbs_dgm.s_tid = 0;
+	nbtd.nbs_ns.s_tid = 0;
+
+	smb_netbios_cache_fini();
+
+	if (smb_netbios_error()) {
+		smb_netbios_event(NETBIOS_EVENT_RESET);
+		if (smb_netbios_start() != 0)
+			syslog(LOG_ERR, "netbios: restart failed");
 	}
-
-	return (0);
 }
 
 int
@@ -264,3 +251,283 @@
 	dest->addr_list.attributes = addr_attr;
 	dest->addr_list.forw = dest->addr_list.back = &dest->addr_list;
 }
+
+void
+smb_netbios_event(netbios_event_t event)
+{
+	static char *event_msg[] = {
+		"startup",
+		"shutdown",
+		"restart",
+		"name service started",
+		"name service stopped",
+		"datagram service started",
+		"datagram service stopped",
+		"browser service started",
+		"browser service stopped",
+		"timer service started",
+		"timer service stopped",
+		"error",
+		"dump"
+	};
+
+	(void) mutex_lock(&nbtd.nbs_mtx);
+
+	if (event == NETBIOS_EVENT_DUMP) {
+		if (nbtd.nbs_last_event == NULL)
+			nbtd.nbs_last_event = event_msg[event];
+		smb_netbios_dump();
+		(void) mutex_unlock(&nbtd.nbs_mtx);
+		return;
+	}
+
+	nbtd.nbs_last_event = event_msg[event];
+	syslog(LOG_DEBUG, "netbios: %s", nbtd.nbs_last_event);
+
+	switch (nbtd.nbs_state) {
+	case NETBIOS_STATE_INIT:
+		if (event == NETBIOS_EVENT_START)
+			nbtd.nbs_state = NETBIOS_STATE_RUNNING;
+		break;
+
+	case NETBIOS_STATE_RUNNING:
+		switch (event) {
+		case NETBIOS_EVENT_NS_START:
+			nbtd.nbs_ns.s_tid = pthread_self();
+			nbtd.nbs_ns.s_up = B_TRUE;
+			break;
+		case NETBIOS_EVENT_NS_STOP:
+			nbtd.nbs_ns.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_DGM_START:
+			nbtd.nbs_dgm.s_tid = pthread_self();
+			nbtd.nbs_dgm.s_up = B_TRUE;
+			break;
+		case NETBIOS_EVENT_DGM_STOP:
+			nbtd.nbs_dgm.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_BROWSER_START:
+			nbtd.nbs_browser.s_tid = pthread_self();
+			nbtd.nbs_browser.s_up = B_TRUE;
+			break;
+		case NETBIOS_EVENT_BROWSER_STOP:
+			nbtd.nbs_browser.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_TIMER_START:
+			nbtd.nbs_timer.s_tid = pthread_self();
+			nbtd.nbs_timer.s_up = B_TRUE;
+			break;
+		case NETBIOS_EVENT_TIMER_STOP:
+			nbtd.nbs_timer.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_STOP:
+			nbtd.nbs_state = NETBIOS_STATE_CLOSING;
+			break;
+		case NETBIOS_EVENT_ERROR:
+			nbtd.nbs_state = NETBIOS_STATE_ERROR;
+			++nbtd.nbs_errors;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case NETBIOS_STATE_CLOSING:
+	case NETBIOS_STATE_ERROR:
+	default:
+		switch (event) {
+		case NETBIOS_EVENT_NS_STOP:
+			nbtd.nbs_ns.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_DGM_STOP:
+			nbtd.nbs_dgm.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_BROWSER_STOP:
+			nbtd.nbs_browser.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_TIMER_STOP:
+			nbtd.nbs_timer.s_up = B_FALSE;
+			break;
+		case NETBIOS_EVENT_STOP:
+			nbtd.nbs_state = NETBIOS_STATE_CLOSING;
+			break;
+		case NETBIOS_EVENT_RESET:
+			nbtd.nbs_state = NETBIOS_STATE_INIT;
+			break;
+		case NETBIOS_EVENT_ERROR:
+			++nbtd.nbs_errors;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+
+	smb_netbios_dump();
+	(void) cond_broadcast(&nbtd.nbs_cv);
+	(void) mutex_unlock(&nbtd.nbs_mtx);
+}
+
+void
+smb_netbios_wait(netbios_event_t event)
+{
+	boolean_t *svc = NULL;
+	boolean_t desired_state;
+
+	(void) mutex_lock(&nbtd.nbs_mtx);
+
+	switch (event) {
+	case NETBIOS_EVENT_NS_START:
+	case NETBIOS_EVENT_NS_STOP:
+		svc = &nbtd.nbs_ns.s_up;
+		desired_state =
+		    (event == NETBIOS_EVENT_NS_START) ? B_TRUE : B_FALSE;
+		break;
+	case NETBIOS_EVENT_DGM_START:
+	case NETBIOS_EVENT_DGM_STOP:
+		svc = &nbtd.nbs_dgm.s_up;
+		desired_state =
+		    (event == NETBIOS_EVENT_DGM_START) ? B_TRUE : B_FALSE;
+		break;
+	case NETBIOS_EVENT_BROWSER_START:
+	case NETBIOS_EVENT_BROWSER_STOP:
+		svc = &nbtd.nbs_browser.s_up;
+		desired_state =
+		    (event == NETBIOS_EVENT_BROWSER_START) ? B_TRUE : B_FALSE;
+		break;
+	default:
+		(void) mutex_unlock(&nbtd.nbs_mtx);
+		return;
+	}
+
+	while (*svc != desired_state) {
+		if (nbtd.nbs_state != NETBIOS_STATE_RUNNING)
+			break;
+
+		(void) cond_wait(&nbtd.nbs_cv, &nbtd.nbs_mtx);
+	}
+
+	(void) mutex_unlock(&nbtd.nbs_mtx);
+}
+
+void
+smb_netbios_sleep(time_t seconds)
+{
+	timestruc_t reltimeout;
+
+	(void) mutex_lock(&nbtd.nbs_mtx);
+
+	if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) {
+		if (seconds == 0)
+			seconds  = 1;
+		reltimeout.tv_sec = seconds;
+		reltimeout.tv_nsec = 0;
+
+		(void) cond_reltimedwait(&nbtd.nbs_cv,
+		    &nbtd.nbs_mtx, &reltimeout);
+	}
+
+	(void) mutex_unlock(&nbtd.nbs_mtx);
+}
+
+boolean_t
+smb_netbios_running(void)
+{
+	boolean_t is_running;
+
+	(void) mutex_lock(&nbtd.nbs_mtx);
+
+	if (nbtd.nbs_state == NETBIOS_STATE_RUNNING)
+		is_running = B_TRUE;
+	else
+		is_running = B_FALSE;
+
+	(void) mutex_unlock(&nbtd.nbs_mtx);
+	return (is_running);
+}
+
+boolean_t
+smb_netbios_error(void)
+{
+	boolean_t error;
+
+	(void) mutex_lock(&nbtd.nbs_mtx);
+
+	if (nbtd.nbs_state == NETBIOS_STATE_ERROR)
+		error = B_TRUE;
+	else
+		error = B_FALSE;
+
+	(void) mutex_unlock(&nbtd.nbs_mtx);
+	return (error);
+}
+
+/*
+ * Write the service state to /var/run/smb/netbios.
+ *
+ * This is a private interface.  To update the file use:
+ *	smb_netbios_event(NETBIOS_EVENT_DUMP);
+ */
+static void
+smb_netbios_dump(void)
+{
+	static struct {
+		netbios_state_t state;
+		char		*text;
+	} sm[] = {
+		{ NETBIOS_STATE_INIT,		"init" },
+		{ NETBIOS_STATE_RUNNING,	"running" },
+		{ NETBIOS_STATE_CLOSING,	"closing" },
+		{ NETBIOS_STATE_ERROR,		"error" }
+	};
+
+	char		fname[MAXPATHLEN];
+	FILE		*fp;
+	struct passwd	*pwd;
+	struct group	*grp;
+	uid_t		uid;
+	gid_t		gid;
+	char		*last_event = "none";
+	int		i;
+
+	(void) snprintf(fname, MAXPATHLEN, "%s/%s",
+	    SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE);
+
+	if ((fp = fopen(fname, "w")) == NULL)
+		return;
+
+	pwd = getpwnam("root");
+	grp = getgrnam("sys");
+	uid = (pwd == NULL) ? 0 : pwd->pw_uid;
+	gid = (grp == NULL) ? 3 : grp->gr_gid;
+
+	(void) lockf(fileno(fp), F_LOCK, 0);
+	(void) fchmod(fileno(fp), 0600);
+	(void) fchown(fileno(fp), uid, gid);
+
+	if (nbtd.nbs_last_event)
+		last_event = nbtd.nbs_last_event;
+
+	for (i = 0; i < sizeof (sm) / sizeof (sm[0]); ++i) {
+		if (nbtd.nbs_state == sm[i].state) {
+			(void) fprintf(fp,
+			    "State             %s  (event: %s, errors: %u)\n",
+			    sm[i].text, last_event, nbtd.nbs_errors);
+			break;
+		}
+	}
+
+	(void) fprintf(fp, "Name Service      %-7s  (%u)\n",
+	    nbtd.nbs_ns.s_up ? "up" : "down", nbtd.nbs_ns.s_tid);
+	(void) fprintf(fp, "Datagram Service  %-7s  (%u)\n",
+	    nbtd.nbs_dgm.s_up ? "up" : "down", nbtd.nbs_dgm.s_tid);
+	(void) fprintf(fp, "Browser Service   %-7s  (%u)\n",
+	    nbtd.nbs_browser.s_up ? "up" : "down", nbtd.nbs_browser.s_tid);
+	(void) fprintf(fp, "Timer Service     %-7s  (%u)\n",
+	    nbtd.nbs_timer.s_up ? "up" : "down", nbtd.nbs_timer.s_tid);
+
+	smb_netbios_cache_dump(fp);
+
+	(void) lockf(fileno(fp), F_ULOCK, 0);
+	(void) fclose(fp);
+}
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h	Mon Oct 05 11:03:34 2009 -0700
@@ -49,24 +49,45 @@
 	(e)->forw = 0;			\
 	(e)->back = 0;
 
-#define	NETBIOS_NAME_SVC_LAUNCHED	0x00001
-#define	NETBIOS_NAME_SVC_RUNNING	0x00002
-#define	NETBIOS_NAME_SVC_FAILED		0x00004
-
-#define	NETBIOS_DATAGRAM_SVC_LAUNCHED	0x00010
-#define	NETBIOS_DATAGRAM_SVC_RUNNING	0x00020
-#define	NETBIOS_DATAGRAM_SVC_FAILED	0x00040
+typedef enum {
+	NETBIOS_EVENT_START = 0,
+	NETBIOS_EVENT_STOP,
+	NETBIOS_EVENT_RESET,
+	NETBIOS_EVENT_NS_START,
+	NETBIOS_EVENT_NS_STOP,
+	NETBIOS_EVENT_DGM_START,
+	NETBIOS_EVENT_DGM_STOP,
+	NETBIOS_EVENT_BROWSER_START,
+	NETBIOS_EVENT_BROWSER_STOP,
+	NETBIOS_EVENT_TIMER_START,
+	NETBIOS_EVENT_TIMER_STOP,
+	NETBIOS_EVENT_ERROR,
+	NETBIOS_EVENT_DUMP
+} netbios_event_t;
 
-#define	NETBIOS_TIMER_LAUNCHED		0x00100
-#define	NETBIOS_TIMER_RUNNING		0x00200
-#define	NETBIOS_TIMER_FAILED		0x00400
+typedef enum {
+	NETBIOS_STATE_INIT = 0,
+	NETBIOS_STATE_RUNNING,
+	NETBIOS_STATE_CLOSING,
+	NETBIOS_STATE_ERROR
+} netbios_state_t;
+
+typedef struct {
+	pthread_t	s_tid;
+	boolean_t	s_up;
+} netbios_svc_t;
 
-#define	NETBIOS_BROWSER_LAUNCHED	0x01000
-#define	NETBIOS_BROWSER_RUNNING		0x02000
-#define	NETBIOS_BROWSER_FAILED		0x04000
-
-#define	NETBIOS_SHUTTING_DOWN		0x10000
-#define	NETBIOS_SHUT_DOWN		0x20000
+typedef struct {
+	mutex_t		nbs_mtx;
+	cond_t		nbs_cv;
+	netbios_svc_t	nbs_ns;
+	netbios_svc_t	nbs_dgm;
+	netbios_svc_t	nbs_browser;
+	netbios_svc_t	nbs_timer;
+	netbios_state_t	nbs_state;
+	uint32_t	nbs_errors;
+	char		*nbs_last_event;
+} netbios_service_t;
 
 char smb_node_type;
 
@@ -75,13 +96,6 @@
 #define	SMB_NODETYPE_M	'M'
 #define	SMB_NODETYPE_H	'H'
 
-typedef struct {
-	mutex_t mtx;
-	cond_t cv;
-	uint32_t state;
-} netbios_status_t;
-extern netbios_status_t nb_status;
-
 /*
  * NAME service definitions
  */
@@ -614,14 +628,22 @@
 #define	NETBIOS_NAME_IS_STAR(name) \
 	(bcmp(name, "*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NETBIOS_NAME_SZ) == 0)
 
-void smb_netbios_chg_status(uint32_t status, int set);
+
+/*
+ * NetBIOS service state machine interface
+ */
+void smb_netbios_event(netbios_event_t);
+void smb_netbios_wait(netbios_event_t);
+void smb_netbios_sleep(time_t);
+boolean_t smb_netbios_running(void);
+boolean_t smb_netbios_error(void);
 
 /*
  * Name Cache Functions
  */
 int  smb_netbios_cache_init(void);
 void smb_netbios_cache_fini(void);
-void smb_netbios_cache_dump(void);
+void smb_netbios_cache_dump(FILE *fp);
 int smb_netbios_cache_count(void);
 void smb_netbios_cache_clean(void);
 void smb_netbios_cache_reset_ttl(void);
@@ -640,13 +662,13 @@
 int smb_netbios_cache_getfirst(nbcache_iter_t *);
 int smb_netbios_cache_getnext(nbcache_iter_t *);
 
-void smb_netbios_name_dump(struct name_entry *entry);
+void smb_netbios_name_dump(FILE *fp, struct name_entry *entry);
 void smb_netbios_name_logf(struct name_entry *entry);
 void smb_netbios_name_freeaddrs(struct name_entry *entry);
 struct name_entry *smb_netbios_name_dup(struct name_entry *, int);
 
 /* Name service functions */
-void *smb_netbios_name_service_daemon(void *);
+void *smb_netbios_name_service(void *);
 void smb_init_name_struct(unsigned char *, char, unsigned char *, uint32_t,
     unsigned short, uint32_t, uint32_t, struct name_entry *);
 
@@ -665,14 +687,14 @@
     struct name_entry *);
 
 /* Datagram service functions */
-void *smb_netbios_datagram_service_daemon(void *);
+void *smb_netbios_datagram_service(void *);
 int smb_netbios_datagram_send(struct name_entry *,
     struct name_entry *, unsigned char *, int);
 void smb_netbios_datagram_tick(void);
 
 /* browser functions */
 void *smb_browser_dispatch(void *arg);
-void *smb_browser_daemon(void *);
+void *smb_browser_service(void *);
 int smb_browser_load_transact_header(unsigned char *, int, int, int, char *);
 
 /* Netlogon function */
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <synch.h>
 #include <stdio.h>
 #include <syslog.h>
@@ -38,42 +36,37 @@
 #define	NETBIOS_HTAB_SZ	128
 #define	NETBIOS_HKEY_SZ	(NETBIOS_NAME_SZ + NETBIOS_DOMAIN_NAME_MAX)
 
-#define	NETBIOS_NAMEBUF  char namebuf[20]
-
 #define	NETBIOS_SAME_IP(addr1, addr2) \
 	((addr1)->sin.sin_addr.s_addr == (addr2)->sin.sin_addr.s_addr)
 
-int smb_netbios_name_debug = 0;
-
 typedef char nb_key_t[NETBIOS_HKEY_SZ];
 static HT_HANDLE *smb_netbios_cache = 0;
 static rwlock_t nb_cache_lock;
 
-static char *smb_strname(struct name_entry *name, char *buf, int bufsize);
+static void smb_strname(struct name_entry *name, char *buf, int bufsize);
 static void hash_callback(HT_ITEM *item);
 static int smb_netbios_match(const char *key1, const char *key2, size_t n);
 static void smb_netbios_cache_key(char *key, unsigned char *name,
 					unsigned char *scope);
 
 int
-smb_netbios_cache_init()
+smb_netbios_cache_init(void)
 {
 	(void) rw_wrlock(&nb_cache_lock);
-	if (smb_netbios_cache == 0) {
+	if (smb_netbios_cache == NULL) {
 		smb_netbios_cache = ht_create_table(NETBIOS_HTAB_SZ,
 		    NETBIOS_HKEY_SZ, HTHF_FIXED_KEY);
-		if (smb_netbios_cache == 0) {
-			syslog(LOG_ERR,
-			    "smbd: cannot create NetBIOS name cache");
+		if (smb_netbios_cache == NULL) {
+			syslog(LOG_ERR, "nbns: cannot create name cache");
 			(void) rw_unlock(&nb_cache_lock);
-			return (0);
+			return (-1);
 		}
 		(void) ht_register_callback(smb_netbios_cache, hash_callback);
 		ht_set_cmpfn(smb_netbios_cache, smb_netbios_match);
 	}
 	(void) rw_unlock(&nb_cache_lock);
 
-	return (1);
+	return (0);
 }
 
 void
@@ -81,7 +74,7 @@
 {
 	(void) rw_wrlock(&nb_cache_lock);
 	ht_destroy_table(smb_netbios_cache);
-	smb_netbios_cache = 0;
+	smb_netbios_cache = NULL;
 	(void) rw_unlock(&nb_cache_lock);
 }
 
@@ -201,8 +194,8 @@
 smb_netbios_cache_lookup_addr(struct name_entry *name)
 {
 	struct name_entry *entry = 0;
-	struct addr_entry *addr;
-	struct addr_entry *name_addr;
+	addr_entry_t *addr;
+	addr_entry_t *name_addr;
 	HT_ITEM *item;
 	nb_key_t key;
 
@@ -234,8 +227,8 @@
 smb_netbios_cache_insert(struct name_entry *name)
 {
 	struct name_entry *entry;
-	struct addr_entry *addr;
-	struct addr_entry *name_addr;
+	addr_entry_t *addr;
+	addr_entry_t *name_addr;
 	HT_ITEM *item;
 	nb_key_t key;
 	int rc;
@@ -275,7 +268,7 @@
 			}
 		}
 
-		if ((addr = malloc(sizeof (struct addr_entry))) != NULL) {
+		if ((addr = malloc(sizeof (addr_entry_t))) != NULL) {
 			*addr = name->addr_list;
 			entry->attributes |= addr->attributes;
 			QUEUE_INSERT_TAIL(&entry->addr_list, addr);
@@ -337,7 +330,7 @@
 smb_netbios_cache_insert_list(struct name_entry *name)
 {
 	struct name_entry entry;
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 
 	addr = &name->addr_list;
 	do {
@@ -361,8 +354,8 @@
 smb_netbios_cache_update_entry(struct name_entry *entry,
     struct name_entry *name)
 {
-	struct addr_entry *addr;
-	struct addr_entry *name_addr;
+	addr_entry_t *addr;
+	addr_entry_t *name_addr;
 
 	addr = &entry->addr_list;
 	name_addr = &name->addr_list;
@@ -442,7 +435,7 @@
 void
 smb_netbios_cache_reset_ttl()
 {
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 	struct name_entry *name;
 	HT_ITERATOR hti;
 	HT_ITEM *item;
@@ -524,7 +517,7 @@
 smb_netbios_cache_refresh(name_queue_t *refq)
 {
 	struct name_entry *name;
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 	HT_ITERATOR hti;
 	HT_ITEM *item;
 
@@ -608,7 +601,7 @@
 void
 smb_netbios_name_freeaddrs(struct name_entry *entry)
 {
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 
 	if (entry == 0)
 		return;
@@ -637,19 +630,28 @@
 }
 
 void
-smb_netbios_cache_dump(void)
+smb_netbios_cache_dump(FILE *fp)
 {
 	struct name_entry *name;
 	HT_ITERATOR hti;
 	HT_ITEM *item;
 
 	(void) rw_rdlock(&nb_cache_lock);
+
+	if (ht_get_total_items(smb_netbios_cache) != 0) {
+		(void) fprintf(fp, "\n%-22s %-16s %-16s  %s\n",
+		    "Name", "Type", "Address", "TTL");
+		(void) fprintf(fp, "%s%s\n",
+		    "-------------------------------",
+		    "------------------------------");
+	}
+
 	item = ht_findfirst(smb_netbios_cache, &hti);
 	while (item) {
 		if (item->hi_data) {
 			name = (struct name_entry *)item->hi_data;
 			(void) mutex_lock(&name->mtx);
-			smb_netbios_name_dump(name);
+			smb_netbios_name_dump(fp, name);
 			(void) mutex_unlock(&name->mtx);
 		}
 		item = ht_findnext(&hti);
@@ -658,29 +660,28 @@
 }
 
 void
-smb_netbios_name_dump(struct name_entry *entry)
+smb_netbios_name_dump(FILE *fp, struct name_entry *entry)
 {
-	struct addr_entry *addr;
-	int count = 0;
+	char		buf[MAXHOSTNAMELEN];
+	addr_entry_t	*addr;
+	char		*type;
+	int		count = 0;
 
-	if (smb_netbios_name_debug == 0)
-		return;
+	smb_strname(entry, buf, sizeof (buf));
+	type = (IS_UNIQUE(entry->attributes)) ? "UNIQUE" : "GROUP";
 
-	syslog(LOG_DEBUG, "name='%15.15s<%02X>' scope='%s' attr=0x%x",
-	    entry->name, entry->name[15],
-	    entry->scope, entry->attributes);
+	(void) fprintf(fp, "%s %-6s (0x%04x)  ", buf, type, entry->attributes);
+
 	addr = &entry->addr_list;
 	do {
-		syslog(LOG_DEBUG, "addr_list[%d]:", count++);
-		syslog(LOG_DEBUG, "  attributes     = 0x%x", addr->attributes);
-		syslog(LOG_DEBUG, "  conflict_timer = %d",
-		    addr->conflict_timer);
-		syslog(LOG_DEBUG, "  refresh_ttl    = %d", addr->refresh_ttl);
-		syslog(LOG_DEBUG, "  ttl            = %d", addr->ttl);
-		syslog(LOG_DEBUG, "  sin.sin_addr   = %s",
-		    inet_ntoa(addr->sin.sin_addr));
-		syslog(LOG_DEBUG, "  sin.sin_port   = %d", addr->sin.sin_port);
-		syslog(LOG_DEBUG, "  sin.sinlen     = %d", addr->sinlen);
+		if (count == 0)
+			(void) fprintf(fp, "%-16s  %d\n",
+			    inet_ntoa(addr->sin.sin_addr), addr->ttl);
+		else
+			(void) fprintf(fp, "%-28s  (0x%04x)  %-16s  %d\n",
+			    " ", addr->attributes,
+			    inet_ntoa(addr->sin.sin_addr), addr->ttl);
+		++count;
 		addr = addr->forw;
 	} while (addr != &entry->addr_list);
 }
@@ -688,16 +689,17 @@
 void
 smb_netbios_name_logf(struct name_entry *entry)
 {
-	struct addr_entry *addr;
-	NETBIOS_NAMEBUF;
+	char		namebuf[MAXHOSTNAMELEN];
+	addr_entry_t	*addr;
 
-	(void) smb_strname(entry, namebuf, sizeof (namebuf));
+	smb_strname(entry, namebuf, sizeof (namebuf));
 	syslog(LOG_DEBUG, "%s flags=0x%x\n", namebuf, entry->attributes);
 	addr = &entry->addr_list;
 	do {
-		syslog(LOG_DEBUG, "  %s ttl=%d flags=0x%x",
+		syslog(LOG_DEBUG, "  %s ttl=%d flags=0x%x port=%d",
 		    inet_ntoa(addr->sin.sin_addr),
-		    addr->ttl, addr->attributes);
+		    addr->ttl, addr->attributes,
+		    addr->sin.sin_port);
 		addr = addr->forw;
 	} while (addr && (addr != &entry->addr_list));
 }
@@ -716,8 +718,8 @@
 struct name_entry *
 smb_netbios_name_dup(struct name_entry *entry, int alladdr)
 {
-	struct addr_entry *addr;
-	struct addr_entry *dup_addr;
+	addr_entry_t *addr;
+	addr_entry_t *dup_addr;
 	struct name_entry *dup;
 	int addr_cnt = 0;
 	int size = 0;
@@ -731,7 +733,7 @@
 	}
 
 	size = sizeof (struct name_entry) +
-	    (addr_cnt * sizeof (struct addr_entry));
+	    (addr_cnt * sizeof (addr_entry_t));
 	dup = (struct name_entry *)malloc(size);
 	if (dup == 0)
 		return (0);
@@ -750,7 +752,7 @@
 		return (dup);
 
 	/* LINTED - E_BAD_PTR_CAST_ALIGN */
-	dup_addr = (struct addr_entry *)((unsigned char *)dup +
+	dup_addr = (addr_entry_t *)((unsigned char *)dup +
 	    sizeof (struct name_entry));
 
 	addr = entry->addr_list.forw;
@@ -764,17 +766,22 @@
 	return (dup);
 }
 
-static char *
-smb_strname(struct name_entry *name, char *buf, int bufsize)
+static void
+smb_strname(struct name_entry *entry, char *buf, int bufsize)
 {
-	char *p;
+	char	tmp[MAXHOSTNAMELEN];
+	char	*p;
 
-	(void) snprintf(buf, bufsize, "%15.15s", name->name);
-	p = strchr(buf, ' ');
-	if (p)
-		(void) snprintf(p, 5, "<%02X>", name->name[15]);
+	(void) snprintf(tmp, MAXHOSTNAMELEN, "%15.15s", entry->name);
+	if ((p = strchr(tmp, ' ')) != NULL)
+		*p = '\0';
 
-	return (buf);
+	if (entry->scope[0] != '\0') {
+		(void) strlcat(tmp, ".", MAXHOSTNAMELEN);
+		(void) strlcat(tmp, (char *)entry->scope, MAXHOSTNAMELEN);
+	}
+
+	(void) snprintf(buf, bufsize, "%-16s  <%02X>", tmp, entry->name[15]);
 }
 
 static void
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c	Mon Oct 05 11:03:34 2009 -0700
@@ -55,7 +55,7 @@
  *   The following are Defined Constants for the NetBIOS Datagram
  *   Service:
  *
- *   - DGM_SRVC_UDP_PORT: the globally well-known UDP port allocated
+ *   - IPPORT_NETBIOS_DGM: the globally well-known UDP port allocated
  *     where the NetBIOS Datagram Service receives UDP packets.  See
  *     section 6, "Defined Constants", for its value.
  */
@@ -103,11 +103,12 @@
  *
  *   DATAGRAM SERVICE:
  *
- *      DGM_SRVC_UDP_PORT          138 (decimal)
+ *      IPPORT_NETBIOS_DGM          138 (decimal)
  *
  *      FRAGMENT_TO                2 seconds (default)
  */
 
+#include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
@@ -210,7 +211,7 @@
  *             half-ASCII, biased encoded name;
  *        SOURCE_NAME = cat(source, SCOPE_ID);
  *        SOURCE_IP = this nodes IP address;
- *        SOURCE_PORT =  DGM_SRVC_UDP_PORT;
+ *        SOURCE_PORT =  IPPORT_NETBIOS_DGM;
  *
  *        IF NetBIOS broadcast THEN
  *        BEGIN
@@ -318,7 +319,7 @@
 {
 	smb_inaddr_t ipaddr;
 	size_t count, srclen, destlen, sinlen;
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 	struct sockaddr_in sin;
 	char *buffer;
 	char ha_source[NETBIOS_DOMAIN_NAME_MAX];
@@ -333,9 +334,8 @@
 	destlen = strlen(ha_dest) + 1;
 
 	/* give some extra room */
-	buffer = (char *)malloc(MAX_DATAGRAM_LENGTH * 4);
-	if (buffer == 0) {
-		syslog(LOG_ERR, "netbios: datagram send (resource shortage)");
+	if ((buffer = malloc(MAX_DATAGRAM_LENGTH * 4)) == NULL) {
+		syslog(LOG_ERR, "nbt datagram: send: %m");
 		return (-1);
 	}
 
@@ -399,7 +399,7 @@
 {
 	smb_inaddr_t ipaddr;
 	size_t count, srclen, destlen, sinlen;
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 	struct sockaddr_in sin;
 	char *buffer;
 	char ha_source[NETBIOS_DOMAIN_NAME_MAX];
@@ -414,9 +414,8 @@
 	destlen = strlen(ha_dest) + 1;
 
 	/* give some extra room */
-	buffer = (char *)malloc(MAX_DATAGRAM_LENGTH * 4);
-	if (buffer == 0) {
-		syslog(LOG_ERR, "netbios: datagram send (resource shortage)");
+	if ((buffer = malloc(MAX_DATAGRAM_LENGTH * 4)) == NULL) {
+		syslog(LOG_ERR, "nbt datagram: send_to_net: %m");
 		return (-1);
 	}
 
@@ -570,7 +569,7 @@
 
 /*
  * Function: int smb_netbios_process_BPM_datagram(unsigned char *packet,
- *		struct addr_entry *addr)
+ *		addr_entry_t *addr)
  *
  * Description from rfc1002:
  *
@@ -797,7 +796,7 @@
 			(void) memcpy(&datagram->rawbuf[4],
 			    &datagram->src.addr_list.sin.sin_addr.s_addr,
 			    sizeof (uint32_t));
-			BE_OUT16(&datagram->rawbuf[8], DGM_SRVC_UDP_PORT);
+			BE_OUT16(&datagram->rawbuf[8], IPPORT_NETBIOS_DGM);
 
 			(void) sendto(datagram_sock, datagram->rawbuf,
 			    datagram->rawbytes, 0,
@@ -812,180 +811,12 @@
 	free(datagram);
 }
 
-
 /*
- * smb_netbios_process_NBDD_datagram
- *
- * Description from rfc1002:
- *
- *
- *  5.3.4.  PROTOCOLS FOR THE NBDD
- *
- *   The key to NetBIOS Datagram forwarding service is the packet
- *   delivered to the destination end node must have the same NetBIOS
- *   header as if the source end node sent the packet directly to the
- *   destination end node.  Consequently, the NBDD does not reassemble
- *   NetBIOS Datagrams.  It forwards the UDP packet as is.
- *
- *   PROCEDURE  datagram_packet(packet)
- *
- *   (*
- *    * processing initiated by a incoming datagram service
- *    * packet on a NBDD node.
- *    *)
- *
- *   BEGIN
- *        CASE packet type OF
- *
- *           DATAGRAM SERVICE:
- *           BEGIN
- *                IF packet was sent as a directed
- *                   NetBIOS datagram THEN
- *                BEGIN
- *                  (*
- *                   * provide group forwarding service
- *                   *
- *                   * Forward datagram to each member of the
- *                   * group.  Can forward via:
- *                   *   1) get list of group members and send
- *                   *   the DATAGRAM SERVICE packet unicast
- *                   *   to each
- *                   *   2) use Group Multicast, if available
- *                   *   3) combination of 1) and 2)
- *                   *)
- *
- *                  ...
- *
- *                END
- *
- *                ELSE
- *                BEGIN
- *                  (*
- *                   * provide broadcast forwarding service
- *                   *
- *                   * Forward datagram to every node in the
- *                   * NetBIOS scope.  Can forward via:
- *                   *   1) get list of group members and send
- *                   *   the DATAGRAM SERVICE packet unicast
- *                   *   to each
- *                   *   2) use Group Multicast, if available
- *                   *   3) combination of 1) and 2)
- *                   *)
- *
- *                  ...
- *
- *                END
- *           END (* datagram service *)
- *
- *           DATAGRAM ERROR:
- *           BEGIN
- *             (*
- *              * Should never receive these because Datagrams
- *              * forwarded have source end node IP address and
- *              * port in NetBIOS header.
- *              *)
- *
- *             send DELETE NAME REQUEST with incorrect name and
- *                  IP address to NetBIOS Name Server;
- *
- *           END (* datagram error *)
- *
- *           DATAGRAM QUERY REQUEST:
- *           BEGIN
- *             IF can send packet to DESTINATION_NAME THEN
- *             BEGIN
- *                  (*
- *                   * NBDD is able to relay Datagrams for
- *                   * this name
- *                   *)
- *
- *                  send POSITIVE DATAGRAM QUERY RESPONSE to
- *                    REQUEST source IP address and UDP port
- *                    with requests DGM_ID;
- *             END
- *             ELSE
- *             BEGIN
- *                  (*
- *                   * NBDD is NOT able to relay Datagrams for
- *                   * this name
- *                   *)
- *
- *                  send NEGATIVE DATAGRAM QUERY RESPONSE to
- *                    REQUEST source IP address and UDP port
- *
- *                    with requests DGM_ID;
- *             END
- *           END (* datagram query request *)
- *
- *        END (* case *)
- *   END (* procedure *)
+ * NetBIOS Datagram Service (port 138)
  */
-
-
-/*
- * Function: int smb_netbios_datagram_service_daemon(void)
- *
- * Description:
- *
- * 4.4.  DATAGRAM SERVICE PACKETS
- *
- * 4.4.1.  NetBIOS DATAGRAM HEADER
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                           SOURCE_IP                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          SOURCE_PORT          |          DGM_LENGTH           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         PACKET_OFFSET         |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   MSG_TYPE values (in hexidecimal):
- *
- *           10 -  DIRECT_UNIQUE DATAGRAM
- *           11 -  DIRECT_GROUP DATAGRAM
- *           12 -  BROADCAST DATAGRAM
- *           13 -  DATAGRAM ERROR
- *           14 -  DATAGRAM QUERY REQUEST
- *           15 -  DATAGRAM POSITIVE QUERY RESPONSE
- *           16 -  DATAGRAM NEGATIVE QUERY RESPONSE
- *
- *   Bit definitions of the FLAGS field:
- *
- *     0   1   2   3   4   5   6   7
- *   +---+---+---+---+---+---+---+---+
- *   | 0 | 0 | 0 | 0 |  SNT  | F | M |
- *   +---+---+---+---+---+---+---+---+
- *
- *   Symbol     Bit(s)   Description
- *
- *   M               7   MORE flag, If set then more NetBIOS datagram
- *                       fragments follow.
- *
- *   F               6   FIRST packet flag,  If set then this is first
- *                       (and possibly only) fragment of NetBIOS
- *                       datagram
- *
- *   SNT           4,5   Source End-Node type:
- *                          00 = B node
- *                          01 = P node
- *                          10 = M node
- *                          11 = NBDD
- *   RESERVED      0-3   Reserved, must be zero (0)
- *
- * Inputs:
- *	Nothing
- *
- * Returns:
- *	int	-> Description
- */
-
 /*ARGSUSED*/
 void *
-smb_netbios_datagram_service_daemon(void *arg)
+smb_netbios_datagram_service(void *arg)
 {
 	struct sockaddr_in 	sin;
 	struct datagram 	*datagram;
@@ -999,37 +830,40 @@
 	(void) mutex_unlock(&smb_dgq_mtx);
 
 	if ((datagram_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		syslog(LOG_ERR,
-		    "smbd: Could not create AF_INET, SOCK_DGRAM, socket");
-		smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_FAILED, 1);
-		return (0);
+		syslog(LOG_ERR, "nbt datagram: socket failed: %m");
+		smb_netbios_event(NETBIOS_EVENT_ERROR);
+		return (NULL);
 	}
 
+	flag = 1;
+	(void) setsockopt(datagram_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
+	    sizeof (flag));
+
 	bzero(&sin, sizeof (sin));
 	sin.sin_family = AF_INET;
-	sin.sin_port = htons(DGM_SRVC_UDP_PORT);
+	sin.sin_port = htons(IPPORT_NETBIOS_DGM);
 	if (bind(datagram_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
-		syslog(LOG_ERR, "smbd: Bind to name service port %d failed",
-		    DGM_SRVC_UDP_PORT);
+		syslog(LOG_ERR, "nbt datagram: bind(%d) failed: %m",
+		    IPPORT_NETBIOS_DGM);
 		(void) close(datagram_sock);
-		smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_FAILED, 1);
-		return (0);
+		smb_netbios_event(NETBIOS_EVENT_ERROR);
+		return (NULL);
 	}
+
+	flag = 1;
 	(void) setsockopt(datagram_sock, SOL_SOCKET, SO_BROADCAST, &flag,
 	    sizeof (flag));
 
-	smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_RUNNING, 1);
+	smb_netbios_event(NETBIOS_EVENT_DGM_START);
 
-	while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) ||
-	    (nb_status.state & NETBIOS_BROWSER_RUNNING)) {
-		if ((datagram = (struct datagram *)
-		    malloc(sizeof (struct datagram))) == 0) {
-			/* Sleep for 10 sec and try again */
-			(void) sleep(10);
+	while (smb_netbios_running()) {
+		if ((datagram = malloc(sizeof (struct datagram))) == NULL) {
+			/* Sleep for 10 seconds and try again */
+			smb_netbios_sleep(10);
 			continue;
 		}
 
-ignore:		bzero(&datagram->inaddr, sizeof (struct addr_entry));
+ignore:		bzero(&datagram->inaddr, sizeof (addr_entry_t));
 		datagram->inaddr.sinlen = sizeof (datagram->inaddr.sin);
 		datagram->inaddr.forw = datagram->inaddr.back =
 		    &datagram->inaddr;
@@ -1038,9 +872,8 @@
 		    MAX_DATAGRAM_LENGTH, 0,
 		    (struct sockaddr *)&datagram->inaddr.sin,
 		    &datagram->inaddr.sinlen)) < 0) {
-			syslog(LOG_ERR,
-			    "smbd: NETBIOS datagram - recvfrom failed");
-			smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_FAILED, 1);
+			syslog(LOG_ERR, "nbt datagram: recvfrom failed: %m");
+			smb_netbios_event(NETBIOS_EVENT_ERROR);
 			break;
 		}
 
@@ -1071,17 +904,12 @@
 		smb_netbios_BPM_datagram(datagram);
 	}
 
-	smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_RUNNING, 0);
-
-	(void) mutex_lock(&nb_status.mtx);
-	while (nb_status.state & NETBIOS_BROWSER_RUNNING)
-		(void) cond_wait(&nb_status.cv, &nb_status.mtx);
-	(void) mutex_unlock(&nb_status.mtx);
+	smb_netbios_event(NETBIOS_EVENT_DGM_STOP);
+	(void) smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP);
 
 	(void) close(datagram_sock);
 	smb_netbios_datagram_fini();
-	smb_tracef("smbd: Netbios Datagram Service is down\n");
-	return (0);
+	return (NULL);
 }
 
 static char
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c	Mon Oct 05 11:03:34 2009 -0700
@@ -24,65 +24,42 @@
  */
 
 /*
- * Description:
- *
- *	Contains base code for netbios name service.
- *
+ * NetBIOS name resolution node types.
  *
- * 6.  DEFINED CONSTANTS AND VARIABLES
- *
- *   GENERAL:
- *
- *      SCOPE_ID                   The name of the NetBIOS scope.
+ * A B-node (broadcast node) uses broadcasts for name registration
+ * and resolution.  Routers typically do not forward broadcasts and
+ * only computers on the local subnet will respond.
  *
- *                                 This is expressed as a character
- *                                 string meeting the requirements of
- *                                 the domain name system and without
- *                                 a leading or trailing "dot".
+ * A P-node (peer-to-peer node) uses a NetBIOS name server (WINS)
+ * to resolve NetBIOS names, which allows it to work across routers.
+ * In order to function in a P-node environment, all computers must
+ * be configured to use the NetBIOS name server because P-nodes do
+ * not broadcast on the network.
  *
- *                                 An implementation may elect to make
- *                                 this a single global value for the
- *                                 node or allow it to be specified
- *                                 with each separate NetBIOS name
- *                                 (thus permitting cross-scope
- *                                 references.)
- *
- *      BROADCAST_ADDRESS          An IP address composed of the
- *                                 nodes's network and subnetwork
- *                                 numbers with all remaining bits set
- *                                 to one.
+ * A mixed node (M-node) behaves as a B-node by default.  If it cannot
+ * resolve the name via broadcast then it tries a NetBIOS name server
+ * lookup (P-node).
  *
- *                                 I.e. "Specific subnet" broadcast
- *                                 addressing according to section 2.3
- *                                 of RFC 950.
- *
- *      BCAST_REQ_RETRY_TIMEOUT    250 milliseconds.
- *                                 An adaptive timer may be used.
+ * A hybrid node (H-node) behaves as a P-node by default.  If it cannot
+ * resolve the name using a NetBIOS name server then it resorts to
+ * broadcasts (B-node).
  *
- *      BCAST_REQ_RETRY_COUNT      3
- *
- *      UCAST_REQ_RETRY_TIMEOUT    5 seconds
- *                                 An adaptive timer may be used.
- *
- *      UCAST_REQ_RETRY_COUNT      3
- *
- *      MAX_DATAGRAM_LENGTH        576 bytes (default)
+ * NetBIOS Name Service Protocols
  *
- *
- *   NAME SERVICE:
- *
- *      REFRESH_TIMER              Negotiated with NAME for each name.
+ * A REQUEST packet is always sent to the well known UDP port 137.
+ * The destination address is normally either the IP broadcast address or
+ * the address of the NAME - the address of the NAME server it set up at
+ * initialization time.  In rare cases, a request packet will be sent to
+ * an end node, e.g.  a NAME QUERY REQUEST sent to "challenge" a node.
  *
- *      CONFLICT_TIMER             1 second
- *                                 Implementations may chose a longer
- *                                 value.
- *
+ * A RESPONSE packet is always sent to the source UDP port and source IP
+ * address of the request packet.
  *
- *      NAME_SERVICE_TCP_PORT      137 (decimal)
+ * A DEMAND packet must always be sent to the well known UDP port 137.
+ * There is no restriction on the target IP address.
  *
- *      NAME_SERVICE_UDP_PORT      137 (decimal)
- *
- *      INFINITE_TTL               0
+ * A transaction ID is a value composed from the requestor's IP address and
+ * a unique 16 bit value generated by the originator of the transaction.
  */
 
 #include <unistd.h>
@@ -99,54 +76,113 @@
 #include <smbsrv/libsmbns.h>
 #include <smbns_netbios.h>
 
-#define	NAME_HEADER_SIZE 12
+/*
+ * RFC 1002 4.2.1.1.  HEADER
+ */
+#define	QUESTION_TYPE_NETBIOS_GENERAL	0x20
+#define	QUESTION_TYPE_NETBIOS_STATUS	0x21
+
+#define	QUESTION_CLASS_INTERNET		0x0001
+
+/*
+ * RFC 1002 4.2.1.3.  RESOURCE RECORD
+ */
+#define	RR_TYPE_IP_ADDRESS_RESOURCE	0x0001
+#define	RR_TYPE_NAME_SERVER_RESOURCE	0x0002
+#define	RR_TYPE_NULL_RESOURCE		0x000A
+#define	RR_TYPE_NETBIOS_RESOURCE	0x0020
+#define	RR_TYPE_NETBIOS_STATUS		0x0021
+
+/*
+ *
+ * RESOURCE RECORD RR_CLASS field definitions
+ */
+#define	RR_CLASS_INTERNET_CLASS		0x0001
 
-typedef struct name_reply {
-	struct name_reply *forw;
-	struct name_reply *back;
-	struct name_packet *packet;
-	struct addr_entry *addr;
-	unsigned short name_trn_id;
-	unsigned short flags;
-} name_reply;
+/*
+ * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of NB.
+ */
+#define	RR_FLAGS_NB_ONT_MASK		0x6000
+#define	RR_FLAGS_NB_ONT_B_NODE		0x0000
+#define	RR_FLAGS_NB_ONT_P_NODE		0x2000
+#define	RR_FLAGS_NB_ONT_M_NODE		0x4000
+#define	RR_FLAGS_NB_ONT_RESERVED	0x6000
+#define	RR_FLAGS_NB_GROUP_NAME		0x8000
 
-static struct name_reply reply_queue;
-static mutex_t rq_mtx;
+#define	NAME_FLAGS_PERMANENT_NAME	0x0200
+#define	NAME_FLAGS_ACTIVE_NAME		0x0400
+#define	NAME_FLAGS_CONFLICT		0x0800
+#define	NAME_FLAGS_DEREGISTER		0x1000
+#define	NAME_FLAGS_ONT_MASK		0x6000
+#define	NAME_FLAGS_ONT_B_NODE		0x0000
+#define	NAME_FLAGS_ONT_P_NODE		0x2000
+#define	NAME_FLAGS_ONT_M_NODE		0x4000
+#define	NAME_FLAGS_ONT_RESERVED		0x6000
+#define	NAME_FLAGS_GROUP_NAME		0x8000
+
+#define	MAX_NETBIOS_REPLY_DATA_SIZE	500
+
+#define	NAME_HEADER_SIZE		12
 
-static mutex_t reply_mtx;
-static cond_t reply_cv;
+typedef struct nbt_name_reply {
+	struct nbt_name_reply	*forw;
+	struct nbt_name_reply	*back;
+	struct name_packet	*packet;
+	addr_entry_t		*addr;
+	uint16_t		name_trn_id;
+	boolean_t		reply_ready;
+} nbt_name_reply_t;
+
+static nbt_name_reply_t reply_queue;
+static mutex_t rq_mtx;
+static cond_t rq_cv;
+
+static mutex_t nbt_name_config_mtx;
 
 static name_queue_t delete_queue;
 static name_queue_t refresh_queue;
 
-/*
- * Flag to control whether or not NetBIOS name refresh requests
- * are logged. Set to non-zero to enable logging.
- */
-
-static unsigned short netbios_name_transcation_id = 1;
 static int name_sock = 0;
 
 static int bcast_num = 0;
 static int nbns_num = 0;
-static struct addr_entry smb_bcast_list[SMB_PI_MAX_NETWORKS];
-static struct addr_entry smb_nbns[SMB_PI_MAX_WINS];
+static addr_entry_t smb_bcast_list[SMB_PI_MAX_NETWORKS];
+static addr_entry_t smb_nbns[SMB_PI_MAX_WINS];
 
-static int smb_netbios_process_response(unsigned short, struct addr_entry *,
+static int smb_netbios_process_response(uint16_t, addr_entry_t *,
     struct name_packet *, uint32_t);
 
-static int smb_send_name_service_packet(struct addr_entry *addr,
+static int smb_send_name_service_packet(addr_entry_t *addr,
     struct name_packet *packet);
 
+/*
+ * Allocate a transaction id.
+ */
+static uint16_t
+smb_netbios_name_trn_id(void)
+{
+	static uint16_t trn_id;
+	static mutex_t trn_id_mtx;
+
+	(void) mutex_lock(&trn_id_mtx);
+
+	do {
+		++trn_id;
+	} while (trn_id == 0 || trn_id == (uint16_t)-1);
+
+	(void) mutex_unlock(&trn_id_mtx);
+	return (trn_id);
+}
+
 static int
-smb_end_node_challenge(struct name_reply *reply_info)
+smb_end_node_challenge(nbt_name_reply_t *reply_info)
 {
 	int			rc;
 	uint32_t		retry;
-	unsigned short		tid;
+	uint16_t		tid;
 	struct resource_record	*answer;
 	struct name_question	question;
-	struct addr_entry 	*addr;
+	addr_entry_t		*addr;
 	struct name_entry 	*destination;
 	struct name_packet	packet;
 	struct timespec 	st;
@@ -176,7 +212,7 @@
 
 	addr = &destination->addr_list;
 	for (retry = 0; retry < UCAST_REQ_RETRY_COUNT; retry++) {
-		tid = netbios_name_transcation_id++;
+		tid = smb_netbios_name_trn_id();
 		packet.name_trn_id = tid;
 		if (smb_send_name_service_packet(addr, &packet) >= 0) {
 			if ((rc = smb_netbios_process_response(tid, addr,
@@ -191,21 +227,20 @@
 	return (0);
 }
 
-
-static struct name_reply *
-smb_name_get_reply(unsigned short tid, uint32_t timeout)
+static nbt_name_reply_t *
+smb_name_get_reply(uint16_t tid, uint32_t timeout)
 {
-	unsigned short		info;
+	uint16_t		info;
 	struct resource_record	*answer;
-	struct name_reply 	*reply;
+	nbt_name_reply_t 	*reply;
 	uint32_t 		wait_time, to_save; /* in millisecond */
 	struct timeval 		wt;
 	timestruc_t 		to;
 
 	to_save = timeout;
-	reply = (struct name_reply *)malloc(sizeof (struct name_reply));
-	if (reply != 0) {
-		reply->flags = 0;
+	reply = malloc(sizeof (nbt_name_reply_t));
+	if (reply != NULL) {
+		reply->reply_ready = B_FALSE;
 		reply->name_trn_id = tid;
 		(void) mutex_lock(&rq_mtx);
 		QUEUE_INSERT_TAIL(&reply_queue, reply);
@@ -215,13 +250,13 @@
 			(void) gettimeofday(&wt, 0);
 			wait_time = wt.tv_usec / 1000;
 
-			(void) mutex_lock(&reply_mtx);
 			to.tv_sec = 0;
 			to.tv_nsec = timeout * 1000000;
-			(void) cond_reltimedwait(&reply_cv, &reply_mtx, &to);
-			(void) mutex_unlock(&reply_mtx);
+			(void) mutex_lock(&rq_mtx);
+			(void) cond_reltimedwait(&rq_cv, &rq_mtx, &to);
+			(void) mutex_unlock(&rq_mtx);
 
-			if (reply->flags != 0) {
+			if (reply->reply_ready) {
 				info = reply->packet->info;
 				if (PACKET_TYPE(info) == WACK_RESPONSE) {
 					answer = reply->packet->answer;
@@ -231,7 +266,7 @@
 					free(reply->addr);
 					free(reply->packet);
 					timeout = to_save + wait_time;
-					reply->flags = 0;
+					reply->reply_ready = B_FALSE;
 					reply->name_trn_id = tid;
 					(void) mutex_lock(&rq_mtx);
 					QUEUE_INSERT_TAIL(&reply_queue, reply);
@@ -257,9 +292,9 @@
 }
 
 static void
-smb_reply_ready(struct name_packet *packet, struct addr_entry *addr)
+smb_reply_ready(struct name_packet *packet, addr_entry_t *addr)
 {
-	struct name_reply *reply;
+	nbt_name_reply_t *reply;
 	struct resource_record *answer;
 
 	(void) mutex_lock(&rq_mtx);
@@ -267,16 +302,12 @@
 	    reply = reply->forw) {
 		if (reply->name_trn_id == packet->name_trn_id) {
 			QUEUE_CLIP(reply);
-			(void) mutex_unlock(&rq_mtx);
 
 			reply->addr = addr;
 			reply->packet = packet;
-
-			(void) mutex_lock(&reply_mtx);
-			reply->flags |= 0x0001; /* reply ready */
-			(void) cond_signal(&reply_cv);
-			(void) mutex_unlock(&reply_mtx);
-
+			reply->reply_ready = B_TRUE;
+			(void) cond_signal(&rq_cv);
+			(void) mutex_unlock(&rq_mtx);
 			return;
 		}
 	}
@@ -292,12 +323,12 @@
 }
 
 static int
-smb_netbios_process_response(unsigned short tid, struct addr_entry *addr,
+smb_netbios_process_response(uint16_t tid, addr_entry_t *addr,
     struct name_packet *packet, uint32_t timeout)
 {
 	int			rc = 0;
-	unsigned short		info;
-	struct name_reply 	*reply;
+	uint16_t		info;
+	nbt_name_reply_t 	*reply;
 	struct resource_record	*answer;
 	struct name_entry 	*name;
 	struct name_entry 	*entry;
@@ -322,13 +353,16 @@
 				 */
 				addr->attributes &= ~NAME_ATTR_LOCAL;
 
-				addr->refresh_ttl = addr->ttl =
-				    (answer && answer->ttl) ?
-				    (answer->ttl >> 1) :
-				    TO_SECONDS(DEFAULT_TTL);
+				if (answer->ttl)
+					addr->ttl = answer->ttl;
+				else
+					addr->ttl = DEFAULT_TTL;
+				addr->refresh_ttl = TO_SECONDS(addr->ttl);
+				addr->ttl = addr->refresh_ttl;
+
 				addr = addr->forw;
 			} while (addr != &answer->name->addr_list);
-			smb_netbios_name_dump(answer->name);
+			smb_netbios_name_logf(answer->name);
 			(void) smb_netbios_cache_insert_list(answer->name);
 			rc = 1;
 		} else {
@@ -362,7 +396,7 @@
 					 */
 					entry->attributes |= NAME_ATTR_CONFLICT;
 					syslog(LOG_DEBUG,
-					    "NETBIOS Name conflict: %15.15s",
+					    "nbns: name conflict: %15.15s",
 					    entry->name);
 					smb_netbios_cache_unlock_entry(entry);
 				}
@@ -377,8 +411,8 @@
 		 *   TTL, for this name
 		 */
 		question = packet->question;
-		ttl = (answer && answer->ttl) ? answer->ttl >> 1
-		    : TO_SECONDS(DEFAULT_TTL);
+		ttl = (answer && answer->ttl) ? answer->ttl : DEFAULT_TTL;
+		ttl = TO_SECONDS(ttl);
 		if ((entry = smb_netbios_cache_lookup(question->name)) != 0) {
 			addr = &entry->addr_list;
 			do {
@@ -442,13 +476,11 @@
  *	-1	-> Hard error, can not possibly encode
  *	-2	-> Need more memory in buf -- it's too small
  */
-
 static int
-smb_name_buf_from_packet(unsigned char *buf,
-    int n_buf,
+smb_name_buf_from_packet(unsigned char *buf, int n_buf,
     struct name_packet *npb)
 {
-	struct addr_entry 	*raddr;
+	addr_entry_t		*raddr;
 	unsigned char 		*heap = buf;
 	unsigned char 		*end_heap = heap + n_buf;
 	unsigned char 		*dnptrs[32];
@@ -624,27 +656,15 @@
 	return (name_len);
 }
 
-
 /*
  * smb_name_buf_to_packet
  *
- * Description:
- *	Convert the bits and bytes that came from the wire
- *	into a NetBIOS Name Server Packet Block (npb).
- *	The "block" is used as a heap.
+ * Convert the bits and bytes that came from the wire into a NetBIOS
+ * Name Server Packet Block (npb).  The "block" is used as a heap.
  *
- * Inputs:
- *	char *		buf	-> Buffer, from the wire
- *	int		n_buf	-> Length of 'buf'
- *	name_packet	*npb	-> Packet block, decode into
- *	int		n_npb	-> Max bytes in 'npb'
- *
- * Returns:
- *	>0	-> Decode (parse) successful, value is byte length of npb
- *	-1	-> Hard error, can not possibly decode
- *	-2	-> Need more memory in npb -- it's too small
+ * Returns a pointer to a name packet on success.  Otherwise, returns
+ * a NULL pointer.
  */
-
 static struct name_packet *
 smb_name_buf_to_packet(char *buf, int n_buf)
 {
@@ -655,16 +675,15 @@
 	char name_buf[MAX_NAME_LENGTH];
 	struct resource_record *nrr = 0;
 	int	rc, i, n, nn, ns;
-	unsigned short name_trn_id, info;
-	unsigned short qdcount, ancount, nscount, arcount;
-	struct addr_entry *next;
+	uint16_t name_trn_id, info;
+	uint16_t qdcount, ancount, nscount, arcount;
+	addr_entry_t *next;
 	int name_len;
 
 	if (n_buf < NAME_HEADER_SIZE) {
 		/* truncated header */
-		syslog(LOG_DEBUG, "SmbNBNS: packet is too short (%d)",
-		    n_buf);
-		return (0);
+		syslog(LOG_DEBUG, "nbns: short packet (%d bytes)", n_buf);
+		return (NULL);
 	}
 
 	name_trn_id = BE_IN16(scan); scan += 2;
@@ -681,11 +700,10 @@
 	    ((unsigned)nscount * (sizeof (struct resource_record) + ns)) +
 	    ((unsigned)arcount * (sizeof (struct resource_record) + ns));
 
-	if ((npb = (struct name_packet *)malloc(n)) == 0) {
-		return (0);
-	}
+	if ((npb = malloc(n)) == NULL)
+		return (NULL);
+
 	bzero(npb, n);
-
 	heap = npb->block_data;
 	npb->name_trn_id = name_trn_id;
 	npb->info = info;
@@ -748,7 +766,7 @@
 		    (char *)scan_end);
 		if (name_len <= 0) {
 			free(npb);
-			return (0);
+			return (NULL);
 		}
 
 		smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
@@ -758,14 +776,14 @@
 		if (rc < 0) {
 			/* Couldn't decode the question name */
 			free(npb);
-			return (0);
+			return (NULL);
 		}
 
 		scan += name_len;
 		if (scan + 4 > scan_end) {
 			/* no room for Question Type(2) and Class(2) fields */
 			free(npb);
-			return (0);
+			return (NULL);
 		}
 
 		npb->question[i].question_type = BE_IN16(scan); scan += 2;
@@ -786,7 +804,7 @@
 			    (char *)scan_end);
 			if (name_len <= 0) {
 				free(npb);
-				return (0);
+				return (NULL);
 			}
 			rc = name_len;
 		}
@@ -798,7 +816,7 @@
 			 * RDLENGTH (2) fields.
 			 */
 			free(npb);
-			return (0);
+			return (NULL);
 		}
 
 		smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
@@ -806,7 +824,7 @@
 		if ((rc = smb_first_level_name_decode((unsigned char *)name_buf,
 		    nrr[i].name)) < 0) {
 			free(npb);
-			return (0);
+			return (NULL);
 		}
 
 		nrr[i].rr_type = BE_IN16(scan); scan += 2;
@@ -818,7 +836,7 @@
 			if ((scan + n) > scan_end) {
 				/* no room for RDATA */
 				free(npb);
-				return (0);
+				return (NULL);
 			}
 			bcopy(scan, heap, n);
 
@@ -829,13 +847,12 @@
 					if (nn == 6)
 						next = &nrr[i].name->addr_list;
 					else {
-						next = (struct addr_entry *)
-						    malloc(
-						    sizeof (struct addr_entry));
+						next = malloc(
+						    sizeof (addr_entry_t));
 						if (next == 0) {
 							/* not enough memory */
 							free(npb);
-							return (0);
+							return (NULL);
 						}
 						QUEUE_INSERT_TAIL(
 						    &nrr[i].name->addr_list,
@@ -849,7 +866,7 @@
 					    &next->sin.sin_addr.s_addr,
 					    scan + 2, sizeof (uint32_t));
 					next->sin.sin_port =
-					    htons(DGM_SRVC_UDP_PORT);
+					    htons(IPPORT_NETBIOS_DGM);
 					nn -= 6;
 					scan += 6;
 				}
@@ -863,7 +880,6 @@
 	return (npb);
 }
 
-
 /*
  * smb_send_name_service_packet
  *
@@ -879,10 +895,8 @@
  *	success	->  >0
  *	failure	-> <=0
  */
-
 static int
-smb_send_name_service_packet(struct addr_entry *addr,
-				struct name_packet *packet)
+smb_send_name_service_packet(addr_entry_t *addr, struct name_packet *packet)
 {
 	unsigned char buf[MAX_DATAGRAM_LENGTH];
 	int len;
@@ -897,293 +911,6 @@
 }
 
 /*
- * 4.2.1.1.  HEADER
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           | OPCODE  |   NM_FLAGS  | RCODE |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          QDCOUNT              |           ANCOUNT             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          NSCOUNT              |           ARCOUNT             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   Field     Description
- *
- *   NAME_TRN_ID      Transaction ID for Name Service Transaction.
- *                    Requester places a unique value for each active
- *                    transaction.  Responder puts NAME_TRN_ID value
- *                    from request packet in response packet.
- *
- *   OPCODE           Packet type code, see table below.
- *
- *   NM_FLAGS         Flags for operation, see table below.
- *
- *   RCODE            Result codes of request.  Table of RCODE values
- *                    for each response packet below.
- *
- *   QDCOUNT          Unsigned 16 bit integer specifying the number of
- *                    entries in the question section of a Name
- *
- *                    Service packet.  Always zero (0) for responses.
- *                    Must be non-zero for all NetBIOS Name requests.
- *
- *   ANCOUNT          Unsigned 16 bit integer specifying the number of
- *                    resource records in the answer section of a Name
- *                    Service packet.
- *
- *   NSCOUNT          Unsigned 16 bit integer specifying the number of
- *                    resource records in the authority section of a
- *                    Name Service packet.
- *
- *   ARCOUNT          Unsigned 16 bit integer specifying the number of
- *                    resource records in the additional records
- *                    section of a Name Service packet.
- *
- *   The OPCODE field is defined as:
- *
- *     0   1   2   3   4
- *   +---+---+---+---+---+
- *   | R |    OPCODE     |
- *   +---+---+---+---+---+
- *
- *   Symbol     Bit(s)   Description
- *
- *   OPCODE        1-4   Operation specifier:
- *                         0 = query
- *                         5 = registration
- *                         6 = release
- *                         7 = WACK
- *                         8 = refresh
- *
- *   R               0   RESPONSE flag:
- *                         if bit == 0 then request packet
- *                         if bit == 1 then response packet.
- */
-
-
-/*
- *   The NM_FLAGS field is defined as:
- *
- *
- *     0   1   2   3   4   5   6
- *   +---+---+---+---+---+---+---+
- *   |AA |TC |RD |RA | 0 | 0 | B |
- *   +---+---+---+---+---+---+---+
- *
- *   Symbol     Bit(s)   Description
- *
- *   B               6   Broadcast Flag.
- *                         = 1: packet was broadcast or multicast
- *                         = 0: unicast
- *
- *   RA              3   Recursion Available Flag.
- *
- *                       Only valid in responses from a NetBIOS Name
- *                       Server -- must be zero in all other
- *                       responses.
- *
- *                       If one (1) then the NAME supports recursive
- *                       query, registration, and release.
- *
- *                       If zero (0) then the end-node must iterate
- *                       for query and challenge for registration.
- *
- *   RD              2   Recursion Desired Flag.
- *
- *                       May only be set on a request to a NetBIOS
- *                       Name Server.
- *
- *                       The NAME will copy its state into the
- *                       response packet.
- *
- *                       If one (1) the NAME will iterate on the
- *                       query, registration, or release.
- *
- *   TC              1   Truncation Flag.
- *
- *                       Set if this message was truncated because the
- *                       datagram carrying it would be greater than
- *                       576 bytes in length.  Use TCP to get the
- *                       information from the NetBIOS Name Server.
- *
- *   AA              0   Authoritative Answer flag.
- *
- *                       Must be zero (0) if R flag of OPCODE is zero
- *                       (0).
- *
- *                       If R flag is one (1) then if AA is one (1)
- *                       then the node responding is an authority for
- *                       the domain name.
- *
- *                       End nodes responding to queries always set
- *                       this bit in responses.
- *
- */
-
-/*
- * 4.2.1.2.  QUESTION SECTION
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                         QUESTION_NAME                         /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         QUESTION_TYPE         |        QUESTION_CLASS         |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   Field            Description
- *
- *   QUESTION_NAME    The compressed name representation of the
- *                    NetBIOS name for the request.
- *
- *   QUESTION_TYPE    The type of request.  The values for this field
- *                    are specified for each request.
- *
- *   QUESTION_CLASS   The class of the request.  The values for this
- *                    field are specified for each request.
- *
- *   QUESTION_TYPE is defined as:
- *
- *   Symbol      Value   Description:
- *
- *   NB         0x0020   NetBIOS general Name Service Resource Record
- *   NBSTAT     0x0021   NetBIOS NODE STATUS Resource Record (See NODE
- *                       STATUS REQUEST)
- *
- *   QUESTION_CLASS is defined as:
- *
- *   Symbol      Value   Description:
- *
- *   IN         0x0001   Internet class
- */
-
-#define	QUESTION_TYPE_NETBIOS_GENERAL	0x20
-#define	QUESTION_TYPE_NETBIOS_STATUS	0x21
-
-#define	QUESTION_CLASS_INTERNET		0x0001
-
-/*
- *
- * 4.2.1.3.  RESOURCE RECORD
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           RR_TYPE             |          RR_CLASS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           RDLENGTH            |                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
- *   /                                                               /
- *   /                             RDATA                             /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   Field            Description
- *
- *   RR_NAME          The compressed name representation of the
- *                    NetBIOS name corresponding to this resource
- *                    record.
- *
- *   RR_TYPE          Resource record type code
- *
- *   RR_CLASS         Resource record class code
- *
- *   TTL              The Time To Live of a the resource record's
- *                    name.
- *
- *   RDLENGTH         Unsigned 16 bit integer that specifies the
- *                    number of bytes in the RDATA field.
- *
- *   RDATA            RR_CLASS and RR_TYPE dependent field.  Contains
- *                    the resource information for the NetBIOS name.
- *
- *   RESOURCE RECORD RR_TYPE field definitions:
- *
- *   Symbol      Value   Description:
- *
- *   A          0x0001   IP address Resource Record (See REDIRECT NAME
- *                       QUERY RESPONSE)
- *   NS         0x0002   Name Server Resource Record (See REDIRECT
- *                       NAME QUERY RESPONSE)
- *   NULL       0x000A   NULL Resource Record (See WAIT FOR
- *                       ACKNOWLEDGEMENT RESPONSE)
- *   NB         0x0020   NetBIOS general Name Service Resource Record
- *                       (See NB_FLAGS and NB_ADDRESS, below)
- *   NBSTAT     0x0021   NetBIOS NODE STATUS Resource Record (See NODE
- *                       STATUS RESPONSE)
- */
-
-#define	RR_TYPE_IP_ADDRESS_RESOURCE	0x0001
-#define	RR_TYPE_NAME_SERVER_RESOURCE	0x0002
-#define	RR_TYPE_NULL_RESOURCE		0x000A
-#define	RR_TYPE_NETBIOS_RESOURCE	0x0020
-#define	RR_TYPE_NETBIOS_STATUS		0x0021
-
-/*
- *
- *   RESOURCE RECORD RR_CLASS field definitions:
- *
- *   Symbol      Value   Description:
- *
- *   IN         0x0001   Internet class
- */
-#define	RR_CLASS_INTERNET_CLASS		0x0001
-
-/*
- *
- *   NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of
- *   "NB":
- *
- *                                             1   1   1   1   1   1
- *     0   1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
- *   +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
- *   | G |  ONT  |                RESERVED                           |
- *   +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
- *
- *   Symbol     Bit(s)   Description:
- *
- *   RESERVED     3-15   Reserved for future use.  Must be zero (0).
- *   ONT           1,2   Owner Node Type:
- *                          00 = B node
- *                          01 = P node
- *                          10 = M node
- *                          11 = Reserved for future use
- *                       For registration requests this is the
- *                       claimant's type.
- *                       For responses this is the actual owner's
- *                       type.
- *
- *   G               0   Group Name Flag.
- *                       If one (1) then the RR_NAME is a GROUP
- *                       NetBIOS name.
- *                       If zero (0) then the RR_NAME is a UNIQUE
- *                       NetBIOS name.
- *
- *   The NB_ADDRESS field of the RESOURCE RECORD RDATA field for
- *   RR_TYPE of "NB" is the IP address of the name's owner.
- *
- */
-#define	RR_FLAGS_NB_ONT_MASK		0x6000
-#define	RR_FLAGS_NB_ONT_B_NODE		0x0000
-#define	RR_FLAGS_NB_ONT_P_NODE		0x2000
-#define	RR_FLAGS_NB_ONT_M_NODE		0x4000
-#define	RR_FLAGS_NB_ONT_RESERVED	0x6000
-
-#define	RR_FLAGS_NB_GROUP_NAME		0x8000
-
-/*
  * smb_netbios_send_rcv
  *
  * This function sends the given NetBIOS packet to the given
@@ -1195,12 +922,11 @@
  *		1		Got reply
  */
 static int
-smb_netbios_send_rcv(int bcast, struct addr_entry *destination,
-					struct name_packet *packet,
-					uint32_t retries, uint32_t timeout)
+smb_netbios_send_rcv(int bcast, addr_entry_t *destination,
+    struct name_packet *packet, uint32_t retries, uint32_t timeout)
 {
 	uint32_t retry;
-	unsigned short	tid;
+	uint16_t	tid;
 	struct timespec st;
 	int	rc;
 
@@ -1208,7 +934,7 @@
 		if ((destination->flags & ADDR_FLAG_VALID) == 0)
 			return (0);
 
-		tid = netbios_name_transcation_id++;
+		tid = smb_netbios_name_trn_id();
 		packet->name_trn_id = tid;
 		if (smb_send_name_service_packet(destination, packet) >= 0) {
 			rc = smb_netbios_process_response(tid, destination,
@@ -1230,45 +956,7 @@
 }
 
 /*
- * 4.2.2.  NAME REGISTRATION REQUEST
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |0|  0x5  |0|0|1|0|0 0|B|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0001               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                         QUESTION_NAME                         /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |        IN (0x0001)            |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   Since the RR_NAME is the same name as the QUESTION_NAME, the
- *   RR_NAME representation must use pointers to the QUESTION_NAME
- *   name's labels to guarantee the length of the datagram is less
- *   than the maximum 576 bytes.  See section above on name formats
- *   and also page 31 and 32 of RFC 883, Domain Names - Implementation
- *   and Specification, for a complete description of compressed name
- *   label pointers.
+ * RFC 1002 4.2.2.  NAME REGISTRATION REQUEST
  */
 static int
 smb_send_name_registration_request(int bcast, struct name_question *question,
@@ -1277,15 +965,15 @@
 	int gotreply = 0;
 	uint32_t retries;
 	uint32_t timeout;
-	struct addr_entry *destination;
+	addr_entry_t *destination;
 	struct name_packet packet;
 	unsigned char type;
 	int i, addr_num, rc;
 
 	type = question->name->name[15];
-	if ((type != 0x00) && (type != 0x20)) {
-		syslog(LOG_ERR, "netbios: error trying to register"
-		    " non-local name");
+	if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
+		syslog(LOG_DEBUG, "nbns: name registration bad type (0x%02x)",
+		    type);
 		smb_netbios_name_logf(question->name);
 		question->name->attributes &= ~NAME_ATTR_LOCAL;
 		return (-1);
@@ -1340,38 +1028,7 @@
 }
 
 /*
- *
- * 4.2.4.  NAME REFRESH REQUEST
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |0|  0x8  |0|0|0|0|0 0|B|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0001               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                         QUESTION_NAME                         /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |        IN (0x0001)            |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * RFC 1002 4.2.4.  NAME REFRESH REQUEST
  */
 /*ARGSUSED*/
 static int
@@ -1382,15 +1039,15 @@
 	int gotreply = 0;
 	uint32_t retries;
 	uint32_t timeout;
-	struct addr_entry *addr;
-	struct addr_entry *destination;
+	addr_entry_t *addr;
+	addr_entry_t *destination;
 	struct name_packet packet;
 	unsigned char type;
 	int i, addr_num, q_addrs = 0;
 
 	type = question->name->name[15];
-	if ((type != 0x00) && (type != 0x20)) {
-		syslog(LOG_ERR, "attempt to refresh non-local name");
+	if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
+		syslog(LOG_DEBUG, "nbns: name refresh bad type (0x%02x)", type);
 		smb_netbios_name_logf(question->name);
 		question->name->attributes &= ~NAME_ATTR_LOCAL;
 		return (-1);
@@ -1471,78 +1128,12 @@
 }
 
 /*
- * 4.2.5.  POSITIVE NAME REGISTRATION RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x5  |1|0|1|1|0 0|0|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *
- *
- * 4.2.6.  NEGATIVE NAME REGISTRATION RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x5  |1|0|1|1|0 0|0| RCODE |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   RCODE field values:
- *
- *   Symbol      Value   Description:
- *
- *   FMT_ERR       0x1   Format Error.  Request was invalidly
- *                       formatted.
- *   SRV_ERR       0x2   Server failure.  Problem with NAME, cannot
- *                       process name.
- *   IMP_ERR       0x4   Unsupported request error.  Allowable only
- *                       for challenging NAME when gets an Update type
- *                       registration request.
- *   RFS_ERR       0x5   Refused error.  For policy reasons server
- *                       will not register this name from this host.
- *   ACT_ERR       0x6   Active error.  Name is owned by another node.
- *   CFT_ERR       0x7   Name in conflict error.  A UNIQUE name is
- *                       owned by more than one node.
+ * RFC 1002 4.2.5.  POSITIVE NAME REGISTRATION RESPONSE
+ * RFC 1002 4.2.6.  NEGATIVE NAME REGISTRATION RESPONSE
  */
 static int
-smb_send_name_registration_response(struct addr_entry *addr,
-    struct name_packet *original_packet, unsigned short rcode)
+smb_send_name_registration_response(addr_entry_t *addr,
+    struct name_packet *original_packet, uint16_t rcode)
 {
 	struct name_packet	packet;
 	struct resource_record	answer;
@@ -1573,43 +1164,7 @@
 }
 
 /*
- * 4.2.9.  NAME RELEASE REQUEST & DEMAND
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |0|  0x6  |0|0|0|0|0 0|B|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0001               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                         QUESTION_NAME                         /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |        IN (0x0001)            |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          0x00000000                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   Since the RR_NAME is the same name as the QUESTION_NAME, the
- *   RR_NAME representation must use label string pointers to the
- *   QUESTION_NAME labels to guarantee the length of the datagram is
- *   less than the maximum 576 bytes.  This is the same condition as
- *   with the NAME REGISTRATION REQUEST.
+ * RFC 1002 4.2.9.  NAME RELEASE REQUEST & DEMAND
  */
 static int
 smb_send_name_release_request_and_demand(int bcast,
@@ -1620,7 +1175,7 @@
 	int addr_num;
 	uint32_t retries;
 	uint32_t timeout;
-	struct addr_entry *destination;
+	addr_entry_t *destination;
 	struct name_packet packet;
 
 	if (bcast == BROADCAST) {
@@ -1661,81 +1216,13 @@
 }
 
 /*
- * 4.2.10.  POSITIVE NAME RELEASE RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x6  |1|0|0|0|0 0|0|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *
- * 4.2.11.  NEGATIVE NAME RELEASE RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x6  |1|0|0|0|0 0|0| RCODE |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0006              |          NB_FLAGS             |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          NB_ADDRESS                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   RCODE field values:
- *
- *   Symbol      Value   Description:
- *
- *   FMT_ERR       0x1   Format Error.  Request was invalidly
- *                       formatted.
- *
- *   SRV_ERR       0x2   Server failure.  Problem with NAME, cannot
- *                       process name.
- *
- *   RFS_ERR       0x5   Refused error.  For policy reasons server
- *                       will not release this name from this host.
- *
- *   ACT_ERR       0x6   Active error.  Name is owned by another node.
- *                       Only that node may release it.  A NetBIOS
- *                       Name Server can optionally allow a node to
- *                       release a name it does not own.  This would
- *                       facilitate detection of inactive names for
- *                       nodes that went down silently.
+ * RFC 1002 4.2.10.  POSITIVE NAME RELEASE RESPONSE
+ * RFC 1002 4.2.11.  NEGATIVE NAME RELEASE RESPONSE
  */
 static int
 /* LINTED - E_STATIC_UNUSED */
-smb_send_name_release_response(struct addr_entry *addr,
-    struct name_packet *original_packet, unsigned short rcode)
+smb_send_name_release_response(addr_entry_t *addr,
+    struct name_packet *original_packet, uint16_t rcode)
 {
 	struct name_packet	packet;
 	struct resource_record	answer;
@@ -1765,25 +1252,7 @@
 }
 
 /*
- *
- * 4.2.12.  NAME QUERY REQUEST
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |0|  0x0  |0|0|1|0|0 0|B|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0001               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                         QUESTION_NAME                         /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |        IN (0x0001)            |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * RFC 1002 4.2.12.  NAME QUERY REQUEST
  */
 static int
 smb_send_name_query_request(int bcast, struct name_question *question)
@@ -1791,8 +1260,8 @@
 	int			rc = 0;
 	uint32_t		retry, retries;
 	uint32_t		timeout;
-	unsigned short		tid;
-	struct addr_entry 	*destination;
+	uint16_t		tid;
+	addr_entry_t		*destination;
 	struct name_packet	packet;
 	int 			i, addr_num;
 	struct timespec 	st;
@@ -1825,9 +1294,9 @@
 
 	for (i = 0; i < addr_num; i++) {
 		for (retry = 0; retry < retries; retry++) {
-			if ((destination->flags & ADDR_FLAG_VALID) == 0)
+			if ((destination[i].flags & ADDR_FLAG_VALID) == 0)
 				break;
-			tid = netbios_name_transcation_id++;
+			tid = smb_netbios_name_trn_id();
 			packet.name_trn_id = tid;
 
 			if (smb_send_name_service_packet(&destination[i],
@@ -1846,101 +1315,19 @@
 	return (rc);
 }
 
-
 /*
- *
- * 4.2.13.  POSITIVE NAME QUERY RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x0  |1|T|1|?|0 0|0|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NB (0x0020)         |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                              TTL                              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           RDLENGTH            |                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
- *   |                                                               |
- *   /                       ADDR_ENTRY ARRAY                        /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   The ADDR_ENTRY ARRAY a sequence of zero or more ADDR_ENTRY
- *   records.  Each ADDR_ENTRY record represents an owner of a name.
- *   For group names there may be multiple entries.  However, the list
- *   may be incomplete due to packet size limitations.  Bit 22, "T",
- *   will be set to indicate truncated data.
- *
- *   Each ADDR_ENTRY has the following format:
- *
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          NB_FLAGS             |          NB_ADDRESS           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |   NB_ADDRESS (continued)      |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *
- *
- * 4.2.14.  NEGATIVE NAME QUERY RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x0  |1|0|1|?|0 0|0| RCODE |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   /                                                               /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           NULL (0x000A)       |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          0x00000000                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   RCODE field values:
- *
- *   Symbol      Value   Description
- *
- *   FMT_ERR       0x1   Format Error.  Request was invalidly
- *                       formatted.
- *   SRV_ERR       0x2   Server failure.  Problem with NAME, cannot
- *                       process name.
- *   NAM_ERR       0x3   Name Error.  The name requested does not
- *                       exist.
- *   IMP_ERR       0x4   Unsupported request error.  Allowable only
- *                       for challenging NAME when gets an Update type
- *                       registration request.
- *   RFS_ERR       0x5   Refused error.  For policy reasons server
- *                       will not register this name from this host.
+ * RFC 1002 4.2.13.  POSITIVE NAME QUERY RESPONSE
+ * RFC 1002 4.2.14.  NEGATIVE NAME QUERY RESPONSE
  */
 static int
-smb_send_name_query_response(struct addr_entry *addr,
+smb_send_name_query_response(addr_entry_t *addr,
     struct name_packet *original_packet, struct name_entry *entry,
-    unsigned short rcode)
+    uint16_t rcode)
 {
-	struct addr_entry 	*raddr;
+	addr_entry_t		*raddr;
 	struct name_packet	packet;
 	struct resource_record	answer;
-	unsigned short		attr;
+	uint16_t		attr;
 	unsigned char 		data[MAX_DATAGRAM_LENGTH];
 	unsigned char 		*scan = data;
 	uint32_t		ret_addr;
@@ -1989,141 +1376,10 @@
 }
 
 /*
- * 4.2.18.  NODE STATUS RESPONSE
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_TRN_ID           |1|  0x0  |1|0|0|0|0 0|0|  0x0  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0001              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          0x0000               |           0x0000              |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   /                            RR_NAME                            /
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |        NBSTAT (0x0021)        |         IN (0x0001)           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                          0x00000000                           |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |          RDLENGTH             |   NUM_NAMES   |               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               +
- *   |                                                               |
- *   +                                                               +
- *   /                         NODE_NAME ARRAY                       /
- *   +                                                               +
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   +                                                               +
- *   /                           STATISTICS                          /
- *   +                                                               +
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries
- *   of NODE_NAME records.  Each NODE_NAME entry represents an active
- *   name in the same NetBIOS scope as the requesting name in the
- *   local name table of the responder.  RR_NAME is the requesting
- *   name.
- *
- *   NODE_NAME Entry:
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                                                               |
- *   +---                                                         ---+
- *   |                                                               |
- *   +---                    NETBIOS FORMAT NAME                  ---+
- *   |                                                               |
- *   +---                                                         ---+
- *   |                                                               |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |         NAME_FLAGS            |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- *   The NAME_FLAGS field:
- *
- *                                             1   1   1   1   1   1
- *     0   1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
- *   +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
- *   | G |  ONT  |DRG|CNF|ACT|PRM|          RESERVED                 |
- *   +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
- *
- *   The NAME_FLAGS field is defined as:
- *
- *   Symbol     Bit(s)   Description:
- *
- *   RESERVED     7-15   Reserved for future use.  Must be zero (0).
- *   PRM             6   Permanent Name Flag.  If one (1) then entry
- *                       is for the permanent node name.  Flag is zero
- *                       (0) for all other names.
- *   ACT             5   Active Name Flag.  All entries have this flag
- *                       set to one (1).
- *   CNF             4   Conflict Flag.  If one (1) then name on this
- *                       node is in conflict.
- *   DRG             3   Deregister Flag.  If one (1) then this name
- *                       is in the process of being deleted.
- *   ONT           1,2   Owner Node Type:
- *                          00 = B node
- *                          01 = P node
- *                          10 = M node
- *                          11 = Reserved for future use
- *   G               0   Group Name Flag.
- *                       If one (1) then the name is a GROUP NetBIOS
- *                       name.
- *                       If zero (0) then it is a UNIQUE NetBIOS name.
+ * RFC 1002 4.2.18.  NODE STATUS RESPONSE
  */
-#define	NAME_FLAGS_PERMANENT_NAME	0x0200
-#define	NAME_FLAGS_ACTIVE_NAME		0x0400
-#define	NAME_FLAGS_CONFLICT		0x0800
-#define	NAME_FLAGS_DEREGISTER		0x1000
-#define	NAME_FLAGS_ONT_MASK		0x6000
-#define	NAME_FLAGS_ONT_B_NODE		0x0000
-#define	NAME_FLAGS_ONT_P_NODE		0x2000
-#define	NAME_FLAGS_ONT_M_NODE		0x4000
-#define	NAME_FLAGS_ONT_RESERVED		0x6000
-#define	NAME_FLAGS_GROUP_NAME		0x8000
-
-
-/*
- *   STATISTICS Field of the NODE STATUS RESPONSE:
- *
- *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
- *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |               UNIT_ID (Unique unit ID)                        |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |       UNIT_ID,continued       |    JUMPERS    |  TEST_RESULT  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |       VERSION_NUMBER          |      PERIOD_OF_STATISTICS     |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |       NUMBER_OF_CRCs          |     NUMBER_ALIGNMENT_ERRORS   |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |       NUMBER_OF_COLLISIONS    |        NUMBER_SEND_ABORTS     |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                       NUMBER_GOOD_SENDS                       |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |                      NUMBER_GOOD_RECEIVES                     |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |       NUMBER_RETRANSMITS      | NUMBER_NO_RESOURCE_CONDITIONS |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |  NUMBER_FREE_COMMAND_BLOCKS   |  TOTAL_NUMBER_COMMAND_BLOCKS  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |MAX_TOTAL_NUMBER_COMMAND_BLOCKS|    NUMBER_PENDING_SESSIONS    |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |  MAX_NUMBER_PENDING_SESSIONS  |  MAX_TOTAL_SESSIONS_POSSIBLE  |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *   |   SESSION_DATA_PACKET_SIZE    |
- *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-#define	MAX_NETBIOS_REPLY_DATA_SIZE	500
-
 static int
-smb_send_node_status_response(struct addr_entry *addr,
+smb_send_node_status_response(addr_entry_t *addr,
     struct name_packet *original_packet)
 {
 	uint32_t		net_ipaddr;
@@ -2265,152 +1521,14 @@
 	return (smb_send_name_service_packet(addr, &packet));
 }
 
-/*
- *
- * 5.1.  NAME SERVICE PROTOCOLS
- *
- *   A REQUEST packet is always sent to the well known UDP port -
- *   NAME_SERVICE_UDP_PORT.  The destination address is normally
- *   either the IP broadcast address or the address of the NAME - the
- *   address of the NAME server it set up at initialization time.  In
- *   rare cases, a request packet will be sent to an end node, e.g.  a
- *   NAME QUERY REQUEST sent to "challenge" a node.
- *
- *   A RESPONSE packet is always sent to the source UDP port and
- *   source IP address of the request packet.
- *
- *   A DEMAND packet must always be sent to the well known UDP port -
- *   NAME_SERVICE_UDP_PORT.  There is no restriction on the target IP
- *   address.
- *
- *   Terms used in this section:
- *
- *   tid -            Transaction ID.  This is a value composed from
- *                    the requestor's IP address and a unique 16 bit
- *                    value generated by the originator of the
- *                    transaction.
- */
-
-
-/*
- *
- * 5.1.1.  B-NODE ACTIVITY
- *
- * 5.1.1.1.  B-NODE ADD NAME
- *
- *   PROCEDURE add_name(name)
- *
- *   (*
- *    * Host initiated processing for a B node
- *    *)
- *   BEGIN
- *
- *        REPEAT
- *
- *             (* build name service packet *)
- *
- *             ONT = B_NODE; (* broadcast node *)
- *             G = UNIQUE;   (* unique name *)
- *             TTL = 0;
- *
- *             broadcast NAME REGISTRATION REQUEST packet;
- *
- *             (*
- *              * remote node(s) will send response packet
- *              * if applicable
- *              *)
- *             pause(BCAST_REQ_RETRY_TIMEOUT);
- *
- *        UNTIL response packet is received or
- *             retransmit count has been exceeded
- *
- *        IF no response packet was received THEN
- *        BEGIN (* no response *)
- *             (*
- *              * Build packet
- *              *)
- *
- *             ONT = B_NODE; (* broadcast node *)
- *             G = UNIQUE;   (* unique name *)
- *             TTL = 0;
- *
- *             (*
- *              * Let other nodes known you have the name
- *              *)
- *
- *             broadcast NAME UPDATE REQUEST packet;
- *             (* name can be added to local name table *)
- *             return success;
- *        END (* no response *)
- *        ELSE
- *        BEGIN (* got response *)
- *
- *             (*
- *              * Match return transaction id
- *              * against tid sent in request
- *              *)
- *
- *            IF NOT response tid = request tid THEN
- *            BEGIN
- *             ignore response packet;
- *            END
- *            ELSE
- *            CASE packet type OF
- *
- *            NEGATIVE NAME REGISTRATION RESPONSE:
- *
- *                 return failure; (* name cannot be added *)
- *
- *            POSITIVE NAME REGISTRATION RESPONSE:
- *            END-NODE CHALLENGE NAME REGISTRATION RESPONSE:
- *
- *                 (*
- *                  * B nodes should normally not get this
- *                  * response.
- *                  *)
- *
- *                  ignore packet;
- *            END (* case *);
- *        END (* got response *)
- *   END (* procedure *)
- *
- *
- *
- * 5.1.1.2.  B-NODE ADD_GROUP NAME
- *
- *   PROCEDURE add_group_name(name)
- *
- *   (*
- *    * Host initiated processing for a B node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * same as for a unique name with the
- *         * exception that the group bit (G) must
- *         * be set in the request packets.
- *         *)
- *
- *        ...
- *        G = GROUP;
- *        ...
- *        ...
- *
- *        (*
- *         * broadcast request ...
- *         *)
- *
- *
- *   END
- */
 static int
 smb_name_Bnode_add_name(struct name_entry *name)
 {
 	struct name_question		question;
 	struct resource_record		additional;
 	unsigned char 			data[8];
-	unsigned short			attr;
-	struct addr_entry *addr;
+	uint16_t			attr;
+	addr_entry_t			*addr;
 	int rc = 0;
 
 	addr = &name->addr_list;
@@ -2447,68 +1565,6 @@
 	return (rc);
 }
 
-/*
- * 5.1.1.3.  B-NODE FIND_NAME
- *
- *   PROCEDURE find_name(name)
- *
- *   (*
- *    * Host initiated processing for a B node
- *    *)
- *
- *   BEGIN
- *
- *        REPEAT
- *             (*
- *              * build packet
- *              *)
- *             ONT = B;
- *             TTL = 0;
- *             G = DONT CARE;
- *			raddr = raddr->forw;
- *
- *             broadcast NAME QUERY REQUEST packet;
- *             (*
- *              * a node might send response packet
- *              *)
- *
- *             pause(BCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL response packet received OR
- *             max transmit threshold exceeded
- *
- *        IF no response packet received THEN
- *             return failure;
- *        ELSE
- *        IF NOT response tid = request tid THEN
- *             ignore packet;
- *        ELSE
- *        CASE packet type OF
- *        POSITIVE NAME QUERY RESPONSE:
- *             (*
- *              * Start a timer to detect conflict.
- *              *
- *              * Be prepared to detect conflict if
- *              * any more response packets are received.
- *              *
- *              *)
- *
- *             save response as authoritative response;
- *             start_timer(CONFLICT_TIMER);
- *             return success;
- *
- *        NEGATIVE NAME QUERY RESPONSE:
- *        REDIRECT NAME QUERY RESPONSE:
- *
- *             (*
- *              * B Node should normally not get either
- *              * response.
- *              *)
- *
- *              ignore response packet;
- *
- *        END (* case *)
- *   END (* procedure *)
- */
 static int
 smb_name_Bnode_find_name(struct name_entry *name)
 {
@@ -2521,42 +1577,14 @@
 	return (smb_send_name_query_request(BROADCAST, &question));
 }
 
-/*
- * 5.1.1.4.  B NODE NAME RELEASE
- *
- *   PROCEDURE delete_name (name)
- *   BEGIN
- *
- *        REPEAT
- *
- *             (*
- *              * build packet
- *              *)
- *             ...
- *
- *             (*
- *              * send request
- *              *)
- *
- *             broadcast NAME RELEASE REQUEST packet;
- *
- *             (*
- *              * no response packet expected
- *              *)
- *
- *             pause(BCAST_REQ_RETRY_TIMEOUT);
- *
- *        UNTIL retransmit count has been exceeded
- *   END (* procedure *)
- */
 static int
 smb_name_Bnode_delete_name(struct name_entry *name)
 {
 	struct name_question	question;
 	struct resource_record	additional;
-	struct addr_entry 	*raddr;
-	unsigned char 		data[MAX_DATAGRAM_LENGTH];
-	unsigned char 		*scan = data;
+	addr_entry_t		*raddr;
+	unsigned char		data[MAX_DATAGRAM_LENGTH];
+	unsigned char		*scan = data;
 	uint32_t		attr;
 	uint32_t		ret_addr;
 
@@ -2591,212 +1619,14 @@
 	    &question, &additional));
 }
 
-/*
- *
- * 5.1.2.  P-NODE ACTIVITY
- *
- *   All packets sent or received by P nodes are unicast UDP packets.
- *   A P node sends name service requests to the NAME node that is
- *   specified in the P-node configuration.
- *
- * 5.1.2.1.  P-NODE ADD_NAME
- *
- *   PROCEDURE add_name(name)
- *
- *   (*
- *    * Host initiated processing for a P node
- *    *)
- *
- *   BEGIN
- *
- *        REPEAT
- *             (*
- *              * build packet
- *              *)
- *
- *             ONT = P;
- *             G = UNIQUE;
- *             ...
- *
- *             (*
- *              * send request
- *              *)
- *
- *             unicast NAME REGISTRATION REQUEST packet;
- *
- *             (*
- *              * NAME will send response packet
- *              *)
- *
- *             IF receive a WACK RESPONSE THEN
- *                  pause(time from TTL field of response);
- *             ELSE
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL response packet is received OR
- *             retransmit count has been exceeded
- *
- *        IF no response packet was received THEN
- *        BEGIN (* no response *)
- *             (*
- *              * NAME is down.  Cannot claim name.
- *              *)
- *
- *             return failure; (* name cannot be claimed *)
- *        END (* no response *)
- *        ELSE
- *        BEGIN (* response *)
- *            IF NOT response tid = request tid THEN
- *            BEGIN
- *             (*  Packet may belong to another transaction  *)
- *             ignore response packet;
- *            END
- *            ELSE
- *            CASE packet type OF
- *
- *            POSITIVE NAME REGISTRATION RESPONSE:
- *
- *                 (*
- *                  * name can be added
- *                  *)
- *
- *                 adjust refresh timeout value, TTL, for this name;
- *                 return success;      (* name can be added *)
- *
- *            NEGATIVE NAME REGISTRATION RESPONSE:
- *                 return failure; (* name cannot be added *)
- *
- *            END-NODE CHALLENGE REGISTRATION REQUEST:
- *            BEGIN (* end node challenge *)
- *
- *                 (*
- *                  * The response packet has in it the
- *                  * address of the presumed owner of the
- *                  * name.  Challenge that owner.
- *                  * If owner either does not
- *                  * respond or indicates that he no longer
- *                  * owns the name, claim the name.
- *                  * Otherwise, the name cannot be claimed.
- *                  *
- *                  *)
- *
- *                 REPEAT
- *                  (*
- *                   * build packet
- *                   *)
- *                  ...
- *
- *                  unicast NAME QUERY REQUEST packet to the
- *                       address contained in the END NODE
- *                       CHALLENGE RESPONSE packet;
- *
- *                  (*
- *                   * remote node may send response packet
- *                   *)
- *
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *
- *                 UNTIL response packet is received or
- *                     retransmit count has been exceeded
- *                 IF no response packet is received OR
- *                       NEGATIVE NAME QUERY RESPONSE packet
- *                       received THEN
- *                 BEGIN (* update *)
- *
- *                  (*
- *                   * name can be claimed
- *                   *)
- *
- *                  REPEAT
- *
- *                      (*
- *                       * build packet
- *                       *)
- *                       ...
- *
- *                      unicast NAME UPDATE REQUEST to NAME;
- *
- *                      (*
- *                       * NAME node will send response packet
- *                       *)
- *
- *                      IF receive a WACK RESPONSE THEN
- *                            pause(time from TTL field of response);
- *                      ELSE
- *                            pause(UCAST_REQ_RETRY_TIMEOUT);
- *                  UNTIL response packet is received or
- *                      retransmit count has been exceeded
- *                  IF no response packet received THEN
- *                  BEGIN (* no response *)
- *
- *                       (*
- *                        * name could not be claimed
- *                        *)
- *
- *                       return failure;
- *                  END (* no response *)
- *                  ELSE
- *                  CASE packet type OF
- *                       POSITIVE NAME REGISTRATION RESPONSE:
- *                            (*
- *                             * add name
- *                             *)
- *                            return success;
- *                       NEGATIVE NAME REGISTRATION RESPONSE:
- *
- *                            (*
- *                             * you lose  ...
- *                             *)
- *                            return failure;
- *                       END (* case *)
- *                 END (* update *)
- *                 ELSE
- *
- *                 (*
- *                  * received a positive response to the "challenge"
- *                  * Remote node still has name
- *                  *)
- *
- *                  return failure;
- *            END (* end node challenge *)
- *        END (* response *)
- *   END (* procedure *)
- *
- *
- * 5.1.2.2.  P-NODE ADD GROUP NAME
- *
- *   PROCEDURE add_group_name(name)
- *
- *   (*
- *    * Host initiated processing for a P node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * same as for a unique name, except that the
- *         * request packet must indicate that a
- *         * group name claim is being made.
- *         *)
- *
- *        ...
- *        G = GROUP;
- *        ...
- *
- *        (*
- *         * send packet
- *         *)
- *         ...
- *
- *
- *   END
- */
 static int
 smb_name_Pnode_add_name(struct name_entry *name)
 {
 	struct name_question		question;
 	struct resource_record		additional;
 	unsigned char 			data[8];
-	unsigned short			attr;
-	struct addr_entry *addr;
+	uint16_t			attr;
+	addr_entry_t			*addr;
 	int rc = 0;
 
 	/* build packet */
@@ -2835,8 +1665,8 @@
 	struct name_question		question;
 	struct resource_record		additional;
 	unsigned char 			data[8];
-	unsigned short			attr;
-	struct addr_entry *addr;
+	uint16_t			attr;
+	addr_entry_t			*addr;
 	int rc = 0;
 
 	/* build packet */
@@ -2868,63 +1698,6 @@
 	return (rc);
 }
 
-/*
- * 5.1.2.3.  P-NODE FIND NAME
- *
- *   PROCEDURE find_name(name)
- *
- *   (*
- *    * Host initiated processing for a P node
- *    *)
- *
- *   BEGIN
- *        REPEAT
- *             (*
- *              * build packet
- *              *)
- *
- *             ONT = P;
- *             G = DONT CARE;
- *
- *             unicast NAME QUERY REQUEST packet;
- *
- *             (*
- *              * a NAME node might send response packet
- *              *)
- *
- *             IF receive a WACK RESPONSE THEN
- *                  pause(time from TTL field of response);
- *             ELSE
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL response packet received OR
- *             max transmit threshold exceeded
- *
- *        IF no response packet received THEN
- *             return failure;
- *        ELSE
- *        IF NOT response tid = request tid THEN
- *             ignore packet;
- *        ELSE
- *        CASE packet type OF
- *        POSITIVE NAME QUERY RESPONSE:
- *             return success;
- *
- *        REDIRECT NAME QUERY RESPONSE:
- *
- *             (*
- *              * NAME node wants this end node
- *              * to use some other NAME node
- *              * to resolve the query.
- *              *)
- *
- *              repeat query with NAME address
- *                  in the response packet;
- *        NEGATIVE NAME QUERY RESPONSE:
- *             return failure;
- *
- *        END (* case *)
- *   END (* procedure *)
- */
 static int
 smb_name_Pnode_find_name(struct name_entry *name)
 {
@@ -2941,59 +1714,14 @@
 	return (smb_send_name_query_request(UNICAST, &question));
 }
 
-/*
- * 5.1.2.4.  P-NODE DELETE_NAME
- *
- *   PROCEDURE delete_name (name)
- *
- *   (*
- *    * Host initiated processing for a P node
- *    *)
- *
- *   BEGIN
- *
- *        REPEAT
- *
- *             (*
- *              * build packet
- *              *)
- *             ...
- *
- *             (*
- *              * send request
- *              *)
- *
- *             unicast NAME RELEASE REQUEST packet;
- *             IF receive a WACK RESPONSE THEN
- *                  pause(time from TTL field of response);
- *             ELSE
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL retransmit count has been exceeded
- *             or response been received
- *
- *        IF response has been received THEN
- *        CASE packet type OF
- *        POSITIVE NAME RELEASE RESPONSE:
- *             return success;
- *        NEGATIVE NAME RELEASE RESPONSE:
- *
- *             (*
- *              * NAME does want node to delete this
- *              * name !!!
- *              *)
- *
- *             return failure;
- *        END (* case *)
- *   END (* procedure *)
- */
 static int
 smb_name_Pnode_delete_name(struct name_entry *name)
 {
 	struct name_question	question;
 	struct resource_record	additional;
-	struct addr_entry 	*raddr;
-	unsigned char 		data[MAX_DATAGRAM_LENGTH];
-	unsigned char 		*scan = data;
+	addr_entry_t		*raddr;
+	unsigned char		data[MAX_DATAGRAM_LENGTH];
+	unsigned char		*scan = data;
 	uint32_t		attr;
 	uint32_t		ret_addr;
 
@@ -3031,254 +1759,6 @@
 	return (1);
 }
 
-/*
- * 5.1.3.  M-NODE ACTIVITY
- *
- *   M nodes behavior is similar to that of P nodes with the addition
- *   of some B node-like broadcast actions.  M node name service
- *   proceeds in two steps:
- *
- *   1.Use broadcast UDP based name service.  Depending on the
- *     operation, goto step 2.
- *
- *   2.Use directed UDP name service.
- *
- *   The following code for M nodes is exactly the same as for a P
- *   node, with the exception that broadcast operations are done
- *   before P type operation is attempted.
- *
- * 5.1.3.1.  M-NODE ADD NAME
- *
- *   PROCEDURE add_name(name)
- *
- *   (*
- *    * Host initiated processing for a M node
- *    *)
- *
- *   BEGIN
- *
- *        (*
- *         * check if name exists on the
- *         * broadcast area
- *         *)
- *        REPEAT
- *            (* build packet *)
- *
- *            ....
- *            broadcast NAME REGISTRATION REQUEST packet;
- *            pause(BCAST_REQ_RETRY_TIMEOUT);
- *
- *        UNTIL response packet is received or
- *             retransmit count has been  exceeded
- *
- *        IF valid response received THEN
- *        BEGIN
- *             (* cannot claim name *)
- *
- *             return failure;
- *        END
- *
- *        (*
- *         * No objections received within the
- *         * broadcast area.
- *         * Send request to name server.
- *         *)
- *
- *        REPEAT
- *             (*
- *              * build packet
- *              *)
- *
- *             ONT = M;
- *             ...
- *
- *             unicast NAME REGISTRATION REQUEST packet;
- *
- *             (*
- *              * remote NAME will send response packet
- *              *)
- *
- *             IF receive a WACK RESPONSE THEN
- *                  pause(time from TTL field of response);
- *             ELSE
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *
- *        UNTIL response packet is received or
- *             retransmit count has been exceeded
- *
- *        IF no response packet was received THEN
- *        BEGIN (* no response *)
- *             (*
- *              * NAME is down.  Cannot claim name.
- *              *)
- *             return failure; (* name cannot be claimed *)
- *        END (* no response *)
- *        ELSE
- *        BEGIN (* response *)
- *            IF NOT response tid = request tid THEN
- *            BEGIN
- *             ignore response packet;
- *            END
- *            ELSE
- *            CASE packet type OF
- *            POSITIVE NAME REGISTRATION RESPONSE:
- *
- *                 (*
- *                  * name can be added
- *                  *)
- *
- *                 adjust refresh timeout value, TTL;
- *                 return success;      (* name can be added *)
- *
- *            NEGATIVE NAME REGISTRATION RESPONSE:
- *                 return failure; (* name cannot be added *)
- *
- *            END-NODE CHALLENGE REGISTRATION REQUEST:
- *            BEGIN (* end node challenge *)
- *
- *                 (*
- *                  * The response packet has in it the
- *                  * address of the presumed owner of the
- *                  * name.  Challenge that owner.
- *                  * If owner either does not
- *                  * respond or indicates that he no longer
- *                  * owns the name, claim the name.
- *                  * Otherwise, the name cannot be claimed.
- *                  *
- *                  *)
- *
- *                 REPEAT
- *                  (*
- *                   * build packet
- *                   *)
- *                  ...
- *
- *                  (*
- *                   * send packet to address contained in the
- *                   * response packet
- *                   *)
- *
- *                  unicast NAME QUERY REQUEST packet;
- *
- *                  (*
- *                   * remote node may send response packet
- *                   *)
- *
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *
- *                 UNTIL response packet is received or
- *                     retransmit count has been exceeded
- *                 IF no response packet is received THEN
- *                 BEGIN (* no response *)
- *
- *                  (*
- *                   * name can be claimed
- *                   *)
- *                  REPEAT
- *
- *                      (*
- *                       * build packet
- *                       *)
- *                       ...
- *
- *                      unicast NAME UPDATE REQUEST to NAME;
- *
- *                      (*
- *                       * NAME node will send response packet
- *                       *)
- *
- *                      IF receive a WACK RESPONSE THEN
- *                            pause(time from TTL field of response);
- *                  ELSE
- *                       pause(UCAST_REQ_RETRY_TIMEOUT);
- *
- *                  UNTIL response packet is received or
- *                      retransmit count has been exceeded
- *                  IF no response packet received THEN
- *                  BEGIN (* no response *)
- *
- *                       (*
- *                        * name could not be claimed
- *                        *)
- *
- *                       return failure;
- *                  END (* no response *)
- *                  ELSE
- *                  CASE packet type OF
- *                  POSITIVE NAME REGISTRATION RESPONSE:
- *                       (*
- *                        * add name
- *                        *)
- *
- *                       return success;
- *                  NEGATIVE NAME REGISTRATION RESPONSE:
- *                       (*
- *                        * you lose  ...
- *                        *)
- *
- *                       return failure;
- *                  END (* case *)
- *                 END (* no response *)
- *                 ELSE
- *                 IF NOT response tid = request tid THEN
- *                 BEGIN
- *                  ignore response packet;
- *                 END
- *
- *                 (*
- *                  * received a response to the "challenge"
- *                  * packet
- *                  *)
- *
- *                 CASE packet type OF
- *                 POSITIVE NAME QUERY:
- *
- *                  (*
- *                   * remote node still has name.
- *                   *)
- *
- *                  return failure;
- *                 NEGATIVE NAME QUERY:
- *
- *                  (*
- *                   * remote node no longer has name
- *                   *)
- *
- *                  return success;
- *                 END (* case *)
- *            END (* end node challenge *)
- *            END (* case *)
- *        END (* response *)
- *   END (* procedure *)
- *
- *
- * 5.1.3.2.  M-NODE ADD GROUP NAME
- *
- *   PROCEDURE add_group_name(name)
- *
- *   (*
- *    * Host initiated processing for a P node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * same as for a unique name, except that the
- *         * request packet must indicate that a
- *         * group name claim is being made.
- *         *)
- *
- *        ...
- *        G = GROUP;
- *        ...
- *
- *        (*
- *         * send packet
- *         *)
- *         ...
- *
- *
- *   END
- */
 static int
 smb_name_Mnode_add_name(struct name_entry *name)
 {
@@ -3302,89 +1782,6 @@
 	return (smb_name_Bnode_add_name(name));
 }
 
-/*
- * 5.1.3.3.  M-NODE FIND NAME
- *
- *   PROCEDURE find_name(name)
- *
- *   (*
- *    * Host initiated processing for a M node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * check if any node on the broadcast
- *         * area has the name
- *         *)
- *
- *        REPEAT
- *             (* build packet *)
- *             ...
- *
- *             broadcast NAME QUERY REQUEST packet;
- *             pause(BCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL response packet received OR
- *             max transmit threshold exceeded
- *
- *        IF valid response received THEN
- *        BEGIN
- *             save response as authoritative response;
- *             start_timer(CONFLICT_TIMER);
- *             return success;
- *        END
- *
- *        (*
- *         * no valid response on the b'cast segment.
- *         * Try the name server.
- *         *)
- *
- *        REPEAT
- *             (*
- *              * build packet
- *              *)
- *
- *             ONT = M;
- *             G = DONT CARE;
- *
- *             unicast NAME QUERY REQUEST packet to NAME;
- *
- *             (*
- *              * a NAME node might send response packet
- *              *)
- *
- *             IF receive a WACK RESPONSE THEN
- *                  pause(time from TTL field of response);
- *             ELSE
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL response packet received OR
- *             max transmit threshold exceeded
- *
- *        IF no response packet received THEN
- *             return failure;
- *        ELSE
- *        IF NOT response tid = request tid THEN
- *             ignore packet;
- *        ELSE
- *        CASE packet type OF
- *        POSITIVE NAME QUERY RESPONSE:
- *             return success;
- *
- *        REDIRECT NAME QUERY RESPONSE:
- *
- *             (*
- *              * NAME node wants this end node
- *              * to use some other NAME node
- *              * to resolve the query.
- *              *)
- *
- *              repeat query with NAME address
- *                  in the response packet;
- *        NEGATIVE NAME QUERY RESPONSE:
- *             return failure;
- *
- *        END (* case *)
- *   END (* procedure *)
- */
 static int
 smb_name_Mnode_find_name(struct name_entry *name)
 {
@@ -3407,68 +1804,6 @@
 	return (smb_name_Bnode_find_name(name));
 }
 
-/*
- * 5.1.3.4.  M-NODE DELETE NAME
- *
- *   PROCEDURE delete_name (name)
- *
- *   (*
- *    * Host initiated processing for a P node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * First, delete name on NAME
- *         *)
- *
- *        REPEAT
- *
- *             (*
- *              * build packet
- *	struct addr_entry *addr;
- *              *)
- *             ...
- *
- *             (*
- *              * send request
- *              *)
- *
- *             unicast NAME RELEASE REQUEST packet to NAME;
- *
- *             IF receive a WACK RESPONSE THEN
- *                  pause(time from TTL field of response);
- *             ELSE
- *                  pause(UCAST_REQ_RETRY_TIMEOUT);
- *        UNTIL retransmit count has been exceeded
- *             or response been received
- *
- *        IF response has been received THEN
- *        CASE packet type OF
- *        POSITIVE NAME RELEASE RESPONSE:
- *             (*
- *              * Deletion of name on b'cast segment is deferred
- *              * until after NAME has deleted the name
- *              *)
- *
- *             REPEAT
- *                  (* build packet *)
- *
- *                  ...
- *                  broadcast NAME RELEASE REQUEST;
- *                  pause(BCAST_REQ_RETRY_TIMEOUT);
- *             UNTIL rexmt threshold exceeded
- *
- *             return success;
- *        NEGATIVE NAME RELEASE RESPONSE:
- *
- *             (*
- *              * NAME does want node to delete this
- *              * name
- *              *)
- *             return failure;
- *        END (* case *)
- *   END (* procedure *)
- */
 static int
 smb_name_Mnode_delete_name(struct name_entry *name)
 {
@@ -3493,146 +1828,8 @@
 	return (smb_name_Bnode_delete_name(name));
 }
 
-/*
- * 5.1.1.5.  B-NODE INCOMING PACKET PROCESSING
- *
- *   Following processing is done when broadcast or unicast packets
- *   are received at the NAME_SERVICE_UDP_PORT.
- *
- *   PROCEDURE process_incoming_packet(packet)
- *
- *   (*
- *    * Processing initiated by incoming packets for a B node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * Note: response packets are always sent
- *         * to:
- *         * source IP address of request packet
- *         * source UDP port of request packet
- *         *)
- *
- *        CASE packet type OF
- *
- *        NAME REGISTRATION REQUEST (UNIQUE):
- *             IF name exists in local name table THEN
- *                  send NEGATIVE_NAME_REGISTRATION_RESPONSE ;
- *        NAME REGISTRATION REQUEST (GROUP):
- *             IF name exists in local name table THEN
- *             BEGIN
- *                  IF local entry is a unique name THEN
- *                      send NEGATIVE_NAME_REGISTRATION_RESPONSE ;
- *             END
- *        NAME QUERY REQUEST:
- *             IF name exists in local name table THEN
- *             BEGIN
- *                  build response packet;
- *                  send POSITIVE_NAME_QUERY_RESPONSE;
- *        POSITIVE NAME QUERY RESPONSE:
- *             IF name conflict timer is not active THEN
- *                 BEGIN
- *                      (*
- *                       * timer has expired already...  ignore this
- *                       * packet
- *                       *)
- *
- *                      return;
- *                 END
- *             ELSE (* timer is active *)
- *                 IF a response for this name has previously been
- *                      received THEN
- *                     BEGIN (* existing entry *)
- *
- *                      (*
- *                       * we sent out a request packet, and
- *                       * have already received (at least)
- *                       * one response
- *                       *
- *                       * Check if conflict exists.
- *                       * If so, send out a conflict packet.
- *                       *
- *                       * Note: detecting conflict does NOT
- *                       * affect any existing sessions.
- *                       *
- *                       *)
- *
- *                      (*
- *                       * Check for name conflict.
- *                       * See "Name Conflict" in Concepts and Methods
- *                       *)
- *                      check saved authoritative response against
- *                           information in this response packet;
- *                      IF conflict detected THEN
- *                      BEGIN
- *                           unicast NAME CONFLICT DEMAND packet;
- *                           IF entry exists in cache THEN
- *                           BEGIN
- *                                remove entry from cache;
- *                           END
- *                      END
- *                 END (* existing entry *)
- *             ELSE
- *                 BEGIN
- *                      (*
- *                       * Note: If this was the first response
- *                       * to a name query, it would have been
- *                       * handled in the
- *                       * find_name() procedure.
- *                       *)
- *
- *                      ignore packet;
- *                 END
- *        NAME CONFLICT DEMAND:
- *             IF name exists in local name table THEN
- *             BEGIN
- *                  mark name as conflict detected;
- *
- *                  (*
- *                   * a name in the state "conflict detected"
- *                   * does not "logically" exist on that node.
- *                   * No further session will be accepted on
- *                   * that name.
- *                   * No datagrams can be sent against that name.
- *                   * Such an entry will not be used for
- *                   * purposes of processing incoming request
- *                   * packets.
- *                   * The only valid user NetBIOS operation
- *                   * against such a name is DELETE NAME.
- *                   *)
- *             END
- *        NAME RELEASE REQUEST:
- *             IF caching is being done THEN
- *             BEGIN
- *                  remove entry from cache;
- *             END
- *        NAME UPDATE REQUEST:
- *             IF caching is being done THEN
- *             BEGIN
- *                  IF entry exists in cache already,
- *                       update cache;
- *                  ELSE IF name is "interesting" THEN
- *                  BEGIN
- *                       add entry to cache;
- *                  END
- *             END
- *
- *        NODE STATUS REQUEST:
- *             IF name exists in local name table THEN
- *             BEGIN
- *                  (*
- *                   * send only those names that are
- *                   * in the same scope as the scope
- *                   * field in the request packet
- *                   *)
- *
- *                  send NODE STATUS RESPONSE;
- *             END
- *   END
- */
 static void
-smb_name_process_Bnode_packet(struct name_packet *packet,
-    struct addr_entry *addr)
+smb_name_process_Bnode_packet(struct name_packet *packet, addr_entry_t *addr)
 {
 	struct name_entry 	*name;
 	struct name_entry 	*entry;
@@ -3711,372 +1908,8 @@
 	}
 }
 
-/*
- * 5.1.2.5.  P-NODE INCOMING PACKET PROCESSING
- *
- *   Processing initiated by reception of packets at a P node
- *
- *   PROCEDURE process_incoming_packet(packet)
- *
- *   (*
- *    * Processing initiated by incoming packets at a P node
- *    *)
- *
- *   BEGIN
- *        (*
- *         * always ignore UDP broadcast packets
- *         *)
- *
- *        IF packet was sent as a broadcast THEN
- *        BEGIN
- *             ignore packet;
- *             return;
- *        END
- *        CASE packet type of
- *
- *        NAME CONFLICT DEMAND:
- *             IF name exists in local name table THEN
- *                  mark name as in conflict;
- *             return;
- *
- *        NAME QUERY REQUEST:
- *             IF name exists in local name table THEN
- *             BEGIN (* name exists *)
- *
- *                  (*
- *                   * build packet
- *                   *)
- *                  ...
- *
- *                  (*
- *                   * send response to the IP address and port
- *                   * number from which the request was received.
- *                   *)
- *
- *                  send POSITIVE_NAME_QUERY_RESPONSE ;
- *                  return;
- *             END (* exists *)
- *             ELSE
- *             BEGIN (* does not exist *)
- *
- *                  (*
- *                   * send response to the requestor
- *                   *)
- *
- *                  send NEGATIVE_NAME_QUERY_RESPONSE ;
- *                  return;
- *             END (* does not exist *)
- *        NODE STATUS REQUEST:
- *             (*
- *              * Name of "*" may be used for force node to
- *              * divulge status for administrative purposes
- *              *)
- *             IF name in local name table OR name = "*" THEN
- *             BEGIN
- *                  (*
- *                   * Build response packet and
- *                   * send to requestor node
- *                   * Send only those names that are
- *                   * in the same scope as the scope
- *                   * in the request packet.
- *                   *)
- *
- *                  send NODE_STATUS_RESPONSE;
- *             END
- *
- *        NAME RELEASE REQUEST:
- *             (*
- *              * This will be received if the NAME wants to flush the
- *              * name from the local name table, or from the local
- *              * cache.
- *              *)
- *
- *             IF name exists in the local name table THEN
- *             BEGIN
- *                  delete name from local name table;
- *                  inform user that name has been deleted;
- *             END
- *        END (* case *)
- *   END (* procedure *)
- *
- *   (*
- *    * Incoming packet processing on a NS node
- *    *)
- *
- *   BEGIN
- *        IF packet was sent as a broadcast THEN
- *        BEGIN
- *             discard packet;
- *             return;
- *        END
- *        CASE packet type of
- *
- *        NAME REGISTRATION REQUEST (UNIQUE):
- *             IF unique name exists in data base THEN
- *             BEGIN (* unique name exists *)
- *                  (*
- *                   * NAME node may be a "passive"
- *                   * server in that it expects the
- *                   * end node to do the challenge
- *                   * server.  Such a NAME node is
- *                   * called a "non-secure" server.
- *                   * A "secure" server will do the
- *                   * challenging before it sends
- *                   * back a response packet.
- *                   *)
- *
- *                  IF non-secure THEN
- *                  BEGIN
- *                       (*
- *                        * build response packet
- *                        *)
- *                       ...
- *
- *
- *                       (*
- *                        * let end node do the challenge
- *                        *)
- *
- *                       send END-NODE CHALLENGE NAME REGISTRATION
- *                            RESPONSE;
- *                       return;
- *                  END
- *                  ELSE
- *                  (*
- *                   * secure server - do the name
- *                   * challenge operation
- *                   *)
- *
- *                  REPEAT
- *                      send NAME QUERY REQUEST;
- *                      pause(UCAST_REQ_RETRY_TIMEOUT);
- *                  UNTIL response has been received or
- *                       retransmit count has been exceeded
- *                  IF no response was received THEN
- *                  BEGIN
- *
- *                       (* node down *)
- *
- *                       update data base - remove entry;
- *                       update data base - add new entry;
- *                       send POSITIVE NAME REGISTRATION RESPONSE;
- *                       return;
- *                  END
- *                  ELSE
- *                  BEGIN (* challenged node replied *)
- *                      (*
- *                       * challenged node replied with
- *                       * a response packet
- *                       *)
- *
- *                      CASE packet type
- *
- *                      POSITIVE NAME QUERY RESPONSE:
- *
- *                       (*
- *                        * name still owned by the
- *                        * challenged node
- *                        *
- *                        * build packet and send response
- *                        *)
- *                        ...
- *
- *
- *                       (*
- *                        * Note: The NAME will need to
- *                        * keep track (based on transaction id) of
- *                        * the IP address and port number
- *                        * of the original requestor.
- *                        *)
- *
- *                       send NEGATIVE NAME REGISTRATION RESPONSE;
- *                       return;
- *                      NEGATIVE NAME QUERY RESPONSE:
- *
- *                       update data base - remove entry;
- *                       update data base - add new  entry;
- *
- *                       (*
- *                        * build response packet and send
- *                        * response
- *                        *)
- *                       send POSITIVE NAME REGISTRATION RESPONSE;
- *                       return;
- *                      END (* case *)
- *                  END (* challenged node replied *)
- *             END (* unique name exists in data base *)
- *             ELSE
- *             IF group name exists in data base THEN
- *             BEGIN (* group names exists *)
- *
- *                  (*
- *                   * Members of a group name are NOT
- *                   * challenged.
- *                   * Make the assumption that
- *                   * at least some of the group members
- *                   * are still alive.
- *                   * Refresh mechanism will
- *                   * allow the NAME to detect when all
- *                   * members of a group no longer use that
- *                   * name
- *                   *)
- *
- *                   send NEGATIVE NAME REGISTRATION RESPONSE;
- *             END (* group name exists *)
- *             ELSE
- *             BEGIN (* name does not exist *)
- *
- *                  (*
- *                   * Name does not exist in data base
- *                   *
- *                   * This code applies to both non-secure
- *                   * and secure server.
- *                   *)
- *
- *                  update data base - add new entry;
- *                  send POSITIVE NAME REGISTRATION RESPONSE;
- *                  return;
- *             END
- *
- *        NAME QUERY REQUEST:
- *             IF name exists in data base THEN
- *             BEGIN
- *                  (*
- *                   * build response packet and send to
- *                   * requestor
- *                   *)
- *                   ...
- *
- *                  send POSITIVE NAME QUERY RESPONSE;
- *                  return;
- *             ELSE
- *             BEGIN
- *                  (*
- *                   * build response packet and send to
- *                   * requestor
- *                   *)
- *                   ...
- *
- *                  send NEGATIVE NAME QUERY RESPONSE;
- *                  return;
- *             END
- *
- *        NAME REGISTRATION REQUEST (GROUP):
- *             IF name exists in data base THEN
- *             BEGIN
- *                  IF local entry is a unique name THEN
- *                  BEGIN (* local is unique *)
- *
- *                      IF non-secure THEN
- *                      BEGIN
- *                       send  END-NODE CHALLENGE NAME
- *                            REGISTRATION RESPONSE;
- *                       return;
- *                      END
- *
- *                      REPEAT
- *                       send NAME QUERY REQUEST;
- *                       pause(UCAST_REQ_RETRY_TIMEOUT);
- *                      UNTIL response received or
- *                           retransmit count exceeded
- *                      IF no response received or
- *                           NEGATIVE NAME QUERY RESPONSE
- *                            received THEN
- *                      BEGIN
- *                       update data base - remove entry;
- *                       update data base - add new entry;
- *                       send POSITIVE NAME REGISTRATION RESPONSE;
- *                       return;
- *                      END
- *                      ELSE
- *                      BEGIN
- *                       (*
- *                        * name still being held
- *                        * by challenged node
- *                        *)
- *
- *                        send NEGATIVE NAME REGISTRATION RESPONSE;
- *                      END
- *                  END (* local is unique *)
- *                  ELSE
- *                  BEGIN (* local is group  *)
- *                       (*
- *                        * existing entry is a group name
- *                        *)
- *
- *                       update data base - remove entry;
- *                       update data base - add new entry;
- *                       send POSITIVE NAME REGISTRATION RESPONSE;
- *                       return;
- *                  END (* local is group *)
- *             END (* names exists *)
- *             ELSE
- *             BEGIN (* does not exist *)
- *
- *                  (* name does not exist in data base *)
- *
- *                  update data base - add new entry;
- *                  send POSITIVE NAME REGISTRATION RESPONSE;
- *                  return;
- *             END (* does not exist *)
- *
- *        NAME RELEASE REQUEST:
- *
- *             (*
- *              * secure server may choose to disallow
- *              * a node from deleting a name
- *              *)
- *
- *             update data base - remove entry;
- *             send POSITIVE NAME RELEASE RESPONSE;
- *             return;
- *
- *        NAME UPDATE REQUEST:
- *
- *             (*
- *              * End-node completed a successful challenge,
- *              * no update database
- *              *)
- *
- *             IF secure server THEN
- *                  send NEGATIVE NAME REGISTRATION RESPONSE;
- *             ELSE
- *             BEGIN (* new entry *)
- *                  IF entry already exists THEN
- *                       update data base - remove entry;
- *                  update data base - add new entry;
- *                  send POSITIVE NAME REGISTRATION RESPONSE;
- *                  start_timer(TTL);
- *             END
- *
- *        NAME REFRESH REQUEST:
- *             check for consistency;
- *
- *             IF node not allowed to have name THEN
- *             BEGIN
- *
- *                  (*
- *                   * tell end node that it can't have name
- *                   *)
- *                  send NEGATIVE NAME REGISTRATION RESPONSE;
- *             END
- *             ELSE
- *             BEGIN
- *
- *                  (*
- *                   * send confirmation response to the
- *                   * end node.
- *                   *)
- *                  send POSITIVE NAME REGISTRATION;
- *                  start_timer(TTL);
- *             END
- *             return;
- *        END (* case *)
- *   END (* procedure *)
- */
 static void
-smb_name_process_Pnode_packet(struct name_packet *packet,
-    struct addr_entry *addr)
+smb_name_process_Pnode_packet(struct name_packet *packet, addr_entry_t *addr)
 {
 	struct name_entry 	*name;
 	struct name_entry 	*entry;
@@ -4174,102 +2007,8 @@
 	}
 }
 
-/*
- * 5.1.3.5.  M-NODE INCOMING PACKET PROCESSING
- *
- *   Processing initiated by reception of packets at a M node
- *
- *   PROCEDURE process_incoming_packet(packet)
- *
- *   (*
- *    * Processing initiated by incoming packets at a M node
- *    *)
- *
- *   BEGIN
- *        CASE packet type of
- *
- *        NAME CONFLICT DEMAND:
- *             IF name exists in local name table THEN
- *                  mark name as in conflict;
- *             return;
- *
- *        NAME QUERY REQUEST:
- *             IF name exists in local name table THEN
- *             BEGIN (* name exists *)
- *
- *                  (*
- *                   * build packet
- *                   *)
- *                  ...
- *
- *                  (*
- *                   * send response to the IP address and port
- *                   * number from which the request was received.
- *                   *)
- *
- *                  send POSITIVE NAME QUERY RESPONSE ;
- *                  return;
- *             END (* exists *)
- *             ELSE
- *             BEGIN (* does not exist *)
- *
- *                  (*
- *                   * send response to the requestor
- *                   *)
- *
- *                  IF request NOT broadcast THEN
- *                       (*
- *                        * Don't send negative responses to
- *                        * queries sent by B nodes
- *                        *)
- *                       send NEGATIVE NAME QUERY RESPONSE ;
- *                  return;
- *             END (* does not exist *)
- *        NODE STATUS REQUEST:
- *             BEGIN
- *             (*
- *              * Name of "*" may be used to force node to
- *              * divulge status for administrative purposes
- *              *)
- *             IF name in local name table OR name = "*" THEN
- *                  (*
- *                   * Build response packet and
- *                   * send to requestor node
- *                   * Send only those names that are
- *                   * in the same scope as the scope
- *                   * in the request packet.
- *                   *)
- *
- *                  send NODE STATUS RESPONSE;
- *             END
- *
- *        NAME RELEASE REQUEST:
- *             (*
- *              * This will be received if the NAME wants to flush the
- *              * name from the local name table, or from the local
- *              * cache.
- *              *)
- *
- *             IF name exists in the local name table THEN
- *             BEGIN
- *                  delete name from local name table;
- *                  inform user that name has been deleted;
- *             END
- *        NAME REGISTRATION REQUEST (UNIQUE):
- *             IF name exists in local name table THEN
- *                  send NEGATIVE NAME REGISTRATION RESPONSE ;
- *        NAME REGISTRATION REQUEST (GROUP):
- *             IF name exists in local name table THEN
- *             BEGIN
- *                  IF local entry is a unique name THEN
- *                      send NEGATIVE NAME REGISTRATION RESPONSE ;
- *             END
- *        END (* case *)
- *   END (* procedure *)
- */
 static void
-smb_name_process_Mnode_packet(struct name_packet *packet,
-    struct addr_entry *addr)
+smb_name_process_Mnode_packet(struct name_packet *packet, addr_entry_t *addr)
 {
 	if (packet->info & NAME_NM_FLAGS_B)
 		smb_name_process_Bnode_packet(packet, addr);
@@ -4278,8 +2017,7 @@
 }
 
 static void
-smb_name_process_Hnode_packet(struct name_packet *packet,
-    struct addr_entry *addr)
+smb_name_process_Hnode_packet(struct name_packet *packet, addr_entry_t *addr)
 {
 	if (packet->info & NAME_NM_FLAGS_B)
 		smb_name_process_Bnode_packet(packet, addr);
@@ -4319,7 +2057,6 @@
 	smb_netbios_cache_reset_ttl();
 }
 
-
 /*
  * smb_name_find_name
  *
@@ -4368,7 +2105,7 @@
 {
 	int			rc = 1;
 
-	smb_netbios_name_dump(name);
+	smb_netbios_name_logf(name);
 
 	switch (smb_node_type) {
 	case 'B':
@@ -4399,9 +2136,8 @@
 	unsigned char type;
 
 	type = name->name[15];
-	if ((type != 0x00) && (type != 0x20)) {
-		syslog(LOG_ERR,
-		    "netbios: error trying to delete non-local name");
+	if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
+		syslog(LOG_DEBUG, "nbns: name delete bad type (0x%02x)", type);
 		smb_netbios_name_logf(name);
 		name->attributes &= ~NAME_ATTR_LOCAL;
 		return (-1);
@@ -4432,7 +2168,7 @@
 }
 
 typedef struct {
-	struct addr_entry *addr;
+	addr_entry_t *addr;
 	char *buf;
 	int length;
 } worker_param_t;
@@ -4447,16 +2183,16 @@
 smb_netbios_worker(void *arg)
 {
 	worker_param_t *p = (worker_param_t *)arg;
-	struct addr_entry *addr = p->addr;
+	addr_entry_t *addr = p->addr;
 	struct name_packet *packet;
 
-	if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != 0) {
+	if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != NULL) {
 		if (packet->info & NAME_OPCODE_R) {
 			/* Reply packet */
 			smb_reply_ready(packet, addr);
 			free(p->buf);
 			free(p);
-			return (0);
+			return (NULL);
 		}
 
 		/* Request packet */
@@ -4480,29 +2216,48 @@
 			smb_netbios_name_freeaddrs(packet->answer->name);
 		free(packet);
 	} else {
-		syslog(LOG_DEBUG, "SmbNBNS: error decoding received packet");
+		syslog(LOG_ERR, "nbns: packet decode failed");
 	}
 
 	free(addr);
 	free(p->buf);
 	free(p);
-	return (0);
+	return (NULL);
 }
 
+/*
+ * Configure the node type.  If a WINS server has been specified,
+ * act like an H-node.  Otherwise, behave like a B-node.
+ */
 static void
-smb_netbios_wins_config(char *ip)
+smb_netbios_node_config(void)
 {
-	uint32_t ipaddr;
+	static smb_cfg_id_t	wins[SMB_PI_MAX_WINS] = {
+		SMB_CI_WINS_SRV1,
+		SMB_CI_WINS_SRV2
+	};
+	char		ipstr[16];
+	uint32_t	ipaddr;
+	int		i;
 
-	ipaddr = inet_addr(ip);
-	if (ipaddr != INADDR_NONE) {
+	smb_node_type = SMB_NODETYPE_B;
+	nbns_num = 0;
+	bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS);
+
+	for (i = 0; i < SMB_PI_MAX_WINS; ++i) {
+		ipstr[0] = '\0';
+		(void) smb_config_getstr(wins[i], ipstr, sizeof (ipstr));
+
+		if ((ipaddr = inet_addr(ipstr)) == INADDR_NONE)
+			continue;
+
+		smb_node_type = SMB_NODETYPE_H;
 		smb_nbns[nbns_num].flags = ADDR_FLAG_VALID;
 		smb_nbns[nbns_num].sinlen = sizeof (struct sockaddr_in);
 		smb_nbns[nbns_num].sin.sin_family = AF_INET;
 		smb_nbns[nbns_num].sin.sin_addr.s_addr = ipaddr;
-		smb_nbns[nbns_num++].sin.sin_port =
-		    htons(NAME_SERVICE_UDP_PORT);
-		smb_node_type = SMB_NODETYPE_H;
+		smb_nbns[nbns_num].sin.sin_port = htons(IPPORT_NETBIOS_NS);
+		nbns_num++;
 	}
 }
 
@@ -4539,70 +2294,58 @@
 	}
 }
 
+/*
+ * Note that the node configuration must be setup before calling
+ * smb_init_name_struct().
+ */
 void
 smb_netbios_name_config(void)
 {
-	struct name_entry name;
-	char wins_ip[16];
-	smb_niciter_t ni;
-	int rc;
+	addr_entry_t		*bcast_entry;
+	struct name_entry	name;
+	smb_niciter_t		ni;
+	int			rc;
 
-	/* Start with no broadcast addresses */
+	(void) mutex_lock(&nbt_name_config_mtx);
+	smb_netbios_node_config();
+
 	bcast_num = 0;
 	bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS);
 
-	/* Add all of the broadcast addresses */
 	rc = smb_nic_getfirst(&ni);
 	while (rc == 0) {
-		if (ni.ni_nic.nic_smbflags &
-		    (SMB_NICF_ALIAS | SMB_NICF_NBEXCL)) {
+		if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
+		    (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS)) {
 			rc = smb_nic_getnext(&ni);
 			continue;
 		}
-		smb_bcast_list[bcast_num].flags = ADDR_FLAG_VALID;
-		smb_bcast_list[bcast_num].attributes = NAME_ATTR_LOCAL;
-		smb_bcast_list[bcast_num].sinlen = sizeof (struct sockaddr_in);
-		smb_bcast_list[bcast_num].sin.sin_family = AF_INET;
-		smb_bcast_list[bcast_num].sin.sin_port =
-		    htons(NAME_SERVICE_UDP_PORT);
-		smb_bcast_list[bcast_num++].sin.sin_addr.s_addr =
-		    ni.ni_nic.nic_bcast;
-		rc = smb_nic_getnext(&ni);
-	}
 
-	/* Start with no WINS */
-	smb_node_type = SMB_NODETYPE_B;
-	nbns_num = 0;
-	bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS);
-
-	/* add any configured WINS */
-	(void) smb_config_getstr(SMB_CI_WINS_SRV1, wins_ip, sizeof (wins_ip));
-	smb_netbios_wins_config(wins_ip);
-	(void) smb_config_getstr(SMB_CI_WINS_SRV2, wins_ip, sizeof (wins_ip));
-	smb_netbios_wins_config(wins_ip);
-
-	if (smb_nic_getfirst(&ni) != 0)
-		return;
-
-	do {
-		if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
-		    (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS))
-			continue;
+		bcast_entry = &smb_bcast_list[bcast_num];
+		bcast_entry->flags = ADDR_FLAG_VALID;
+		bcast_entry->attributes = NAME_ATTR_LOCAL;
+		bcast_entry->sinlen = sizeof (struct sockaddr_in);
+		bcast_entry->sin.sin_family = AF_INET;
+		bcast_entry->sin.sin_port = htons(IPPORT_NETBIOS_NS);
+		bcast_entry->sin.sin_addr.s_addr = ni.ni_nic.nic_bcast;
+		bcast_num++;
 
 		smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
-		    0x00, 0, ni.ni_nic.nic_ip.a_ipv4,
-		    htons(DGM_SRVC_UDP_PORT),
+		    NBT_WKSTA, 0, ni.ni_nic.nic_ip.a_ipv4,
+		    htons(IPPORT_NETBIOS_DGM),
 		    NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
 		(void) smb_netbios_cache_insert(&name);
 
 		smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
-		    0x20, 0, ni.ni_nic.nic_ip.a_ipv4,
-		    htons(DGM_SRVC_UDP_PORT),
+		    NBT_SERVER, 0, ni.ni_nic.nic_ip.a_ipv4,
+		    htons(IPPORT_NETBIOS_DGM),
 		    NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
 		(void) smb_netbios_cache_insert(&name);
-	} while (smb_nic_getnext(&ni) == 0);
+
+		rc = smb_nic_getnext(&ni);
+	}
 
 	smb_netbios_name_registration();
+	(void) mutex_unlock(&nbt_name_config_mtx);
 }
 
 void
@@ -4610,6 +2353,7 @@
 {
 	struct name_entry *name;
 
+	(void) mutex_lock(&nbt_name_config_mtx);
 	(void) mutex_lock(&delete_queue.mtx);
 	smb_netbios_cache_delete_locals(&delete_queue);
 
@@ -4619,6 +2363,7 @@
 		free(name);
 	}
 	(void) mutex_unlock(&delete_queue.mtx);
+	(void) mutex_unlock(&nbt_name_config_mtx);
 }
 
 void
@@ -4629,27 +2374,17 @@
 }
 
 /*
- * process_incoming Function: void smb_netbios_name_service_daemon(void)
- *
- * Description:
- *
- *	Put test description here.
- *
- * Inputs:
- *	Nothing
- *
- * Returns:
- *	int	-> Description
+ * NetBIOS Name Service (port 137)
  */
 /*ARGSUSED*/
 void *
-smb_netbios_name_service_daemon(void *arg)
+smb_netbios_name_service(void *arg)
 {
 	struct sockaddr_in	sin;
-	struct addr_entry 	*addr;
+	addr_entry_t		*addr;
 	int			len;
 	int			flag = 1;
-	char 			*buf;
+	char			*buf;
 	worker_param_t 		*worker_param;
 	smb_inaddr_t		ipaddr;
 
@@ -4659,53 +2394,43 @@
 	bzero(&reply_queue, sizeof (reply_queue));
 	reply_queue.forw = reply_queue.back = &reply_queue;
 
-	if (!smb_netbios_cache_init())
-		return (0);
-
-	bcast_num = 0;
-	bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS);
-
 	if ((name_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		syslog(LOG_ERR,
-		    "smbd: Could not create AF_INET, SOCK_DGRAM, socket");
-		smb_netbios_cache_fini();
-		smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1);
-		return (0);
+		syslog(LOG_ERR, "nbns: socket failed: %m");
+		smb_netbios_event(NETBIOS_EVENT_ERROR);
+		return (NULL);
 	}
 
+	flag = 1;
+	(void) setsockopt(name_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
+	    sizeof (flag));
+	flag = 1;
 	(void) setsockopt(name_sock, SOL_SOCKET, SO_BROADCAST, &flag,
 	    sizeof (flag));
 
 	bzero(&sin, sizeof (struct sockaddr_in));
 	sin.sin_family = AF_INET;
-	sin.sin_port = htons(NAME_SERVICE_UDP_PORT);
+	sin.sin_port = htons(IPPORT_NETBIOS_NS);
 	if (bind(name_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
-		syslog(LOG_ERR,
-		    "smbd: Bind to name service port %d failed (%d)",
-		    NAME_SERVICE_UDP_PORT, errno);
-		smb_netbios_cache_fini();
+		syslog(LOG_ERR, "nbns: bind(%d) failed: %m",
+		    IPPORT_NETBIOS_NS);
 		(void) close(name_sock);
-		smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1);
-		return (0);
+		smb_netbios_event(NETBIOS_EVENT_ERROR);
+		return (NULL);
 	}
 
-	smb_netbios_chg_status(NETBIOS_NAME_SVC_RUNNING, 1);
+	smb_netbios_event(NETBIOS_EVENT_NS_START);
 
-	while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) ||
-	    (nb_status.state & NETBIOS_BROWSER_RUNNING)) {
-		if ((buf = malloc(MAX_DATAGRAM_LENGTH)) == 0) {
-			/* Sleep for 10 sec and try again */
-			(void) sleep(10);
+	while (smb_netbios_running()) {
+		buf = malloc(MAX_DATAGRAM_LENGTH);
+		addr = malloc(sizeof (addr_entry_t));
+		if ((buf == NULL) || (addr == NULL)) {
+			/* Sleep for 10 seconds and try again */
+			free(addr);
+			free(buf);
+			smb_netbios_sleep(10);
 			continue;
 		}
-		if ((addr = (struct addr_entry *)
-		    malloc(sizeof (struct addr_entry))) == 0) {
-			/* Sleep for 10 sec and try again */
-			free(buf);
-			(void) sleep(10);
-			continue;
-		}
-ignore:		bzero(addr, sizeof (struct addr_entry));
+ignore:		bzero(addr, sizeof (addr_entry_t));
 		addr->sinlen = sizeof (addr->sin);
 		addr->forw = addr->back = addr;
 
@@ -4713,17 +2438,16 @@
 		    0, (struct sockaddr *)&addr->sin, &addr->sinlen)) < 0) {
 			if (errno == ENOMEM || errno == ENFILE ||
 			    errno == EMFILE) {
-				/* Sleep for 10 sec and try again */
+				/* Sleep for 10 seconds and try again */
 				free(buf);
 				free(addr);
-				(void) sleep(10);
+				smb_netbios_sleep(10);
 				continue;
 			}
-			syslog(LOG_ERR,
-				"smbd: NETBIOS name service - recvfrom failed");
+			syslog(LOG_ERR, "nbns: recvfrom failed: %m");
 			free(buf);
 			free(addr);
-			smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1);
+			smb_netbios_event(NETBIOS_EVENT_ERROR);
 			goto shutdown;
 		}
 
@@ -4737,8 +2461,7 @@
 		/*
 		 * Launch a netbios worker to process the received packet.
 		 */
-		worker_param = (worker_param_t *)
-		    malloc(sizeof (worker_param_t));
+		worker_param = malloc(sizeof (worker_param_t));
 		if (worker_param) {
 			pthread_t worker;
 			pthread_attr_t tattr;
@@ -4757,23 +2480,12 @@
 	}
 
 shutdown:
-	smb_netbios_chg_status(NETBIOS_NAME_SVC_RUNNING, 0);
-
-	(void) mutex_lock(&nb_status.mtx);
-	while (nb_status.state & NETBIOS_BROWSER_RUNNING)
-		(void) cond_wait(&nb_status.cv, &nb_status.mtx);
-	(void) mutex_unlock(&nb_status.mtx);
+	smb_netbios_event(NETBIOS_EVENT_NS_STOP);
+	smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP);
 
-	if ((nb_status.state & NETBIOS_NAME_SVC_FAILED) == 0) {
-		/* this might delay shutdown, do we want to do this? */
-		/*
-		 * it'll send name release requests but nobody's waiting
-		 * for response and it'll eventually timeout.
-		 */
+	if (!smb_netbios_error())
 		smb_netbios_name_unconfig();
-	}
+
 	(void) close(name_sock);
-	smb_netbios_cache_fini();
-	syslog(LOG_DEBUG, "smbd: Netbios Name Service is down\n");
-	return (0);
+	return (NULL);
 }
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c	Mon Oct 05 11:03:34 2009 -0700
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)smbns_netlogon.c	1.7	08/07/16 SMI"
-
 /*
  * This module handles the primary domain controller location protocol.
  * The document claims to be version 1.15 of the browsing protocol. It also
@@ -81,7 +79,7 @@
 void
 smb_netlogon_request(struct name_entry *server, char *domain)
 {
-	nt_domain_t di;
+	smb_domain_t di;
 	smb_sid_t *sid = NULL;
 	int protocol = NETLOGON_PROTO_NETLOGON;
 
@@ -216,13 +214,13 @@
 		return;
 	}
 
-	if (domain == 0 || primary == 0) {
+	if (domain == NULL || primary == NULL) {
 		syslog(LOG_ERR, "NetLogonResponse: malformed packet");
 		smb_msgbuf_term(&mb);
 		return;
 	}
 
-	syslog(LOG_DEBUG, "DC Offer Dom=%s PDC=%s From=%s",
+	syslog(LOG_DEBUG, "DC Offer Domain=%s PDC=%s From=%s",
 	    domain, primary, src_name);
 
 	(void) mutex_lock(&ntdomain_mtx);
@@ -449,8 +447,8 @@
 		smb_init_name_struct((unsigned char *)domain, suffix[i],
 		    0, 0, 0, 0, 0, &dname);
 
-		syslog(LOG_DEBUG, "smb_netlogon_send");
-		smb_netbios_name_dump(&dname);
+		syslog(LOG_DEBUG, "SmbNetlogonSend");
+		smb_netbios_name_logf(&dname);
 		if ((dest = smb_name_find_name(&dname)) != 0) {
 			dest_dup = smb_netbios_name_dup(dest, 1);
 			smb_name_unlock_name(dest);
@@ -460,7 +458,8 @@
 				free(dest_dup);
 			}
 		} else {
-			syslog(LOG_DEBUG, "smbd: NBNS couldn't find %s<0x%X>",
+			syslog(LOG_DEBUG,
+			    "SmbNetlogonSend: could not find %s<0x%X>",
 			    domain, suffix[i]);
 		}
 	}
--- a/usr/src/lib/smbsrv/libsmbrdr/Makefile.com	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/Makefile.com	Mon Oct 05 11:03:34 2009 -0700
@@ -19,17 +19,14 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 LIBRARY =	libsmbrdr.a
 VERS =		.1
 
 OBJS_COMMON =			\
-	smbrdr_ipc_util.o	\
 	smbrdr_lib.o		\
 	smbrdr_logon.o		\
 	smbrdr_netbios.o	\
--- a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h	Mon Oct 05 11:03:34 2009 -0700
@@ -32,28 +32,8 @@
 extern "C" {
 #endif
 
-typedef struct smbrdr_session_info {
-	int si_server_os;
-	int si_server_lm;
-	int si_dc_type;
-} smbrdr_session_info_t;
-
-/*
- * Redirector IPC functions
- *
- * The following functions are required by the mlsvc_join to
- * apply new authentication information for the authenticated IPC, rollback
- * or commit the changes to the original authentication information.
- */
-extern void smbrdr_ipc_set(char *, unsigned char *);
-extern void smbrdr_ipc_commit(void);
-extern void smbrdr_ipc_rollback(void);
-extern char *smbrdr_ipc_get_user(void);
-extern unsigned char *smbrdr_ipc_get_passwd(void);
-
-
 /* Redirector LOGON function */
-extern int mlsvc_logon(char *, char *, char *);
+extern int smbrdr_logon(char *, char *, char *);
 extern int smbrdr_get_ssnkey(int, unsigned char *, size_t);
 
 /* Redirector named pipe functions */
@@ -63,10 +43,8 @@
 extern int smbrdr_transact(int, char *, int, char *, int);
 
 /* Redirector session functions */
-extern void smbrdr_init(void);
-extern int smbrdr_session_info(int, smbrdr_session_info_t *);
-extern int mlsvc_echo(char *);
-extern void mlsvc_disconnect(char *);
+extern int smbrdr_echo(const char *);
+extern void smbrdr_disconnect(const char *);
 
 /* DEBUG functions */
 extern void smbrdr_dump_ofiles(void);
--- a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers	Mon Oct 05 11:03:34 2009 -0700
@@ -39,23 +39,16 @@
 
 SUNWprivate {
     global:
-	mlsvc_disconnect;
-	mlsvc_echo;
-	mlsvc_logon;
 	smbrdr_close_pipe;
+	smbrdr_disconnect;
 	smbrdr_dump_netuse;
 	smbrdr_dump_ofiles;
 	smbrdr_dump_sessions;
+	smbrdr_echo;
 	smbrdr_get_ssnkey;
-	smbrdr_init;
-	smbrdr_ipc_commit;
-	smbrdr_ipc_get_user;
-	smbrdr_ipc_rollback;
-	smbrdr_ipc_set;
-	smbrdr_ipc_get_passwd;
+	smbrdr_logon;
 	smbrdr_open_pipe;
 	smbrdr_readx;
-	smbrdr_session_info;
 	smbrdr_transact;
     local:
 	*;
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h	Mon Oct 05 11:03:34 2009 -0700
@@ -204,7 +204,7 @@
  * smbrdr_session.c
  */
 int smbrdr_negotiate(char *, char *);
-struct sdb_session *smbrdr_session_lock(char *, char *, int);
+struct sdb_session *smbrdr_session_lock(const char *, const char *, int);
 void smbrdr_session_unlock(struct sdb_session *);
 
 /*
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c	Mon Oct 05 13:48:48 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * The IPC connection information is encapsulated within SMB Redirector.
- * Utility functions are defined here to allow other modules to get and
- * set the ipc configuration, as well as, to rollback or commit the
- * changes to the original authentication information.
- */
-
-#include <string.h>
-#include <strings.h>
-#include <synch.h>
-
-#include <smbsrv/libsmbrdr.h>
-#include <smbsrv/smbinfo.h>
-#include <smbrdr.h>
-#include <smbrdr_ipc_util.h>
-
-#define	SMBRDR_IPC_GETDOMAIN_TIMEOUT	10000
-
-static rwlock_t		smbrdr_ipc_lock;
-static smbrdr_ipc_t	ipc_info;
-static smbrdr_ipc_t	orig_ipc_info;
-
-static int
-smbrdr_get_machine_pwd_hash(unsigned char *hash)
-{
-	char pwd[SMB_PASSWD_MAXLEN + 1];
-	int rc = 0;
-
-	rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd));
-	if ((rc != SMBD_SMF_OK) || *pwd == '\0') {
-		return (-1);
-	}
-
-	if (smb_auth_ntlm_hash(pwd, hash) != 0)
-		rc = -1;
-
-	return (rc);
-}
-
-/*
- * smbrdr_ipc_init
- *
- * Get system configuration regarding IPC connection
- * credentials and initialize related variables.
- * This function will normally be called at startup
- * (i.e. at the time smbrdr gets loaded).
- */
-void
-smbrdr_ipc_init(void)
-{
-	int rc;
-
-	(void) rw_wrlock(&smbrdr_ipc_lock);
-	bzero(&ipc_info, sizeof (smbrdr_ipc_t));
-	bzero(&orig_ipc_info, sizeof (smbrdr_ipc_t));
-
-	(void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
-	rc = smbrdr_get_machine_pwd_hash(ipc_info.passwd);
-	if (rc != 0)
-		*ipc_info.passwd = 0;
-	(void) rw_unlock(&smbrdr_ipc_lock);
-
-}
-
-/*
- * smbrdr_ipc_set
- *
- * The given username and password hash will be applied to the
- * ipc_info, which will be used for setting up the authenticated IPC
- * channel during join domain.
- *
- * If domain join operation succeeds, smbrdr_ipc_commit() should be
- * invoked to set the ipc_info with host credentials. Otherwise,
- * smbrdr_ipc_rollback() should be called to restore the previous
- * credentials.
- */
-void
-smbrdr_ipc_set(char *plain_user, unsigned char *passwd_hash)
-{
-	(void) rw_wrlock(&smbrdr_ipc_lock);
-	(void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user));
-	(void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ);
-	(void) rw_unlock(&smbrdr_ipc_lock);
-
-}
-
-/*
- * smbrdr_ipc_commit
- *
- * Save the host credentials, which will be used for any authenticated
- * IPC channel establishment after domain join.
- *
- * The host credentials is also saved to the original IPC info as
- * rollback data in case the join domain process fails in the future.
- */
-void
-smbrdr_ipc_commit()
-{
-	(void) rw_wrlock(&smbrdr_ipc_lock);
-	(void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
-	(void) smbrdr_get_machine_pwd_hash(ipc_info.passwd);
-	(void) memcpy(&orig_ipc_info, &ipc_info, sizeof (smbrdr_ipc_t));
-	(void) rw_unlock(&smbrdr_ipc_lock);
-}
-
-/*
- * smbrdr_ipc_rollback
- *
- * Restore the original credentials
- */
-void
-smbrdr_ipc_rollback()
-{
-	(void) rw_wrlock(&smbrdr_ipc_lock);
-	(void) strlcpy(ipc_info.user, orig_ipc_info.user,
-	    sizeof (ipc_info.user));
-	(void) memcpy(ipc_info.passwd, orig_ipc_info.passwd,
-	    sizeof (ipc_info.passwd));
-	(void) rw_unlock(&smbrdr_ipc_lock);
-}
-
-/*
- * Get & Set functions
- */
-char *
-smbrdr_ipc_get_user()
-{
-	char	*user;
-
-	(void) rw_rdlock(&smbrdr_ipc_lock);
-	user = ipc_info.user;
-	(void) rw_unlock(&smbrdr_ipc_lock);
-	return (user);
-}
-
-unsigned char *
-smbrdr_ipc_get_passwd()
-{
-	unsigned char	*passwd;
-
-	(void) rw_rdlock(&smbrdr_ipc_lock);
-	passwd = ipc_info.passwd;
-	(void) rw_unlock(&smbrdr_ipc_lock);
-	return (passwd);
-}
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h	Mon Oct 05 13:48:48 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SMBSRV_IPC_UTIL_H
-#define	_SMBSRV_IPC_UTIL_H
-
-/*
- * This file defines the data structure for the IPC connection and utility
- * function prototypes.
- */
-
-#include <smbsrv/libsmb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * smbrdr_ipc_t
- *
- * This structure contains credentials for establishing authenticated
- * IPC connection.
- */
-typedef struct {
-	char user[SMB_USERNAME_MAXLEN];
-	unsigned char passwd[SMBAUTH_HASH_SZ];
-} smbrdr_ipc_t;
-
-
-void smbrdr_ipc_init(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SMBSRV_IPC_UTIL_H */
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c	Mon Oct 05 11:03:34 2009 -0700
@@ -37,7 +37,6 @@
 #include <smbsrv/libsmbrdr.h>
 #include <smbsrv/ntstatus.h>
 #include <smbsrv/smb.h>
-#include <smbrdr_ipc_util.h>
 #include <smbrdr.h>
 
 #define	SMBRDR_ANON_USER	"IPC$"
@@ -53,14 +52,12 @@
 static int smbrdr_authenticate(char *, char *, char *, unsigned char *);
 
 /*
- * mlsvc_logon
- *
  * If the username is SMBRDR_ANON_USER, an anonymous session will be
  * established. Otherwise, an authenticated session will be established
  * based on the specified credentials.
  */
 int
-mlsvc_logon(char *domain_controller, char *domain, char *username)
+smbrdr_logon(char *domain_controller, char *domain, char *username)
 {
 	int rc;
 
@@ -145,15 +142,15 @@
 smbrdr_auth_logon(char *domain_controller, char *domain_name, char *username)
 {
 	int erc;
-	unsigned char *pwd_hash = NULL;
+	uint8_t pwd_hash[SMBAUTH_HASH_SZ];
 
 	if (username == NULL || *username == 0) {
 		syslog(LOG_DEBUG, "smbrdr_auth_logon: no username");
 		return (-1);
 	}
 
-	pwd_hash = smbrdr_ipc_get_passwd();
-	if (!pwd_hash || *pwd_hash == 0) {
+	smb_ipc_get_passwd(pwd_hash, SMBAUTH_HASH_SZ);
+	if (*pwd_hash == 0) {
 		syslog(LOG_DEBUG, "smbrdr_auth_logon: no password");
 		return (-1);
 	}
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,7 +43,7 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/time.h>
-
+#include <netinet/in.h>
 #include <stdio.h>
 #include <pthread.h>
 
@@ -124,7 +124,7 @@
 	int nothing;
 	int rc;
 
-	if (port == SMB_SRVC_TCP_PORT)
+	if (port == IPPORT_SMB)
 		return (0);
 
 	(void) mutex_lock(&nb_mutex);
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -62,8 +62,8 @@
  */
 static struct sdb_ofile ofile_table[N_OFILE_TABLE];
 
-static int mlsvc_pipe_recon_wait = 50;
-static int mlsvc_pipe_recon_tries = 3;
+static int smbrdr_pipe_recon_wait = 50;
+static int smbrdr_pipe_recon_tries = 3;
 
 
 /*
@@ -83,7 +83,7 @@
 	struct timespec st;
 	int i;
 
-	if (mlsvc_logon(hostname, domain, username) != 0)
+	if (smbrdr_logon(hostname, domain, username) != 0)
 		return (-1);
 
 	/*
@@ -93,7 +93,7 @@
 	for (i = 0; i < 2; i++) {
 		status = smbrdr_tree_connect(hostname, username, "IPC$", &tid);
 		if (i == 0 && status == NT_STATUS_UNEXPECTED_NETWORK_ERROR) {
-			if (mlsvc_logon(hostname, domain, username) != 0)
+			if (smbrdr_logon(hostname, domain, username) != 0)
 				return (-1);
 			continue;
 		}
@@ -128,7 +128,7 @@
 
 	status = NT_STATUS_OPEN_FAILED;
 
-	for (retry = 0; retry < mlsvc_pipe_recon_tries; retry++) {
+	for (retry = 0; retry < smbrdr_pipe_recon_tries; retry++) {
 		status = smbrdr_ntcreatex(ofile);
 
 		switch (status) {
@@ -146,7 +146,7 @@
 			 * the pipe becomes available.
 			 */
 			st.tv_sec = 0;
-			st.tv_nsec = mlsvc_pipe_recon_wait * 1000000;
+			st.tv_nsec = smbrdr_pipe_recon_wait * 1000000;
 			(void) nanosleep(&st, 0);
 			break;
 
@@ -154,7 +154,7 @@
 			/*
 			 * Something else went wrong: no more retries.
 			 */
-			retry = mlsvc_pipe_recon_tries;
+			retry = smbrdr_pipe_recon_tries;
 			break;
 		}
 	}
@@ -259,7 +259,7 @@
  *
  * This function can be used when closing a share to ensure that all
  * ofiles resources are released. Don't call smbrdr_close_pipe because
- * that will call mlsvc_smb_tdcon and we don't know what state
+ * that will disconnect the tree and we don't know what state
  * the share is in. The server will probably close all files anyway.
  * We are more interested in releasing the ofile resources.
  */
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c	Mon Oct 05 11:03:34 2009 -0700
@@ -47,13 +47,12 @@
 #include <smbsrv/cifs.h>
 #include <smbsrv/ntstatus.h>
 #include <smbrdr.h>
-#include <smbrdr_ipc_util.h>
 
 #define	SMBRDR_DOMAIN_MAX		32
 
 static uint16_t smbrdr_ports[] = {
-	SMB_SRVC_TCP_PORT,
-	SSN_SRVC_TCP_PORT
+	IPPORT_SMB,
+	IPPORT_NETBIOS_SSN
 };
 
 static int smbrdr_nports = sizeof (smbrdr_ports) / sizeof (smbrdr_ports[0]);
@@ -66,7 +65,7 @@
 static int smbrdr_trnsprt_connect(struct sdb_session *, uint16_t);
 static int smbrdr_session_connect(char *, char *);
 static int smbrdr_smb_negotiate(struct sdb_session *);
-static int smbrdr_echo(struct sdb_session *);
+static int smbrdr_smb_echo(struct sdb_session *);
 static void smbrdr_session_disconnect(struct sdb_session *, int);
 
 
@@ -77,21 +76,10 @@
 }
 
 /*
- * Entry pointy for smbrdr initialization.
- */
-void
-smbrdr_init(void)
-{
-	smbrdr_ipc_init();
-}
-
-/*
- * mlsvc_disconnect
- *
  * Disconnects the session with given server.
  */
 void
-mlsvc_disconnect(char *server)
+smbrdr_disconnect(const char *server)
 {
 	struct sdb_session *session;
 
@@ -282,7 +270,7 @@
 	 * Otherwise, we're doing NetBIOS-less SMB, i.e. SMB over TCP,
 	 * which is typically on port 445.
 	 */
-	if (port == SSN_SRVC_TCP_PORT) {
+	if (port == IPPORT_NETBIOS_SSN) {
 		if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) != 0) {
 			syslog(LOG_DEBUG, "smbrdr: no hostname");
 			if (sock != 0)
@@ -532,7 +520,7 @@
  *            the pointer.
  */
 struct sdb_session *
-smbrdr_session_lock(char *server, char *username, int lmode)
+smbrdr_session_lock(const char *server, const char *username, int lmode)
 {
 	struct sdb_session *session;
 	int i;
@@ -566,39 +554,6 @@
 }
 
 /*
- * smbrdr_session_info
- *
- * Return session information related to the specified
- * named pipe (fid).
- */
-int
-smbrdr_session_info(int fid, smbrdr_session_info_t *si)
-{
-	struct sdb_session *session;
-	struct sdb_netuse *netuse;
-	struct sdb_ofile *ofile;
-
-	if (si == NULL)
-		return (-1);
-
-	if ((ofile = smbrdr_ofile_get(fid)) == NULL) {
-		syslog(LOG_DEBUG,
-		    "smbrdr_session_info: unknown file (%d)", fid);
-		return (-1);
-	}
-
-	netuse = ofile->netuse;
-	session = netuse->session;
-
-	si->si_server_os = session->remote_os;
-	si->si_server_lm = session->remote_lm;
-	si->si_dc_type = session->pdc_type;
-
-	smbrdr_ofile_put(ofile);
-	return (0);
-}
-
-/*
  * smbrdr_dump_sessions
  *
  * Debug function to dump the session table.
@@ -635,11 +590,8 @@
 	}
 }
 
-/*
- * mlsvc_echo
- */
 int
-mlsvc_echo(char *server)
+smbrdr_echo(const char *server)
 {
 	struct sdb_session *session;
 	int res = 0;
@@ -647,7 +599,7 @@
 	if ((session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE)) == 0)
 		return (1);
 
-	if (smbrdr_echo(session) != 0) {
+	if (smbrdr_smb_echo(session) != 0) {
 		session->state = SDB_SSTATE_STALE;
 		res = -1;
 	}
@@ -657,8 +609,6 @@
 }
 
 /*
- * smbrdr_echo
- *
  * This request can be used to test the connection to the server. The
  * server should echo the data sent. The server should ignore the tid
  * in the header, so this request when there are no tree connections.
@@ -667,7 +617,7 @@
  * Return 0 on success. Otherwise return a -ve error code.
  */
 static int
-smbrdr_echo(struct sdb_session *session)
+smbrdr_smb_echo(struct sdb_session *session)
 {
 	static char *echo_str = "smbrdr";
 	smbrdr_handle_t srh;
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c	Mon Oct 05 11:03:34 2009 -0700
@@ -641,31 +641,31 @@
 int
 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
 {
-	int rc;
+	int rc = 0;
 	smb_attr_t attr;
 
-	mutex_enter(&node->n_mutex);
-
-	if ((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) ||
-	    (node->readonly_creator)) {
-		mutex_exit(&node->n_mutex);
+	if (node->readonly_creator)
 		return (-1);
-	}
 
 	bzero(&attr, sizeof (smb_attr_t));
 	attr.sa_mask = SMB_AT_DOSATTR;
 	rc = smb_fsop_getattr(NULL, kcred, node, &attr);
 	if ((rc != 0) || (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) {
-		mutex_exit(&node->n_mutex);
 		return (-1);
 	}
 
-	crhold(cr);
-	node->delete_on_close_cred = cr;
-	node->n_delete_on_close_flags = flags;
-	node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
+	mutex_enter(&node->n_mutex);
+	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
+		rc = -1;
+	} else {
+		crhold(cr);
+		node->delete_on_close_cred = cr;
+		node->n_delete_on_close_flags = flags;
+		node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
+		rc = 0;
+	}
 	mutex_exit(&node->n_mutex);
-	return (0);
+	return (rc);
 }
 
 void
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c	Mon Oct 05 11:03:34 2009 -0700
@@ -652,7 +652,7 @@
 	/*
 	 * netbios must be ipv4
 	 */
-	rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT,
+	rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN,
 	    AF_INET, ioc->error);
 
 	if (rc) {
@@ -700,10 +700,10 @@
 
 	if (sv->sv_cfg.skc_ipv6_enable)
 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
-		    SMB_SRVC_TCP_PORT, AF_INET6, ioc->error);
+		    IPPORT_SMB, AF_INET6, ioc->error);
 	else
 		rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
-		    SMB_SRVC_TCP_PORT, AF_INET, ioc->error);
+		    IPPORT_SMB, AF_INET, ioc->error);
 	if (rc) {
 		mutex_enter(&sv->sv_mutex);
 		sv->sv_tcp_daemon.ld_kth = NULL;
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c	Mon Oct 05 11:03:34 2009 -0700
@@ -314,14 +314,14 @@
 		return (rc);
 
 	switch (session->s_local_port) {
-	case SSN_SRVC_TCP_PORT:
+	case IPPORT_NETBIOS_SSN:
 		ret_hdr->xh_type = buf[0];
 		ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) |
 		    ((uint32_t)buf[2] << 8) |
 		    ((uint32_t)buf[3]);
 		break;
 
-	case SMB_SRVC_TCP_PORT:
+	case IPPORT_SMB:
 		ret_hdr->xh_type = buf[0];
 
 		if (ret_hdr->xh_type != 0) {
@@ -358,14 +358,14 @@
 	}
 
 	switch (session->s_local_port) {
-	case SSN_SRVC_TCP_PORT:
+	case IPPORT_NETBIOS_SSN:
 		buf[0] = hdr->xh_type;
 		buf[1] = ((hdr->xh_length >> 16) & 1);
 		buf[2] = (hdr->xh_length >> 8) & 0xff;
 		buf[3] = hdr->xh_length & 0xff;
 		break;
 
-	case SMB_SRVC_TCP_PORT:
+	case IPPORT_SMB:
 		buf[0] = hdr->xh_type;
 		buf[1] = (hdr->xh_length >> 16) & 0xff;
 		buf[2] = (hdr->xh_length >> 8) & 0xff;
@@ -486,7 +486,7 @@
 	if (session == NULL)
 		return (EINVAL);
 
-	if (session->s_local_port == SSN_SRVC_TCP_PORT) {
+	if (session->s_local_port == IPPORT_NETBIOS_SSN) {
 		rc = smb_session_request(session);
 		if (rc) {
 			smb_rwx_rwenter(&session->s_lock, RW_WRITER);
@@ -631,7 +631,7 @@
 }
 
 /*
- * Port will be SSN_SRVC_TCP_PORT or SMB_SRVC_TCP_PORT.
+ * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB.
  */
 smb_session_t *
 smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
--- a/usr/src/uts/common/smbsrv/cifs.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/cifs.h	Mon Oct 05 11:03:34 2009 -0700
@@ -46,13 +46,6 @@
 extern "C" {
 #endif
 
-
-/*
- * SMB-over-TCP (NETBIOS-less SMB) TCP port
- */
-#define	SMB_SRVC_TCP_PORT		445
-
-
 /* Share types */
 #ifndef _SHARE_TYPES_DEFINED_
 #define	_SHARE_TYPES_DEFINED_
--- a/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -49,6 +49,10 @@
 #define ARG_IS(X)	[arg_is(X)]
 
 #define REFERENCE	[reference]
+#define REF		[reference]
+#define UNIQUE		[unique]
+#define PTR		[ptr]
+#define POINTER_DEFAULT(X)	[pointer_default(X)]
 
 #define ANY_SIZE_ARRAY	*
 
@@ -57,6 +61,7 @@
 #define BYTE	uchar
 #define WORD	ushort
 #define DWORD	ulong
+#define ntstatus_t	ulong
 
 #define LPTSTR	STRING wchar *
 
@@ -101,6 +106,10 @@
 #define ARG_IS(X)
 
 #define REFERENCE
+#define REF
+#define UNIQUE
+#define PTR
+#define POINTER_DEFAULT(X)
 
 #define IMPORT_EXTERN
 
--- a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,20 +32,24 @@
 
 #include "ndrtypes.ndl"
 
-
-#define SAMR_OPNUM_ConnectAnon			0x00
+/* Windows NT */
+#define SAMR_OPNUM_ConnectAnon			0x00	/* SamrConnect */
 #define SAMR_OPNUM_CloseHandle			0x01
+#define SAMR_OPNUM_SetSecObject			0x02
 #define SAMR_OPNUM_QuerySecObject		0x03
+#define SAMR_OPNUM_ShutdownSamServer		0x04	/* NotUsedOnWire */
 #define SAMR_OPNUM_LookupDomain			0x05
 #define SAMR_OPNUM_EnumLocalDomains		0x06
 #define SAMR_OPNUM_OpenDomain			0x07
 #define SAMR_OPNUM_QueryDomainInfo		0x08
+#define SAMR_OPNUM_SetDomainInfo		0x09
 #define SAMR_OPNUM_CreateDomainGroup		0x0a
 #define SAMR_OPNUM_QueryDomainGroups		0x0b
+#define SAMR_OPNUM_CreateDomainUser		0x0c
 #define SAMR_OPNUM_EnumDomainUsers		0x0d
 #define SAMR_OPNUM_CreateDomainAlias		0x0e
 #define SAMR_OPNUM_EnumDomainAliases		0x0f
-#define SAMR_OPNUM_LookupIds			0x10
+#define SAMR_OPNUM_LookupIds			0x10	/* GetAliasMembership */
 #define SAMR_OPNUM_LookupNames			0x11
 #define SAMR_OPNUM_LookupDomainIds		0x12
 #define SAMR_OPNUM_OpenGroup			0x13
@@ -55,6 +59,7 @@
 #define SAMR_OPNUM_DeleteDomainGroup		0x17
 #define SAMR_OPNUM_DeleteGroupMember		0x18
 #define SAMR_OPNUM_ListGroupMembers		0x19
+#define SAMR_OPNUM_SetGroupMemberAttributes	0x1a
 #define SAMR_OPNUM_OpenAlias			0x1b
 #define SAMR_OPNUM_QueryAliasInfo		0x1c
 #define SAMR_OPNUM_SetAliasInfo			0x1d
@@ -65,19 +70,45 @@
 #define SAMR_OPNUM_OpenUser			0x22
 #define SAMR_OPNUM_DeleteUser			0x23
 #define SAMR_OPNUM_QueryUserInfo		0x24
+#define SAMR_OPNUM_SetUserInfo0			0x25	/* SetUserInfo */
+#define SAMR_OPNUM_ChangeUserPassword0		0x26	/* ChangeUserPassword */
 #define SAMR_OPNUM_QueryUserGroups		0x27
 #define SAMR_OPNUM_QueryDispInfo		0x28	/* QueryDispInfo1 */
+#define	SAMR_OPNUM_GetDisplayEnumIndex		0x29
+#define	SAMR_OPNUM_TestPrivateDomainFunctions	0x2a	/* NotUsedOnWire */
+#define	SAMR_OPNUM_TestPrivateUserFunctions	0x2b	/* NotUsedOnWire */
 #define SAMR_OPNUM_GetUserPwInfo		0x2c
-#define SAMR_OPNUM_EnumDomainGroups		0x30	/* QueryDispInfo3 */
-#define SAMR_OPNUM_CreateUser			0x32
-#define SAMR_OPNUM_QueryDispInfo4		0x33
-#define SAMR_OPNUM_AddMultiAliasMember		0x34
-#define SAMR_OPNUM_ChangeUserPasswd		0x37
+
+/* Windows 2000 */
+#define	SAMR_OPNUM_RemoveMemberFromForeignDomain        0x2d
+#define	SAMR_OPNUM_QueryInfoDomain2		0x2e
+#define	SAMR_OPNUM_QueryInfoUser2		0x2f
+#define	SAMR_OPNUM_EnumDomainGroups		0x30    /* QueryDispInfo2 */
+#define	SAMR_OPNUM_GetDisplayEnumIndex2		0x31
+#define	SAMR_OPNUM_CreateUser			0x32
+#define	SAMR_OPNUM_QueryDispInfo4		0x33
+#define	SAMR_OPNUM_AddMultipleAliasMembers	0x34
+#define	SAMR_OPNUM_RemoveMultipleAliasMembers	0x35
+#define	SAMR_OPNUM_ChangeUserOemPassword	0x36
+#define SAMR_OPNUM_ChangeUserPasswd		0x37	/* UnicodePasswd */
 #define SAMR_OPNUM_GetDomainPwInfo		0x38
-#define SAMR_OPNUM_Connect			0x39
+#define SAMR_OPNUM_Connect			0x39	/* SamrConnect2 */
 #define SAMR_OPNUM_SetUserInfo			0x3a
-#define SAMR_OPNUM_Connect3			0x3e
-#define SAMR_OPNUM_Connect4			0x40
+#define	SAMR_OPNUM_SetBootKeyInformation	0x3b
+#define	SAMR_OPNUM_GetBootKeyInformation	0x3c
+#define	SAMR_OPNUM_Connect2			0x3d	/* SamrConnect3 */
+#define	SAMR_OPNUM_Connect3			0x3e	/* SamrConnect4 */
+#define	SAMR_OPNUM_ChangeUserUnicodePassword3	0x3f
+
+/* Windows XP and Windows Server 2003 */
+#define	SAMR_OPNUM_Connect4			0x40	/* SamrConnect5 */
+#define	SAMR_OPNUM_RidToSid                     0x41
+#define	SAMR_OPNUM_SetDSRMPassword              0x42
+#define	SAMR_OPNUM_ValidatePassword             0x43
+
+/* Windows Vista */
+#define SAMR_OPNUM_QueryLocalizableAccountsInDomain     0x44
+#define SAMR_OPNUM_PerformGenericOperation              0x45
 
 
 /*
@@ -130,6 +161,10 @@
 #define SAMR_ALIAS_ACCESS_DEL_MEMBER		0x00000002
 #define SAMR_ALIAS_ACCESS_ADD_MEMBER		0x00000001
 
+#define	SAMR_REVISION_1			1	/* Pre Windows 2000 */
+#define	SAMR_REVISION_2			2	/* Windows 2000 */
+#define	SAMR_REVISION_3			3	/* Post Windows 2000 */
+
 /*
  * Definition for a SID. The ndl compiler does not allow a typedef of
  * a structure containing variable size members.
@@ -247,7 +282,7 @@
 OPERATION(SAMR_OPNUM_Connect3)
 struct samr_Connect3 {
 	IN	LPTSTR servername;
-	IN	DWORD unknown_02;
+	IN	DWORD revision;
 	IN	DWORD access_mask;
 	OUT	samr_handle_t handle;
 	OUT	DWORD status;
@@ -258,9 +293,31 @@
  ***********************************************************************
  * SamrConnect4. A new form of connect first seen with Windows XP.
  * The server name is the fully qualified domain name, i.e.
- *	\\server.procom.com.
+ *	\\server.sun.com.
+ *
+ * [in]  DWORD	 InVersion,
+ * [in]  [switch_is(InVersion)]    samr_revision_info *InRevisionInfo
+ * [out] DWORD	 *OutVersion
+ * [out] [switch_is(*OutVersion)] *samr_revision_info *OutRevisionInfo
+ *
+ * SupportedFeatures (see notes in [MS-SAMR]
+ *	0x00000001	RID values returned from the server must not be
+ *			concatenated with the domain SID.
+ *	0x00000002	Reserved
+ *	0x00000004	Reserved
  ***********************************************************************
  */
+struct samr_revision_info1 {
+	DWORD revision;
+	DWORD supported_features;
+};
+typedef struct samr_revision_info1 samr_revision_info1_t;
+
+union samr_revision_info {
+	UNION_INFO_ENT(1,samr_revision_info);
+	DEFAULT	char *nullptr;
+};
+
 OPERATION(SAMR_OPNUM_Connect4)
 struct samr_Connect4 {
 	IN		LPTSTR servername;
@@ -911,12 +968,10 @@
  * CreateUser
  *
  * Create a user in the domain specified by the domain handle. The
- * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain. There
- * is an unknown value at the end of the request: 0xe00500b0.
+ * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain.
+ * DesiredAccess: 0xe00500b0.
  * The output will be a handle for use with the specified user and the
- * user's RID. I think the RID may be a pointer but the value came back
- * as zero once so I've padded it out so that the marshalling doesn't
- * get confused.
+ * user's RID. I think the RID may be a unique pointer (it can be null).
  ***********************************************************************
  */
 OPERATION(SAMR_OPNUM_CreateUser)
@@ -924,7 +979,7 @@
 	IN	samr_handle_t handle;
 	IN	samr_vcbuf_t username;
 	IN	DWORD account_flags;
-	IN	DWORD unknown_e00500b0;
+	IN	DWORD desired_access;
 	OUT	samr_handle_t user_handle;
 	OUT	DWORD maybe_ptr;
 	OUT	DWORD rid;
--- a/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl	Mon Oct 05 11:03:34 2009 -0700
@@ -1056,11 +1056,11 @@
 #define SV_TYPE_DIALIN_SERVER       0x00000400
 #define SV_TYPE_XENIX_SERVER        0x00000800
 #define SV_TYPE_SERVER_UNIX         SV_TYPE_XENIX_SERVER
-#define SV_TYPE_NT                  0x00001000
-#define SV_TYPE_WFW                 0x00002000
+#define SV_TYPE_NT                  0x00001000	/* NT Workstation */
+#define SV_TYPE_WFW                 0x00002000	/* Windows for Workgroups */
 
 #define SV_TYPE_SERVER_MFPN         0x00004000
-#define SV_TYPE_SERVER_NT           0x00008000
+#define SV_TYPE_SERVER_NT           0x00008000	/* NT Server */
 #define SV_TYPE_POTENTIAL_BROWSER   0x00010000
 #define SV_TYPE_BACKUP_BROWSER      0x00020000
 #define SV_TYPE_MASTER_BROWSER      0x00040000
@@ -1068,8 +1068,7 @@
 #define SV_TYPE_SERVER_OSF          0x00100000
 #define SV_TYPE_SERVER_VMS          0x00200000
 #define SV_TYPE_WINDOWS             0x00400000  /* Windows95 and above */
-#define SV_TYPE_ALTERNATE_XPORT     0x20000000  /* return list for
-						 * alternate transport */
+#define SV_TYPE_ALTERNATE_XPORT     0x20000000  /* Return alt transport list */
 #define SV_TYPE_LOCAL_LIST_ONLY     0x40000000  /* Return local list only */
 #define SV_TYPE_DOMAIN_ENUM         0x80000000
 #define SV_TYPE_ALL                 0xFFFFFFFF  /* handy for NetServerEnum2 */
--- a/usr/src/uts/common/smbsrv/ndr.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/ndr.h	Mon Oct 05 11:03:34 2009 -0700
@@ -150,6 +150,8 @@
 struct ndr_stream;
 struct ndr_reference;
 
+typedef uint16_t ndr_wchar_t;
+
 typedef struct ndr_typeinfo {
 	unsigned char		version;	/* sanity check */
 	unsigned char		alignment;	/* mask */
--- a/usr/src/uts/common/smbsrv/netbios.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/netbios.h	Mon Oct 05 11:03:34 2009 -0700
@@ -58,9 +58,9 @@
  * This is then encoded as a 32 byte string.
  *
  * NetBIOS Name:  NetBIOS
- * NetBIOS Scope: PROCOM.COM
- * First Level:   EOGFHEECEJEPFDCACACACACACACACACA.PROCOM.COM
- * Second Level:  <32>EOGFHEECEJEPFDCACACACACACACACACA<6>PROCOM<3>COM<0>
+ * NetBIOS Scope: DOMAIN.COM
+ * First Level:   EOGFHEECEJEPFDCACACACACACACACACA.DOMAIN.COM
+ * Second Level:  <32>EOGFHEECEJEPFDCACACACACACACACACA<6>DOMAIN<3>COM<0>
  */
 #define	NETBIOS_NAME_SZ			16
 #define	NETBIOS_ENCODED_NAME_SZ		32
@@ -71,6 +71,22 @@
 	((NETBIOS_ENCODED_NAME_SZ + 2) * 2)
 
 #define	NETBIOS_HDR_SZ			4	/* bytes */
+
+/*
+ * NetBIOS name type/suffix: 16th byte of the NetBIOS name.
+ * The NetBIOS suffix is used by to identify computer services.
+ */
+#define	NBT_WKSTA			0x00	/* Workstation Service */
+#define	NBT_CLIENT			0x03	/* Messenger Service */
+#define	NBT_RASSRVR			0x06	/* RAS Server Service */
+#define	NBT_DMB				0x1B	/* Domain Master Browser */
+#define	NBT_IP				0x1C	/* Domain Controller */
+#define	NBT_MB				0x1D	/* Master Browser */
+#define	NBT_BS				0x1E	/* Browser Elections */
+#define	NBT_NETDDE			0x1F	/* NetDDE Service */
+#define	NBT_SERVER			0x20	/* Server Service */
+#define	NBT_RASCLNT			0x21	/* RAS Client Service */
+
 /*
  * Session Packet Types (RFC 1002 4.3.1).
  */
@@ -107,10 +123,6 @@
 #define	DATAGRAM_INVALID_SOURCE_NAME_FORMAT		0x83
 #define	DATAGRAM_INVALID_DESTINATION_NAME_FORMAT	0x84
 
-#define	NAME_SERVICE_TCP_PORT		137
-#define	NAME_SERVICE_UDP_PORT		137
-#define	DGM_SRVC_UDP_PORT		138
-#define	SSN_SRVC_TCP_PORT		139
 #define	MAX_DATAGRAM_LENGTH		576
 #define	DATAGRAM_HEADER_LENGTH		14
 #define	DATAGRAM_ERR_HEADER_LENGTH	11
--- a/usr/src/uts/common/smbsrv/smbinfo.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/smbinfo.h	Mon Oct 05 11:03:34 2009 -0700
@@ -42,19 +42,10 @@
 #define	NATIVE_OS_DEFINED
 
 #define	NATIVE_OS_UNKNOWN	0x00000000
-#define	NATIVE_OS_NT4_0		0x00000001
+#define	NATIVE_OS_WINNT		0x00000001
 #define	NATIVE_OS_WIN95		0x00000002
-#define	NATIVE_OS_OTHER		0x00000003
-#define	NATIVE_OS_NT5_0		0x00000004
-#define	NATIVE_OS_NT5_1		0x00000005
-#define	NATIVE_OS_MACOS		0x00000006
-
-/*
- * Backward compatibility aliases.
- */
-#define	NATIVE_OS_WINNT		NATIVE_OS_NT4_0
-#define	NATIVE_OS_WIN2000	NATIVE_OS_NT5_0
-#define	NATIVE_OS_WINXP		NATIVE_OS_NT5_1
+#define	NATIVE_OS_MACOS		0x00000003
+#define	NATIVE_OS_WIN2000	0x00000004
 
 #endif /* NATIVE_OS_DEFINED */
 
--- a/usr/src/uts/common/smbsrv/wintypes.h	Mon Oct 05 13:48:48 2009 -0400
+++ b/usr/src/uts/common/smbsrv/wintypes.h	Mon Oct 05 11:03:34 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -42,6 +42,7 @@
 typedef	uint8_t BYTE;
 typedef	uint16_t WORD;
 typedef	uint32_t DWORD;
+typedef	uint32_t ntstatus_t;
 typedef	uint8_t *LPTSTR;
 typedef	uint8_t *LPBYTE;
 typedef	uint16_t *LPWORD;