diff options
Diffstat (limited to 'usr/src')
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. |