changeset 9021:3b15214a2c50

6794156 ADS messages in syslog on domain join failure are too vague 6764265 Share is not published to specified AD site DC. 6810842 idmapd dumped core in list_mappings_cb() 6812513 idmap show -c -v with inhibited mapping yields garbage 6812272 Netbench cannot read file login.sem 6811318 filenames begining with / created in root directory instead of current directory 6812270 Netbench hangs when running with oplocks enabled 6814639 SmbTrans2QueryFSInfo should report Unicode on disk 6752857 CIFS server should not clear the NET_MAC_AWARE privilege 6809498 Unable to join domain using NetBIOS name which is different than the first label of the FQDN. 6808475 smbadm list does not show the IP address of domain controller 6813718 smbd freezes and doesn't respond after a while running the test programs 6812760 CIFS I/O Fails with 64k or greater block sizes 6752022 The MDB DCMD smbreq doesn't display properly the structure smb_request_t
author Alan Wright <amw@Sun.COM>
date Thu, 12 Mar 2009 15:41:34 -0700
parents 9719cd667187
children 4eecb577dc66
files usr/src/cmd/idmap/idmap/idmap.c usr/src/cmd/idmap/idmapd/dbutils.c usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c usr/src/cmd/smbsrv/smbadm/smbadm.c usr/src/common/smbsrv/smb_inet.c usr/src/common/smbsrv/smb_native.c usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c usr/src/lib/smbsrv/libsmb/common/libsmb.h usr/src/lib/smbsrv/libsmb/common/mapfile-vers usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c usr/src/lib/smbsrv/libsmb/common/smb_nic.c usr/src/lib/smbsrv/libsmb/common/smb_util.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_krb.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/uts/common/fs/smbsrv/smb_common_open.c usr/src/uts/common/fs/smbsrv/smb_delete.c usr/src/uts/common/fs/smbsrv/smb_fem.c usr/src/uts/common/fs/smbsrv/smb_node.c usr/src/uts/common/fs/smbsrv/smb_ofile.c usr/src/uts/common/fs/smbsrv/smb_oplock.c usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c usr/src/uts/common/fs/smbsrv/smb_rename.c usr/src/uts/common/fs/smbsrv/smb_server.c usr/src/uts/common/fs/smbsrv/smb_session.c usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c usr/src/uts/common/fs/smbsrv/smb_set_information.c usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c usr/src/uts/common/fs/smbsrv/smb_tree.c usr/src/uts/common/smbsrv/smb_inet.h usr/src/uts/common/smbsrv/smb_kproto.h usr/src/uts/common/smbsrv/smb_ktypes.h usr/src/uts/common/smbsrv/smbinfo.h
diffstat 38 files changed, 587 insertions(+), 505 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/idmap/idmap/idmap.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/cmd/idmap/idmap/idmap.c	Thu Mar 12 15:41:34 2009 -0700
@@ -1484,6 +1484,8 @@
 	name_mapping_t	nm;
 	char		*rule_text;
 
+	(void) memset(&nm, 0, sizeof (nm));
+
 	switch (how->map_type) {
 	case IDMAP_MAP_TYPE_DS_AD:
 		(void) fprintf(stderr,
--- a/usr/src/cmd/idmap/idmapd/dbutils.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/cmd/idmap/idmapd/dbutils.c	Thu Mar 12 15:41:34 2009 -0700
@@ -1355,33 +1355,24 @@
 				continue;
 			res->id.idmap_id_u.uid = wksids[i].pid;
 			res->direction = wksids[i].direction;
-			if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
-				res->info.how.map_type =
-				    IDMAP_MAP_TYPE_KNOWN_SID;
-				res->info.src = IDMAP_MAP_SRC_HARD_CODED;
-			}
+			res->info.how.map_type = IDMAP_MAP_TYPE_KNOWN_SID;
+			res->info.src = IDMAP_MAP_SRC_HARD_CODED;
 			return (IDMAP_SUCCESS);
 		case IDMAP_GID:
 			if (wksids[i].is_user == 1)
 				continue;
 			res->id.idmap_id_u.gid = wksids[i].pid;
 			res->direction = wksids[i].direction;
-			if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
-				res->info.how.map_type =
-				    IDMAP_MAP_TYPE_KNOWN_SID;
-				res->info.src = IDMAP_MAP_SRC_HARD_CODED;
-			}
+			res->info.how.map_type = IDMAP_MAP_TYPE_KNOWN_SID;
+			res->info.src = IDMAP_MAP_SRC_HARD_CODED;
 			return (IDMAP_SUCCESS);
 		case IDMAP_POSIXID:
 			res->id.idmap_id_u.uid = wksids[i].pid;
 			res->id.idtype = (!wksids[i].is_user) ?
 			    IDMAP_GID : IDMAP_UID;
 			res->direction = wksids[i].direction;
-			if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
-				res->info.how.map_type =
-				    IDMAP_MAP_TYPE_KNOWN_SID;
-				res->info.src = IDMAP_MAP_SRC_HARD_CODED;
-			}
+			res->info.how.map_type = IDMAP_MAP_TYPE_KNOWN_SID;
+			res->info.src = IDMAP_MAP_SRC_HARD_CODED;
 			return (IDMAP_SUCCESS);
 		default:
 			return (IDMAP_ERR_NOTSUPPORTED);
@@ -1414,11 +1405,8 @@
 				return (IDMAP_ERR_MEMORY);
 			}
 			res->direction = wksids[i].direction;
-			if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
-				res->info.how.map_type =
-				    IDMAP_MAP_TYPE_KNOWN_SID;
-				res->info.src = IDMAP_MAP_SRC_HARD_CODED;
-			}
+			res->info.how.map_type = IDMAP_MAP_TYPE_KNOWN_SID;
+			res->info.src = IDMAP_MAP_SRC_HARD_CODED;
 			return (IDMAP_SUCCESS);
 		}
 	}
@@ -2463,7 +2451,7 @@
 	if (res->id.idtype == IDMAP_SID)
 		res->id.idtype = is_user ? IDMAP_USID : IDMAP_GSID;
 
-	if (!fallback && req->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
+	if (!fallback) {
 		res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID;
 		res->info.src = IDMAP_MAP_SRC_ALGORITHMIC;
 	}
@@ -2530,10 +2518,8 @@
 	default:
 		return (IDMAP_ERR_NOTSUPPORTED);
 	}
-	if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) {
-		res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID;
-		res->info.src = IDMAP_MAP_SRC_ALGORITHMIC;
-	}
+	res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID;
+	res->info.src = IDMAP_MAP_SRC_ALGORITHMIC;
 	return (IDMAP_SUCCESS);
 }
 
@@ -2824,7 +2810,6 @@
 out:
 	if (sql != NULL)
 		sqlite_freemem(sql);
-	res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED;
 	if (retcode == IDMAP_SUCCESS) {
 		if (values[1] != NULL)
 			res->direction =
@@ -2843,6 +2828,10 @@
 		idmap_namerule_set(rule, values[3], values[2],
 		    values[0], is_wuser, is_user, strtol(values[4], &end, 10),
 		    res->direction);
+	}
+
+	if (retcode != IDMAP_ERR_NOTFOUND) {
+		res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED;
 		res->info.src = IDMAP_MAP_SRC_NEW;
 	}
 
@@ -3997,7 +3986,6 @@
 out:
 	if (sql != NULL)
 		sqlite_freemem(sql);
-	res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED;
 	if (retcode == IDMAP_SUCCESS) {
 		res->id.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID;
 
@@ -4021,8 +4009,13 @@
 		    is_user, strtol(values[3], &end, 10),
 		    strtol(values[5], &end, 10),
 		    rule->direction);
+	}
+
+	if (retcode != IDMAP_ERR_NOTFOUND) {
+		res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED;
 		res->info.src = IDMAP_MAP_SRC_NEW;
 	}
+
 	if (vm != NULL)
 		(void) sqlite_finalize(vm, NULL);
 	return (retcode);
--- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c	Thu Mar 12 15:41:34 2009 -0700
@@ -24,6 +24,8 @@
  */
 
 #include <sys/mdb_modapi.h>
+#include <sys/thread.h>
+#include <sys/taskq_impl.h>
 #include <smbsrv/smb_vops.h>
 #include <smbsrv/smb.h>
 #include <smbsrv/smb_ktypes.h>
@@ -246,6 +248,7 @@
 	SMB_COM_ENTRY(SMB_COM_NT_TRANSACT, "No"),
 	SMB_COM_ENTRY(SMB_COM_NT_TRANSACT_SECONDARY, "No"),
 	SMB_COM_ENTRY(SMB_COM_NT_CREATE_ANDX, "No"),
+	SMB_COM_ENTRY(0xA3, "?"),
 	SMB_COM_ENTRY(SMB_COM_NT_CANCEL, "No"),
 	SMB_COM_ENTRY(SMB_COM_NT_RENAME, "No"),
 	SMB_COM_ENTRY(0xA6, "?"),
@@ -303,6 +306,7 @@
 	SMB_COM_ENTRY(SMB_COM_WRITE_BULK_DATA, "No"),
 	SMB_COM_ENTRY(0xDB, "?"),
 	SMB_COM_ENTRY(0xDC, "?"),
+	SMB_COM_ENTRY(0xDD, "?"),
 	SMB_COM_ENTRY(0xDE, "?"),
 	SMB_COM_ENTRY(0xDF, "?"),
 	SMB_COM_ENTRY(0xE0, "?"),
@@ -370,6 +374,7 @@
 static int smb_dcmd_setopt(uint_t, int, mdb_arg_t *);
 static int smb_obj_expand(uintptr_t, uint_t, const smb_exp_t *, ulong_t);
 static int smb_obj_list(const char *, uint_t, uint_t);
