summaryrefslogtreecommitdiff
path: root/usr/src/cmd/smbsrv
diff options
context:
space:
mode:
authorafshin salek ardakani - Sun Microsystems - Irvine United States <Afshin.Ardakani@Sun.COM>2010-03-20 13:03:54 -0700
committerafshin salek ardakani - Sun Microsystems - Irvine United States <Afshin.Ardakani@Sun.COM>2010-03-20 13:03:54 -0700
commit9fb67ea305c66b6a297583b9b0db6796b0dfe497 (patch)
treec349f5290a8e9d20887b690df8c81dd17e405c9c /usr/src/cmd/smbsrv
parente58a2f26c9663323aa315835a769f6008a17f7e4 (diff)
downloadillumos-joyent-9fb67ea305c66b6a297583b9b0db6796b0dfe497.tar.gz
PSARC/2009/534 SMB/CIFS Standalone DFS
PSARC/2010/052 idmap flush 6711751 SMB/CIFS Distributed File System (DFS) 6650858 cache flush sub-command could be useful 6916379 share modes should be checked for directories as well as files 6906874 Automatic primary group mapping based on user mapping 6879236 No error report when ad-container refers to nonexistent container 6919087 Intermittent smbd crash during share access 6853811 Kerberized applications fail even after a successful domain join via smbadm 6907640 Current algorithm of anonymous authentication is not correct 6888813 SMB/CIFS support for ZFS user and group quotas 6921142 Guest issues with idmap rule and with workgroup mode 6924843 smb_sam_lookup_sid() leaks memory 6919600 Unable to delete ACE from ACL on a share 6915463 smb_nic interface needs LOG_ERR syslog entries and proper return codes 6926137 WritePrinter requires multi-fragment NDR RPC support 6926211 smbd could report clock skew 6925697 Quota usage does not decrease after deleting files from Mac Snow Leopard 10.6 6849962 smbadm show cannot display all groups with error 'cannot obtain a SID' 6926265 SMB watch tree change notification 6811424 must restart smb/server when idmapd restarts 6927745 Consolidate file system query/set information handlers 6924281 SMB_WRITE_RAW_COM doesn't work. 6925618 idmap show -v gets type of UNIX ID wrong in "Rule" output 6807651 rule changes do not flush cache 6928550 libsmbrdr doesn't cleanup stale sessions 6861058 MMC: Error message printed on log entries 6817392 smbd will not exit 6931027 core file due to NULL zpool handle in zfs_open() --HG-- rename : usr/src/common/smbsrv/smb_common_door_decode.c => usr/src/common/smbsrv/smb_door_legacy.c rename : usr/src/common/smbsrv/smb_xdr_utils.c => usr/src/common/smbsrv/smb_xdr.c rename : usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c => usr/src/lib/smbsrv/libmlsvc/common/wkssvc_svc.c rename : usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c => usr/src/uts/common/fs/smbsrv/smb_fsinfo.c rename : usr/src/uts/common/fs/smbsrv/smb_kdoor_clnt.c => usr/src/uts/common/fs/smbsrv/smb_kdoor.c rename : usr/src/uts/common/fs/smbsrv/smb_util.c => usr/src/uts/common/fs/smbsrv/smb_kutil.c rename : usr/src/uts/common/smbsrv/smb_common_door.h => usr/src/uts/common/smbsrv/smb_door.h
Diffstat (limited to 'usr/src/cmd/smbsrv')
-rw-r--r--usr/src/cmd/smbsrv/dtrace/msrpc.d6
-rw-r--r--usr/src/cmd/smbsrv/smbadm/smbadm.c18
-rw-r--r--usr/src/cmd/smbsrv/smbd/Makefile14
-rw-r--r--usr/src/cmd/smbsrv/smbd/eventlog.dllbin0 -> 1536 bytes
-rw-r--r--usr/src/cmd/smbsrv/smbd/server.xml6
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd.h54
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_door_ops.c509
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c892
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_logon.c19
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_main.c251
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_opipe_doorsvc.c110
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c57
12 files changed, 1147 insertions, 789 deletions
diff --git a/usr/src/cmd/smbsrv/dtrace/msrpc.d b/usr/src/cmd/smbsrv/dtrace/msrpc.d
index 15f92ac93e..4462934cd6 100644
--- a/usr/src/cmd/smbsrv/dtrace/msrpc.d
+++ b/usr/src/cmd/smbsrv/dtrace/msrpc.d
@@ -127,11 +127,11 @@ door_ki_upcall:return
sdt:smbsrv::smb-sessionsetup-clntinfo
{
- clnt = (netr_client_t *)arg0;
+ user_info = (smb_logon_t *)arg0;
printf("domain\\username=%s\\%s\n\n",
- stringof(clnt->domain),
- stringof(clnt->username));
+ stringof(user_info->lg_domain),
+ stringof(user_info->lg_username));
}
smb_tree_connect:entry
diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c
index 2533bf6cc4..ecf0f52615 100644
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c
@@ -931,10 +931,14 @@ smbadm_group_show(int argc, char **argv)
smb_lgrp_iterclose(&gi);
- if (status != SMB_LGRP_NO_MORE) {
+ if ((status != SMB_LGRP_NO_MORE) || smb_lgrp_itererror(&gi)) {
+ if (status != SMB_LGRP_NO_MORE)
+ syslog(LOG_ERR, "smb_lgrp_iterate: %s",
+ smb_lgrp_strerror(status));
+
(void) fprintf(stderr,
- gettext("failed to get all the groups (%s)\n"),
- smb_lgrp_strerror(status));
+ gettext("\nAn error occurred while retrieving group data.\n"
+ "Check the system log for more information.\n"));
return (status);
}
@@ -1439,17 +1443,10 @@ smbadm_init(void)
switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) {
case SMBADM_CMDF_GROUP:
- if (smb_idmap_start() != 0) {
- (void) fprintf(stderr,
- gettext("failed to contact idmap service\n"));
- return (1);
- }
-
if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) {
(void) fprintf(stderr,
gettext("failed to initialize (%s)\n"),
smb_lgrp_strerror(rc));
- smb_idmap_stop();
return (1);
}
break;
@@ -1471,7 +1468,6 @@ smbadm_fini(void)
switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) {
case SMBADM_CMDF_GROUP:
smb_lgrp_stop();
- smb_idmap_stop();
break;
case SMBADM_CMDF_USER:
diff --git a/usr/src/cmd/smbsrv/smbd/Makefile b/usr/src/cmd/smbsrv/smbd/Makefile
index 0c0a0bcee2..dff759c94f 100644
--- a/usr/src/cmd/smbsrv/smbd/Makefile
+++ b/usr/src/cmd/smbsrv/smbd/Makefile
@@ -19,14 +19,13 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
PROG= smbd
SRCS= \
- smbd_door_ops.c \
smbd_doorsvc.c \
smbd_join.c \
smbd_logon.c \
@@ -39,11 +38,15 @@ include ../../Makefile.cmd
MANIFEST= server.xml
SVCMETHOD= svc-smbd
+LOGDLL= eventlog.dll
ROOTMANIFESTDIR = $(ROOTSVCSMB)
-$(ROOTMANIFEST):= FILEMODE = 0444
+ROOTVARSMBDLLDIR = $(ROOTVARSMB)/cvol/windows/system32
+ROOTVARSMBDLL= $(LOGDLL:%=$(ROOTVARSMBDLLDIR)/%)
+$(ROOTMANIFEST):= FILEMODE = 0444
$(ROOTSVCMETHOD):= FILEMODE = 0555
+$(ROOTVARSMBDLL):= FILEMODE = 0755
include ../Makefile.smbsrv.defs
@@ -60,6 +63,9 @@ $(ROOTSMBDFILE):= FILEMODE = 0555
$(ROOTSMBDDIR)/%: %
$(INS.file)
+$(ROOTVARSMBDLLDIR)/%: %
+ $(INS.file)
+
all: $(PROG)
clean:
@@ -78,4 +84,4 @@ _msg:
include ../../Makefile.targ
install: all .WAIT $(ROOTETCDEFAULTFILES) $(ROOTMANIFEST) \
- $(ROOTSMBDFILE) ${ROOTSVCMETHOD}
+ $(ROOTSMBDFILE) ${ROOTSVCMETHOD} $(ROOTVARSMBDLL)
diff --git a/usr/src/cmd/smbsrv/smbd/eventlog.dll b/usr/src/cmd/smbsrv/smbd/eventlog.dll
new file mode 100644
index 0000000000..7e66801aa1
--- /dev/null
+++ b/usr/src/cmd/smbsrv/smbd/eventlog.dll
Binary files differ
diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml
index 208a64d0d8..30bbedd595 100644
--- a/usr/src/cmd/smbsrv/smbd/server.xml
+++ b/usr/src/cmd/smbsrv/smbd/server.xml
@@ -21,7 +21,7 @@ information: Portions Copyright [yyyy] [name of copyright owner]
CDDL HEADER END
-Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+Copyright 2010 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
NOTE: This service manifest is not editable; its contents will
@@ -65,7 +65,7 @@ file.
<!-- Must have idmap service started -->
<dependency name='idmap'
grouping='require_all'
- restart_on='error'
+ restart_on='restart'
type='service'>
<service_fmri value='svc:/system/idmap:default'/>
</dependency>
@@ -205,6 +205,8 @@ file.
value='0' override='true'/>
<propval name='ipv6_enable' type='boolean'
value='false' override='true'/>
+ <propval name='sv_version' type='astring'
+ value='5.0' override='true'/>
</property_group>
<!-- SMB service-specific shares exec configuration defaults -->
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h
index e0192dcbee..23bba19cbb 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd.h
+++ b/usr/src/cmd/smbsrv/smbd/smbd.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,31 +32,30 @@ extern "C" {
#endif
#include <sys/types.h>
+#include <thread.h>
+#include <synch.h>
#include <smbsrv/smb_ioctl.h>
#include <smbsrv/smb_token.h>
#include <smbsrv/libsmb.h>
#include <smbsrv/libmlsvc.h>
-extern int smbd_opipe_dsrv_start(void);
-extern void smbd_opipe_dsrv_stop(void);
+int smbd_opipe_start(void);
+void smbd_opipe_stop(void);
+int smbd_share_start(void);
+void smbd_share_stop(void);
+boolean_t smbd_set_netlogon_cred(void);
+int smbd_locate_dc_start(void);
+smb_token_t *smbd_user_auth_logon(smb_logon_t *);
+void smbd_user_nonauth_logon(uint32_t);
+void smbd_user_auth_logoff(uint32_t);
+uint32_t smbd_join(smb_joininfo_t *);
+void smbd_set_secmode(int);
+boolean_t smbd_online(void);
-extern int smb_share_dsrv_start(void);
-extern void smb_share_dsrv_stop(void);
-
-extern boolean_t smbd_set_netlogon_cred(void);
-extern int smbd_locate_dc_start(void);
-
-extern smb_token_t *smbd_user_auth_logon(netr_client_t *);
-extern void smbd_user_nonauth_logon(uint32_t);
-extern void smbd_user_auth_logoff(uint32_t);
-extern uint32_t smbd_join(smb_joininfo_t *);
-
-extern void smbd_set_secmode(int);
-
-extern int smbd_vss_get_count(const char *, uint32_t *);
-extern void smbd_vss_get_snapshots(const char *, uint32_t, uint32_t *,
+int smbd_vss_get_count(const char *, uint32_t *);
+void smbd_vss_get_snapshots(const char *, uint32_t, uint32_t *,
uint32_t *, char **);
-extern int smbd_vss_map_gmttoken(const char *, char *, char *);
+int smbd_vss_map_gmttoken(const char *, char *, char *);
typedef struct smbd {
const char *s_version; /* smbd version string */
@@ -65,6 +64,7 @@ typedef struct smbd {
uid_t s_uid; /* UID of current daemon */
gid_t s_gid; /* GID of current daemon */
int s_fg; /* Run in foreground */
+ boolean_t s_initialized;
boolean_t s_shutting_down; /* shutdown control */
volatile uint_t s_sigval;
volatile uint_t s_refreshes;
@@ -80,6 +80,22 @@ typedef struct smbd {
boolean_t s_fatal_error;
} smbd_t;
+#define SMBD_DOOR_NAMESZ 16
+
+typedef struct smbd_door {
+ mutex_t sd_mutex;
+ cond_t sd_cv;
+ uint32_t sd_ncalls;
+ char sd_name[SMBD_DOOR_NAMESZ];
+} smbd_door_t;
+
+int smbd_door_start(void);
+void smbd_door_stop(void);
+void smbd_door_init(smbd_door_t *, const char *);
+void smbd_door_fini(smbd_door_t *);
+void smbd_door_enter(smbd_door_t *);
+void smbd_door_return(smbd_door_t *, char *, size_t, door_desc_t *, uint_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c b/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c
deleted file mode 100644
index dbf6e70efe..0000000000
--- a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * SMBd door operations
- */
-#include <stdlib.h>
-#include <synch.h>
-#include <strings.h>
-#include <smbsrv/smb_common_door.h>
-#include <smbsrv/smb_token.h>
-#include <smbsrv/libmlsvc.h>
-#include <smbsrv/libsmbns.h>
-#include "smbd.h"
-
-static char *smb_dop_user_auth_logon(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_user_nonauth_logon(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_user_auth_logoff(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-
-static char *smb_dop_lookup_sid(char *, size_t, door_desc_t *, uint_t,
- size_t *, int *);
-static char *smb_dop_lookup_name(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_join(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_get_dcinfo(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-
-static char *smb_dop_vss_get_count(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_vss_get_snapshots(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_vss_map_gmttoken(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-static char *smb_dop_ads_find_host(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err);
-
-/* SMB daemon's door operation table */
-smb_dr_op_t smb_doorsrv_optab[] =
-{
- smb_dop_user_auth_logon, /* SMB_DR_USER_AUTH_LOGON */
- smb_dop_user_nonauth_logon, /* SMB_DR_USER_NONAUTH_LOGON */
- smb_dop_user_auth_logoff, /* SMB_DR_USER_AUTH_LOGOFF */
- smb_dop_lookup_sid, /* SMB_DR_LOOKUP_SID */
- smb_dop_lookup_name, /* SMB_DR_LOOKUP_NAME */
- smb_dop_join, /* SMB_DR_JOIN */
- smb_dop_get_dcinfo, /* SMB_DR_GET_DCINFO */
- smb_dop_vss_get_count, /* SMB_DR_VSS_GET_COUNT */
- smb_dop_vss_get_snapshots, /* SMB_DR_VSS_GET_SNAPSHOTS */
- smb_dop_vss_map_gmttoken, /* SMB_DR_VSS_MAP_GMTTOKEN */
- smb_dop_ads_find_host /* SMB_DR_ADS_FIND_HOST */
-};
-
-/*ARGSUSED*/
-static char *
-smb_dop_user_nonauth_logon(char *argp, size_t arg_size, door_desc_t *dp,
- uint_t n_desc, size_t *rbufsize, int *err)
-{
- char *buf;
- uint32_t sid;
-
- if (smb_dr_decode_common(argp, arg_size, xdr_uint32_t, &sid) != 0) {
- *rbufsize = 0;
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- smbd_user_nonauth_logon(sid);
-
- if ((buf = smb_dr_set_res_stat(SMB_DR_OP_SUCCESS, rbufsize)) == NULL) {
- *rbufsize = 0;
- *err = SMB_DR_OP_ERR_ENCODE;
- return (NULL);
- }
-
- *err = SMB_DR_OP_SUCCESS;
- return (buf);
-}
-
-/*ARGSUSED*/
-static char *
-smb_dop_user_auth_logoff(char *argp, size_t arg_size, door_desc_t *dp,
- uint_t n_desc, size_t *rbufsize, int *err)
-{
- char *buf;
- uint32_t sid;
-
- if (smb_dr_decode_common(argp, arg_size, xdr_uint32_t, &sid) != 0) {
- *rbufsize = 0;
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- smbd_user_auth_logoff(sid);
-
- if ((buf = smb_dr_set_res_stat(SMB_DR_OP_SUCCESS, rbufsize)) == NULL) {
- *rbufsize = 0;
- *err = SMB_DR_OP_ERR_ENCODE;
- return (NULL);
- }
-
- *err = SMB_DR_OP_SUCCESS;
- return (buf);
-}
-
-/*
- * smb_dr_is_valid_opcode
- *
- * Validates the given door opcode.
- */
-int
-smb_dr_is_valid_opcode(int opcode)
-{
- if (opcode < 0 ||
- opcode > (sizeof (smb_doorsrv_optab) / sizeof (smb_dr_op_t)))
- return (-1);
- else
- return (0);
-}
-
-/*
- * Obtains an access token on successful user authentication.
- */
-/*ARGSUSED*/
-static char *
-smb_dop_user_auth_logon(char *argp, size_t arg_size, door_desc_t *dp,
- uint_t n_desc, size_t *rbufsize, int *err)
-{
- netr_client_t *clnt_info;
- smb_token_t *token;
- char *buf;
-
- *rbufsize = 0;
- *err = 0;
- clnt_info = smb_dr_decode_arg_get_token(argp, arg_size);
- if (clnt_info == NULL) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- token = smbd_user_auth_logon(clnt_info);
-
- netr_client_xfree(clnt_info);
-
- if (!token) {
- *err = SMB_DR_OP_ERR_EMPTYBUF;
- return (NULL);
- }
-
- if ((buf = smb_dr_encode_res_token(token, rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- }
-
- smb_token_destroy(token);
- return (buf);
-}
-
-/*ARGSUSED*/
-static char *
-smb_dop_lookup_name(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- smb_domain_t dinfo;
- smb_account_t ainfo;
- lsa_account_t acct;
- char buf[MAXNAMELEN];
- char *rbuf = NULL;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
-
- if (smb_dr_decode_common(argp, arg_size, lsa_account_xdr, &acct) != 0) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- if (*acct.a_domain == '\0')
- (void) snprintf(buf, MAXNAMELEN, "%s", acct.a_name);
- else if (strchr(acct.a_domain, '.') != NULL)
- (void) snprintf(buf, MAXNAMELEN, "%s@%s", acct.a_name,
- acct.a_domain);
- else
- (void) snprintf(buf, MAXNAMELEN, "%s\\%s", acct.a_domain,
- acct.a_name);
-
- acct.a_status = lsa_lookup_name(buf, acct.a_sidtype, &ainfo);
- if (acct.a_status == NT_STATUS_SUCCESS) {
- acct.a_sidtype = ainfo.a_type;
- smb_sid_tostr(ainfo.a_sid, acct.a_sid);
- (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
-
- if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
- (void) strlcpy(acct.a_domain, dinfo.di_fqname,
- MAXNAMELEN);
- else
- (void) strlcpy(acct.a_domain, ainfo.a_domain,
- MAXNAMELEN);
- smb_account_free(&ainfo);
- }
-
- if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &acct,
- lsa_account_xdr, rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- *rbufsize = 0;
- }
-
- return (rbuf);
-}
-
-/*ARGSUSED*/
-static char *
-smb_dop_lookup_sid(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- smb_domain_t dinfo;
- smb_account_t ainfo;
- lsa_account_t acct;
- smb_sid_t *sid;
- char *rbuf = NULL;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
-
- if (smb_dr_decode_common(argp, arg_size, lsa_account_xdr, &acct) != 0) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- sid = smb_sid_fromstr(acct.a_sid);
- acct.a_status = lsa_lookup_sid(sid, &ainfo);
- smb_sid_free(sid);
-
- if (acct.a_status == NT_STATUS_SUCCESS) {
- acct.a_sidtype = ainfo.a_type;
- smb_sid_tostr(ainfo.a_sid, acct.a_sid);
- (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
-
- if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
- (void) strlcpy(acct.a_domain, dinfo.di_fqname,
- MAXNAMELEN);
- else
- (void) strlcpy(acct.a_domain, ainfo.a_domain,
- MAXNAMELEN);
-
- smb_account_free(&ainfo);
- }
-
- if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &acct,
- lsa_account_xdr, rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- *rbufsize = 0;
- }
-
- return (rbuf);
-}
-
-/*ARGSUSED*/
-static char *
-smb_dop_join(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- smb_joininfo_t jdi;
- uint32_t status;
- char *rbuf = NULL;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
-
- if (smb_dr_decode_common(argp, arg_size, xdr_smb_dr_joininfo_t, &jdi)
- != 0) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- status = smbd_join(&jdi);
-
- if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &status,
- xdr_uint32_t, rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- *rbufsize = 0;
- }
-
- return (rbuf);
-}
-
-/*ARGSUSED*/
-static char *
-smb_dop_get_dcinfo(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- char *rbuf = NULL;
- smb_domainex_t dxi;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
-
- if (!smb_domain_getinfo(&dxi)) {
- *err = SMB_DR_OP_ERR_EMPTYBUF;
- return (NULL);
- }
-
- if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, dxi.d_dc,
- rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- *rbufsize = 0;
- }
- return (rbuf);
-}
-
-/*
- * This routine returns the number of snapshots for a dataset
- */
-
-/*ARGSUSED*/
-static char *
-smb_dop_vss_get_count(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- char *rbuf = NULL;
- uint32_t count;
- char *path;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
-
- if ((path = smb_dr_decode_string(argp, arg_size)) == NULL) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- if (smbd_vss_get_count(path, &count) == 0) {
- if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &count,
- xdr_uint32_t, rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- }
- }
-
- xdr_free(xdr_string, (char *)&path);
-
- return (rbuf);
-}
-
-/*
- * This routine returns the count and list of snapshots.
- * The list is in the Microsoft @GMT token format.
- */
-/*ARGSUSED*/
-static char *
-smb_dop_vss_get_snapshots(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- char *rbuf = NULL, **gmtp;
- smb_dr_get_gmttokens_t request;
- smb_dr_return_gmttokens_t reply;
- uint_t i;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
- bzero(&request, sizeof (smb_dr_get_gmttokens_t));
- bzero(&reply, sizeof (smb_dr_return_gmttokens_t));
-
- if (smb_dr_decode_common(argp, arg_size,
- xdr_smb_dr_get_gmttokens_t, &request) != 0) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- reply.rg_gmttokens.rg_gmttokens_val = malloc(request.gg_count *
- sizeof (char *));
- bzero(reply.rg_gmttokens.rg_gmttokens_val, request.gg_count *
- sizeof (char *));
-
- if (reply.rg_gmttokens.rg_gmttokens_val == NULL) {
- xdr_free(xdr_smb_dr_get_gmttokens_t, (char *)&request);
- return (NULL);
- }
-
- smbd_vss_get_snapshots(request.gg_path, request.gg_count,
- &reply.rg_count,
- &reply.rg_gmttokens.rg_gmttokens_len,
- reply.rg_gmttokens.rg_gmttokens_val);
-
- if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &reply,
- xdr_smb_dr_return_gmttokens_t, rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- }
-
- for (i = 0, gmtp = reply.rg_gmttokens.rg_gmttokens_val;
- (i < request.gg_count); i++) {
- if (*gmtp)
- free(*gmtp);
- gmtp++;
- }
- free(reply.rg_gmttokens.rg_gmttokens_val);
- xdr_free(xdr_smb_dr_get_gmttokens_t, (char *)&request);
- return (rbuf);
-}
-
-/*
- * This routine returns the snapshot name of the snapshot
- * that matches path of the pathname of the dataset and
- * the @GMT token.
- */
-
-/*ARGSUSED*/
-static char *
-smb_dop_vss_map_gmttoken(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- char *rbuf = NULL;
- char *snapname;
- smb_dr_map_gmttoken_t request;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
- bzero(&request, sizeof (smb_dr_map_gmttoken_t));
-
- if (smb_dr_decode_common(argp, arg_size, xdr_smb_dr_map_gmttoken_t,
- &request) != 0) {
- *err = SMB_DR_OP_ERR_DECODE;
- xdr_free(xdr_smb_dr_map_gmttoken_t, (char *)&request);
- return (NULL);
- }
-
- snapname = (char *)malloc(MAXPATHLEN);
-
- if (snapname == NULL) {
- xdr_free(xdr_smb_dr_map_gmttoken_t, (char *)&request);
- return (NULL);
- }
-
- if ((smbd_vss_map_gmttoken(request.mg_path, request.mg_gmttoken,
- snapname) != 0)) {
- *snapname = '\0';
- }
-
- rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, snapname, rbufsize);
-
- if (rbuf == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- *rbufsize = 0;
- }
-
- xdr_free(xdr_smb_dr_map_gmttoken_t, (char *)&request);
- free(snapname);
- return (rbuf);
-}
-
-/*ARGSUSED*/
-static char *
-smb_dop_ads_find_host(char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err)
-{
- smb_ads_host_info_t *hinfo = NULL;
- char *hostname;
- char *fqdn = NULL;
- char *rbuf = NULL;
-
- *err = SMB_DR_OP_SUCCESS;
- *rbufsize = 0;
-
- /* Decode */
- if ((fqdn = smb_dr_decode_string(argp, arg_size)) == 0) {
- *err = SMB_DR_OP_ERR_DECODE;
- return (NULL);
- }
-
- if ((hinfo = smb_ads_find_host(fqdn, NULL)) == NULL)
- hostname = "";
- else
- hostname = hinfo->name;
-
- xdr_free(xdr_string, (char *)&fqdn);
-
- /* Encode the result and return */
- if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, hostname,
- rbufsize)) == NULL) {
- *err = SMB_DR_OP_ERR_ENCODE;
- *rbufsize = 0;
- }
-
- free(hinfo);
- return (rbuf);
-}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
index 8b8954f50b..7dc3eef535 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
@@ -19,20 +19,17 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-/*
- * SMBd door server
- */
-
+#include <sys/list.h>
+#include <assert.h>
#include <alloca.h>
#include <door.h>
#include <errno.h>
#include <syslog.h>
#include <unistd.h>
-#include <varargs.h>
#include <stdio.h>
#include <synch.h>
#include <string.h>
@@ -41,161 +38,874 @@
#include <fcntl.h>
#include <pthread.h>
#include <strings.h>
-#include <smbsrv/smb_door_svc.h>
-#include <smbsrv/smb_common_door.h>
+#include <smbsrv/smb_door.h>
+#include <smbsrv/smb_xdr.h>
+#include <smbsrv/smb_token.h>
+#include <smbsrv/libmlsvc.h>
+#include <smbsrv/libsmbns.h>
+#include "smbd.h"
+
+/*
+ * Parameter for door operations.
+ */
+typedef struct smbd_arg {
+ list_node_t lnd;
+ smb_doorhdr_t hdr;
+ const char *opname;
+ char *data;
+ size_t datalen;
+ char *rbuf;
+ size_t rsize;
+ uint32_t status;
+} smbd_arg_t;
+
+/*
+ * The list contains asynchronous requests that have been initiated
+ * but have not yet been collected (via smbd_dop_async_response).
+ */
+typedef struct smbd_doorsvc {
+ mutex_t sd_mutex;
+ cond_t sd_cv;
+ list_t sd_async_list;
+ uint32_t sd_async_count;
+} smbd_doorsvc_t;
+
+static int smbd_dop_null(smbd_arg_t *);
+static int smbd_dop_async_response(smbd_arg_t *);
+static int smbd_dop_user_auth_logon(smbd_arg_t *);
+static int smbd_dop_user_nonauth_logon(smbd_arg_t *);
+static int smbd_dop_user_auth_logoff(smbd_arg_t *);
+static int smbd_dop_lookup_sid(smbd_arg_t *);
+static int smbd_dop_lookup_name(smbd_arg_t *);
+static int smbd_dop_join(smbd_arg_t *);
+static int smbd_dop_get_dcinfo(smbd_arg_t *);
+static int smbd_dop_vss_get_count(smbd_arg_t *);
+static int smbd_dop_vss_get_snapshots(smbd_arg_t *);
+static int smbd_dop_vss_map_gmttoken(smbd_arg_t *);
+static int smbd_dop_ads_find_host(smbd_arg_t *);
+static int smbd_dop_quota_query(smbd_arg_t *);
+static int smbd_dop_quota_set(smbd_arg_t *);
+static int smbd_dop_dfs_get_referrals(smbd_arg_t *);
+
+typedef int (*smbd_dop_t)(smbd_arg_t *);
+
+typedef struct smbd_doorop {
+ smb_dopcode_t opcode;
+ smbd_dop_t op;
+} smbd_doorop_t;
+smbd_doorop_t smbd_doorops[] = {
+ { SMB_DR_NULL, smbd_dop_null },
+ { SMB_DR_ASYNC_RESPONSE, smbd_dop_async_response },
+ { SMB_DR_USER_AUTH_LOGON, smbd_dop_user_auth_logon },
+ { SMB_DR_USER_NONAUTH_LOGON, smbd_dop_user_nonauth_logon },
+ { SMB_DR_USER_AUTH_LOGOFF, smbd_dop_user_auth_logoff },
+ { SMB_DR_LOOKUP_SID, smbd_dop_lookup_sid },
+ { SMB_DR_LOOKUP_NAME, smbd_dop_lookup_name },
+ { SMB_DR_JOIN, smbd_dop_join },
+ { SMB_DR_GET_DCINFO, smbd_dop_get_dcinfo },
+ { SMB_DR_VSS_GET_COUNT, smbd_dop_vss_get_count },
+ { SMB_DR_VSS_GET_SNAPSHOTS, smbd_dop_vss_get_snapshots },
+ { SMB_DR_VSS_MAP_GMTTOKEN, smbd_dop_vss_map_gmttoken },
+ { SMB_DR_ADS_FIND_HOST, smbd_dop_ads_find_host },
+ { SMB_DR_QUOTA_QUERY, smbd_dop_quota_query },
+ { SMB_DR_QUOTA_SET, smbd_dop_quota_set },
+ { SMB_DR_DFS_GET_REFERRALS, smbd_dop_dfs_get_referrals }
+};
-static int smb_doorsrv_fildes = -1;
-static mutex_t smb_doorsrv_mutex;
+static int smbd_ndoorop = (sizeof (smbd_doorops) / sizeof (smbd_doorops[0]));
-static void smb_door_srv_func(void *cookie, char *ptr, size_t size,
- door_desc_t *dp, uint_t n_odesc);
+static smbd_doorsvc_t smbd_doorsvc;
+static int smbd_door_fd = -1;
+static int smbd_door_cookie = 0x534D4244; /* SMBD */
+static smbd_door_t smbd_door_sdh;
+
+static void smbd_door_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
+static int smbd_door_dispatch_async(smbd_arg_t *);
+static void smbd_door_release_async(smbd_arg_t *);
+static void *smbd_door_dispatch_op(void *);
/*
- * smb_door_srv_start
- *
* Start the smbd door service. Create and bind to a door.
* Returns 0 on success. Otherwise, -1.
*/
int
-smb_door_srv_start()
+smbd_door_start(void)
{
int newfd;
- (void) mutex_lock(&smb_doorsrv_mutex);
+ (void) mutex_lock(&smbd_doorsvc.sd_mutex);
- if (smb_doorsrv_fildes != -1) {
+ if (smbd_door_fd != -1) {
(void) fprintf(stderr, "smb_doorsrv_start: already started");
- (void) mutex_unlock(&smb_doorsrv_mutex);
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
return (-1);
}
- if ((smb_doorsrv_fildes = door_create(smb_door_srv_func,
- SMB_DR_SVC_COOKIE, DOOR_UNREF)) < 0) {
+ smbd_door_init(&smbd_door_sdh, "doorsrv");
+
+ list_create(&smbd_doorsvc.sd_async_list, sizeof (smbd_arg_t),
+ offsetof(smbd_arg_t, lnd));
+ smbd_doorsvc.sd_async_count = 0;
+
+ if ((smbd_door_fd = door_create(smbd_door_dispatch,
+ &smbd_door_cookie, DOOR_UNREF)) < 0) {
(void) fprintf(stderr, "smb_doorsrv_start: door_create: %s",
strerror(errno));
- smb_doorsrv_fildes = -1;
- (void) mutex_unlock(&smb_doorsrv_mutex);
+ smbd_door_fd = -1;
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
return (-1);
}
- (void) unlink(SMB_DR_SVC_NAME);
+ (void) unlink(SMBD_DOOR_NAME);
- if ((newfd = creat(SMB_DR_SVC_NAME, 0644)) < 0) {
+ if ((newfd = creat(SMBD_DOOR_NAME, 0644)) < 0) {
(void) fprintf(stderr, "smb_doorsrv_start: open: %s",
strerror(errno));
- (void) door_revoke(smb_doorsrv_fildes);
- smb_doorsrv_fildes = -1;
- (void) mutex_unlock(&smb_doorsrv_mutex);
+ (void) door_revoke(smbd_door_fd);
+ smbd_door_fd = -1;
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
return (-1);
}
(void) close(newfd);
- (void) fdetach(SMB_DR_SVC_NAME);
+ (void) fdetach(SMBD_DOOR_NAME);
- if (fattach(smb_doorsrv_fildes, SMB_DR_SVC_NAME) < 0) {
+ if (fattach(smbd_door_fd, SMBD_DOOR_NAME) < 0) {
(void) fprintf(stderr, "smb_doorsrv_start: fattach: %s",
strerror(errno));
- (void) door_revoke(smb_doorsrv_fildes);
- smb_doorsrv_fildes = -1;
- (void) mutex_unlock(&smb_doorsrv_mutex);
+ (void) door_revoke(smbd_door_fd);
+ smbd_door_fd = -1;
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
return (-1);
}
- (void) mutex_unlock(&smb_doorsrv_mutex);
- return (smb_doorsrv_fildes);
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
+ return (smbd_door_fd);
}
-
/*
- * smb_door_srv_stop
- *
* Stop the smbd door service.
*/
void
-smb_door_srv_stop(void)
+smbd_door_stop(void)
+{
+ (void) mutex_lock(&smbd_doorsvc.sd_mutex);
+
+ smbd_door_fini(&smbd_door_sdh);
+
+ if (smbd_door_fd != -1) {
+ (void) fdetach(SMBD_DOOR_NAME);
+ (void) door_revoke(smbd_door_fd);
+ smbd_door_fd = -1;
+ }
+
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
+}
+
+/*ARGSUSED*/
+static void
+smbd_door_dispatch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
+ uint_t n_desc)
{
- (void) mutex_lock(&smb_doorsrv_mutex);
+ smbd_arg_t dop_arg;
+ smb_doorhdr_t *hdr;
+ size_t hdr_size;
+ char *rbuf = NULL;
+
+ smbd_door_enter(&smbd_door_sdh);
+
+ if (!smbd_online())
+ smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
+
+ bzero(&dop_arg, sizeof (smbd_arg_t));
+ hdr = &dop_arg.hdr;
+ hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr);
+
+ if ((cookie != &smbd_door_cookie) || (argp == NULL) ||
+ (arg_size < hdr_size)) {
+ smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
+ }
- if (smb_doorsrv_fildes != -1) {
- (void) fdetach(SMB_DR_SVC_NAME);
- (void) door_revoke(smb_doorsrv_fildes);
- smb_doorsrv_fildes = -1;
+ if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) {
+ syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed");
+ smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
}
- (void) mutex_unlock(&smb_doorsrv_mutex);
+ if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) || (hdr->dh_txid == 0)) {
+ syslog(LOG_DEBUG, "smbd_door_dispatch: invalid header");
+ smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
+ }
+
+ dop_arg.opname = smb_doorhdr_opname(hdr->dh_op);
+ dop_arg.data = argp + hdr_size;
+ dop_arg.datalen = hdr->dh_datalen;
+
+ if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) {
+ /*
+ * ASYNC_RESPONSE is used to collect the response
+ * to an async call; it cannot be an async call.
+ */
+ hdr->dh_flags &= ~SMB_DF_ASYNC;
+ }
+
+ if (hdr->dh_flags & SMB_DF_ASYNC) {
+ if (smbd_door_dispatch_async(&dop_arg) == 0)
+ hdr->dh_door_rc = SMB_DOP_SUCCESS;
+ else
+ hdr->dh_door_rc = SMB_DOP_NOT_CALLED;
+
+ } else {
+ (void) smbd_door_dispatch_op(&dop_arg);
+ }
+
+ if ((rbuf = (char *)alloca(dop_arg.rsize + hdr_size)) == NULL) {
+ errno = ENOMEM;
+ syslog(LOG_DEBUG, "smbd_door_dispatch[%s]: alloca %m",
+ dop_arg.opname);
+ smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
+ }
+
+ if (dop_arg.rbuf != NULL) {
+ (void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize);
+ free(dop_arg.rbuf);
+ }
+
+ hdr->dh_datalen = dop_arg.rsize;
+ (void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size);
+ dop_arg.rsize += hdr_size;
+
+ smbd_door_return(&smbd_door_sdh, rbuf, dop_arg.rsize, NULL, 0);
+ /*NOTREACHED*/
}
/*
- * smb_door_err_hdlr
+ * Launch a thread to process an asynchronous door call.
+ */
+static int
+smbd_door_dispatch_async(smbd_arg_t *req_arg)
+{
+ smbd_arg_t *arg = NULL;
+ char *data = NULL;
+ pthread_attr_t attr;
+ pthread_t tid;
+ int rc;
+
+ if ((req_arg->hdr.dh_flags & SMB_DF_ASYNC) == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((arg = malloc(sizeof (smbd_arg_t))) == NULL) {
+ syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m",
+ req_arg->opname);
+ return (-1);
+ }
+
+ (void) memcpy(arg, req_arg, sizeof (smbd_arg_t));
+ arg->data = NULL;
+
+ if (req_arg->datalen != 0) {
+ if ((data = malloc(req_arg->datalen)) == NULL) {
+ free(arg);
+ syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m",
+ req_arg->opname);
+ return (-1);
+ }
+
+ (void) memcpy(data, req_arg->data, req_arg->datalen);
+ arg->data = data;
+ }
+
+ (void) mutex_lock(&smbd_doorsvc.sd_mutex);
+ list_insert_tail(&smbd_doorsvc.sd_async_list, arg);
+ ++smbd_doorsvc.sd_async_count;
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
+
+ (void) pthread_attr_init(&attr);
+ (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ rc = pthread_create(&tid, &attr, smbd_door_dispatch_op, arg);
+ (void) pthread_attr_destroy(&attr);
+
+ if (rc != 0) {
+ (void) mutex_lock(&smbd_doorsvc.sd_mutex);
+ smbd_door_release_async(arg);
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
+ }
+
+ return (rc);
+}
+
+/*
+ * Remove an entry from the async response pending list and free
+ * the arg and associated data.
+ *
+ * Must only be called while holding the smbd_doorsvc mutex.
+ */
+static void
+smbd_door_release_async(smbd_arg_t *arg)
+{
+ if (arg != NULL) {
+ list_remove(&smbd_doorsvc.sd_async_list, arg);
+ --smbd_doorsvc.sd_async_count;
+ free(arg->data);
+ free(arg);
+ }
+}
+
+/*
+ * All door calls are processed here: synchronous or asynchronous:
+ * - synchronous calls are invoked by direct function call
+ * - asynchronous calls are invoked from a launched thread
*
- * Encode the appropriate error code to the first 4-byte of the result
- * buffer upon any door operation failure.
+ * We send a notification when asynchronous (ASYNC) door calls
+ * from the kernel (SYSSPACE) have completed.
*/
-static char *
-smb_door_srv_err_hdlr(int stat, size_t *rbufsize)
+static void *
+smbd_door_dispatch_op(void *thread_arg)
{
- char *rbuf;
+ smbd_arg_t *arg = (smbd_arg_t *)thread_arg;
+ smbd_doorop_t *doorop;
+ smb_doorhdr_t *hdr;
+ int i;
- if ((rbuf = smb_dr_set_res_stat(stat, rbufsize)) == NULL) {
- *rbufsize = 0;
+ if ((!smbd_online()) || arg == NULL)
return (NULL);
+
+ hdr = &arg->hdr;
+ arg->opname = smb_doorhdr_opname(hdr->dh_op);
+
+ for (i = 0; i < smbd_ndoorop; ++i) {
+ doorop = &smbd_doorops[i];
+
+ if (hdr->dh_op == doorop->opcode) {
+ hdr->dh_door_rc = doorop->op(arg);
+ hdr->dh_status = arg->status;
+
+ if ((hdr->dh_flags & SMB_DF_SYSSPACE) &&
+ (hdr->dh_flags & SMB_DF_ASYNC)) {
+ assert(hdr->dh_op != SMB_DR_ASYNC_RESPONSE);
+ (void) smb_kmod_event_notify(hdr->dh_txid);
+ }
+
+ return (NULL);
+ }
}
- return (rbuf);
+ syslog(LOG_ERR, "smbd_door_dispatch_op[%s]: invalid op %u",
+ arg->opname, hdr->dh_op);
+ return (NULL);
}
/*
- * smb_door_srv_func
+ * Wrapper for door_return. smbd_door_enter() increments a reference count
+ * when a door call is dispatched and smbd_door_return() decrements the
+ * reference count when it completes.
*
- * This function will determine the opcode by decoding the first 4-byte of
- * the argument buffer passed by a door client. The corresponding door
- * operation will be looked up from the optab and get invoked.
- * Basically, any door operation will takes the argument buffer as its
- * parameter, and generates the result buffer.
+ * The reference counting is used in smbd_door_fini() to wait for active
+ * calls to complete before closing the door.
*/
-/*ARGSUSED*/
void
-smb_door_srv_func(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
- uint_t n_desc)
+smbd_door_init(smbd_door_t *sdh, const char *name)
+{
+ (void) strlcpy(sdh->sd_name, name, SMBD_DOOR_NAMESZ);
+}
+
+void
+smbd_door_enter(smbd_door_t *sdh)
+{
+ (void) mutex_lock(&sdh->sd_mutex);
+ ++sdh->sd_ncalls;
+ (void) mutex_unlock(&sdh->sd_mutex);
+}
+
+/*
+ * We have two calls to door_return because the first call (with data)
+ * can fail, which can leave the door call blocked here. The second
+ * call (with NULL) is guaranteed to unblock and return to the caller.
+ */
+void
+smbd_door_return(smbd_door_t *sdh, char *data_ptr, size_t data_size,
+ door_desc_t *desc_ptr, uint_t num_desc)
{
- char *resbuf = NULL, *tmpbuf = NULL;
- size_t rbufsize = 0;
- int opcode;
- int err;
- smb_dr_op_t smbop;
+ (void) mutex_lock(&sdh->sd_mutex);
+
+ if (sdh->sd_ncalls == 0)
+ syslog(LOG_ERR, "smbd_door_return[%s]: unexpected count=0",
+ sdh->sd_name);
+ else
+ --sdh->sd_ncalls;
+
+ (void) cond_broadcast(&sdh->sd_cv);
+ (void) mutex_unlock(&sdh->sd_mutex);
+
+ (void) door_return(data_ptr, data_size, desc_ptr, num_desc);
+ (void) door_return(NULL, 0, NULL, 0);
+ /* NOTREACHED */
+}
- if ((cookie != SMB_DR_SVC_COOKIE) || (argp == NULL) ||
- (arg_size < sizeof (uint32_t))) {
- (void) door_return(NULL, 0, NULL, 0);
+/*
+ * A door service is about to terminate.
+ * Give active requests a small grace period to complete.
+ */
+void
+smbd_door_fini(smbd_door_t *sdh)
+{
+ timestruc_t delay;
+ int rc = 0;
+
+ (void) mutex_lock(&sdh->sd_mutex);
+
+ while (rc != ETIME && sdh->sd_ncalls != 0) {
+ delay.tv_sec = 1;
+ delay.tv_nsec = 0;
+ rc = cond_reltimedwait(&sdh->sd_cv, &sdh->sd_mutex, &delay);
}
- if ((opcode = smb_dr_get_opcode(argp, arg_size)) < 0) {
- tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_DECODE,
- &rbufsize);
- goto door_return;
+ if (sdh->sd_ncalls != 0)
+ syslog(LOG_NOTICE, "smbd_door_fini[%s]: %d remaining",
+ sdh->sd_name, sdh->sd_ncalls);
+
+ (void) mutex_unlock(&sdh->sd_mutex);
+}
+
+/*
+ * Null door operation: always returns success.
+ * Assumes no request or response data.
+ */
+/*ARGSUSED*/
+static int
+smbd_dop_null(smbd_arg_t *arg)
+{
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Async response handler: setup the rbuf and rsize for the specified
+ * transaction. This function is used by the kernel to collect the
+ * response half of an asynchronous door call.
+ */
+static int
+smbd_dop_async_response(smbd_arg_t *rsp_arg)
+{
+ list_t *arg_list = &smbd_doorsvc.sd_async_list;
+ smbd_arg_t *arg;
+
+ (void) mutex_lock(&smbd_doorsvc.sd_mutex);
+ arg = list_head(arg_list);
+
+ while (arg != NULL) {
+ if (arg->hdr.dh_txid == rsp_arg->hdr.dh_txid) {
+ rsp_arg->rbuf = arg->rbuf;
+ rsp_arg->rsize = arg->rsize;
+ arg->rbuf = NULL;
+ arg->rsize = 0;
+ smbd_door_release_async(arg);
+ break;
+ }
+
+ arg = list_next(arg_list, arg);
}
- if (smb_dr_is_valid_opcode(opcode) != 0) {
- tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_INVALID_OPCODE,
- &rbufsize);
- } else {
- smbop = smb_doorsrv_optab[opcode];
- if ((tmpbuf = smbop(argp + sizeof (opcode),
- arg_size - sizeof (opcode), dp, n_desc,
- &rbufsize, &err)) == NULL)
- tmpbuf = smb_door_srv_err_hdlr(err, &rbufsize);
+ (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_user_nonauth_logon(smbd_arg_t *arg)
+{
+ uint32_t sid;
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ xdr_uint32_t, &sid) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ smbd_user_nonauth_logon(sid);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_user_auth_logoff(smbd_arg_t *arg)
+{
+ uint32_t sid;
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ xdr_uint32_t, &sid) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ smbd_user_auth_logoff(sid);
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Obtains an access token on successful user authentication.
+ */
+static int
+smbd_dop_user_auth_logon(smbd_arg_t *arg)
+{
+ smb_logon_t *user_info;
+ smb_token_t *token;
+
+ user_info = smb_logon_decode((uint8_t *)arg->data,
+ arg->datalen);
+ if (user_info == NULL)
+ return (SMB_DOP_DECODE_ERROR);
+
+ token = smbd_user_auth_logon(user_info);
+
+ smb_logon_free(user_info);
+
+ if (token == NULL)
+ return (SMB_DOP_EMPTYBUF);
+
+ arg->rbuf = (char *)smb_token_encode(token, &arg->rsize);
+ smb_token_destroy(token);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_lookup_name(smbd_arg_t *arg)
+{
+ smb_domain_t dinfo;
+ smb_account_t ainfo;
+ lsa_account_t acct;
+ char buf[MAXNAMELEN];
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ lsa_account_xdr, &acct) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ if (*acct.a_domain == '\0')
+ (void) snprintf(buf, MAXNAMELEN, "%s", acct.a_name);
+ else if (strchr(acct.a_domain, '.') != NULL)
+ (void) snprintf(buf, MAXNAMELEN, "%s@%s", acct.a_name,
+ acct.a_domain);
+ else
+ (void) snprintf(buf, MAXNAMELEN, "%s\\%s", acct.a_domain,
+ acct.a_name);
+
+ acct.a_status = lsa_lookup_name(buf, acct.a_sidtype, &ainfo);
+ if (acct.a_status == NT_STATUS_SUCCESS) {
+ acct.a_sidtype = ainfo.a_type;
+ smb_sid_tostr(ainfo.a_sid, acct.a_sid);
+ (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
+
+ if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
+ (void) strlcpy(acct.a_domain, dinfo.di_fqname,
+ MAXNAMELEN);
+ else
+ (void) strlcpy(acct.a_domain, ainfo.a_domain,
+ MAXNAMELEN);
+ smb_account_free(&ainfo);
}
-door_return:
- if (tmpbuf) {
- if ((resbuf = (char *)alloca(rbufsize)) == NULL)
- rbufsize = 0;
+ arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_lookup_sid(smbd_arg_t *arg)
+{
+ smb_domain_t dinfo;
+ smb_account_t ainfo;
+ lsa_account_t acct;
+ smb_sid_t *sid;
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ lsa_account_xdr, &acct) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ sid = smb_sid_fromstr(acct.a_sid);
+ acct.a_status = lsa_lookup_sid(sid, &ainfo);
+ smb_sid_free(sid);
+
+ if (acct.a_status == NT_STATUS_SUCCESS) {
+ acct.a_sidtype = ainfo.a_type;
+ smb_sid_tostr(ainfo.a_sid, acct.a_sid);
+ (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
+
+ if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
+ (void) strlcpy(acct.a_domain, dinfo.di_fqname,
+ MAXNAMELEN);
else
- (void) memcpy(resbuf, tmpbuf, rbufsize);
- free(tmpbuf);
+ (void) strlcpy(acct.a_domain, ainfo.a_domain,
+ MAXNAMELEN);
+
+ smb_account_free(&ainfo);
}
- (void) door_return(resbuf, rbufsize, NULL, 0);
- /*NOTREACHED*/
+ arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_join(smbd_arg_t *arg)
+{
+ smb_joininfo_t jdi;
+ uint32_t status;
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_joininfo_xdr, &jdi) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ status = smbd_join(&jdi);
+
+ arg->rbuf = smb_common_encode(&status, xdr_uint32_t, &arg->rsize);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_get_dcinfo(smbd_arg_t *arg)
+{
+ smb_domainex_t dxi;
+
+ if (!smb_domain_getinfo(&dxi))
+ return (SMB_DOP_EMPTYBUF);
+
+ arg->rbuf = smb_string_encode(dxi.d_dc, &arg->rsize);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Return the number of snapshots for a dataset
+ */
+static int
+smbd_dop_vss_get_count(smbd_arg_t *arg)
+{
+ smb_string_t path;
+ uint32_t count;
+
+ bzero(&path, sizeof (smb_string_t));
+ arg->rbuf = NULL;
+
+ if (smb_string_decode(&path, arg->data, arg->datalen) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ if (smbd_vss_get_count(path.buf, &count) == 0)
+ arg->rbuf = smb_common_encode(&count, xdr_uint32_t,
+ &arg->rsize);
+
+ xdr_free(smb_string_xdr, (char *)&path);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Return the count and list of snapshots.
+ * The list is in @GMT token format.
+ */
+static int
+smbd_dop_vss_get_snapshots(smbd_arg_t *arg)
+{
+ char **gmtp;
+ smb_gmttoken_query_t request;
+ smb_gmttoken_response_t reply;
+ uint_t i;
+
+ bzero(&request, sizeof (smb_gmttoken_query_t));
+ bzero(&reply, sizeof (smb_gmttoken_response_t));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_gmttoken_query_xdr, &request) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ reply.gtr_gmttokens.gtr_gmttokens_val = malloc(request.gtq_count *
+ sizeof (char *));
+ bzero(reply.gtr_gmttokens.gtr_gmttokens_val, request.gtq_count *
+ sizeof (char *));
+
+ if (reply.gtr_gmttokens.gtr_gmttokens_val == NULL) {
+ xdr_free(smb_gmttoken_query_xdr, (char *)&request);
+ return (SMB_DOP_EMPTYBUF);
+ }
+
+ smbd_vss_get_snapshots(request.gtq_path, request.gtq_count,
+ &reply.gtr_count,
+ &reply.gtr_gmttokens.gtr_gmttokens_len,
+ reply.gtr_gmttokens.gtr_gmttokens_val);
+
+ arg->rbuf = smb_common_encode(&reply, smb_gmttoken_response_xdr,
+ &arg->rsize);
+ if (arg->rbuf == NULL) {
+ xdr_free(smb_gmttoken_query_xdr, (char *)&request);
+ return (SMB_DOP_ENCODE_ERROR);
+ }
+
+ for (i = 0, gmtp = reply.gtr_gmttokens.gtr_gmttokens_val;
+ (i < request.gtq_count); i++) {
+ if (*gmtp)
+ free(*gmtp);
+ gmtp++;
+ }
+
+ free(reply.gtr_gmttokens.gtr_gmttokens_val);
+ xdr_free(smb_gmttoken_query_xdr, (char *)&request);
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Return the name of the snapshot that matches the dataset path
+ * and @GMT token.
+ */
+static int
+smbd_dop_vss_map_gmttoken(smbd_arg_t *arg)
+{
+ char *snapname;
+ smb_gmttoken_snapname_t request;
+
+ bzero(&request, sizeof (smb_gmttoken_snapname_t));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_gmttoken_snapname_xdr, &request) != 0) {
+ xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
+ return (SMB_DOP_DECODE_ERROR);
+ }
+
+ if ((snapname = malloc(MAXPATHLEN)) == NULL) {
+ xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
+ return (NULL);
+ }
+
+ if ((smbd_vss_map_gmttoken(request.gts_path, request.gts_gmttoken,
+ snapname) != 0)) {
+ *snapname = '\0';
+ }
+
+ arg->rbuf = smb_string_encode(snapname, &arg->rsize);
+ xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
+ free(snapname);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_ads_find_host(smbd_arg_t *arg)
+{
+ smb_ads_host_info_t *hinfo = NULL;
+ char *hostname = "";
+ smb_string_t fqdn;
+
+ bzero(&fqdn, sizeof (smb_string_t));
+
+ if (smb_string_decode(&fqdn, arg->data, arg->datalen) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ if ((hinfo = smb_ads_find_host(fqdn.buf, NULL)) != NULL)
+ hostname = hinfo->name;
+
+ xdr_free(smb_string_xdr, (char *)&fqdn);
+
+ arg->rbuf = smb_string_encode(hostname, &arg->rsize);
+ free(hinfo);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Query the list of user/group quota entries for a given filesystem.
+ */
+static int
+smbd_dop_quota_query(smbd_arg_t *arg)
+{
+ smb_quota_query_t request;
+ smb_quota_response_t reply;
+ uint32_t status;
+
+ bzero(&request, sizeof (smb_quota_query_t));
+ bzero(&reply, sizeof (smb_quota_response_t));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_quota_query_xdr, &request) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ status = smb_quota_query(&request, &reply);
+ reply.qr_status = status;
+
+ arg->rbuf = smb_common_encode(&reply, smb_quota_response_xdr,
+ &arg->rsize);
+
+ xdr_free(smb_quota_query_xdr, (char *)&request);
+ smb_quota_free(&reply);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+/*
+ * Set a list of user/group quota entries for a given filesystem.
+ */
+static int
+smbd_dop_quota_set(smbd_arg_t *arg)
+{
+ smb_quota_set_t request;
+ uint32_t status = 0;
+
+ bzero(&request, sizeof (smb_quota_set_t));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ smb_quota_set_xdr, &request) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ status = smb_quota_set(&request);
+
+ arg->rbuf = smb_common_encode(&status, xdr_uint32_t, &arg->rsize);
+ xdr_free(smb_quota_set_xdr, (char *)&request);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
+}
+
+static int
+smbd_dop_dfs_get_referrals(smbd_arg_t *arg)
+{
+ dfs_referral_query_t request;
+ dfs_referral_response_t reply;
+
+ bzero(&request, sizeof (request));
+ bzero(&reply, sizeof (reply));
+
+ if (smb_common_decode(arg->data, arg->datalen,
+ dfs_referral_query_xdr, &request) != 0)
+ return (SMB_DOP_DECODE_ERROR);
+
+ reply.rp_status = dfs_get_referrals((const char *)request.rq_path,
+ request.rq_type, &reply.rp_referrals);
+
+ if (reply.rp_status != ERROR_SUCCESS)
+ bzero(&reply.rp_referrals, sizeof (dfs_info_t));
+
+ arg->rbuf = smb_common_encode(&reply, dfs_referral_response_xdr,
+ &arg->rsize);
+
+ if (reply.rp_status == ERROR_SUCCESS)
+ dfs_info_free(&reply.rp_referrals);
+
+ xdr_free(dfs_referral_query_xdr, (char *)&request);
+
+ if (arg->rbuf == NULL)
+ return (SMB_DOP_ENCODE_ERROR);
+ return (SMB_DOP_SUCCESS);
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_logon.c b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
index a6d21596dd..97f9e47b51 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -76,7 +76,7 @@ static smb_audit_t *smbd_audit_unlink(uint32_t);
* user, start an audit session and audit the event.
*/
smb_token_t *
-smbd_user_auth_logon(netr_client_t *clnt)
+smbd_user_auth_logon(smb_logon_t *user_info)
{
smb_token_t *token;
smb_audit_t *entry;
@@ -92,12 +92,12 @@ smbd_user_auth_logon(netr_client_t *clnt)
int status;
int retval;
- if ((token = smb_logon(clnt)) == NULL) {
+ if ((token = smb_logon(user_info)) == NULL) {
uid = ADT_NO_ATTRIB;
gid = ADT_NO_ATTRIB;
sid = NT_NULL_SIDSTR;
- username = clnt->e_username;
- domain = clnt->e_domain;
+ username = user_info->lg_e_username;
+ domain = user_info->lg_e_domain;
status = ADT_FAILURE;
retval = ADT_FAIL_VALUE_AUTH;
} else {
@@ -126,13 +126,14 @@ smbd_user_auth_logon(netr_client_t *clnt)
}
(void) memset(&termid, 0, sizeof (au_tid_addr_t));
- termid.at_port = clnt->local_port;
+ termid.at_port = user_info->lg_local_port;
- if (clnt->ipaddr.a_family == AF_INET) {
- termid.at_addr[0] = clnt->ipaddr.a_ipv4;
+ if (user_info->lg_clnt_ipaddr.a_family == AF_INET) {
+ termid.at_addr[0] = user_info->lg_clnt_ipaddr.a_ipv4;
termid.at_type = AU_IPv4;
} else {
- bcopy(&clnt->ipaddr.a_ip, termid.at_addr, IPV6_ADDR_LEN);
+ bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
+ IPV6_ADDR_LEN);
termid.at_type = AU_IPv6;
}
adt_set_termid(ah, &termid);
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c
index 1df2cda39f..72c5b110b8 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c
@@ -50,7 +50,7 @@
#include <pwd.h>
#include <grp.h>
-#include <smbsrv/smb_door_svc.h>
+#include <smbsrv/smb_door.h>
#include <smbsrv/smb_ioctl.h>
#include <smbsrv/string.h>
#include <smbsrv/libsmb.h>
@@ -110,11 +110,21 @@ static pthread_t refresh_thr;
static pthread_cond_t refresh_cond;
static pthread_mutex_t refresh_mutex;
+static cond_t listener_cv;
+static mutex_t listener_mutex;
+
+/*
+ * Mutex to ensure that smbd_service_fini() and smbd_service_init()
+ * are atomic w.r.t. one another. Otherwise, if a shutdown begins
+ * before initialization is complete, resources can get deallocated
+ * while initialization threads are still using them.
+ */
+static mutex_t smbd_service_mutex;
+static cond_t smbd_service_cv;
+
smbd_t smbd;
/*
- * smbd user land daemon
- *
* Use SMF error codes only on return or exit.
*/
int
@@ -157,6 +167,7 @@ main(int argc, char *argv[])
act.sa_handler = smbd_sig_handler;
act.sa_flags = 0;
+ (void) sigaction(SIGABRT, &act, NULL);
(void) sigaction(SIGTERM, &act, NULL);
(void) sigaction(SIGHUP, &act, NULL);
(void) sigaction(SIGINT, &act, NULL);
@@ -193,7 +204,7 @@ main(int argc, char *argv[])
smbd_daemonize_fini(pfd, SMF_EXIT_OK);
}
- (void) atexit(smbd_service_fini);
+ (void) atexit(smb_kmod_stop);
while (!smbd.s_shutting_down) {
if (smbd.s_sigval == 0 && smbd.s_refreshes == 0)
@@ -204,6 +215,7 @@ main(int argc, char *argv[])
switch (sigval) {
case 0:
case SIGPIPE:
+ case SIGABRT:
break;
case SIGHUP:
@@ -399,6 +411,7 @@ smbd_daemonize_fini(int fd, int exit_status)
(void) priv_addset(pset, PRIV_PROC_AUDIT);
(void) priv_addset(pset, PRIV_SYS_DEVICES);
(void) priv_addset(pset, PRIV_SYS_SMB);
+ (void) priv_addset(pset, PRIV_SYS_MOUNT);
priv_inverse(pset);
@@ -417,12 +430,29 @@ smbd_daemonize_fini(int fd, int exit_status)
static int
smbd_service_init(void)
{
- int rc;
+ static struct dir {
+ char *name;
+ int perm;
+ } dir[] = {
+ { SMB_DBDIR, 0700 },
+ { SMB_CVOL, 0755 },
+ { SMB_SYSROOT, 0755 },
+ { SMB_SYSTEM32, 0755 },
+ { SMB_VSS, 0755 }
+ };
+ int rc, i;
+
+ (void) mutex_lock(&smbd_service_mutex);
smbd.s_pid = getpid();
- if ((mkdir(SMB_DBDIR, 0700) < 0) && (errno != EEXIST)) {
- smbd_report("mkdir %s: %s", SMB_DBDIR, strerror(errno));
- return (1);
+ for (i = 0; i < sizeof (dir)/sizeof (dir[0]); ++i) {
+ if ((mkdir(dir[i].name, dir[i].perm) < 0) &&
+ (errno != EEXIST)) {
+ smbd_report("mkdir %s: %s", dir[i].name,
+ strerror(errno));
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
+ }
}
if ((rc = smb_ccache_init(SMB_VARRUN_DIR, SMB_CCACHE_FILE)) != 0) {
@@ -431,16 +461,12 @@ smbd_service_init(void)
strerror(errno));
else
smbd_report("unable to set KRB5CCNAME");
- return (1);
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
}
smb_codepage_init();
- if (!smb_wka_init()) {
- smbd_report("out of memory");
- return (1);
- }
-
if (smb_nicmon_start(SMBD_DEFAULT_INSTANCE_FMRI) != 0)
smbd_report("NIC monitoring failed to start");
@@ -452,104 +478,124 @@ smbd_service_init(void)
else
smbd_report("NetBIOS services started");
- /* Get the ID map client handle */
- if ((rc = smb_idmap_start()) != 0) {
- smbd_report("no idmap handle");
- return (rc);
- }
-
smbd.s_secmode = smb_config_get_secmode();
if ((rc = smb_domain_init(smbd.s_secmode)) != 0) {
if (rc == SMB_DOMAIN_NOMACHINE_SID) {
smbd_report(
"no machine SID: check idmap configuration");
- return (rc);
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
}
}
smb_ads_init();
- if ((rc = mlsvc_init()) != 0) {
+ if (mlsvc_init() != 0) {
smbd_report("msrpc initialization failed");
- return (rc);
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
}
if (smbd.s_secmode == SMB_SECMODE_DOMAIN)
if (smbd_locate_dc_start() != 0)
smbd_report("dc discovery failed %s", strerror(errno));
- smbd.s_door_srv = smb_door_srv_start();
- if (smbd.s_door_srv < 0)
- return (rc);
+ smbd.s_door_srv = smbd_door_start();
+ smbd.s_door_opipe = smbd_opipe_start();
+ if (smbd.s_door_srv < 0 || smbd.s_door_opipe < 0) {
+ smbd_report("door initialization failed %s", strerror(errno));
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
+ }
- if ((rc = smbd_refresh_init()) != 0)
- return (rc);
+ if (smbd_refresh_init() != 0) {
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
+ }
dyndns_update_zones();
-
(void) smbd_localtime_init();
-
- smbd.s_door_opipe = smbd_opipe_dsrv_start();
- if (smbd.s_door_opipe < 0) {
- smbd_report("opipe initialization failed %s",
- strerror(errno));
- return (rc);
- }
-
(void) smb_lgrp_start();
-
smb_pwd_init(B_TRUE);
- if ((rc = smb_shr_start()) != 0) {
+ if (smb_shr_start() != 0) {
smbd_report("share initialization failed: %s", strerror(errno));
- return (rc);
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
}
- smbd.s_door_lmshr = smb_share_dsrv_start();
- if (smbd.s_door_lmshr < 0) {
+ smbd.s_door_lmshr = smbd_share_start();
+ if (smbd.s_door_lmshr < 0)
smbd_report("share initialization failed");
- }
- if ((rc = smbd_kernel_bind()) != 0) {
- smbd_report("kernel bind error: %s", strerror(errno));
- return (rc);
+ if (smbd_kernel_bind() != 0) {
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
}
- if ((rc = smb_shr_load()) != 0) {
+ if (smb_shr_load() != 0) {
smbd_report("failed to start loading shares: %s",
strerror(errno));
- return (rc);
+ (void) mutex_unlock(&smbd_service_mutex);
+ return (-1);
}
+ smbd.s_initialized = B_TRUE;
+ smbd_report("service initialized");
+ (void) cond_signal(&smbd_service_cv);
+ (void) mutex_unlock(&smbd_service_mutex);
return (0);
}
/*
- * Close the kernel service and shutdown smbd services.
- * This function is registered with atexit(): ensure that anything
- * called from here is safe to be called multiple times.
+ * Shutdown smbd and smbsrv kernel services.
+ *
+ * Shutdown will not begin until initialization has completed.
+ * Only one thread is allowed to perform the shutdown. Other
+ * threads will be blocked on fini_in_progress until the process
+ * has exited.
*/
static void
smbd_service_fini(void)
{
- smbd_opipe_dsrv_stop();
- smb_wka_fini();
+ static uint_t fini_in_progress;
+
+ (void) mutex_lock(&smbd_service_mutex);
+
+ while (!smbd.s_initialized)
+ (void) cond_wait(&smbd_service_cv, &smbd_service_mutex);
+
+ if (atomic_swap_uint(&fini_in_progress, 1) != 0) {
+ while (fini_in_progress)
+ (void) cond_wait(&smbd_service_cv, &smbd_service_mutex);
+ /*NOTREACHED*/
+ }
+
+ smbd.s_shutting_down = B_TRUE;
+ smbd_report("service shutting down");
+
+ smb_kmod_stop();
+ smb_logon_abort();
+ smb_lgrp_stop();
+ smbd_opipe_stop();
+ smbd_door_stop();
smbd_refresh_fini();
smbd_kernel_unbind();
- smb_door_srv_stop();
- smb_share_dsrv_stop();
+ smbd_share_stop();
smb_shr_stop();
dyndns_stop();
smb_nicmon_stop();
- smb_idmap_stop();
- smb_lgrp_stop();
smb_ccache_remove(SMB_CCACHE_PATH);
smb_pwd_fini();
smb_domain_fini();
mlsvc_fini();
smb_ads_fini();
smb_netbios_stop();
-}
+ smbd.s_initialized = B_FALSE;
+ smbd_report("service terminated");
+ (void) mutex_unlock(&smbd_service_mutex);
+ exit((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK);
+}
/*
* smbd_refresh_init()
@@ -587,10 +633,11 @@ smbd_refresh_init()
static void
smbd_refresh_fini()
{
- (void) pthread_cancel(refresh_thr);
-
- (void) pthread_cond_destroy(&refresh_cond);
- (void) pthread_mutex_destroy(&refresh_mutex);
+ if (pthread_self() != refresh_thr) {
+ (void) pthread_cancel(refresh_thr);
+ (void) pthread_cond_destroy(&refresh_cond);
+ (void) pthread_mutex_destroy(&refresh_mutex);
+ }
}
/*
@@ -615,11 +662,12 @@ smbd_refresh_monitor(void *arg)
(void) pthread_mutex_unlock(&refresh_mutex);
if (smbd.s_shutting_down) {
- syslog(LOG_DEBUG, "shutting down");
- exit((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL :
- SMF_EXIT_OK);
+ smbd_service_fini();
+ /*NOTREACHED*/
}
+ (void) mutex_lock(&smbd_service_mutex);
+
/*
* We've been woken up by a refresh event so go do
* what is necessary.
@@ -636,13 +684,15 @@ smbd_refresh_monitor(void *arg)
dyndns_clear_zones();
/* re-initialize NIC table */
- if (smb_nic_init() != 0)
+ if (smb_nic_init() != SMB_NIC_SUCCESS)
smbd_report("failed to get NIC information");
smb_netbios_name_reconfig();
smb_browser_reconfig();
smbd_refresh_dc();
dyndns_update_zones();
+ (void) mutex_unlock(&smbd_service_mutex);
+
if (smbd_set_netlogon_cred()) {
/*
* Restart required because the domain changed
@@ -650,22 +700,18 @@ smbd_refresh_monitor(void *arg)
*/
if (smb_smf_restart_service() != 0) {
syslog(LOG_ERR,
- "unable to restart smb service. "
+ "unable to restart smb/server. "
"Run 'svcs -xv smb/server' for more "
"information.");
- smbd.s_shutting_down = B_TRUE;
- exit(SMF_EXIT_OK);
+ smbd_service_fini();
+ /*NOTREACHED*/
}
break;
}
if (!smbd.s_kbound) {
- error = smbd_kernel_bind();
- if (error != 0)
- smbd_report("kernel bind error: %s",
- strerror(error));
- else
+ if ((error = smbd_kernel_bind()) == 0)
(void) smb_shr_load();
continue;
@@ -718,6 +764,16 @@ smbd_set_secmode(int secmode)
}
/*
+ * The service is online if initialization is complete and shutdown
+ * has not begun.
+ */
+boolean_t
+smbd_online(void)
+{
+ return (smbd.s_initialized && !smbd.s_shutting_down);
+}
+
+/*
* If the door has already been opened by another process (non-zero pid
* in target), we assume that another smbd is already running. If there
* is a race here, it will be caught later when smbsrv is opened because
@@ -729,7 +785,7 @@ smbd_already_running(void)
door_info_t info;
int door;
- if ((door = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
+ if ((door = open(SMBD_DOOR_NAME, O_RDONLY)) < 0)
return (0);
if (door_info(door, &info) < 0)
@@ -757,14 +813,16 @@ smbd_kernel_bind(void)
smbd_kernel_unbind();
- rc = smb_kmod_bind();
- if (rc == 0) {
+ if ((rc = smb_kmod_bind()) == 0) {
rc = smbd_kernel_start();
if (rc != 0)
smb_kmod_unbind();
else
smbd.s_kbound = B_TRUE;
}
+
+ if (rc != 0)
+ smbd_report("kernel bind error: %s", strerror(errno));
return (rc);
}
@@ -1010,18 +1068,47 @@ smbd_start_listeners(void)
return (rc2);
}
+/*
+ * Stop the listener threads. In an attempt to ensure that the listener
+ * threads get the signal, we use the timed wait loop to harass the
+ * threads into terminating. Then, if they are still running, we make
+ * one final attempt to deliver the signal before calling thread join
+ * to wait for them. Note: if these threads don't terminate, smbd will
+ * hang here and SMF will probably end up killing the contract.
+ */
static void
smbd_stop_listeners(void)
{
- void *status;
+ void *status;
+ timestruc_t delay;
+ int rc = 0;
+
+ (void) mutex_lock(&listener_mutex);
+
+ while ((smbd.s_nbt_listener_running || smbd.s_tcp_listener_running) &&
+ (rc != ETIME)) {
+ if (smbd.s_nbt_listener_running)
+ (void) pthread_kill(smbd.s_nbt_listener_id, SIGTERM);
+
+ if (smbd.s_tcp_listener_running)
+ (void) pthread_kill(smbd.s_tcp_listener_id, SIGTERM);
+
+ delay.tv_sec = 3;
+ delay.tv_nsec = 0;
+ rc = cond_reltimedwait(&listener_cv, &listener_mutex, &delay);
+ }
+
+ (void) mutex_unlock(&listener_mutex);
if (smbd.s_nbt_listener_running) {
+ syslog(LOG_WARNING, "NBT listener still running");
(void) pthread_kill(smbd.s_nbt_listener_id, SIGTERM);
(void) pthread_join(smbd.s_nbt_listener_id, &status);
smbd.s_nbt_listener_running = B_FALSE;
}
if (smbd.s_tcp_listener_running) {
+ syslog(LOG_WARNING, "TCP listener still running");
(void) pthread_kill(smbd.s_tcp_listener_id, SIGTERM);
(void) pthread_join(smbd.s_tcp_listener_id, &status);
smbd.s_tcp_listener_running = B_FALSE;
@@ -1075,6 +1162,10 @@ smbd_nbt_listener(void *arg)
if (!smbd.s_shutting_down)
smbd_fatal_error("NBT listener thread terminated unexpectedly");
+ (void) mutex_lock(&listener_mutex);
+ smbd.s_nbt_listener_running = B_FALSE;
+ (void) cond_broadcast(&listener_cv);
+ (void) mutex_unlock(&listener_mutex);
return (NULL);
}
@@ -1111,6 +1202,10 @@ smbd_tcp_listener(void *arg)
if (!smbd.s_shutting_down)
smbd_fatal_error("TCP listener thread terminated unexpectedly");
+ (void) mutex_lock(&listener_mutex);
+ smbd.s_tcp_listener_running = B_FALSE;
+ (void) cond_broadcast(&listener_cv);
+ (void) mutex_unlock(&listener_mutex);
return (NULL);
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_opipe_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_opipe_doorsvc.c
index 393c398b9f..c092e1b395 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_opipe_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_opipe_doorsvc.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,25 +32,26 @@
#include <sys/stat.h>
#include <door.h>
#include <errno.h>
-#include <syslog.h>
#include <pthread.h>
#include <smbsrv/libsmb.h>
#include <smbsrv/libmlrpc.h>
-
+#include "smbd.h"
static int smbd_opipe_fd = -1;
static int smbd_opipe_cookie = 0x50495045; /* PIPE */
static pthread_mutex_t smbd_opipe_mutex = PTHREAD_MUTEX_INITIALIZER;
+static smbd_door_t smbd_opipe_sdh;
static void smbd_opipe_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
+static int smbd_opipe_exec_async(uint32_t);
/*
* Create the smbd opipe door service.
* Returns the door descriptor on success. Otherwise returns -1.
*/
int
-smbd_opipe_dsrv_start(void)
+smbd_opipe_start(void)
{
(void) pthread_mutex_lock(&smbd_opipe_mutex);
@@ -60,6 +61,8 @@ smbd_opipe_dsrv_start(void)
return (-1);
}
+ smbd_door_init(&smbd_opipe_sdh, "opipe");
+
errno = 0;
if ((smbd_opipe_fd = door_create(smbd_opipe_dispatch,
&smbd_opipe_cookie, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
@@ -74,10 +77,12 @@ smbd_opipe_dsrv_start(void)
* Stop the smbd opipe door service.
*/
void
-smbd_opipe_dsrv_stop(void)
+smbd_opipe_stop(void)
{
(void) pthread_mutex_lock(&smbd_opipe_mutex);
+ smbd_door_fini(&smbd_opipe_sdh);
+
if (smbd_opipe_fd != -1) {
(void) door_revoke(smbd_opipe_fd);
smbd_opipe_fd = -1;
@@ -95,72 +100,111 @@ smbd_opipe_dispatch(void *cookie, char *argp, size_t arg_size,
door_desc_t *dd, uint_t n_desc)
{
char buf[SMB_OPIPE_DOOR_BUFSIZE];
- smb_opipe_hdr_t hdr;
+ smb_doorhdr_t hdr;
size_t hdr_size;
uint8_t *data;
uint32_t datalen;
- bzero(&hdr, sizeof (smb_opipe_hdr_t));
- hdr_size = xdr_sizeof(smb_opipe_hdr_xdr, &hdr);
+ smbd_door_enter(&smbd_opipe_sdh);
+
+ if (!smbd_online())
+ smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
+
+ bzero(&hdr, sizeof (smb_doorhdr_t));
+ hdr_size = xdr_sizeof(smb_doorhdr_xdr, &hdr);
if ((cookie != &smbd_opipe_cookie) || (argp == NULL) ||
(arg_size < hdr_size)) {
- (void) door_return(NULL, 0, NULL, 0);
+ smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
}
- if (smb_opipe_hdr_decode(&hdr, (uint8_t *)argp, hdr_size) == -1)
- (void) door_return(NULL, 0, NULL, 0);
+ if (smb_doorhdr_decode(&hdr, (uint8_t *)argp, hdr_size) == -1)
+ smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
- if ((hdr.oh_magic != SMB_OPIPE_HDR_MAGIC) || (hdr.oh_fid == 0))
- (void) door_return(NULL, 0, NULL, 0);
+ if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) || (hdr.dh_fid == 0))
+ smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
- if (hdr.oh_datalen > SMB_OPIPE_DOOR_BUFSIZE)
- hdr.oh_datalen = SMB_OPIPE_DOOR_BUFSIZE;
+ if (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)
+ hdr.dh_datalen = SMB_OPIPE_DOOR_BUFSIZE;
data = (uint8_t *)argp + hdr_size;
- datalen = hdr.oh_datalen;
+ datalen = hdr.dh_datalen;
- switch (hdr.oh_op) {
+ switch (hdr.dh_op) {
case SMB_OPIPE_OPEN:
- hdr.oh_status = ndr_pipe_open(hdr.oh_fid, data, datalen);
+ hdr.dh_door_rc = ndr_pipe_open(hdr.dh_fid, data, datalen);
- hdr.oh_datalen = 0;
- hdr.oh_resid = 0;
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
datalen = hdr_size;
break;
case SMB_OPIPE_CLOSE:
- hdr.oh_status = ndr_pipe_close(hdr.oh_fid);
+ hdr.dh_door_rc = ndr_pipe_close(hdr.dh_fid);
- hdr.oh_datalen = 0;
- hdr.oh_resid = 0;
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
datalen = hdr_size;
break;
case SMB_OPIPE_READ:
data = (uint8_t *)buf + hdr_size;
- datalen = hdr.oh_datalen;
+ datalen = hdr.dh_datalen;
- hdr.oh_status = ndr_pipe_read(hdr.oh_fid, data, &datalen,
- &hdr.oh_resid);
+ hdr.dh_door_rc = ndr_pipe_read(hdr.dh_fid, data, &datalen,
+ &hdr.dh_resid);
- hdr.oh_datalen = datalen;
+ hdr.dh_datalen = datalen;
datalen += hdr_size;
break;
case SMB_OPIPE_WRITE:
- hdr.oh_status = ndr_pipe_write(hdr.oh_fid, data, datalen);
+ hdr.dh_door_rc = ndr_pipe_write(hdr.dh_fid, data, datalen);
+
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
+ datalen = hdr_size;
+ break;
+
+ case SMB_OPIPE_EXEC:
+ hdr.dh_door_rc = smbd_opipe_exec_async(hdr.dh_fid);
- hdr.oh_datalen = 0;
- hdr.oh_resid = 0;
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
datalen = hdr_size;
break;
default:
- (void) door_return(NULL, 0, NULL, 0);
+ smbd_door_return(&smbd_opipe_sdh, NULL, 0, NULL, 0);
break;
}
- (void) smb_opipe_hdr_encode(&hdr, (uint8_t *)buf, hdr_size);
- (void) door_return(buf, datalen, NULL, 0);
+ (void) smb_doorhdr_encode(&hdr, (uint8_t *)buf, hdr_size);
+ smbd_door_return(&smbd_opipe_sdh, buf, datalen, NULL, 0);
+}
+
+/*
+ * On success, arg will be freed by the thread.
+ */
+static int
+smbd_opipe_exec_async(uint32_t fid)
+{
+ pthread_attr_t attr;
+ pthread_t tid;
+ uint32_t *arg;
+ int rc;
+
+ if ((arg = malloc(sizeof (uint32_t))) == NULL)
+ return (ENOMEM);
+
+ *arg = fid;
+
+ (void) pthread_attr_init(&attr);
+ (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ rc = pthread_create(&tid, &attr, ndr_pipe_transact, arg);
+ (void) pthread_attr_destroy(&attr);
+
+ if (rc != 0)
+ free(arg);
+ return (rc);
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
index 78d33dd1c4..5ec93bd59f 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,44 +37,43 @@
#include <string.h>
#include <strings.h>
#include <pthread.h>
-
#include <smbsrv/libsmb.h>
-
#include <smbsrv/smb_share.h>
#include <smbsrv/smbinfo.h>
+#include "smbd.h"
#define SMB_SHARE_DSRV_VERSION 1
#define SMB_SHARE_DSRV_COOKIE ((void*)(0xdeadbeef^SMB_SHARE_DSRV_VERSION))
static int smb_share_dsrv_fd = -1;
static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER;
+static smbd_door_t smb_share_sdh;
-static void smb_share_dsrv_dispatch(void *, char *, size_t, door_desc_t *,
- uint_t);
-static int smb_share_dsrv_enum(smb_enumshare_info_t *esi);
+static void smbd_share_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
+static int smbd_share_enum(smb_enumshare_info_t *esi);
/*
- * smb_share_dsrv_start
- *
* Start the LanMan share door service.
* Returns 0 on success. Otherwise, -1.
*/
int
-smb_share_dsrv_start(void)
+smbd_share_start(void)
{
int newfd;
(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
if (smb_share_dsrv_fd != -1) {
- syslog(LOG_ERR, "smb_share_dsrv_start: duplicate");
+ syslog(LOG_ERR, "smbd_share_start: duplicate");
(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
return (smb_share_dsrv_fd);
}
- if ((smb_share_dsrv_fd = door_create(smb_share_dsrv_dispatch,
+ smbd_door_init(&smb_share_sdh, "share");
+
+ if ((smb_share_dsrv_fd = door_create(smbd_share_dispatch,
SMB_SHARE_DSRV_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
- syslog(LOG_ERR, "smb_share_dsrv_start: door_create: %s",
+ syslog(LOG_ERR, "smbd_share_start: door_create: %s",
strerror(errno));
(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
return (-1);
@@ -83,7 +82,7 @@ smb_share_dsrv_start(void)
(void) unlink(SMB_SHARE_DNAME);
if ((newfd = creat(SMB_SHARE_DNAME, 0644)) < 0) {
- syslog(LOG_ERR, "smb_share_dsrv_start: open: %s",
+ syslog(LOG_ERR, "smbd_share_start: open: %s",
strerror(errno));
(void) door_revoke(smb_share_dsrv_fd);
smb_share_dsrv_fd = -1;
@@ -95,7 +94,7 @@ smb_share_dsrv_start(void)
(void) fdetach(SMB_SHARE_DNAME);
if (fattach(smb_share_dsrv_fd, SMB_SHARE_DNAME) < 0) {
- syslog(LOG_ERR, "smb_share_dsrv_start: fattach: %s",
+ syslog(LOG_ERR, "smbd_share_start: fattach: %s",
strerror(errno));
(void) door_revoke(smb_share_dsrv_fd);
smb_share_dsrv_fd = -1;
@@ -108,15 +107,15 @@ smb_share_dsrv_start(void)
}
/*
- * smb_share_dsrv_stop
- *
* Stop the LanMan share door service.
*/
void
-smb_share_dsrv_stop(void)
+smbd_share_stop(void)
{
(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
+ smbd_door_fini(&smb_share_sdh);
+
if (smb_share_dsrv_fd != -1) {
(void) fdetach(SMB_SHARE_DNAME);
(void) door_revoke(smb_share_dsrv_fd);
@@ -127,15 +126,13 @@ smb_share_dsrv_stop(void)
}
/*
- * smb_share_dsrv_dispatch
- *
* This function with which the LMSHARE door is associated
* will invoke the appropriate CIFS share management function
* based on the request type of the door call.
*/
/*ARGSUSED*/
static void
-smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
+smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
uint_t n_desc)
{
uint32_t rc;
@@ -155,9 +152,11 @@ smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
int exec_type;
smb_execsub_info_t subs;
+ smbd_door_enter(&smb_share_sdh);
+
if ((cookie != SMB_SHARE_DSRV_COOKIE) || (ptr == NULL) ||
(size < sizeof (uint32_t))) {
- (void) door_return(NULL, 0, NULL, 0);
+ smbd_door_return(&smb_share_sdh, NULL, 0, NULL, 0);
}
dec_ctx = smb_dr_decode_start(ptr, size);
@@ -214,7 +213,8 @@ smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
goto decode_error;
}
rc = smb_shr_get(sharename, &lmshr_info);
- smb_shr_hostaccess(&lmshr_info, &ipaddr);
+ if (rc == NERR_Success)
+ smb_shr_hostaccess(&lmshr_info, &ipaddr);
smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
smb_dr_put_uint32(enc_ctx, rc);
smb_dr_put_share(enc_ctx, &lmshr_info);
@@ -263,7 +263,7 @@ smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
goto decode_error;
}
- rc = smb_share_dsrv_enum(&esi);
+ rc = smbd_share_enum(&esi);
smb_dr_free_string(esi.es_username);
@@ -301,8 +301,7 @@ smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
rc = smb_shr_exec(sharename, &subs, exec_type);
if (rc != 0)
- syslog(LOG_NOTICE, "Failed to execute %s" \
- " command.\n",
+ syslog(LOG_NOTICE, "Failed to execute %s command",
(exec_type == SMB_SHR_UNMAP) ? "unmap" : "map");
smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
@@ -325,19 +324,17 @@ smb_share_dsrv_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
(void) smb_dr_encode_finish(enc_ctx, &used);
}
- (void) door_return(buf, used, NULL, 0);
+ smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
return;
decode_error:
smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
smb_dr_put_uint32(enc_ctx, dec_status);
(void) smb_dr_encode_finish(enc_ctx, &used);
- (void) door_return(buf, used, NULL, 0);
+ smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
}
/*
- * smb_share_dsrv_enum
- *
* This function builds a response for a NetShareEnum RAP request which
* originates from smbsrv kernel module. A response buffer is allocated
* with the specified size in esi->es_bufsize. List of shares is scanned
@@ -353,7 +350,7 @@ decode_error:
* encoded in one round without unnecessarily complicating the code.
*/
static int
-smb_share_dsrv_enum(smb_enumshare_info_t *esi)
+smbd_share_enum(smb_enumshare_info_t *esi)
{
smb_shriter_t shi;
smb_share_t *si;