summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAlan Wright <amw@Sun.COM>2009-03-12 15:41:34 -0700
committerAlan Wright <amw@Sun.COM>2009-03-12 15:41:34 -0700
commitfc724630b14603e4c1147df68b7bf45f7de7431f (patch)
treef17f96d6cf8a651c17ee86671237c6de3c121eb3 /usr/src
parentb9bce07ba60f860d2f740034a05b4b030093323e (diff)
downloadillumos-gate-fc724630b14603e4c1147df68b7bf45f7de7431f.tar.gz
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
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.