+static int smb_worker_findstack(uintptr_t);
 
 /*
  * MDB module linkage information:
@@ -805,12 +810,13 @@
 				mdb_printf(
 				    "%<b>%<u>%-?s "
 				    "%-16s "
-				    "%-16s%</u>\n",
+				    "%-16s%</u>%</b>\n",
 				    "SESSION", "CLIENT_IP_ADDR",
 				    "LOCAL_IP_ADDR");
+
 			mdb_printf(
-			    "%-?p %-16I %-16I\n", addr, se->ipaddr,
-			    se->local_ipaddr);
+			    "%-?p %-16I %-16I\n", addr, se->ipaddr.a_ipv4,
+			    se->local_ipaddr.a_ipv4);
 		}
 	}
 	if (smb_obj_expand(addr, opts, smb_session_exp, indent))
@@ -870,7 +876,7 @@
 
 		if (opts & SMB_OPT_VERBOSE) {
 			mdb_printf(
-			    "%<b>%<u>SMB request information (%p):"
+			    "%</b>%</u>SMB request information (%p):"
 			    "%</u>%</b>\n\n", addr);
 			mdb_printf("First SMB COM: %u (%s)\n",
 			    sr->first_smb_com,
@@ -884,16 +890,15 @@
 			    sr->smb_fid, sr->fid_ofile);
 			mdb_printf("PID: %u\n", sr->smb_pid);
 			mdb_printf("MID: %u\n\n", sr->smb_mid);
+			smb_worker_findstack((uintptr_t)sr->sr_worker);
 		} else {
 			if (DCMD_HDRSPEC(flags))
 				mdb_printf(
-				    "%<b>%<u>"
-				    "%-?s "
-				    "%s%</u>%</b>\n"
-				    "ADDR", "COM");
+				    "%<b>%<u>%-?s %-?s %-16s %s%</u>%</b>\n",
+				    "ADDR", "Worker", "STATE", "COM");
 
-			mdb_printf("%-?p %s\n", addr, state,
-			    smb_com[sr->first_smb_com]);
+			mdb_printf("%-?p %-?p %-16s %s\n", addr, sr->sr_worker,
+			    state, smb_com[sr->first_smb_com]);
 		}
 	}
 	return (DCMD_OK);
@@ -2134,3 +2139,38 @@
 	}
 	return (DCMD_OK);
 }
+
+static int
+smb_worker_findstack(uintptr_t addr)
+{
+	kthread_t	t;
+	taskq_t		tq;
+	char		cmd[80];
+	mdb_arg_t	cmdarg;
+
+	if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) {
+		mdb_warn("failed to read kthread_t at %p", addr);
+		return (DCMD_ERR);
+	}
+
+	if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1)
+		tq.tq_name[0] = '\0';
+
+	mdb_inc_indent(2);
+
+	mdb_printf("PC: %a", t.t_pc);
+	if (t.t_tid == 0) {
+		if (tq.tq_name[0] != '\0')
+			mdb_printf("    TASKQ: %s\n", tq.tq_name);
+		else
+			mdb_printf("    THREAD: %a()\n", t.t_startpc);
+	}
+
+	mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", 16);
+	cmdarg.a_type = MDB_TYPE_STRING;
+	cmdarg.a_un.a_str = cmd;
+	(void) mdb_call_dcmd("findstack", addr, DCMD_ADDRSPEC, 1, &cmdarg);
+	mdb_dec_indent(2);
+	mdb_printf("\n");
+	return (DCMD_OK);
+}
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c	Thu Mar 12 15:41:34 2009 -0700
@@ -603,6 +603,8 @@
 	default:
 		(void) fprintf(stderr, gettext("failed to join %s: %s\n"),
 		    jdi.domain_name, xlate_nt_status(status));
+		(void) fprintf(stderr, gettext("Please refer to the system log"
+		    " for more information.\n"));
 		bzero(&jdi, sizeof (jdi));
 		return (1);
 	}
--- a/usr/src/common/smbsrv/smb_inet.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/common/smbsrv/smb_inet.c	Thu Mar 12 15:41:34 2009 -0700
@@ -41,7 +41,23 @@
 const struct in6_addr ipv6addr_any = IN6ADDR_ANY_INIT;
 
 boolean_t
-smb_inet_equal(smb_inaddr_t *ip1, smb_inaddr_t *ip2, uint32_t v4mask)
+smb_inet_equal(smb_inaddr_t *ip1, smb_inaddr_t *ip2)
+{
+	if ((ip1->a_family == AF_INET) &&
+	    (ip2->a_family == AF_INET) &&
+	    (ip1->a_ipv4 == ip2->a_ipv4))
+		return (B_TRUE);
+
+	if ((ip1->a_family == AF_INET6) &&
+	    (ip2->a_family == AF_INET6) &&
+	    (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, IPV6_ADDR_LEN)))
+		return (B_TRUE);
+	else
+		return (B_FALSE);
+}
+
+boolean_t
+smb_inet_same_subnet(smb_inaddr_t *ip1, smb_inaddr_t *ip2, uint32_t v4mask)
 {
 	if ((ip1->a_family == AF_INET) &&
 	    (ip2->a_family == AF_INET) &&
--- a/usr/src/common/smbsrv/smb_native.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/common/smbsrv/smb_native.c	Thu Mar 12 15:41:34 2009 -0700
@@ -19,12 +19,10 @@
  * 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.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * This module defines generic functions to map Native OS and Native
  * LanMan names to values.
@@ -39,11 +37,26 @@
 #include <smbsrv/string.h>
 #include <smbsrv/smbinfo.h>
 
+typedef struct smb_native {
+	int sn_value;
+	const char *sn_name;
+} smb_native_t;
+
 /*
  * smbnative_os_value
  *
  * Return the appropriate native OS value for the specified native OS name.
  *
+ * Example OS values used by Windows:
+ *
+ *	Windows 4.0, Windows NT, Windows NT 4.0
+ *	Windows 5.0, Windows 5.1
+ *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
+ *	Windows 2002
+ *	Windows .NET
+ *	Windows Server 2003
+ *	Windows XP
+ *
  * Windows 2000 server:            "Windows 2000 2195"
  * Windows XP Professional client: "Windows 2002 2543"
  * Windows XP PDC server:          "Windows 5.1"
@@ -58,14 +71,9 @@
  * Samba reports UNIX as its Native OS, which we can map to NT 4.0.
  */
 int
