summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/idmap/idmap/idmap.c2
-rw-r--r--usr/src/cmd/idmap/idmapd/dbutils.c47
-rw-r--r--usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c60
-rw-r--r--usr/src/cmd/smbsrv/smbadm/smbadm.c2
-rw-r--r--usr/src/common/smbsrv/smb_inet.c18
-rw-r--r--usr/src/common/smbsrv/smb_native.c192
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c23
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h3
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers3
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c1
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_nic.c26
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_util.c19
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/libsmbns.h11
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/mapfile-vers2
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c156
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c53
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c6
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c4
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_delete.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fem.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_node.c68
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_ofile.c12
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_oplock.c97
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c5
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_rename.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c34
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session.c87
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c15
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_set_information.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c31
-rw-r--r--usr/src/uts/common/smbsrv/smb_inet.h5
-rw-r--r--usr/src/uts/common/smbsrv/smb_kproto.h16
-rw-r--r--usr/src/uts/common/smbsrv/smb_ktypes.h32
-rw-r--r--usr/src/uts/common/smbsrv/smbinfo.h6
38 files changed, 577 insertions, 495 deletions
diff --git a/usr/src/cmd/idmap/idmap/idmap.c b/usr/src/cmd/idmap/idmap/idmap.c
index 7f2ab276a5..dfc621b636 100644
--- a/usr/src/cmd/idmap/idmap/idmap.c
+++ b/usr/src/cmd/idmap/idmap/idmap.c
@@ -1484,6 +1484,8 @@ print_error_info(idmap_info *info)
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,
diff --git a/usr/src/cmd/idmap/idmapd/dbutils.c b/usr/src/cmd/idmap/idmapd/dbutils.c
index c34d5bb31d..e6bfac0b57 100644
--- a/usr/src/cmd/idmap/idmapd/dbutils.c
+++ b/usr/src/cmd/idmap/idmapd/dbutils.c
@@ -1355,33 +1355,24 @@ lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res, int *wksid)
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 @@ lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user)
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 @@ generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user,
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 @@ lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res)
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 @@ name_based_mapping_sid2pid(lookup_state_t *state,
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 @@ out:
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 @@ name_based_mapping_pid2sid(lookup_state_t *state, const char *unixname,
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 @@ out:
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);
diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
index c0a9a03ea9..8fffbab78f 100644
--- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
+++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
@@ -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 @@ static smb_com_entry_t smb_com[256] =
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 @@ static smb_com_entry_t smb_com[256] =
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_getopt(uint_t *, int, const mdb_arg_t *);
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 @@ smb_dcmd_session(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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 @@ smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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 @@ smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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 @@ smb_obj_list(const char *name, uint_t opts, uint_t flags)
}
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);
+}
diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c
index 9b15b5d1cd..3479dbb92a 100644
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c
@@ -603,6 +603,8 @@ smbadm_join_domain(const char *domain, const char *username)
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);
}
diff --git a/usr/src/common/smbsrv/smb_inet.c b/usr/src/common/smbsrv/smb_inet.c
index f7af3f54af..5822a49b24 100644
--- a/usr/src/common/smbsrv/smb_inet.c
+++ b/usr/src/common/smbsrv/smb_inet.c
@@ -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) &&
diff --git a/usr/src/common/smbsrv/smb_native.c b/usr/src/common/smbsrv/smb_native.c
index 9032042c57..3a06caed57 100644
--- a/usr/src/common/smbsrv/smb_native.c
+++ b/usr/src/common/smbsrv/smb_native.c
@@ -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 @@ smbnative_os_value(char *native_os)
{ 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 @@ smbnative_os_value(char *native_os)
int i;
int len;
- char *os_name;
+ const char *name;
- if (native_os == NULL) {
+ if (native_os == NULL)
return (NATIVE_OS_UNKNOWN);
- }
- if (*native_os == '\0') {
- /*
- * Windows Vista sends an empty native OS string.
- */
+ /*
+ * 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) {
- os_name = os_table[i].os_name;
- len = strlen(os_name);
+ name = os_table[i].sn_name;
+ len = strlen(name);
- if (utf8_strncasecmp(os_name, native_os, len) == 0) {
- return (os_table[i].os_value);
- }
+ if (utf8_strncasecmp(name, native_os, len) == 0)
+ return (os_table[i].sn_value);
}
+
return (NATIVE_OS_UNKNOWN);
}
-
/*
* smbnative_lm_value
*
@@ -117,129 +122,100 @@ smbnative_os_value(char *native_os)
* 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;
- if (native_lm == NULL) {
- return (NATIVE_LM_NONE);
- }
-
- if (*native_lm == '\0') {
- /*
- * Windows Vista sends an empty native LM string.
- */
+ /*
+ * Windows Vista sends an empty native LM string.
+ */
+ if (native_lm == NULL || *native_lm == '\0')
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);
+ name = lm_table[i].sn_name;
+ len = strlen(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);
+ if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
+ (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
+ return (lm_table[i].sn_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.
- *
- * 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.
+ * 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:
+ *
+ * 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);
}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
index 7af1eecc1b..b4d9317a84 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
@@ -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 @@ mlsvc_netlogon(char *server, char *domain)
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 @@ mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text)
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 @@ mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text)
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 @@ mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text)
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);
}
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 5e0e57d387..0e70fbef67 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -725,7 +725,8 @@ int smb_nic_addhost(const char *, const char *, int, const char **);
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 *);
diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
index 73106f8d6f..3daa16a612 100644
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
@@ -252,7 +252,8 @@ SUNWprivate {
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;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
index c4153b32a1..10ef9c0e11 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
@@ -288,6 +288,7 @@ smb_get_dcinfo(char *namebuf, uint32_t namebuflen, smb_inaddr_t *ipaddr)
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);
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c
index 6646883ab1..34e7d7b491 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c
@@ -269,19 +269,35 @@ smb_nic_getnext(smb_niciter_t *ni)
}
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);
}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_util.c b/usr/src/lib/smbsrv/libsmb/common/smb_util.c
index 859f4894c3..a1a5d27f0b 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c
@@ -726,12 +726,19 @@ smb_getdataset(const char *path, char *dataset, size_t len)
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;
}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h
index 0eb8411f92..648031fde9 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h
+++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h
@@ -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 struct smb_ads_handle {
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 @@ typedef enum smb_adjoin_status {
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_lookup_share(smb_ads_handle_t *, const char *, const char *,
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 */
diff --git a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers
index 57758ed715..b897ace548 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers
@@ -44,12 +44,12 @@ SUNWprivate {
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;
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
index cc9c43b878..9f6e7c6c68 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
@@ -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 mutex_t smb_ads_cached_host_mtx;
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 @@ static smb_ads_qstat_t smb_ads_lookup_computer_n_attr(smb_ads_handle_t *,
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 @@ smb_ads_query_dns_server(char *domain, char *msdcs_svc_name)
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 @@ smb_ads_query_dns_server(char *domain, char *msdcs_svc_name)
/* 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_query_dns_server(char *domain, char *msdcs_svc_name)
}
/*
- * 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_find_host(char *domain, char *sought)
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_find_host(char *domain, char *sought)
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 = NULL;
+ smb_ads_get_site_service(site_service, MAXHOSTNAMELEN);
+ if (*site_service != '\0')
+ hlist = smb_ads_query_dns_server(domain, site_service);
- hlist = smb_ads_query_dns_server(domain, msdcs_svc_name[i]);
- if (hlist != NULL)
- break;
- }
+ 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 @@ smb_ads_display_stat(OM_uint32 maj, OM_uint32 min)
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 @@ smb_ads_establish_sec_context(smb_ads_handle_t *ah, gss_ctx_id_t *gss_context,
&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 @@ smb_ads_negotiate_sec_layer(smb_ads_handle_t *ah, gss_ctx_id_t gss_context,
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 @@ smb_ads_add_share(smb_ads_handle_t *ah, const char *adsShareName,
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 @@ smb_ads_del_share(smb_ads_handle_t *ah, const char *adsShareName,
(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 @@ smb_ads_lookup_share(smb_ads_handle_t *ah, const char *adsShareName,
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 @@ smb_ads_computer_op(smb_ads_handle_t *ah, int op, int dclevel, char *dn)
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 @@ smb_ads_computer_op(smb_ads_handle_t *ah, int op, int dclevel, char *dn)
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 @@ smb_ads_del_computer(smb_ads_handle_t *ah, char *dn)
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 @@ smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *ah, int flags, char *dn)
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 @@ smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t *ah, char *dn)
* 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 @@ smb_ads_gen_machine_passwd(char *machine_passwd, int bufsz)
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 @@ smb_ads_gen_machine_passwd(char *machine_passwd, int bufsz)
}
machine_passwd[bufsz - 1] = 0;
- return (0);
}
/*
@@ -2392,11 +2362,7 @@ smb_ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd,
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 @@ smb_ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd,
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 @@ adjoin_cleanup:
}
/*
- * 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");
+ 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)." }
+ };
- return (smb_ads_adjoin_errmsg[status]);
+ 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 @@ smb_ads_select_pdc(smb_ads_host_list_t *hlist)
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);
}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c
index b53eb01dfa..12b910f605 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c
@@ -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 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
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 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
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 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
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 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
"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 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
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 @@ smb_kinit(char *user, char *passwd)
(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 @@ 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') {
- 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 @@ krb5_establish_sec_ctx_kinit(char *user, char *pwd,
(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;
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c
index fc03dc66c6..75970f43cc 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c
@@ -376,7 +376,7 @@ smb_netbios_datagram_send(struct name_entry *src, struct name_entry *dest,
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 @@ smb_netbios_datagram_send_to_net(struct name_entry *src,
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: bzero(&datagram->inaddr, sizeof (struct addr_entry));
/* 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;
}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c
index 97436fc7ae..d627fd186c 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c
@@ -2163,7 +2163,7 @@ smb_send_node_status_response(struct addr_entry *addr,
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 @@ ignore: bzero(addr, sizeof (struct addr_entry));
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;
/*
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c
index 484b3ada97..c48200e11a 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c
@@ -541,15 +541,19 @@ smb_better_dc(uint32_t cur_ip, uint32_t new_ip)
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.
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index 2d8c165f39..9b465ded21 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -539,8 +539,7 @@ smb_open_subr(smb_request_t *sr)
}
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);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c
index cb32ad69f5..3cca213821 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c
@@ -484,7 +484,7 @@ smb_delete_remove_file(smb_request_t *sr, smb_error_t *err)
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);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fem.c b/usr/src/uts/common/fs/smbsrv/smb_fem.c
index f88ff345af..3582ce4986 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fem.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fem.c
@@ -569,7 +569,7 @@ smb_fem_oplock_break(femarg_t *arg, caller_context_t *ct)
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 @@ smb_fem_oplock_break(femarg_t *arg, caller_context_t *ct)
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);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c
index 484bdecfbd..e484973f80 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c
@@ -26,16 +26,36 @@
* SMB Node State Machine
* ----------------------
*
- * +----------------------------+ T0
- * | SMB_NODE_STATE_AVAILABLE |<----------- Creation/Allocation
- * +----------------------------+
+ *
+ * +----------- Creation/Allocation
+ * |
+ * | T0
* |
- * | T1
+ * v
+ * +----------------------------+ T1
+ * | SMB_NODE_STATE_AVAILABLE |--------------------+
+ * +----------------------------+ |
+ * | ^ |
+ * | | v
+ * | | T2 +-------------------------------+
+ * | |<---------| SMB_NODE_STATE_OPLOCK_GRANTED |
+ * | | +-------------------------------+
+ * | T5 | |
+ * | | | T3
+ * | | v
+ * | | T4 +--------------------------------+
+ * | +----------| SMB_NODE_STATE_OPLOCK_BREAKING |
+ * | +--------------------------------+
* |
* v
- * +-----------------------------+ T2
- * | SMB_NODE_STATE_DESTROYING |----------> Deletion/Free
* +-----------------------------+
+ * | 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 @@ smb_node_free(smb_node_t *node)
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);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
index de3ec1837b..37061f0f78 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
@@ -255,8 +255,8 @@ smb_ofile_open(
if (op->created_readonly)
node->readonly_creator = of;
- smb_node_add_ofile(node, of);
smb_node_inc_open_ofiles(node);
+ smb_node_add_ofile(node, of);
}
smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
smb_llist_insert_tail(&tree->t_ofile_list, of);
@@ -325,10 +325,12 @@ smb_ofile_close(
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 @@ smb_ofile_release(
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--;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_oplock.c b/usr/src/uts/common/fs/smbsrv/smb_oplock.c
index 9044ee880c..913b1b681b 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c
@@ -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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
(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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
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 @@ smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op)
* 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 @@ smb_oplock_break(smb_node_t *node, uint64_t sess_id, boolean_t nowait)
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 @@ smb_oplock_break(smb_node_t *node, uint64_t sess_id, boolean_t nowait)
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 @@ smb_oplock_break(smb_node_t *node, uint64_t sess_id, boolean_t nowait)
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 @@ smb_oplock_release(smb_node_t *node, smb_ofile_t *of)
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_oplock_release(smb_node_t *node, smb_ofile_t *of)
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_oplock_conflict(smb_node_t *node, smb_session_t *session, open_param_t *op)
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_oplock_conflict(smb_node_t *node, smb_session_t *session, open_param_t *op)
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 @@ smb_oplock_conflict(smb_node_t *node, smb_session_t *session, open_param_t *op)
* 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 @@ smb_oplock_exit(smb_node_t *node)
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_exit(smb_node_t *node)
/*
* 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--;
}
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c
index 9f65ebc4e4..7927e492d8 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c
@@ -302,10 +302,7 @@ smb_pathname_reduce(
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 {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c
index 42fe8abac6..1450ae68f0 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_rename.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c
@@ -180,8 +180,7 @@ smb_do_rename(
* 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) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index c0deba767a..d23048a78a 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -587,25 +587,6 @@ smb_server_start(struct smb_io_start *io_start)
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 @@ smb_server_listen(
{
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 @@ smb_server_listen(
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 @@ smb_server_listen(
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());
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c
index f3c7a4b2b0..e4e7377554 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c
@@ -43,7 +43,6 @@ static int smb_session_message(smb_session_t *);
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 @@ smb_session_reconnection_check(smb_session_list_t *se, smb_session_t *sess)
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 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
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 @@ smb_session_oplock_break(smb_session_t *session, smb_ofile_t *of)
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_session_oplock_break(smb_session_t *session, smb_ofile_t *of)
}
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();
- }
-}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c
index 8a28585fd4..f2e5785674 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c
@@ -268,6 +268,7 @@ smb_com_session_setup_andx(smb_request_t *sr)
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 @@ smb_com_session_setup_andx(smb_request_t *sr)
&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 @@ smb_com_session_setup_andx(smb_request_t *sr)
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 @@ smb_com_session_setup_andx(smb_request_t *sr)
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;
/*
diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_set_information.c
index 9e5275bbb2..78adc2abf6 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_set_information.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_set_information.c
@@ -132,8 +132,7 @@ smb_com_set_information(smb_request_t *sr)
/*
* 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);
}
/*
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c
index e4fe1a15bd..dd1d88fa39 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c
@@ -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 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa)
}
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;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c
index be82d499e1..64e76c548e 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c
@@ -161,8 +161,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa)
/*
* 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;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index d053031952..4989477563 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -884,8 +884,22 @@ smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
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 @@ smb_tree_get_flags(vfs_t *vfsp, smb_tree_t *tree)
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 @@ smb_tree_get_flags(vfs_t *vfsp, smb_tree_t *tree)
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;
}
diff --git a/usr/src/uts/common/smbsrv/smb_inet.h b/usr/src/uts/common/smbsrv/smb_inet.h
index 2ae07bf520..ff4734be3e 100644
--- a/usr/src/uts/common/smbsrv/smb_inet.h
+++ b/usr/src/uts/common/smbsrv/smb_inet.h
@@ -58,9 +58,8 @@ typedef struct smb_inaddr {
#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);
diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h
index 5381edad76..5d68b27ddb 100644
--- a/usr/src/uts/common/smbsrv/smb_kproto.h
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h
@@ -184,19 +184,14 @@ int smb_net_id(uint32_t);
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 @@ boolean_t smb_oplock_exit(smb_node_t *);
* 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 @@ void smb_session_list_signal(smb_session_list_t *);
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 *);
diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h
index 0d28903a40..775780a2a4 100644
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h
@@ -405,12 +405,40 @@ int MBC_SHADOW_CHAIN(struct mbuf_chain *SUBMBC, struct mbuf_chain *MBC,
#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 @@ typedef struct smb_session {
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 @@ typedef struct smb_user {
#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,
diff --git a/usr/src/uts/common/smbsrv/smbinfo.h b/usr/src/uts/common/smbsrv/smbinfo.h
index 7aef7ccd09..8b3899588e 100644
--- a/usr/src/uts/common/smbsrv/smbinfo.h
+++ b/usr/src/uts/common/smbsrv/smbinfo.h
@@ -126,9 +126,9 @@ typedef struct smb_kmod_cfg {
#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.