-smbnative_os_value(char *native_os)
+smbnative_os_value(const char *native_os)
 {
-	typedef struct native_os_table {
-		int os_value;
-		char *os_name;
-	} native_os_table_t;
-
-	static native_os_table_t os_table[] = {
+	static smb_native_t os_table[] = {
 		{ NATIVE_OS_WINNT,	"Windows NT 4.0"	},
 		{ NATIVE_OS_WINNT,	"Windows NT"		},
 		{ NATIVE_OS_WIN95,	"Windows 4.0"		},
@@ -76,7 +84,7 @@
 		{ NATIVE_OS_WIN2000,	"Windows 2000"		},
 		{ NATIVE_OS_WIN2000,	"Windows 2002"		},
 		{ NATIVE_OS_WIN2000,	"Windows .NET"		},
-		{ NATIVE_OS_WIN2000,	"Windows Server 2003"	},
+		{ NATIVE_OS_WIN2000,	"Windows Server"	},
 		{ NATIVE_OS_WIN2000,	"Windows XP"		},
 		{ NATIVE_OS_WINNT,	"UNIX"			},
 		{ NATIVE_OS_MACOS,	"MacOS" 		}
@@ -84,31 +92,28 @@
 
 	int i;
 	int len;
-	char *os_name;
+	const char *name;
+
+	if (native_os == NULL)
+		return (NATIVE_OS_UNKNOWN);
 
-	if (native_os == NULL) {
-		return (NATIVE_OS_UNKNOWN);
+	/*
+	 * Windows Vista sends an empty native OS string.
+	 */
+	if (*native_os == '\0')
+		return (NATIVE_OS_WIN2000);
+
+	for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) {
+		name = os_table[i].sn_name;
+		len = strlen(name);
+
+		if (utf8_strncasecmp(name, native_os, len) == 0)
+			return (os_table[i].sn_value);
 	}
 
-	if (*native_os == '\0') {
-		/*
-		 * Windows Vista sends an empty native OS string.
-		 */
-		return (NATIVE_OS_WIN2000);
-	}
-
-	for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) {
-		os_name = os_table[i].os_name;
-		len = strlen(os_name);
-
-		if (utf8_strncasecmp(os_name, native_os, len) == 0) {
-			return (os_table[i].os_value);
-		}
-	}
 	return (NATIVE_OS_UNKNOWN);
 }
 
-
 /*
  * smbnative_lm_value
  *
@@ -117,129 +122,100 @@
  * clients that means we can miss the first character, so we do an
  * additional check starting from the second character.
  *
- * DAVE (Thursby Software: CIFS for MacOS) sometimes uses a Unicode
- * character in the LanMan name. Variations seen so far are:
- *
- *	44 00 41 00 56 00 45 00 00 00        D.A.V.E...
+ * Example LanMan values:
  *
- *	44 00 41 00 56 00 45 00 22 21 20 00 56 00 32 00
- *	2E 00 35 00 2E 00 31 00 00 00        D.A.V.E."!..V.2...5...1...
- *
- * Samba reports its own name (Samba) as its Native LM, which we can
- * map to NT LM 4.0.
+ *	NT LAN Manager 4.0
+ *	Windows 4.0
+ *	Windows NT, Windows NT 4.0
+ *	Windows 2000 LAN Manager
+ *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
+ *	Windows 2002, Windows 2002 5.1
+ *	Windows .NET, Windows .NET 5.2
+ *	Windows Server 2003
+ *	Windows XP
+ *	NETSMB		(Solaris CIFS client)
+ *	DAVE		(Thursby Software: CIFS for MacOS)
+ *	Samba
  */
 int
-smbnative_lm_value(char *native_lm)
+smbnative_lm_value(const char *native_lm)
 {
-	typedef struct native_lm_table {
-		int lm_value;
-		char *lm_name;
-	} native_lm_table_t;
-
-	static native_lm_table_t lm_table[] = {
+	static smb_native_t lm_table[] = {
 		{ NATIVE_LM_NT,		"NT LAN Manager 4.0"		},
-		{ NATIVE_LM_NT,		"Windows NT 4.0"		},
 		{ NATIVE_LM_NT,		"Windows NT"			},
 		{ NATIVE_LM_NT,		"Windows 4.0"			},
-		{ NATIVE_LM_WIN2000,	"Windows 2000 LAN Manager"	},
-		{ NATIVE_LM_WIN2000,	"Windows 2000 5.0"		},
-		{ NATIVE_LM_WIN2000,	"Windows 2000 5.1"		},
-		{ NATIVE_LM_WIN2000,	"Windows 2000",			},
-		{ NATIVE_LM_WIN2000,	"Windows 2002 5.1"		},
-		{ NATIVE_LM_WIN2000,	"Windows 2002"			},
-		{ NATIVE_LM_WIN2000,	"Windows .NET 5.2"		},
-		{ NATIVE_LM_WIN2000,	"Windows .NET"			},
-		{ NATIVE_LM_WIN2000,	"Windows Server 2003"		},
-		{ NATIVE_LM_WIN2000,	"Windows XP"			},
-		{ NATIVE_LM_NT,		"Samba"				},
 		{ NATIVE_LM_NT,		"DAVE"				}
 	};
 
 	int i;
 	int len;
-	char *lm_name;
+	const char *name;
+
+	/*
+	 * Windows Vista sends an empty native LM string.
+	 */
+	if (native_lm == NULL || *native_lm == '\0')
+		return (NATIVE_LM_WIN2000);
 
-	if (native_lm == NULL) {
-		return (NATIVE_LM_NONE);
+	for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) {
+		name = lm_table[i].sn_name;
+		len = strlen(name);
+
+		if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
+		    (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
+			return (lm_table[i].sn_value);
+		}
 	}
 
-	if (*native_lm == '\0') {
-		/*
-		 * Windows Vista sends an empty native LM string.
-		 */
-		return (NATIVE_LM_WIN2000);
-	}
-
-	for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) {
-		lm_name = lm_table[i].lm_name;
-		len = strlen(lm_name);
-
-		if ((utf8_strncasecmp(lm_name, native_lm, len) == 0) ||
-		    (utf8_strncasecmp(&lm_name[1], native_lm, len - 1) == 0)) {
-			return (lm_table[i].lm_value);
-		}
-	}
-	return (NATIVE_LM_NONE);
+	return (NATIVE_LM_WIN2000);
 }
 
 /*
  * smbnative_pdc_value
  *
- * This function is used when NetFORCE contacting a PDC
- * to authenticate a connected user to determine and keep
- * the PDC type.
+ * This function is called when libsmbrdr connects to a PDC.
+ * The PDC type is derived from the Native LanMan string.
+ * The PDC value will default to PDC_WIN2000.
+ *
+ * Example strings:
  *
- * The reason for adding this functionality is that NetFORCE
- * doesn't support Samba PDC but code didn't check the PDC type
- * and do authentication agains any PDC. This behaviour could
- * cause problem in some circumstances.
- * Now that we determine the PDC type the authentication code
- * can be configured (by smb.samba.pdc env var) to return access
- * denied to authentication attempts when PDC is Samba.
+ *	NT LAN Manager 4.0
+ *	Windows 4.0, Windows NT, Windows NT 4.0
+ *	Windows 2000 LAN Manager
+ *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
+ *	Windows 2002, Windows 2002 5.1
+ *	Windows .NET, Windows .NET 5.2
+ *	Samba
+ *	DAVE
  */
 int
-smbnative_pdc_value(char *native_lm)
+smbnative_pdc_value(const char *native_lm)
 {
-	typedef struct pdc_table {
-		int pdc_value;
-		char *pdc_lmname;
-	} pdc_table_t;
-
-	static pdc_table_t pdc_table[] = {
+	static smb_native_t pdc_table[] = {
 		{ PDC_WINNT,	"NT LAN Manager 4.0"		},
 		{ PDC_WINNT,	"Windows NT 4.0"		},
 		{ PDC_WINNT,	"Windows NT"			},
 		{ PDC_WINNT,	"Windows 4.0"			},
-		{ PDC_WIN2000,	"Windows 2000 LAN Manager"	},
-		{ PDC_WIN2000,	"Windows 2000 5.0"		},
-		{ PDC_WIN2000,	"Windows 2000 5.1"		},
-		{ PDC_WIN2000,	"Windows 2000",			},
-		{ PDC_WIN2000,	"Windows 2002 5.1"		},
-		{ PDC_WIN2000,	"Windows 2002"			},
-		{ PDC_WIN2000,	"Windows .NET 5.2"		},
-		{ PDC_WIN2000,	"Windows .NET"			},
-		{ PDC_SAMBA,	"Samba"				},
-		{ PDC_WINNT,	"DAVE"				}
+		{ PDC_WINNT,	"DAVE"				},
+		{ PDC_SAMBA,	"Samba"				}
 	};
 
 	int i;
 	int len;
-	char *pdc_lmname;
+	const char *name;
 
-	if (native_lm == 0) {
-		return (PDC_UNKNOWN);
-	}
+	if (native_lm == NULL || *native_lm == '\0')
+		return (PDC_WIN2000);
 
 	for (i = 0; i < sizeof (pdc_table)/sizeof (pdc_table[0]); ++i) {
-		pdc_lmname = pdc_table[i].pdc_lmname;
-		len = strlen(pdc_lmname);
+		name = pdc_table[i].sn_name;
+		len = strlen(name);
 
-		if ((utf8_strncasecmp(pdc_lmname, native_lm, len) == 0) ||
-		    (utf8_strncasecmp(&pdc_lmname[1], native_lm, len - 1)
-		    == 0)) {
-			return (pdc_table[i].pdc_value);
+		if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
+		    (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
+			return (pdc_table[i].sn_value);
 		}
 	}
 
-	return (PDC_UNKNOWN);
+	return (PDC_WIN2000);
 }
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c	Thu Mar 12 15:41:34 2009 -0700
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <sys/time.h>
 #include <sys/systm.h>
+#include <syslog.h>
 
 #include <smbsrv/libsmb.h>
 #include <smbsrv/libsmbrdr.h>
@@ -114,8 +115,10 @@
 	DWORD status;
 
 	if (netr_open(server, domain, &netr_handle) == 0) {
-		status = netlogon_auth(server, &netr_handle,
-		    NETR_FLG_INIT);
+		if ((status = netlogon_auth(server, &netr_handle,
+		    NETR_FLG_INIT)) != NT_STATUS_SUCCESS)
+			syslog(LOG_NOTICE, "Failed to establish NETLOGON "
+			    "credential chain");
 		(void) netr_close(&netr_handle);
 	} else {
 		status = NT_STATUS_OPEN_FAILED;
@@ -136,6 +139,7 @@
 	int erc;
 	DWORD status;
 	char machine_passwd[NETR_MACHINE_ACCT_PASSWD_MAX];
+	smb_adjoin_status_t err;
 
 	machine_passwd[0] = '\0';
 
@@ -149,12 +153,14 @@
 	if (erc == AUTH_USER_GRANT) {
 		if (mlsvc_ntjoin_support == B_FALSE) {
 
-			if (smb_ads_join(dinfo->d_fqdomain, user, plain_text,
-			    machine_passwd, sizeof (machine_passwd))
-			    == SMB_ADJOIN_SUCCESS)
+			if ((err = smb_ads_join(dinfo->d_fqdomain, user,
+			    plain_text, machine_passwd,
+			    sizeof (machine_passwd))) == SMB_ADJOIN_SUCCESS) {
 				status = NT_STATUS_SUCCESS;
-			else
+			} else {
+				smb_ads_join_errmsg(err);
 				status = NT_STATUS_UNSUCCESSFUL;
+			}
 		} else {
 			if (mlsvc_user_getauth(dinfo->d_dc, user, &auth)
 			    != 0) {
@@ -174,8 +180,11 @@
 		if (status == NT_STATUS_SUCCESS) {
 			erc = smb_setdomainprops(NULL, dinfo->d_dc,
 			    machine_passwd);
-			if (erc != 0)
+			if (erc != 0) {
+				syslog(LOG_NOTICE, "Failed to update CIFS "
+				    "configuration");
 				return (NT_STATUS_UNSUCCESSFUL);
+			}
 
 			status = mlsvc_netlogon(dinfo->d_dc, dinfo->d_nbdomain);
 		}
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Thu Mar 12 15:41:34 2009 -0700
@@ -725,7 +725,8 @@
 int smb_nic_delhost(const char *);
 int smb_nic_getfirst(smb_niciter_t *);
 int smb_nic_getnext(smb_niciter_t *);
-boolean_t smb_nic_exists(smb_inaddr_t *, boolean_t);
+boolean_t smb_nic_is_local(smb_inaddr_t *);
+boolean_t smb_nic_is_same_subnet(smb_inaddr_t *);
 
 /* NIC Monitoring functions */
 int smb_nicmon_start(const char *);
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Thu Mar 12 15:41:34 2009 -0700
@@ -252,7 +252,8 @@
 	smb_msgbuf_word_align;
 	smb_nic_addhost;
 	smb_nic_delhost;
-	smb_nic_exists;
+	smb_nic_is_local;
+	smb_nic_is_same_subnet;
 	smb_nic_fini;
 	smb_nic_getfirst;
 	smb_nic_getnext;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c	Thu Mar 12 15:41:34 2009 -0700
@@ -288,6 +288,7 @@
 			bzero(ipaddr, sizeof (smb_inaddr_t));
 		} else {
 			(void) memcpy(ipaddr, h->h_addr, h->h_length);
+			ipaddr->a_family = h->h_addrtype;
 			freehostent(h);
 		}
 		xdr_free(xdr_string, (char *)&srvname);
--- a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c	Thu Mar 12 15:41:34 2009 -0700
@@ -269,19 +269,35 @@
 }
 
 boolean_t
-smb_nic_exists(smb_inaddr_t *ipaddr, boolean_t use_mask)
+smb_nic_is_local(smb_inaddr_t *ipaddr)
 {
 	smb_nic_t *cfg;
-	uint32_t mask = 0;
 	int i;
 
 	(void) rw_rdlock(&smb_niclist.nl_rwl);
 
 	for (i = 0; i < smb_niclist.nl_cnt; i++) {
 		cfg = &smb_niclist.nl_nics[i];
-		if (use_mask)
-			mask = cfg->nic_mask;
-		if (smb_inet_equal(ipaddr, &cfg->nic_ip, mask)) {
+		if (smb_inet_equal(ipaddr, &cfg->nic_ip)) {
+			(void) rw_unlock(&smb_niclist.nl_rwl);
+			return (B_TRUE);
+		}
+	}
+	(void) rw_unlock(&smb_niclist.nl_rwl);
+	return (B_FALSE);
+}
+
+boolean_t
+smb_nic_is_same_subnet(smb_inaddr_t *ipaddr)
+{
+	smb_nic_t *cfg;
+	int i;
+
+	(void) rw_rdlock(&smb_niclist.nl_rwl);
+
+	for (i = 0; i < smb_niclist.nl_cnt; i++) {
+		cfg = &smb_niclist.nl_nics[i];
+		if (smb_inet_same_subnet(ipaddr, &cfg->nic_ip, cfg->nic_mask)) {
 			(void) rw_unlock(&smb_niclist.nl_rwl);
 			return (B_TRUE);
 		}
--- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c	Thu Mar 12 15:41:34 2009 -0700
@@ -726,12 +726,19 @@
 			break;
 		}
 
-		/* strip last component off if there is one */
-		if ((cp = strrchr(cp, '/')) != NULL) {
-			*cp = '\0';
-			if (tmppath[0] == '\0')
-				(void) strcpy(tmppath, "/");
-		}
+		if (strcmp(tmppath, "/") == 0)
+			break;
+
+		if ((cp = strrchr(tmppath, '/')) == NULL)
+			break;
+
+		/*
+		 * The path has multiple components.
+		 * Remove the last component and try again.
+		 */
+		*cp = '\0';
+		if (tmppath[0] == '\0')
+			(void) strcpy(tmppath, "/");
 
 		cp = tmppath;
 	}
--- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h	Thu Mar 12 15:41:34 2009 -0700
@@ -19,15 +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	_LIBSMBNS_H
 #define	_LIBSMBNS_H
 
-#pragma ident	"@(#)libsmbns.h	1.10	08/07/24 SMI"
-
 #include <ldap.h>
 #include <smbsrv/libsmb.h>
 
@@ -55,13 +53,11 @@
 typedef enum smb_adjoin_status {
 	SMB_ADJOIN_SUCCESS = 0,
 	SMB_ADJOIN_ERR_GET_HANDLE,
-	SMB_ADJOIN_ERR_GEN_PASSWD,
 	SMB_ADJOIN_ERR_GET_DCLEVEL,
 	SMB_ADJOIN_ERR_ADD_TRUST_ACCT,
 	SMB_ADJOIN_ERR_MOD_TRUST_ACCT,
 	SMB_ADJOIN_ERR_DUP_TRUST_ACCT,
 	SMB_ADJOIN_ERR_TRUST_ACCT,
-	SMB_ADJOIN_ERR_GET_ENCTYPES,
 	SMB_ADJOIN_ERR_INIT_KRB_CTX,
 	SMB_ADJOIN_ERR_GET_SPNS,
 	SMB_ADJOIN_ERR_KSETPWD,
@@ -69,8 +65,7 @@
 	SMB_ADJOIN_ERR_WRITE_KEYTAB,
 	SMB_ADJOIN_ERR_IDMAP_SET_DOMAIN,
 	SMB_ADJOIN_ERR_IDMAP_REFRESH,
-	SMB_ADJOIN_ERR_COMMIT_KEYTAB,
-	SMB_ADJOIN_NUM_STATUS
+	SMB_ADJOIN_ERR_COMMIT_KEYTAB
 } smb_adjoin_status_t;
 
 /* ADS functions */
@@ -88,7 +83,7 @@
 extern int smb_ads_add_share(smb_ads_handle_t *, const char *, const char *,
     const char *);
 extern smb_adjoin_status_t smb_ads_join(char *, char *, char *, char *, int);
-extern char *smb_adjoin_report_err(smb_adjoin_status_t);
+extern void smb_ads_join_errmsg(smb_adjoin_status_t);
 extern boolean_t smb_ads_lookup_msdcs(char *, char *, char *, uint32_t);
 
 /* DYNDNS functions */
--- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers	Thu Mar 12 15:41:34 2009 -0700
@@ -44,12 +44,12 @@
 	dyndns_stop;
 	dyndns_update;
 	dyndns_update_zones;
-	smb_adjoin_report_err;
 	smb_ads_add_share;
 	smb_ads_build_unc_name;
 	smb_ads_close;
 	smb_ads_init;
 	smb_ads_join;
+	smb_ads_join_errmsg;
 	smb_ads_lookup_msdcs;
 	smb_ads_lookup_share;
 	smb_ads_open;
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c	Thu Mar 12 15:41:34 2009 -0700
@@ -100,7 +100,6 @@
  * Length of "dc=" prefix.
  */
 #define	SMB_ADS_DN_PREFIX_LEN	3
-#define	SMB_ADS_MSDCS_SVC_CNT	2
 
 static char *smb_ads_computer_objcls[] = {
 	"top", "person", "organizationalPerson",
@@ -118,28 +117,6 @@
 static char smb_ads_site[SMB_ADS_SITE_MAX];
 static mutex_t smb_ads_site_mtx;
 
-/*
- * smb_ads_adjoin_errmsg
- *
- * Use the adjoin return status defined in adjoin_status_t as the index
- * to this table.
- */
-static char *smb_ads_adjoin_errmsg[] = {
-	"ADJOIN succeeded.",
-	"ADJOIN failed to get handle.",
-	"ADJOIN failed to generate machine password.",
-	"ADJOIN failed to add workstation trust account.",
-	"ADJOIN failed to modify workstation trust account.",
-	"ADJOIN failed to get list of encryption types.",
-	"ADJOIN failed to initialize kerberos context.",
-	"ADJOIN failed to get Kerberos principal.",
-	"ADJOIN failed to set machine account password on AD.",
-	"ADJOIN failed to modify CONTROL attribute of the account.",
-	"ADJOIN failed to write Kerberos keytab file.",
-	"ADJOIN failed to configure domain_name property for idmapd.",
-	"ADJOIN failed to refresh idmap service."
-};
-
 /* attribute/value pair */
 typedef struct smb_ads_avpair {
 	char *avp_attr;
@@ -163,7 +140,7 @@
     smb_ads_avpair_t *, int, char *);
 static int smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *, int, char *);
 static krb5_kvno smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t *, char *);
-static int smb_ads_gen_machine_passwd(char *, int);
+static void smb_ads_gen_machine_passwd(char *, int);
 static smb_ads_host_info_t *smb_ads_get_cached_host(void);
 static void smb_ads_set_cached_host(smb_ads_host_info_t *);
 static void smb_ads_free_cached_host(void);
@@ -612,15 +589,15 @@
 	    C_IN, T_SRV, msg.buf, sizeof (msg.buf));
 
 	if (len < 0) {
-		smb_tracef("smbns_ads: DNS query for '%s' failed (%s)",
+		syslog(LOG_NOTICE, "DNS query for %s failed: %s",
 		    msdcs_svc_name, hstrerror(res_state.res_h_errno));
 		res_ndestroy(&res_state);
 		return (NULL);
 	}
 
 	if (len > sizeof (msg.buf)) {
-		smb_tracef("smbns_ads: DNS query %s: message too big (%d)",
-		    msdcs_svc_name, len);
+		syslog(LOG_NOTICE,
+		    "DNS query for %s failed: too big", msdcs_svc_name);
 		res_ndestroy(&res_state);
 		return (NULL);
 	}
@@ -631,8 +608,8 @@
 
 	/* check truncated message bit */
 	if (msg.hdr.tc)
-		smb_tracef("smbns_ads: DNS query for '%s' detected "
-		    "truncated TCP reply message", msdcs_svc_name);
+		syslog(LOG_NOTICE,
+		    "DNS query for %s failed: truncated", msdcs_svc_name);
 
 	qcnt = ntohs(msg.hdr.qdcount);
 	ans_cnt = ntohs(msg.hdr.ancount);
@@ -684,19 +661,20 @@
 }
 
 /*
- * smb_ads_set_site_service
+ * smb_ads_get_site_service
  *
- * This method sets the name of the site, to look for the ADS domain.
+ * Gets the msdcs SRV RR for the specified site.
  */
 static void
-smb_ads_set_site_service(char *site_service)
+smb_ads_get_site_service(char *site_service, size_t len)
 {
 	(void) mutex_lock(&smb_ads_site_mtx);
 	if (*smb_ads_site == '\0')
 		*site_service = '\0';
 	else
-		(void) snprintf(site_service, sizeof (site_service),
+		(void) snprintf(site_service, len,
 		    SMB_ADS_MSDCS_SRV_SITE_RR, smb_ads_site);
+
 	(void) mutex_unlock(&smb_ads_site_mtx);
 }
 
@@ -764,8 +742,6 @@
 	smb_ads_host_list_t *hlist;
 	smb_ads_host_info_t *hlistp = NULL, *hentry = NULL, *host = NULL;
 	char site_service[MAXHOSTNAMELEN];
-	char *msdcs_svc_name[SMB_ADS_MSDCS_SVC_CNT] =
-	    {site_service, SMB_ADS_MSDCS_SRV_DC_RR};
 
 	if ((sought) && (*sought == '\0'))
 		sought = NULL;
@@ -791,20 +767,19 @@
 		smb_ads_free_cached_host();
 	}
 
-	smb_ads_set_site_service(site_service);
 
 	/*
 	 * First look for ADS hosts in ADS site if configured.  Then try
 	 * without ADS site info.
 	 */
-	for (i = 0; i < SMB_ADS_MSDCS_SVC_CNT; i++) {
-		if (*msdcs_svc_name[i] == '\0')
-			continue;
-
-		hlist = smb_ads_query_dns_server(domain, msdcs_svc_name[i]);
-		if (hlist != NULL)
-			break;
-	}
+	hlist = NULL;
+	smb_ads_get_site_service(site_service, MAXHOSTNAMELEN);
+	if (*site_service != '\0')
+		hlist = smb_ads_query_dns_server(domain, site_service);
+
+	if (!hlist)
+		hlist = smb_ads_query_dns_server(domain,
+		    SMB_ADS_MSDCS_SRV_DC_RR);
 
 	if ((hlist == NULL) || (hlist->ah_list == NULL) || (hlist->ah_cnt == 0))
 		return (NULL);
@@ -1090,11 +1065,11 @@
 	OM_uint32 min2;
 	(void) gss_display_status(&min2, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID,
 	    &msg_ctx, &msg);
-	smb_tracef("smbns_ads: major status error: %s", (char *)msg.value);
+	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("smbns_ads: minor status error: %s", (char *)msg.value);
+	smb_tracef("minor status: %s", (char *)msg.value);
 	(void) gss_release_buffer(&min2, &msg);
 }
 
@@ -1286,7 +1261,7 @@
 		    &cred, NULL, NULL, sercred);
 		if (stat != LDAP_SUCCESS &&
 		    stat != LDAP_SASL_BIND_IN_PROGRESS) {
-			smb_tracef("smbns_ads: ldap_sasl_bind error: %s",
+			syslog(LOG_NOTICE, "ldap_sasl_bind: %s",
 			    ldap_err2string(stat));
 			if (oid != GSS_C_NO_OID)
 				(void) gss_release_oid(&min, &oid);
@@ -1381,7 +1356,7 @@
 	stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI", &cred, NULL, NULL,
 	    &sercred);
 	if (stat != LDAP_SUCCESS && stat != LDAP_SASL_BIND_IN_PROGRESS) {
-		smb_tracef("smbns_ads: ldap_sasl_bind error: %s:",
+		syslog(LOG_NOTICE, "ldap_sasl_bind: %s",
 		    ldap_err2string(stat));
 		(void) gss_release_buffer(&min, &wrap_outbuf);
 		return (-1);
@@ -1512,8 +1487,7 @@
 	attrs[j]->mod_values = unc_names;
 
 	if ((ret = ldap_add_s(ah->ld, share_dn, attrs)) != LDAP_SUCCESS) {
-		smb_tracef("smbns_ads: %s: ldap_add error: %s",
-		    share_dn, ldap_err2string(ret));
+		smb_tracef("%s: ldap_add: %s", share_dn, ldap_err2string(ret));
 		smb_ads_free_attr(attrs);
 		free(share_dn);
 		return (ret);
@@ -1554,8 +1528,7 @@
 	(void) snprintf(share_dn, len, "cn=%s,%s,%s", adsShareName,
 	    adsContainer, ah->domain_dn);
 	if ((ret = ldap_delete_s(ah->ld, share_dn)) != LDAP_SUCCESS) {
-		smb_tracef("smbns_ads: ldap_delete error: %s",
-		    ldap_err2string(ret));
+		smb_tracef("ldap_delete: %s", ldap_err2string(ret));
 		free(share_dn);
 		return (-1);
 	}
@@ -1672,8 +1645,8 @@
 	if ((ret = ldap_search_s(ah->ld, share_dn,
 	    LDAP_SCOPE_BASE, filter, attrs, 0, &res)) != LDAP_SUCCESS) {
 		if (ret != LDAP_NO_SUCH_OBJECT)
-			smb_tracef("smbns_ads: %s: ldap_search error: %s",
-			    share_dn, ldap_err2string(ret));
+			smb_tracef("%s: ldap_search: %s", share_dn,
+			    ldap_err2string(ret));
 
 		(void) ldap_msgfree(res);
 		free(share_dn);
@@ -2011,7 +1984,7 @@
 	switch (op) {
 	case LDAP_MOD_ADD:
 		if ((ret = ldap_add_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
-			smb_tracef("smbns_ads: ldap_add error: %s",
+			syslog(LOG_NOTICE, "ldap_add: %s",
 			    ldap_err2string(ret));
 			ret = -1;
 		}
@@ -2019,7 +1992,7 @@
 
 	case LDAP_MOD_REPLACE:
 		if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
-			smb_tracef("smbns_ads: ldap_replace error: %s",
+			syslog(LOG_NOTICE, "ldap_modify: %s",
 			    ldap_err2string(ret));
 			ret = -1;
 		}
@@ -2046,8 +2019,7 @@
 	int rc;
 
 	if ((rc = ldap_delete_s(ah->ld, dn)) != LDAP_SUCCESS)
-		smb_tracef("smbns_ads: ldap_delete error: %s",
-		    ldap_err2string(rc));
+		smb_tracef("ldap_delete: %s", ldap_err2string(rc));
 }
 
 /*
@@ -2263,8 +2235,7 @@
 	ctl_val[1] = 0;
 	attrs[0]->mod_values = ctl_val;
 	if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
-		smb_tracef("smbns_ads: ldap_modify error: %s",
-		    ldap_err2string(ret));
+		syslog(LOG_NOTICE, "ldap_modify: %s", ldap_err2string(ret));
 	}
 
 	smb_ads_free_attr(attrs);
@@ -2301,7 +2272,7 @@
  * quality check (three character classes), an uppercase letter is
  * used as the first character of the machine password.
  */
-static int
+static void
 smb_ads_gen_machine_passwd(char *machine_passwd, int bufsz)
 {
 	char *data = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJK"
@@ -2309,8 +2280,8 @@
 	int datalen = strlen(data);
 	int i, data_idx;
 
-	if (!machine_passwd || bufsz == 0)
-		return (-1);
+	assert(machine_passwd);
+	assert(bufsz > 0);
 
 	/*
 	 * The decimal value of upper case 'A' is 65. Randomly pick
@@ -2323,7 +2294,6 @@
 	}
 
 	machine_passwd[bufsz - 1] = 0;
-	return (0);
 }
 
 /*
@@ -2392,11 +2362,7 @@
 		return (SMB_ADJOIN_ERR_GET_HANDLE);
 	}
 
-	if (smb_ads_gen_machine_passwd(machine_passwd, len) != 0) {
-		smb_ads_close(ah);
-		smb_ccache_remove(SMB_CCACHE_PATH);
-		return (SMB_ADJOIN_ERR_GEN_PASSWD);
-	}
+	smb_ads_gen_machine_passwd(machine_passwd, len);
 
 	if ((dclevel = smb_ads_get_dc_level(ah)) == -1) {
 		smb_ads_close(ah);
@@ -2465,7 +2431,7 @@
 		usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
 		    SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
 
-		syslog(LOG_NOTICE, "smbns_ads: Unable to set the "
+		syslog(LOG_NOTICE, "Unable to set the "
 		    "TRUSTED_FOR_DELEGATION userAccountControl flag on "
 		    "the machine account in Active Directory.  Please refer "
 		    "to the Troubleshooting guide for more information.");
@@ -2541,17 +2507,55 @@
 }
 
 /*
- * smb_adjoin_report_err
+ * smb_ads_join_errmsg
  *
  * Display error message for the specific adjoin error code.
  */
-char *
-smb_adjoin_report_err(smb_adjoin_status_t status)
+void
+smb_ads_join_errmsg(smb_adjoin_status_t status)
 {
-	if (status < 0 || status >= SMB_ADJOIN_NUM_STATUS)
-		return ("ADJOIN: unknown status");
-
-	return (smb_ads_adjoin_errmsg[status]);
+	int i;
+	struct xlate_table {
+		smb_adjoin_status_t status;
+		char *msg;
+	} adjoin_table[] = {
+		{ SMB_ADJOIN_ERR_GET_HANDLE, "Failed to connect to an "
+		    "Active Directory server." },
+		{ SMB_ADJOIN_ERR_GET_DCLEVEL, "Unknown functional level of "
+		    "the domain controller. The rootDSE attribute named "
+		    "\"domainControllerFunctionality\" is missing from the "
+		    "Active Directory." },
+		{ SMB_ADJOIN_ERR_ADD_TRUST_ACCT, "Failed to create the "
+		    "workstation trust account." },
+		{ SMB_ADJOIN_ERR_MOD_TRUST_ACCT, "Failed to modify the "
+		    "workstation trust account." },
+		{ SMB_ADJOIN_ERR_DUP_TRUST_ACCT, "Failed to create the "
+		    "workstation trust account because its name is already "
+		    "in use." },
+		{ SMB_ADJOIN_ERR_TRUST_ACCT, "Error in querying the "
+		    "workstation trust account" },
+		{ SMB_ADJOIN_ERR_INIT_KRB_CTX, "Failed to initialize Kerberos "
+		    "context." },
+		{ SMB_ADJOIN_ERR_GET_SPNS, "Failed to get Kerberos "
+		    "principals." },
+		{ SMB_ADJOIN_ERR_KSETPWD, "Failed to set machine password." },
+		{ SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR,  "Failed to modify "
+		    "userAccountControl attribute of the workstation trust "
+		    "account." },
+		{ SMB_ADJOIN_ERR_WRITE_KEYTAB, "Error in writing to local "
+		    "keytab file (i.e /etc/krb5/krb5.keytab)." },
+		{ SMB_ADJOIN_ERR_IDMAP_SET_DOMAIN, "Failed to update idmap "
+		    "configuration." },
+		{ SMB_ADJOIN_ERR_IDMAP_REFRESH, "Failed to refresh idmap "
+		    "service." },
+		{ SMB_ADJOIN_ERR_COMMIT_KEYTAB, "Failed to commit changes to "
+		    "local keytab file (i.e. /etc/krb5/krb5.keytab)." }
+	};
+
+	for (i = 0; i < sizeof (adjoin_table) / sizeof (adjoin_table[0]); i++) {
+		if (adjoin_table[i].status == status)
+			syslog(LOG_NOTICE, "%s", adjoin_table[i].msg);
+	}
 }
 
 /*
@@ -2578,7 +2582,7 @@
 	cnt = hlist->ah_cnt;
 	for (i = 0; i < cnt; i++) {
 		hentry = &hlist->ah_list[i];
-		if (smb_inet_equal(&hentry->ipaddr, &ipaddr, SMB_INET_NOMASK) &&
+		if (smb_inet_equal(&hentry->ipaddr, &ipaddr) &&
 		    (smb_ads_ldap_ping(hentry) == 0))
 			return (hentry);
 	}
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c	Thu Mar 12 15:41: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.
  */
 /*
@@ -178,8 +178,8 @@
 		code = krb5_os_localaddr(k5->ctx, &addresses);
 		if (code != 0) {
 			errmsg = error_message(code);
-			syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "k5_kinit: "
-			    "getting local addresses (%s)"), errmsg);
+			syslog(LOG_ERR, "k5_kinit: getting local addresses "
+			    "(%s)", errmsg);
 			goto cleanup;
 		}
 		krb5_get_init_creds_opt_set_address_list(&options, addresses);
@@ -191,9 +191,8 @@
 		code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);
 		if (code != 0) {
 			errmsg = error_message(code);
-			syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "k5_kinit: "
-			    "resolving keytab %s (%s)"), errmsg,
-			    opts->keytab_name);
+			syslog(LOG_ERR, "k5_kinit: resolving keytab %s (%s)",
+			    errmsg, opts->keytab_name);
 			goto cleanup;
 		}
 	}
@@ -223,16 +222,13 @@
 		switch (opts->action) {
 		case INIT_PW:
 		case INIT_KT:
-			doing = dgettext(TEXT_DOMAIN, "k5_kinit: "
-			    "getting initial credentials");
+			doing = "k5_kinit: getting initial credentials";
 			break;
 		case VALIDATE:
-			doing = dgettext(TEXT_DOMAIN, "k5_kinit: "
-			    "validating credentials");
+			doing = "k5_kinit: validating credentials";
 			break;
 		case RENEW:
-			doing = dgettext(TEXT_DOMAIN, "k5_kinit: "
-			    "renewing credentials");
+			doing = "k5_kinit: renewing credentials";
 			break;
 		}
 
@@ -246,12 +242,10 @@
 			    "You may want the -4 option in the future", doing);
 			return (1);
 		} else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
-			syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "%s "
-			    "(Password incorrect)"), doing);
+			syslog(LOG_ERR, "%s (Password incorrect)", doing);
 		} else {
 			errmsg = error_message(code);
-			syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "%s (%s)"),
-			    doing, errmsg);
+			syslog(LOG_ERR, "%s (%s)", doing, errmsg);
 		}
 		goto cleanup;
 	}
@@ -265,17 +259,15 @@
 	code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me);
 	if (code) {
 		errmsg = error_message(code);
-		syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "k5_kinit: "
-		    "initializing cache %s (%s)"),
-		    opts->k5_cache_name?opts->k5_cache_name:"", errmsg);
+		syslog(LOG_ERR, "k5_kinit: initializing cache %s (%s)",
+		    opts->k5_cache_name ? opts->k5_cache_name : "", errmsg);
 		goto cleanup;
 	}
 
 	code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);
 	if (code) {
 		errmsg = error_message(code);
-		syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "k5_kinit: "
-		    "storing credentials (%s)"), errmsg);
+		syslog(LOG_ERR, "k5_kinit: storing credentials (%s)", errmsg);
 		goto cleanup;
 	}
 
@@ -309,19 +301,16 @@
 	(void) memset(&k5, 0, sizeof (k5));
 
 	if (k5_begin(&opts, &k5) != 0) {
-		syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "smb_kinit: "
-		    "NOT Authenticated to Kerberos v5  k5_begin failed\n"));
+		syslog(LOG_ERR, "NOT authenticated with Kerberos v5. "
+		    "k5_begin failed\n");
 		return (0);
 	}
 
 	authed_k5 = k5_kinit(&opts, &k5);
-	if (authed_k5) {
-		syslog(LOG_DEBUG, dgettext(TEXT_DOMAIN, "smb_kinit: "
-		    "Authenticated to Kerberos v5\n"));
-	} else {
-		syslog(LOG_DEBUG, dgettext(TEXT_DOMAIN, "smb_kinit: "
-		    "NOT Authenticated to Kerberos v5\n"));
-	}
+	if (authed_k5)
+		syslog(LOG_DEBUG, "Authenticated with Kerberos v5\n");
+	else
+		syslog(LOG_DEBUG, "NOT authenticated with Kerberos v5\n");
 
 	k5_end(&k5);
 
@@ -459,8 +448,6 @@
 	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') {
-			syslog(LOG_ERR, "%s: Retry kinit to "
-			    "acquire credential.\n", caller_mod);
 			(void) smb_kinit(user, pwd);
 			*kinit_retry = 1;
 			goto acquire_cred;
@@ -548,8 +535,6 @@
 			(void) gss_delete_sec_context(&min, gss_context, NULL);
 
 		if ((user != NULL) && (pwd != NULL) && !*kinit_retry) {
-			syslog(LOG_ERR, "%s: Retry kinit to establish "
-			    "security context.\n", caller_mod);
 			(void) smb_kinit(user, pwd);
 			*kinit_retry = 1;
 			*do_acquire_cred = 1;
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c	Thu Mar 12 15:41:34 2009 -0700
@@ -376,7 +376,7 @@
 		ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
 		ipaddr.a_family = AF_INET;
 		/* Don't send anything to myself... */
-		if (smb_nic_exists(&ipaddr, B_FALSE))
+		if (smb_nic_is_local(&ipaddr))
 			goto next;
 
 		sin.sin_addr.s_addr = ipaddr.a_ipv4;
@@ -456,7 +456,7 @@
 	do {
 		ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
 		ipaddr.a_family = AF_INET;
-		if (smb_nic_exists(&ipaddr, B_FALSE))
+		if (smb_nic_is_local(&ipaddr))
 			goto next;
 
 		sin.sin_addr.s_addr = ipaddr.a_ipv4;
@@ -1008,7 +1008,7 @@
 		/* Ignore any incoming packets from myself... */
 		ipaddr.a_ipv4 = datagram->inaddr.sin.sin_addr.s_addr;
 		ipaddr.a_family = AF_INET;
-		if (smb_nic_exists(&ipaddr, B_FALSE)) {
+		if (smb_nic_is_local(&ipaddr)) {
 			goto ignore;
 		}
 
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c	Thu Mar 12 15:41:34 2009 -0700
@@ -2163,7 +2163,7 @@
 
 	ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
 	ipaddr.a_family = AF_INET;
-	if (smb_nic_exists(&ipaddr, B_TRUE))
+	if (smb_nic_is_same_subnet(&ipaddr))
 		net_ipaddr = addr->sin.sin_addr.s_addr;
 	else
 		net_ipaddr = 0;
@@ -4728,7 +4728,7 @@
 
 		ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
 		ipaddr.a_family = AF_INET;
-		if (smb_nic_exists(&ipaddr, B_FALSE))
+		if (smb_nic_is_local(&ipaddr))
 			goto ignore;
 
 		/*
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c	Thu Mar 12 15:41:34 2009 -0700
@@ -541,15 +541,19 @@
 
 	if (cur_ip == 0)
 		return (1);
+	/*
+	 * see if there is a DC in the
+	 * same subnet
+	 */
 
 	ipaddr.a_family = AF_INET;
 	ipaddr.a_ipv4 = cur_ip;
-	if (smb_nic_exists(&ipaddr, B_TRUE))
+	if (smb_nic_is_same_subnet(&ipaddr))
 		return (0);
 
 	ipaddr.a_family = AF_INET;
 	ipaddr.a_ipv4 = new_ip;
-	if (smb_nic_exists(&ipaddr, B_TRUE))
+	if (smb_nic_is_same_subnet(&ipaddr))
 		return (1);
 	/*
 	 * Otherwise, just keep the old one.
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c	Thu Mar 12 15:41:34 2009 -0700
@@ -539,8 +539,7 @@
 		}
 
 		if (smb_oplock_conflict(node, sr->session, op))
-			(void) smb_oplock_break(node,
-			    SMB_SESSION_GET_ID(sr->session), B_FALSE);
+			(void) smb_oplock_break(node, sr->session, B_FALSE);
 
 		smb_node_wrlock(node);
 
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c	Thu Mar 12 15:41:34 2009 -0700
@@ -484,7 +484,7 @@
 	fqi = &sr->arg.dirop.fqi;
 	node = fqi->last_snode;
 
-	(void) smb_oplock_break(node, SMB_SESSION_GET_ID(sr->session), B_FALSE);
+	(void) smb_oplock_break(node, sr->session, B_FALSE);
 
 	smb_node_start_crit(node, RW_READER);
 
--- a/usr/src/uts/common/fs/smbsrv/smb_fem.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_fem.c	Thu Mar 12 15:41:34 2009 -0700
@@ -569,7 +569,7 @@
 	SMB_NODE_VALID(node);
 
 	if (ct == NULL) {
-		(void) smb_oplock_break(node, 0, B_FALSE);
+		(void) smb_oplock_break(node, NULL, B_FALSE);
 		return (0);
 	}
 
@@ -577,12 +577,12 @@
 		return (0);
 
 	if (ct->cc_flags & CC_DONTBLOCK) {
-		if (smb_oplock_break(node, 0, B_TRUE))
+		if (smb_oplock_break(node, NULL, B_TRUE))
 			return (0);
 		ct->cc_flags |= CC_WOULDBLOCK;
 		rc = EAGAIN;
 	} else {
-		(void) smb_oplock_break(node, 0, B_FALSE);
+		(void) smb_oplock_break(node, NULL, B_FALSE);
 		rc = 0;
 	}
 	return (rc);
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c	Thu Mar 12 15:41:34 2009 -0700
@@ -26,16 +26,36 @@
  * SMB Node State Machine
  * ----------------------
  *
- *    +----------------------------+	 T0
- *    |  SMB_NODE_STATE_AVAILABLE  |<----------- Creation/Allocation
- *    +----------------------------+
+ *
+ *		    +----------- Creation/Allocation
  *		    |
- *		    | T1
+ *		    | T0
  *		    |
  *		    v
- *    +-----------------------------+    T2
- *    |  SMB_NODE_STATE_DESTROYING  |----------> Deletion/Free
+ *    +----------------------------+        T1
+ *    |  SMB_NODE_STATE_AVAILABLE  |--------------------+
+ *    +----------------------------+			|
+ *		    |	     ^				|
+ *		    |	     |				v
+ *		    |	     |	  T2	+-------------------------------+
+ *		    |	     |<---------| SMB_NODE_STATE_OPLOCK_GRANTED |
+ *		    |	     |		+-------------------------------+
+ *		    | T5     |				|
+ *		    |	     |				| T3
+ *		    |	     |				v
+ *		    |	     |	  T4	+--------------------------------+
+ *		    |	     +----------| SMB_NODE_STATE_OPLOCK_BREAKING |
+ *		    |			+--------------------------------+
+ *		    |
+ *		    v
  *    +-----------------------------+
+ *    |  SMB_NODE_STATE_DESTROYING  |
+ *    +-----------------------------+
+ *		    |
+ *		    |
+ *		    | T6
+ *		    |
+ *		    +----------> Deletion/Free
  *
  * Transition T0
  *
@@ -45,11 +65,42 @@
  *
  * Transition T1
  *
+ *    This transition occurs smb_oplock_acquire() during an OPEN.
+ *
+ * Transition T2
+ *
+ *    This transition occurs in smb_oplock_release(). The events triggering
+ *    it are:
+ *
+ *	- LockingAndX sent by the client that was granted the oplock.
+ *	- Closing of the file.
+ *
+ * Transition T3
+ *
+ *    This transition occurs in smb_oplock_break(). The events triggering
+ *    it are:
+ *
+ *	- Another client wants to open the file.
+ *	- A client is trying to delete the file.
+ *	- A client is trying to rename the file.
+ *	- A client is trying to set/modify  the file attributes.
+ *
+ * Transition T4
+ *
+ *    This transition occurs in smb_oplock_release or smb_oplock_break(). The
+ *    events triggering it are:
+ *
+ *	- The client that was granting the oplock releases it (close or
+ *	  LockingAndx).
+ *	- The time alloted to release the oplock expired.
+ *
+ * Transition T5
+ *
  *    This transition occurs in smb_node_release(). If the reference count
  *    drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
  *    reference count will be given out for that node.
  *
- * Transition T2
+ * Transition T6
  *
  *    This transition occurs in smb_node_release(). The structure is deleted.
  *
@@ -1079,7 +1130,8 @@
 	VERIFY(node->n_lock_list.ll_count == 0);
 	VERIFY(node->n_ofile_list.ll_count == 0);
 	VERIFY(node->n_oplock.ol_xthread == NULL);
-	VERIFY(node->n_oplock.ol_waiters_count == 0);
+	VERIFY(mutex_owner(&node->n_mutex) == NULL);
+	VERIFY(!RW_LOCK_HELD(&node->n_lock));
 	VN_RELE(node->vp);
 	kmem_cache_free(smb_node_cache, node);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c	Thu Mar 12 15:41:34 2009 -0700
@@ -255,8 +255,8 @@
 		if (op->created_readonly)
 			node->readonly_creator = of;
 
+		smb_node_inc_open_ofiles(node);
 		smb_node_add_ofile(node, of);
-		smb_node_inc_open_ofiles(node);
 	}
 	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
 	smb_llist_insert_tail(&tree->t_ofile_list, of);
@@ -325,10 +325,12 @@
 		ASSERT(of->f_refcnt);
 		ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
 		of->f_state = SMB_OFILE_STATE_CLOSED;
-		if (of->f_oplock_granted) {
+		if (of->f_node != NULL) {
 			smb_node_dec_open_ofiles(of->f_node);
-			smb_oplock_release(of->f_node, of);
-			of->f_oplock_granted = B_FALSE;
+			if (of->f_oplock_granted) {
+				smb_oplock_release(of->f_node, of);
+				of->f_oplock_granted = B_FALSE;
+			}
 		}
 		mutex_exit(&of->f_mutex);
 		return;
@@ -410,7 +412,7 @@
 
 	mutex_enter(&of->f_mutex);
 	if (of->f_oplock_exit)
-		if (smb_oplock_exit(of->f_node))
+		if (smb_oplock_broadcast(of->f_node))
 			of->f_oplock_exit = B_FALSE;
 	ASSERT(of->f_refcnt);
 	of->f_refcnt--;
--- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c	Thu Mar 12 15:41:34 2009 -0700
@@ -30,7 +30,7 @@
 #include <smbsrv/smb_fsops.h>
 #include <inet/tcp.h>
 
-static void smb_oplock_enter(smb_node_t *);
+static void smb_oplock_wait(smb_node_t *);
 
 /*
  *	Magic		0xFF 'S' 'M' 'B'
@@ -145,7 +145,6 @@
 
 	if (!smb_session_oplocks_enable(session) ||
 	    smb_tree_has_feature(SMB_OFILE_GET_TREE(of), SMB_TREE_NO_OPLOCKS)) {
-		/* This implies that trees cannot overlap. */
 		op->op_oplock_level = SMB_OPLOCK_NONE;
 		return;
 	}
@@ -153,12 +152,28 @@
 	ol = &node->n_oplock;
 	time = MSEC_TO_TICK(smb_oplock_timeout) + ddi_get_lbolt();
 
+	smb_rwx_rwexit(&session->s_lock);
 	mutex_enter(&node->n_mutex);
 
+	switch (node->n_state) {
+	case SMB_NODE_STATE_OPLOCK_GRANTED:
+		if (SMB_SESSION_GET_ID(session) == ol->ol_sess_id) {
+			mutex_exit(&node->n_mutex);
+			smb_rwx_rwenter(&session->s_lock, RW_READER);
+			return;
+		}
+		break;
+	case SMB_NODE_STATE_AVAILABLE:
+	case SMB_NODE_STATE_OPLOCK_BREAKING:
+		break;
+	default:
+		SMB_PANIC();
+	}
+
 	for (;;) {
 		int	rc;
 
-		smb_oplock_enter(node);
+		smb_oplock_wait(node);
 
 		if (node->n_state == SMB_NODE_STATE_AVAILABLE) {
 			if ((op->op_oplock_level == SMB_OPLOCK_LEVEL_II) ||
@@ -166,6 +181,7 @@
 			    (node->n_open_count > 1)) {
 				mutex_exit(&node->n_mutex);
 				op->op_oplock_level = SMB_OPLOCK_NONE;
+				smb_rwx_rwenter(&session->s_lock, RW_READER);
 				return;
 			}
 			ol->ol_ofile = of;
@@ -176,6 +192,7 @@
 			mutex_exit(&node->n_mutex);
 			if (smb_fsop_oplock_install(node, of->f_mode) == 0) {
 				smb_ofile_set_oplock_granted(of);
+				smb_rwx_rwenter(&session->s_lock, RW_READER);
 				return;
 			}
 			mutex_enter(&node->n_mutex);
@@ -183,8 +200,7 @@
 			node->n_state = SMB_NODE_STATE_AVAILABLE;
 			ol->ol_xthread = NULL;
 			op->op_oplock_level = SMB_OPLOCK_NONE;
-			if (ol->ol_waiters_count != 0)
-				cv_broadcast(&ol->ol_cv);
+			cv_broadcast(&ol->ol_cv);
 			break;
 		}
 
@@ -198,9 +214,7 @@
 
 		ASSERT(node->n_state == SMB_NODE_STATE_OPLOCK_BREAKING);
 
-		ol->ol_waiters_count++;
 		rc = cv_timedwait(&ol->ol_cv, &node->n_mutex, time);
-		ol->ol_waiters_count--;
 
 		if (rc == -1) {
 			/*
@@ -211,16 +225,14 @@
 				ol->ol_xthread = curthread;
 				mutex_exit(&node->n_mutex);
 				smb_fsop_oplock_uninstall(node);
-				smb_session_oplock_break_timedout(
-				    SMB_OFILE_GET_SESSION(ol->ol_ofile));
 				mutex_enter(&node->n_mutex);
 				ol->ol_xthread = NULL;
-				if (ol->ol_waiters_count != 0)
-					cv_broadcast(&ol->ol_cv);
+				cv_broadcast(&ol->ol_cv);
 			}
 		}
 	}
 	mutex_exit(&node->n_mutex);
+	smb_rwx_rwenter(&session->s_lock, RW_READER);
 }
 
 /*
@@ -236,7 +248,7 @@
  *		to B_TRUE;
  */
 boolean_t
-smb_oplock_break(smb_node_t *node, uint64_t sess_id, boolean_t nowait)
+smb_oplock_break(smb_node_t *node, smb_session_t *session, boolean_t nowait)
 {
 	smb_oplock_t	*ol;
 	clock_t		time;
@@ -245,36 +257,46 @@
 	ol = &node->n_oplock;
 	time = MSEC_TO_TICK(smb_oplock_timeout) + ddi_get_lbolt();
 
-	mutex_enter(&node->n_mutex);
-	if (ol->ol_sess_id == sess_id) {
-		mutex_exit(&node->n_mutex);
-		return (B_TRUE);
+	if (session != NULL) {
+		smb_rwx_rwexit(&session->s_lock);
+		mutex_enter(&node->n_mutex);
+		if (SMB_SESSION_GET_ID(session) == ol->ol_sess_id) {
+			mutex_exit(&node->n_mutex);
+			smb_rwx_rwenter(&session->s_lock, RW_READER);
+			return (B_TRUE);
+		}
+	} else {
+		mutex_enter(&node->n_mutex);
 	}
 
 	for (;;) {
 		int	rc;
 
-		smb_oplock_enter(node);
+		smb_oplock_wait(node);
 
 		if (node->n_state == SMB_NODE_STATE_AVAILABLE) {
 			mutex_exit(&node->n_mutex);
+			if (session != NULL)
+				smb_rwx_rwenter(&session->s_lock, RW_READER);
 			return (B_TRUE);
 		}
 
 		if (node->n_state == SMB_NODE_STATE_OPLOCK_GRANTED) {
 			node->n_state = SMB_NODE_STATE_OPLOCK_BREAKING;
+			mutex_exit(&node->n_mutex);
 			smb_session_oplock_break(
 			    SMB_OFILE_GET_SESSION(ol->ol_ofile), ol->ol_ofile);
+			mutex_enter(&node->n_mutex);
 		}
 
 		ASSERT(node->n_state == SMB_NODE_STATE_OPLOCK_BREAKING);
 		if (nowait) {
 			mutex_exit(&node->n_mutex);
+			if (session != NULL)
+				smb_rwx_rwenter(&session->s_lock, RW_READER);
 			return (B_FALSE);
 		}
-		ol->ol_waiters_count++;
 		rc = cv_timedwait(&ol->ol_cv, &node->n_mutex, time);
-		ol->ol_waiters_count--;
 		if (rc == -1) {
 			/*
 			 * Oplock release timed out.
@@ -284,17 +306,16 @@
 				ol->ol_xthread = curthread;
 				mutex_exit(&node->n_mutex);
 				smb_fsop_oplock_uninstall(node);
-				smb_session_oplock_break_timedout(
-				    SMB_OFILE_GET_SESSION(ol->ol_ofile));
 				mutex_enter(&node->n_mutex);
 				ol->ol_xthread = NULL;
-				if (ol->ol_waiters_count != 0)
-					cv_broadcast(&ol->ol_cv);
+				cv_broadcast(&ol->ol_cv);
 				break;
 			}
 		}
 	}
 	mutex_exit(&node->n_mutex);
+	if (session != NULL)
+		smb_rwx_rwenter(&session->s_lock, RW_READER);
 	return (B_TRUE);
 }
 
@@ -307,13 +328,16 @@
 void
 smb_oplock_release(smb_node_t *node, smb_ofile_t *of)
 {
+	smb_session_t	*session;
 	smb_oplock_t	*ol;
 
+	session = SMB_OFILE_GET_SESSION(of);
 	SMB_NODE_VALID(node);
 	ol = &node->n_oplock;
 
+	smb_rwx_rwexit(&session->s_lock);
 	mutex_enter(&node->n_mutex);
-	smb_oplock_enter(node);
+	smb_oplock_wait(node);
 	switch (node->n_state) {
 	case SMB_NODE_STATE_AVAILABLE:
 		break;
@@ -325,12 +349,9 @@
 			ol->ol_xthread = curthread;
 			mutex_exit(&node->n_mutex);
 			smb_fsop_oplock_uninstall(node);
-			smb_session_oplock_released(
-			    SMB_OFILE_GET_SESSION(ol->ol_ofile));
 			mutex_enter(&node->n_mutex);
 			ol->ol_xthread = NULL;
-			if (ol->ol_waiters_count != 0)
-				cv_broadcast(&ol->ol_cv);
+			cv_broadcast(&ol->ol_cv);
 		}
 		break;
 
@@ -338,13 +359,14 @@
 		SMB_PANIC();
 	}
 	mutex_exit(&node->n_mutex);
+	smb_rwx_rwenter(&session->s_lock, RW_READER);
 }
 
 /*
  * smb_oplock_conflict
  *
  * The two checks on "session" and "op" are primarily for the open path.
- * Other CIFS functions may call smb_oplock_conflict() with a session
+ * Other SMB functions may call smb_oplock_conflict() with a session
  * pointer so as to do the session check.
  */
 boolean_t
@@ -355,8 +377,9 @@
 	SMB_NODE_VALID(node);
 	SMB_SESSION_VALID(session);
 
+	smb_rwx_rwexit(&session->s_lock);
 	mutex_enter(&node->n_mutex);
-	smb_oplock_enter(node);
+	smb_oplock_wait(node);
 	switch (node->n_state) {
 	case SMB_NODE_STATE_AVAILABLE:
 		rb = B_FALSE;
@@ -386,11 +409,12 @@
 		SMB_PANIC();
 	}
 	mutex_exit(&node->n_mutex);
+	smb_rwx_rwenter(&session->s_lock, RW_READER);
 	return (rb);
 }
 
 /*
- * smb_oplock_exit
+ * smb_oplock_broadcast
  *
  * The the calling thread has the pointer to its context stored in ol_thread
  * it resets that field. If any other thread is waiting for that field to
@@ -401,7 +425,7 @@
  *	B_FALSE	Oplock still locked
  */
 boolean_t
-smb_oplock_exit(smb_node_t *node)
+smb_oplock_broadcast(smb_node_t *node)
 {
 	smb_oplock_t	*ol;
 	boolean_t	rb;
@@ -413,8 +437,7 @@
 	mutex_enter(&node->n_mutex);
 	if ((ol->ol_xthread != NULL) && (ol->ol_xthread == curthread)) {
 		ol->ol_xthread = NULL;
-		if (ol->ol_waiters_count != 0)
-			cv_broadcast(&ol->ol_cv);
+		cv_broadcast(&ol->ol_cv);
 		rb = B_TRUE;
 	}
 	mutex_exit(&node->n_mutex);
@@ -424,20 +447,18 @@
 /*
  * smb_oplock_wait
  *
- * The mutex of the node must have benn entered before calling this function.
+ * The mutex of the node must have been entered before calling this function.
  * If the field ol_xthread is not NULL and doesn't contain the pointer to the
  * context of the calling thread, the caller will sleep until that field is
  * reset (set to NULL).
  */
 static void
-smb_oplock_enter(smb_node_t *node)
+smb_oplock_wait(smb_node_t *node)
 {
 	smb_oplock_t	*ol = &node->n_oplock;
 
 	if ((ol->ol_xthread != NULL) && (ol->ol_xthread != curthread)) {
-		ol->ol_waiters_count++;
 		while (ol->ol_xthread != NULL)
 			cv_wait(&ol->ol_cv, &node->n_mutex);
-		ol->ol_waiters_count--;
 	}
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c	Thu Mar 12 15:41:34 2009 -0700
@@ -302,10 +302,7 @@
 		ppn.pn_path[0] = '\0';
 	}
 
-	if (strcmp(ppn.pn_buf, "/") == 0) {
-		smb_node_ref(local_root_node);
-		*dir_node = local_root_node;
-	} else if (ppn.pn_buf[0] == '\0') {
+	if ((strcmp(ppn.pn_buf, "/") == 0) || (ppn.pn_buf[0] == '\0')) {
 		smb_node_ref(local_cur_node);
 		*dir_node = local_cur_node;
 	} else {
--- a/usr/src/uts/common/fs/smbsrv/smb_rename.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c	Thu Mar 12 15:41:34 2009 -0700
@@ -180,8 +180,7 @@
 	 * has a file open, this will force a flush or close,
 	 * which may affect the outcome of any share checking.
 	 */
-	(void) smb_oplock_break(src_node, SMB_SESSION_GET_ID(sr->session),
-	    B_FALSE);
+	(void) smb_oplock_break(src_node, sr->session, B_FALSE);
 
 	for (count = 0; count <= 3; count++) {
 		if (count) {
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c	Thu Mar 12 15:41:34 2009 -0700
@@ -587,25 +587,6 @@
 			break;
 		if (rc = smb_thread_start(&sv->si_thread_unexport))
 			break;
-		/*
-		 * XXX We give up the NET_MAC_AWARE privilege because it keeps
-		 * us from re-opening the connection when there are leftover TCP
-		 * connections in TCPS_TIME_WAIT state.  There seem to be some
-		 * security ramifications around reestablishing a connection
-		 * while possessing the NET_MAC_AWARE privilege.
-		 *
-		 * This approach may cause problems when we try to support
-		 * zones.  An alternative would be to retry the connection setup
-		 * for a fixed period of time until the stale connections clear
-		 * up but that implies we would be offline for a couple minutes
-		 * every time the service is restarted with active connections.
-		 */
-		rc = setpflags(NET_MAC_AWARE, 0, CRED());
-		if (rc) {
-			cmn_err(CE_WARN,
-			    "Cannot remove NET_MAC_AWARE privilege");
-			break;
-		}
 		if (rc = smb_opipe_door_open(io_start->opipe)) {
 			cmn_err(CE_WARN, "Cannot open opipe door");
 			break;
@@ -1251,7 +1232,8 @@
 {
 	int			rc;
 	ksocket_t		s_so;
-	uint32_t		on = 1;
+	const uint32_t		on = 1;
+	const uint32_t		off = 0;
 	smb_session_t		*session;
 
 	if (pthread_create_error) {
@@ -1278,8 +1260,10 @@
 		if (ld->ld_so) {
 
 			(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
-			    SO_REUSEADDR, (const void *)&on, sizeof (on),
-			    CRED());
+			    SO_MAC_EXEMPT, &off, sizeof (off), CRED());
+			(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
+			    SO_REUSEADDR, &on, sizeof (on), CRED());
+
 			if (family == AF_INET) {
 				rc = ksocket_bind(ld->ld_so,
 				    (struct sockaddr *)&ld->ld_sin,
@@ -1325,11 +1309,9 @@
 			DTRACE_PROBE1(so__accept, struct sonode *, s_so);
 
 			(void) ksocket_setsockopt(s_so, IPPROTO_TCP,
-			    TCP_NODELAY, (const void *)&on, sizeof (on),
-			    CRED());
+			    TCP_NODELAY, &on, sizeof (on), CRED());
 			(void) ksocket_setsockopt(s_so, SOL_SOCKET,
-			    SO_KEEPALIVE, (const void *)&on, sizeof (on),
-			    CRED());
+			    SO_KEEPALIVE, &on, sizeof (on), CRED());
 			(void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
 			    (const void *)&txbuf_size, sizeof (txbuf_size),
 			    CRED());
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c	Thu Mar 12 15:41:34 2009 -0700
@@ -43,7 +43,6 @@
 static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *,
     uint8_t *, size_t);
 static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *);
-static void smb_session_oplock_broken(smb_session_t *);
 static void smb_request_init_command_mbuf(smb_request_t *sr);
 void dump_smb_inaddr(smb_inaddr_t *ipaddr);
 
@@ -132,10 +131,8 @@
 	while (sn) {
 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
 		if ((sn != sess) &&
-		    smb_inet_equal(&sn->ipaddr, &sess->ipaddr,
-		    SMB_INET_NOMASK) &&
-		    smb_inet_equal(&sn->local_ipaddr, &sess->local_ipaddr,
-		    SMB_INET_NOMASK) &&
+		    smb_inet_equal(&sn->ipaddr, &sess->ipaddr) &&
+		    smb_inet_equal(&sn->local_ipaddr, &sess->local_ipaddr) &&
 		    (strcasecmp(sn->workstation, sess->workstation) == 0) &&
 		    (sn->opentime <= sess->opentime) &&
 		    (sn->s_kid < sess->s_kid)) {
@@ -681,18 +678,28 @@
 			slen = sizeof (sin);
 			(void) ksocket_getsockname(new_so,
 			    (struct sockaddr *)&sin, &slen, CRED());
-			bcopy(&sin, &session->local_ipaddr.a_ip, slen);
+			bcopy(&sin.sin_addr,
+			    &session->local_ipaddr.au_addr.au_ipv4,
+			    sizeof (in_addr_t));
+			slen = sizeof (sin);
 			(void) ksocket_getpeername(new_so,
 			    (struct sockaddr *)&sin, &slen, CRED());
-			bcopy(&sin, &session->ipaddr.a_ip, slen);
+			bcopy(&sin.sin_addr,
+			    &session->ipaddr.au_addr.au_ipv4,
+			    sizeof (in_addr_t));
 		} else {
 			slen = sizeof (sin6);
 			(void) ksocket_getsockname(new_so,
 			    (struct sockaddr *)&sin6, &slen, CRED());
-			bcopy(&sin6, &session->local_ipaddr.a_ip, slen);
+			bcopy(&sin6.sin6_addr,
+			    &session->local_ipaddr.au_addr.au_ipv6,
+			    sizeof (in6_addr_t));
+			slen = sizeof (sin6);
 			(void) ksocket_getpeername(new_so,
 			    (struct sockaddr *)&sin6, &slen, CRED());
-			bcopy(&sin6, &session->ipaddr.a_ip, slen);
+			bcopy(&sin6.sin6_addr,
+			    &session->ipaddr.au_addr.au_ipv6,
+			    sizeof (in6_addr_t));
 		}
 		session->ipaddr.a_family = family;
 		session->local_ipaddr.a_family = family;
@@ -1211,7 +1218,6 @@
 	case SMB_SESSION_STATE_NEGOTIATED:
 	case SMB_SESSION_STATE_OPLOCK_BREAKING:
 		session->s_state = SMB_SESSION_STATE_OPLOCK_BREAKING;
-		session->s_oplock_brkcntr++;
 		(void) smb_session_send(session, 0, mbc);
 		smb_mbc_free(mbc);
 		break;
@@ -1230,64 +1236,3 @@
 	}
 	smb_rwx_rwexit(&session->s_lock);
 }
-
-/*
- * smb_session_oplock_released
- *
- * This function MUST be called in the context of the session of the client
- * holding the oplock. The lock of the session must have been entered in
- * RW_READER or RW_WRITER mode.
- */
-void
-smb_session_oplock_released(smb_session_t *session)
-{
-	krw_t	mode;
-
-	SMB_SESSION_VALID(session);
-
-	mode = smb_rwx_rwupgrade(&session->s_lock);
-	smb_session_oplock_broken(session);
-	smb_rwx_rwdowngrade(&session->s_lock, mode);
-}
-
-/*
- * smb_session_oplock_break_timedout
- *
- * This function MUST be called when the client holding the oplock to file
- * failed to release it in the time alloted. It is a cross-session call (The
- * caller must be calling in the context of another session).
- */
-void
-smb_session_oplock_break_timedout(smb_session_t *session)
-{
-	SMB_SESSION_VALID(session);
-
-	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
-	smb_session_oplock_broken(session);
-	smb_rwx_rwexit(&session->s_lock);
-}
-
-/*
- * smb_session_oplock_broken
- *
- * Does the actual work.
- */
-static void
-smb_session_oplock_broken(smb_session_t *session)
-{
-	switch (session->s_state) {
-	case SMB_SESSION_STATE_OPLOCK_BREAKING:
-		if (--session->s_oplock_brkcntr == 0)
-			session->s_state = SMB_SESSION_STATE_NEGOTIATED;
-		break;
-
-	case SMB_SESSION_STATE_NEGOTIATED:
-	case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
-	case SMB_SESSION_STATE_DISCONNECTED:
-	case SMB_SESSION_STATE_TERMINATED:
-		break;
-
-	default:
-		SMB_PANIC();
-	}
-}
--- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c	Thu Mar 12 15:41:34 2009 -0700
@@ -268,6 +268,7 @@
 	smb_sessionsetup_info_t sinfo;
 	smb_session_key_t *session_key = NULL;
 	char ipaddr_buf[INET6_ADDRSTRLEN];
+	int native_lm;
 	int auth_res;
 	int rc;
 
@@ -327,11 +328,10 @@
 			    &sinfo.ssi_native_lm);
 
 		/*
-		 * Native Lanman could be null so we really don't care
-		 * if above decode fails, but to have a valid value for
-		 * the field we set it to Win NT.
+		 * If the Native Lanman cannot be determined,
+		 * default to Windows NT.
 		 */
-		if (rc != 0)
+		if (rc != 0 || sinfo.ssi_native_lm == NULL)
 			sinfo.ssi_native_lm = "NT LAN Manager 4.0";
 	} else {
 		rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com,
@@ -365,7 +365,8 @@
 		if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_domain) != 0)
 			sinfo.ssi_domain = "";
 
-		sr->session->native_os = NATIVE_OS_UNKNOWN;
+		sr->session->native_os = NATIVE_OS_WINNT;
+		sinfo.ssi_native_lm = "NT LAN Manager 4.0";
 	}
 
 	/*
@@ -402,6 +403,10 @@
 		return (SDRC_ERROR);
 	}
 
+	native_lm = smbnative_lm_value(sinfo.ssi_native_lm);
+	if (native_lm == NATIVE_LM_WIN2000)
+		sinfo.ssi_capabilities |= CAP_LARGE_FILES |
+		    CAP_LARGE_READX | CAP_LARGE_WRITEX;
 	sr->session->capabilities = sinfo.ssi_capabilities;
 
 	/*
--- a/usr/src/uts/common/fs/smbsrv/smb_set_information.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_set_information.c	Thu Mar 12 15:41:34 2009 -0700
@@ -132,8 +132,7 @@
 		/*
 		 * for the benefit of attribute setting later on
 		 */
-		(void) smb_oplock_break(node, SMB_SESSION_GET_ID(sr->session),
-		    B_FALSE);
+		(void) smb_oplock_break(node, sr->session, B_FALSE);
 	}
 
 	/*
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c	Thu Mar 12 15:41: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	"@(#)smb_trans2_query_fs_information.c	1.7	08/08/07 SMI"
-
 /*
  * SMB: trans2_query_fs_information
  *
@@ -375,7 +373,9 @@
 		}
 
 		flags = FILE_CASE_PRESERVED_NAMES;
-		/* flags |= FILE_UNICODE_ON_DISK; */
+
+		if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
+			flags |= FILE_UNICODE_ON_DISK;
 
 		if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
 			flags |= FILE_PERSISTENT_ACLS;
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c	Thu Mar 12 15:41:34 2009 -0700
@@ -161,8 +161,7 @@
 		/*
 		 * for the benefit of attribute setting later on
 		 */
-		(void) smb_oplock_break(ret_snode,
-		    SMB_SESSION_GET_ID(sr->session), B_FALSE);
+		(void) smb_oplock_break(ret_snode, sr->session, B_FALSE);
 	}
 
 	info->node = ret_snode;
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c	Thu Mar 12 15:41:34 2009 -0700
@@ -884,8 +884,22 @@
 static void
 smb_tree_get_flags(vfs_t *vfsp, smb_tree_t *tree)
 {
-	uint32_t flags = SMB_TREE_SUPPORTS_ACLS;
-	char *name;
+	typedef struct smb_mtype {
+		char		*mt_name;
+		size_t		mt_namelen;
+		uint32_t	mt_flags;
+	} smb_mtype_t;
+
+	static smb_mtype_t smb_mtype[] = {
+		{ "zfs",	3,	SMB_TREE_UNICODE_ON_DISK },
+		{ "ufs",	3,	SMB_TREE_UNICODE_ON_DISK },
+		{ "nfs",	3,	SMB_TREE_NFS_MOUNTED },
+		{ "tmpfs",	5,	SMB_TREE_NO_EXPORT }
+	};
+	smb_mtype_t	*mtype;
+	char		*name;
+	uint32_t	flags = SMB_TREE_SUPPORTS_ACLS;
+	int		i;
 
 	if (vfsp->vfs_flag & VFS_RDONLY)
 		flags |= SMB_TREE_READONLY;
@@ -898,11 +912,11 @@
 
 	name = vfssw[vfsp->vfs_fstype].vsw_name;
 
-	if (strcmp(name, "tmpfs") == 0)
-		flags |= SMB_TREE_NO_EXPORT;
-
-	if (strncasecmp(name, NFS, sizeof (NFS)) == 0)
-		flags |= SMB_TREE_NFS_MOUNTED;
+	for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
+		mtype = &smb_mtype[i];
+		if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
+			flags |= mtype->mt_flags;
+	}
 
 	(void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
 	(void) utf8_strupr((char *)tree->t_typename);
@@ -925,7 +939,8 @@
 	if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
 		flags |= SMB_TREE_ACEMASKONACCESS;
 
-	DTRACE_PROBE1(smb__tree__flags, uint32_t, flags);
+	DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
+
 
 	tree->t_flags = flags;
 }
--- a/usr/src/uts/common/smbsrv/smb_inet.h	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/smbsrv/smb_inet.h	Thu Mar 12 15:41:34 2009 -0700
@@ -58,9 +58,8 @@
 #define	SMB_IPSTRLEN(family) \
 ((family == AF_INET) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN)
 
-#define	SMB_INET_NOMASK 0xffffffff
-
-boolean_t smb_inet_equal(smb_inaddr_t *, smb_inaddr_t *, uint32_t);
+boolean_t smb_inet_equal(smb_inaddr_t *, smb_inaddr_t *);
+boolean_t smb_inet_same_subnet(smb_inaddr_t *, smb_inaddr_t *, uint32_t);
 boolean_t smb_inet_iszero(smb_inaddr_t *);
 const char *smb_inet_ntop(smb_inaddr_t *, char *, int);
 
--- a/usr/src/uts/common/smbsrv/smb_kproto.h	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h	Thu Mar 12 15:41:34 2009 -0700
@@ -184,19 +184,14 @@
 void smb_process_file_notify_change_queue(struct smb_ofile *of);
 
 void smb_oplock_acquire(smb_node_t *, smb_ofile_t *, open_param_t	*);
-boolean_t smb_oplock_break(smb_node_t *, uint64_t, boolean_t);
+boolean_t smb_oplock_break(smb_node_t *, smb_session_t *, boolean_t);
 void smb_oplock_release(smb_node_t *, smb_ofile_t *);
 boolean_t smb_oplock_conflict(smb_node_t *, smb_session_t *, open_param_t *);
-boolean_t smb_oplock_exit(smb_node_t *);
+boolean_t smb_oplock_broadcast(smb_node_t *);
 
 /*
  * macros used in oplock processing
  *
- * SMB_SAME_SESSION: Checks for equivalence
- * of session.  If an existing oplock is
- * from the same IP address/session as the current
- * request, the oplock is not broken.
- *
  * SMB_ATTR_ONLY_OPEN: Checks to see if this is
  * an attribute-only open with no contravening
  * dispositions.  Such an open cannot effect an
@@ -205,11 +200,6 @@
  * an oplock break.
  */
 
-#define	SMB_SAME_SESSION(sess1, sess2)				\
-	((sess1) && (sess2) &&					\
-	(smb_inet_equal(&sess1->ipaddr, &sess2->ipaddr, 0)) &&	\
-	((sess1)->s_kid == (sess2)->s_kid))			\
-
 #define	SMB_ATTR_ONLY_OPEN(op)					\
 	((op) && (op)->desired_access &&			\
 	(((op)->desired_access & ~(FILE_READ_ATTRIBUTES |	\
@@ -508,8 +498,6 @@
 smb_user_t *smb_session_dup_user(smb_session_t *, char *, char *);
 void smb_session_correct_keep_alive_values(smb_session_list_t *, uint32_t);
 void smb_session_oplock_break(smb_session_t *, smb_ofile_t *);
-void smb_session_oplock_released(smb_session_t *);
-void smb_session_oplock_break_timedout(smb_session_t *);
 int smb_session_send(smb_session_t *, uint8_t type, mbuf_chain_t *);
 int smb_session_xprt_gethdr(smb_session_t *, smb_xprt_t *);
 boolean_t smb_session_oplocks_enable(smb_session_t *);
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h	Thu Mar 12 15:41:34 2009 -0700
@@ -405,12 +405,40 @@
 
 #define	MBC_ROOM_FOR(b, n) (((b)->chain_offset + (n)) <= (b)->max_bytes)
 
+/*
+ * ol_sess_id:
+ *
+ *	ID of the session holding the oplock (if an oplock was granted).
+ *
+ * ol_xthread:
+ *
+ *	Worker thread treating the command that was granted the oplock. Until
+ *	that thread is done with that command and has submitted the response
+ *	to the network stack, all the other threads will be suspended in
+ *	smb_oplock_enter(). They will be awaken when the worker thread
+ *	referenced in 'ol_xthread' calls smb_oplock_broadcast().
+ *
+ *	The purpose of this mechanism is to prevent another thread from
+ *	triggering a oplock break before the response conveying the grant
+ *	has been sent.
+ *
+ * ol_ofile
+ *
+ *	Open file that was granted the oplock.
+ *
+ * ol_waiters_count
+ *
+ *	Number of threads waiting for a call to smb_oplock_broadcast().
+ *
+ * ol_level
+ *
+ *	Level of the oplock granted.
+ */
 typedef struct smb_oplock {
 	uint64_t		ol_sess_id;
 	kcondvar_t		ol_cv;
 	kthread_t		*ol_xthread;
 	struct smb_ofile	*ol_ofile;
-	uint32_t		ol_waiters_count;
 	uint8_t			ol_level;
 } smb_oplock_t;
 
@@ -718,7 +746,6 @@
 	uchar_t			*outpipe_data;
 	int			outpipe_datalen;
 	int			outpipe_cookie;
-	uint32_t		s_oplock_brkcntr;
 	list_t			s_oplock_brkreqs;
 } smb_session_t;
 
@@ -787,6 +814,7 @@
 #define	SMB_TREE_ACLONCREATE		0x00000400
 #define	SMB_TREE_ACEMASKONACCESS	0x00000800
 #define	SMB_TREE_NFS_MOUNTED		0x00001000
+#define	SMB_TREE_UNICODE_ON_DISK	0x00002000
 
 typedef enum {
 	SMB_TREE_STATE_CONNECTED = 0,
--- a/usr/src/uts/common/smbsrv/smbinfo.h	Thu Mar 12 15:24:41 2009 -0700
+++ b/usr/src/uts/common/smbsrv/smbinfo.h	Thu Mar 12 15:41:34 2009 -0700
@@ -126,9 +126,9 @@
 #define	SMB_VERSION_MAJOR  4
 #define	SMB_VERSION_MINOR  0
 
-int smbnative_os_value(char *native_os);
-int smbnative_lm_value(char *native_lm);
-int smbnative_pdc_value(char *native_lm);
+int smbnative_os_value(const char *);
+int smbnative_lm_value(const char *);
+int smbnative_pdc_value(const char *);
 
 /*
  * Support for passthrough authentication.